更新:2009 年 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版本,但很快就會有。(更新!2009年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專案。就像您可以建立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 檔案
- 在磁碟上建立存根,這些存根是這些Groovy檔案的類似Java的表示。
- 呼叫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專案的方式。它必須像以往一樣快速可靠。
- 儘量避免在Eclipse編譯器中引入任何特定於groovy的依賴項。相反,使用抽象並擴充套件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檔案。
[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]
這些檢查的價值仍在討論中,但目前它們仍處於啟用狀態。
使用者介面
我剛才談論的所有內容都是底層的編譯策略。在Eclipse UI中,它僅表現為用於編譯混合Java/Groovy專案的“構建器”。在此之上,Andrew Eisenberg(也和我一起在溫哥華SpringSource實驗室)一直在為UI注入活力:
- 將現有外掛中在新環境中仍然需要的元件移植過來(並進行演進),將它們重新基於新的編譯基礎設施。
- 開發/增強使用者在IDE中依賴的那些功能:編輯器、大綱檢視、程式碼輔助、導航、除錯等。
最終結果是,Eclipse UI在處理Groovy時看起來和行為都與處理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相關的功能。