更新:09 年 8 月 15 日:评论现已关闭。 如果您需要安装帮助、提供反馈或提问,请加入邮件列表(存档)
在过去几个月里,SpringSource 一直积极参与开发下一版本的 Eclipse Groovy Tools。 最初的目标是让它们在现有基础上进一步发展,成为用于代码开发、构建和测试等关键开发者任务的高度优化的环境。理想情况下,处理混合 Groovy/Java 项目时的体验应该像在 Eclipse 中处理纯 Java 项目一样流畅。
本周,第一个版本的代码已提交到 codehaus 仓库,并且里程碑 1 即将发布。 一个更新站点(适用于 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 下,导航到
Help >
Software Updates。 在
Available Software 选项卡上,点击
Add Site 并输入更新站点 URL:
http://dist.codehaus.org/groovy/distributions/greclipse/snapshot/e3.4。 点击
OK。 现在更新站点将出现在列表中,打开它并标记条目 'Groovy-Eclipse plugin'。 最后,在右上角,点击
Install 并按照对话框完成安装。 安装完成后,有三种方法可以开始使用 Groovy:
- 创建新的 Groovy 项目。 就像创建 Java 项目一样,有一个 Groovy 项目创建向导。 所有 Groovy 项目都实际支持 .java 和 .groovy 文件的混合。
- 修改现有 Java 项目以包含 groovy 代码。 在包资源管理器中选择您的 Java 项目,右键单击并向下导航到上下文菜单中的 Groovy,然后选择 Add Groovy Nature。 完成后,您的项目图标将改变,从那时起,该项目中的任何 .groovy 文件都将与 .java 文件一起构建。
- 迁移现有 Groovy 项目。 如果您有使用旧版插件创建的 Groovy 项目,则必须将其迁移到新版本。 要迁移项目,选择您要迁移的项目,然后右键单击并导航到 Groovy,然后选择 Convert legacy groovy projects。 此选项仅在选定的项目需要迁移时出现。
就是这样!只需像处理 Java 一样开始创建和使用 Groovy 类型。 FAQ
http://groovy.codehaus.org/Eclipse+Plugin+V2+FAQ 尝试回答我们认为关于此 alpha 版本将出现的常见问题,并包含有关报告您遇到的任何问题或提出进一步问题的链接。
现有插件的编译策略
在描述此版本使用的新编译器技术之前,值得简要回顾一下现有版本使用的技术。 当前发布的 Groovy Eclipse 插件利用了现有 groovy 编译器 '联合编译' 的支持。联合编译使得混合 Java/Groovy 代码库能够构建,其中 Java 和 Groovy 类型之间存在引用。 其工作原理基本如下:
- 让 groovy 编译器 (groovyc) 解析 .groovy 文件
- 在磁盘上创建存根,这些存根是这些 groovy 文件的 Java 类似表示。
- 调用 javac 构建 .java 文件,这些文件可以通过存根看到 groovy 文件。
- 完成对 groovy 文件的处理 - 现在可以解析对 Java 类型的 .class 文件的引用
然后用户的所有源文件都被构建成二进制的 .class 文件。
简化项目构建策略
我知道包括我在内的一些用户在设置使用联合编译的 eclipse 插件版本构建项目时遇到了麻烦——它使用的双构建器设置配置起来可能很棘手。 当我们开始设计下一版本的工具时,我想知道是否有一种更优化的方法,即只有一个构建器负责,并且它知道要调用谁来处理 Java 或 Groovy 文件。拥有一个单一的构建器将消除配置项目构建的复杂性。
我最初的想法是让 Eclipse Compiler 负责构建代码,但在必要时应 melibatkan 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 项目的方式。 它必须像以往一样快速可靠。
- 尽量避免在 Eclipse Compiler 中引入任何 Groovy 特定的依赖。 相反,使用抽象并扩展 Eclipse 以支持“某种其他语言”,在这种情况下首先是 groovy。
实现后一个目标将使我们处于有利位置,可以将 Eclipse 编译器更改贡献回 Eclipse。
不只是关于性能
当然,优化编译器之间的通信应该会提高性能,让增量编译适用于 Groovy 会很棒,但迁移到这种新的单一构建器策略(由 Eclipse Compiler 主导)还有一个非常好的理由。如果 Eclipse 能更好地理解 groovy,那么 Eclipse 的一些功能就会“自然而然地”工作。 JUnit 支持就是一个很好的例子。 在 Eclipse 中运行测试用例,通常使用上下文菜单
RunAs > JUnit 或快捷键
Alt+Shift+X, T。 使用当前版本的 groovy 插件,这不会起作用,因为 Eclipse 不知道编辑器中显示的是什么。 在新的体系中,编译器之间的集成层使 Eclipse 能够理解该 groovy 文件的结构——它能看到测试类,能看到任何
@Test 注解,甚至能看到任何
@RunWith 注解来选择测试运行器。 因此,JUnit 启动就自然而然地工作了。 这只是一个无需任何努力就能焕发新生的例子。 这里需要理解的是,Eclipse 编译器本身并没有被修改来直接处理 groovy 代码,它总是委托 groovy 编译器来处理 groovy 代码,但编译器之间的集成层使 eclipse 能够理解 groovyc 调用的结果。
内部结构
使集成层在短时间内可行的是两个编译器现有的灵活结构。 编译的各个阶段在 Eclipse Compiler 中清晰可见且易于访问,在 groovyc 中可能甚至更清晰(它们被称为阶段)。 将编译器集成在一起基本上是定义一个流程,协调和控制每个编译器通过各个阶段/阶段的进展。 尽管实际编译中有许多阶段,但为了理解新设计,可以将其简单地视为一个三个阶段的过程:解析/解析/生成。
在解析阶段,将输入数据从纯文本形式处理成某种内部数据结构——不对该结构进行任何推断。
在解析阶段,追溯结构中名称所引用的实际实体。 例如,如果在源代码中使用了 'Foo',必须确定用户指的是哪个 Foo——这通过适当的解析规则来完成:我的导入有哪些?此包中有什么?类路径上有什么?在 groovy 的情况下,还有额外的规则,例如:我的别名导入有哪些?
在生成阶段,创建实际的 .class 文件。
下图显示了新构建器在编译项目时的体系结构。 所有源文件(.java 和 .groovy)都被传递给 Eclipse 编译器。 根据文件扩展名,Eclipse 编译器要么自己解析文件,要么要求 groovyc 解析文件。 完成后,对发现的所有类型(Groovy 和 Java 类型)运行解析。 两个编译器中的解析策略都经过调整,以便它们能够看到彼此的类型。 最后,在解析之后,运行生成阶段以创建 .class 文件。
[caption id="attachment_2593" align="aligncenter" width="624" caption="新编译系统的结构"]
[/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 测试框架中的 PublisherSubscriberSpecification 示例 (
http://code.google.com/p/spock/ )。 它可以直接作为 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 类型之间的交互方式可能有很多种,尽管我们已经测试了很多,但您尝试的第一个东西可能就会把它弄坏! 我们强烈建议您通过报告任何问题来帮助我们,以便我们在迈向第一个发布版本时提高质量。 FAQ (http://groovy.codehaus.org/Eclipse+Plugin+V2+FAQ) 提供了更多信息,包括提问和报告问题的链接。 目前唯一可用的下载是针对 Eclipse 3.4.2 的。 对 Eclipse 3.5 的支持将很快跟进。 最近的重点是编译和增量编译。 我们知道 UI 的某些部分仍然有点慢(例如代码辅助),并将积极努力加快它们的速度,FAQ 讨论了这种情况的原因。
未来
使用这种新编译器技术的 Eclipse 插件的第一个发布版本旨在成为最有意义并为用户提供价值的最小一致功能集,因此主题是提供优化的编辑/保存/编译/测试体验。 我们认为第一个发布版本可以在几个月内发布。 在即将到来的第一个里程碑发布之后,我们将积极提供更频繁的开发构建版本,以迈向 M2 和最终版本。 其中可能还会包含一些与 Grails 相关的功能。