更新:09 年 8 月 15 日:评论现已关闭。如果您需要安装帮助或提供反馈或提出问题,请加入邮件列表(存档)
在过去几个月里,SpringSource 一直积极参与开发下一版本的 Eclipse Groovy 工具。最初的目标是将它们从当前状态发展成为一个高度优化的环境,用于代码开发、构建和测试等关键开发任务。理想情况下,在处理混合 Groovy/Java 项目时的体验应该与在 Eclipse 中处理纯 Java 项目一样好。
本周,第一个版本的代码已提交到 codehaus 存储库,并且很快将发布第一个里程碑版本。提供了一个包含当前开发版本的更新站点(适用于 Eclipse 3.4.2):http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.4。是的,目前还没有此代码的 Eclipse 3.5 版本,但很快就会有。(更新!09 年 7 月 31 日 Eclipse 3.5 更新站点现已在以下地址提供:http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.5)
在本文中,我将简要介绍如何开始使用新插件,然后重点介绍未来支撑它的新技术以及它带来的功能。
入门
从更新站点安装的方式与其他 Eclipse 功能相同。在 Eclipse 3.4.2 中,导航到**帮助** > **软件更新**。在**可用软件**选项卡上,单击**添加站点**并输入更新站点 URL:
http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.4。单击**确定**。现在更新站点将出现在列表中,打开它并标记“Groovy-Eclipse 插件”条目。最后,在右上方,单击**安装**并按照对话框完成安装。安装完成后,有三种方法可以开始使用 Groovy
- 创建一个新的 Groovy 项目。就像您可以创建 Java 项目一样,也存在 Groovy 项目创建向导。所有 Groovy 项目实际上都支持 .java 和 .groovy 文件的混合。
- 修改现有的 Java 项目,以便您可以包含 Groovy 代码。在包资源管理器中选择您的 Java 项目,右键单击并导航到上下文菜单中的**Groovy**,然后选择**添加 Groovy 特性**。完成后,项目的图标将更改,从那时起,该项目中的任何 .groovy 文件都将与 .java 文件一起构建。
- 迁移现有的 Groovy 项目。如果您使用旧版插件创建了 Groovy 项目,则必须将其迁移到新版本。要迁移项目,请选择要迁移的项目,然后右键单击并导航到**Groovy**,然后选择**转换旧版 Groovy 项目**。仅当选定的项目需要迁移时,才会显示此选项。
就是这样!只需开始创建 Groovy 类型并像使用 Java 一样处理它们。常见问题解答
http://groovy.codehaus.org/Eclipse+Plugin+V2+FAQ 尝试回答我们认为在这个 alpha 版本中会常见的问题,并包含指向您遇到的任何问题或要提出的其他问题的解决方法的链接。
现有插件编译策略
在描述此版本使用的新编译器技术之前,值得简要介绍一下现有版本使用的方法。当前发布版本的 Groovy Eclipse 插件利用了现有的 Groovy 编译器“联合编译”支持。联合编译允许构建混合 Java/Groovy 代码库,其中 Java 和 Groovy 类型之间存在引用。它基本上按如下方式工作
- 让 Groovy 编译器 (groovyc) 解析 .groovy 文件
- 在磁盘上创建类似 Java 的这些 Groovy 文件的存根。
- 调用 javac 来构建 .java 文件,这些文件可以通过存根查看 Groovy 文件。
- 完成 Groovy 文件的处理 - 现在可以解析针对 Java 类型的 .class 文件的引用
用户最终获得所有源代码都构建到二进制 .class 文件中。
简化项目构建策略
我知道一些用户,包括我自己,在设置使用联合编译版本的 Eclipse 插件构建的项目时遇到了麻烦 - 它使用的双构建器设置可能难以正确配置。当我们开始设计下一版本的工具时,我想知道是否有一种更优化的方案,其中只有一个构建器负责,并且它知道要调用谁来处理 Java 或 Groovy 文件。拥有单个构建器将消除围绕配置项目进行构建的任何复杂性。
我最初的想法是让 Eclipse 编译器负责构建代码,但必要时应涉及 groovyc 来处理任何 Groovy 代码。由于我在编译器方面的背景(从事 AspectJ 的工作),我已经非常了解 Eclipse Java 编译器。然后在与 Jochen Theodorou(Groovy 技术负责人)讨论 groovyc 编译器的结构后,看起来可以在 Eclipse 编译器和 groovyc 之间实现更紧密的集成,从而避免使用存根。在正常的联合编译中,磁盘上的存根本质上是 groovyc 告诉 javac 它正在做什么的一种方式,类似地,javac 生成的 .class 文件是 javac 告诉 groovyc 它刚刚做了什么的一种方式。优化编译器之间的通信仅仅意味着它们直接通信而不是通过磁盘上的文件(存根 .java 文件或 .class 文件)。但是,编译器通信方式的任何更改都不能影响现有联合编译策略提供的最重要的功能 - 它允许在两种语言中定义的类型之间进行引用的完全自由。例如,考虑在一个项目中定义的这三种类型
对于“什么应该首先完全编译?”没有正确的答案。如果所有 Groovy 代码都首先编译,它将无法找到 Apple Java 类型。如果 Java 代码首先编译,它将无法找到 Fruit Groovy 类型。显然,当将 Eclipse 编译器和 groovyc 结合在一起时,它们需要在整个编译过程中相互了解并能够相互询问问题(最重要的是:你能解析此类型吗?)。为了支持这种方法,可能需要在两方面进行更改,即在 Eclipse 编译器和 groovyc 中,但会谨慎地最小化这些更改,并且希望将这些更改贡献回这两个编译器项目。
除了“简单任务”将两个编译器粘合在一起之外,新版本还有一些额外的要求
- 启用 Eclipse 为 Java 提供的增量编译行为以用于 Groovy 代码。
- 在任何情况下,Eclipse 编译器构建纯 Java 项目的方式都不能发生变化。它必须像以往一样快速可靠。
- 尝试避免将任何 Groovy 特定的依赖项引入 Eclipse 编译器。而是使用抽象并扩展 Eclipse 以支持“其他一些语言”,在这种情况下,第一个是 Groovy。
实现后一个目标将使我们能够将 Eclipse 编译器更改贡献回 Eclipse。
不仅仅是关于性能
当然,优化编译器之间的通信应该可以提高性能,并且让增量编译适用于 Groovy 将是一件很棒的事情,但将 Eclipse 编译器作为主要构建器的这种新的单一构建器策略还有另一个非常好的理由。如果 Eclipse 可以更好地理解 Groovy,那么 Eclipse 的一些功能将“正常工作”。一个很好的例子是 JUnit 支持。为了在 Eclipse 中运行测试用例,您通常使用上下文菜单**以...方式运行 > JUnit** 或快捷键**Alt+Shift+X, T**。使用当前版本的 Groovy 插件,这将不起作用,Eclipse 不知道编辑器中看到的是什么。在新世界中,编译器之间的集成层使 Eclipse 能够理解该 Groovy 文件中内容的形状 - 它可以看到测试类,它可以看到任何
@Test注释,它甚至可以看到任何
@RunWith注释以选择测试运行器。因此,JUnit 启动就能正常工作。这只是一个无需任何努力即可实现的功能的示例。在这里,重要的是要理解 Eclipse 编译器没有被修改为直接处理 Groovy 代码,它始终委托给 Groovy 编译器来处理 Groovy 代码,但编译器之间的集成层使 Eclipse 能够理解 groovyc 调用的结果。
内部结构
使集成层在短时间内变得可行的是这两个编译器的现有灵活结构。在 Eclipse 编译器中,编译的不同阶段清晰可见且可访问,在 groovyc 中(它们被称为阶段)甚至更清晰。将编译器集成在一起基本上是定义一个流程,该流程协调和控制每个编译器在各个阶段/阶段中的进展。尽管实际编译中有很多阶段,但为了理解新设计,可以很容易地将其视为一个三阶段过程:解析/解析/生成。
在**解析**阶段,输入数据从纯文本形式处理到一些内部数据结构 - 不会推断出该结构的任何信息。
在**解析**阶段,结构中名称引用的实际实体会被追查。例如,如果在源代码中使用了“Foo”,则必须确定用户指的是哪个 Foo - 这是使用适当的解析规则完成的:我的导入是什么?此包中有什么?类路径上有什么?在 Groovy 的情况下,额外的规则如下:我的别名导入是什么?
在**生成**阶段,创建实际的 .class 文件。
下图显示了调用构建项目时新构建器的体系结构。所有源代码(.java 和 .groovy)都传递给 Eclipse 编译器。根据文件扩展名,Eclipse 编译器自己解析文件或请求 groovyc 解析文件。完成后,解析跨所有发现的类型(Groovy 和 Java 类型)运行。两个编译器中的解析策略都进行了调整,以便它们可以相互查看对方的类型。最后,在解析后,运行生成阶段以创建 .class 文件。
[标题 id="attachment_2593" align="aligncenter" width="624" caption="新编译系统的结构"][/标题]
通常,在生成 .class 文件后,Groovy 编译过程会立即将文件写入磁盘,但在新的设计中,它们会被返回给 Eclipse 编译器。这个最后一步是增量编译能够工作的关键。Eclipse 分析 groovyc 生成的类文件,就像它自己创建的类文件一样。类之间引用信息以与常规 Java 类型相同的结构保存 - 这使得我们能够“免费”获得 Groovy 的增量编译支持。由于此引用信息以与 Java 类型相同的方式保存,因此它会在每次 Eclipse 重启时自动持久化到每个项目中,并且其他依赖项目可以利用它。后两项功能对于 AspectJ 来说仍然是一个问题,因为在 AspectJ 中采用了不同的 Eclipse 编译器修改方法。
增量编译
这确实值得单独写一篇博文来介绍,但这里有必要描述一下基本原理。编译后,Eclipse 编译器会记录它处理的所有类型之间的引用。增量编译只不过是在构建某些内容后,查阅引用列表以查看哪些内容受更改影响。如果没有任何内容受到影响,则编译结束。如果某些类型确实依赖于刚刚构建的内容,则会编译它们。此处描述的机制甚至可以为纯 Groovy 项目提供增量编译。
意外收获?
很早就发现,由于 Eclipse 现在可以查看 Groovy 类型的 Java 式结构,因此它会检查该结构。一些检查对于 Groovy 代码无效,因为 Groovy 在允许的内容方面更加灵活,但有些检查很有用。考虑一下,如果代码在利用泛型方面不够正确,Eclipse 编译器会报告无限量的(可配置的)与泛型相关的警告。此屏幕截图显示 Eclipse 编译器实际上正在检查 Groovy 代码。
[caption id="attachment_2594" align="aligncenter" width="708" caption="Groovy 代码的泛型警告"][/caption]
这些检查的价值仍在讨论中,但目前它们保持激活状态。
UI
到目前为止,我讨论的所有内容都是底层的编译策略。在 Eclipse UI 中,它只表现为用于编译混合 Java/Groovy 项目的“构建器”。在此基础上,Andrew Eisenberg(也与我在温哥华 SpringSource 实验室)一直在做很棒的事情,使 UI 焕发生机
- 将(并发展)现有插件中在新世界中仍然需要的组件带到一起,并将它们重新建立在新的编译基础设施上。
- 开发/增强用户在 IDE 中依赖的功能:编辑器、大纲视图、代码辅助、导航、调试等。
最终结果是,当使用 Groovy 时,Eclipse UI 的外观和行为与使用 Java 时完全一样。这是来自 Spock 测试框架(
http://code.google.com/p/spock/)的 PublisherSubscriberSpecification 示例。它可以直接作为 JUnit 测试执行。
[caption id="attachment_2595" align="aligncenter" width="1088" caption="执行 Spock 示例"][/caption]
是的,对于“知情人士”来说,该截图确实表明此新构建器支持 Groovy AST 转换,因为 Spock 就是这样实现的。
IDE 外部
我知道很多人在他们的构建系统中使用 Eclipse 编译器作为 Java 编译器。这让他们对构建系统正在做什么更有信心,因为它是他们在 IDE 中使用的相同编译器。没有什么可以阻止本文中描述的集成 Eclipse/Groovy 编译器以类似的方式使用,无论是直接在命令行上还是通过 Ant。在最终版本中,我们将提供有关如何执行此操作的文档。
Alpha 版本
到目前为止所有工作的成果现已提供下载。下载内容包括用于 Eclipse JDT 编译器的补丁,以公开适当的扩展点,稍微修改的 Groovy 1.7 构建,将它们连接在一起的集成代码,以及最终提供 UI 的其他插件。
运行情况如何?这是一个里程碑 1 之前的版本,所以请理解它还没有准备好投入生产!定义 Groovy 和 Java 类型之间交互的方式有很多,尽管许多方式都经过了测试,但您尝试的第一件事可能会导致它崩溃!我们敦促您帮助我们报告任何问题,以便我们能够在走向第一个版本时提高质量。http://groovy.codehaus.org/Eclipse+Plugin+V2+FAQ 上的常见问题解答提供了更多信息,包括询问问题和提出问题的链接。目前唯一可用的下载是适用于 Eclipse 3.4.2 的下载。Eclipse 3.5 支持即将推出。最近的重点是编译和增量编译。我们知道 UI 的某些部分仍然有点缓慢(例如代码辅助),并且将积极努力加快这些速度,常见问题解答讨论了原因。
未来
使用此新编译器技术的 Eclipse 插件的第一个版本旨在提供最小的、一致的功能集,这些功能集是有意义的,并为用户提供价值,因此主题是提供优化的编辑/保存/编译/测试体验。我们认为第一个版本可以在几个月内发布。在即将发布的第一个里程碑版本之后,我们将积极提供更频繁的开发版本,以便我们能够走向 M2 和最终版本。混合中甚至可能有一些与 Grails 相关的功能。