熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

擴展Eclipse的Java開發工具(四)

2013-11-23 20:20:04  來源: Java開源技術 

  怎樣分析 Java 代碼以進行修改?
  
  JDT 提供了幾個工具來幫助您分析代碼本文有意選擇了最簡單的 IScanner 接口進行演示它的作用域也最有限這個接口屬於 JDT 工具箱可以通過 JDT 的 ToolFactory 類訪問它其 createScanner 方法返回一個掃描程序該掃描程序會簡化對一串 Java 代碼作標記的工作它不處理任何特別困難的操作只是對所返回的標記進行簡單的解析和分類例如它指出下一個標記是 public 關鍵字其後的標記是一個標識符再後面的標記是左圓括號等等隨後只有當您希望分析一小段代碼(您明確理解想要在這段代碼中得到什麼)時這個掃描程序才是合適的您決不會使用掃描程序分析整個 Java 源代碼因為您會轉而使用一些對編譯器迷而言十分熟悉的工具JDT 的抽象語法樹(Abstract Syntax TreeAST)框架
  
  與簡單的掃描程序不同AST 理解語言元素(它們不再只是標記)之間的關系它可以識別象局部變量實例變量表達式以及 if 語句等六十多種不同的語言元素它將幫助您進行涉及范圍廣泛的重構或難以滿足對標記進行一對一分類的模糊程度特別高的重構要更清晰地了解何時使用掃描程序與何時使用 AST 之間的差別請考慮清單 中的代碼
  
  清單 模糊的變量引用
  
  public class Foo {
  int foo = ;
  
  public int foo(int foo) {
  return foo + thisfoo;
  }
  
  public int getFoo() {
  return foo;
  }
  }
  
  如果作為重構的一部分您希望查找對實例變量 foo 的引用那麼就會明白一個單純的解析會使區分本地引用和實例變量引用成為一個難題AST 創建了完整的分析樹其中表示了 Java 源代碼的每個元素並對這些元素進行了區分在這個特例中不同的類會考慮foo引用的上下文foo引用表示成 AST 的節點(如 FieldDeclarationSimpleName 和 ThisExpression)因此您會很輕松地識別它們
  
  正如前面提到的本文將只討論我們所選擇的簡單例子對於比較復雜的修改和分析示例請參閱參考資料一節現在讓我們回到我們前面跳過的用省略號表示的代碼這個代碼將使用 IScanner 的實例以確定並替換源代碼中確定成員可視性的關鍵字我們將處理的可視性修飾符是 publicprivateprotected 和 final通過采用蠻力方法我們可以簡化這個解決方案采用兩個步驟就可以完成首先刪除方法特征符中所有的可視性修飾符(或至少掃描查找它們如果找到就刪除)然後插入所希望的修飾符特別地
  
  如果在方法特征符中找到 publicprivate 或 protected就刪除它們
  
  插入所請求的可視性修飾符(對於包可視性的情況不作任何操作因為這是缺省操作即沒有任何修飾符)
  
  final 修飾符很簡單因為所希望的行為就是插入和除去這個修飾符所以如果它存在我們除去它否則就插入它清單 中的代碼只顯示了一個例子它無條件地將成員的可視性從 pubilc 改成 private在與本文相關的解決方案中您將看到每個操作的公共代碼都被移到了抽象超類中它基本上與下面的代碼相同只不過稍作了整理以避免冗余
  
  清單 掃描是否有 pubilc 關鍵字
  
  ICompilationUnit cu = membergetCompilationUnit();
  
  if (cuisWorkingCopy()) {
  IBuffer buffer = cugetBuffer();
  
  IScanner scanner =
  ToolFactorycreateScanner(false false false false);
  scannersetSource(buffergetCharacters());
  ISourceRange sr = membergetSourceRange();
  scannerresetTo(
  srgetOffset()
  srgetOffset() + srgetLength() );
  
  int token = scannergetNextToken();
  while (token != ITerminalSymbolsTokenNameEOF
  && token != ITerminalSymbolsTokenNameLPAREN)
  token = scannergetNextToken();
  
  if (token == ITerminalSymbolsTokenNamePUBLIC) {
  bufferreplace(
  scannergetCurrentTokenStartPosition()
  scannergetCurrentTokenEndPosition()
  scannergetCurrentTokenStartPosition() +
  private);
  break;
  }
  }
  cureconcile();
  }
  
  注ITerminalSymbols 定義了掃描程序可以返回的標記名稱它們對應於 Java 語法的標准標記您可以進一步查詢掃描程序以詢問當前標記在緩沖區中開始和結束的具體位置它出現在哪一行上當然還有標記本身(特別是象 ITerminalSymbolsTokenNameStringLiteral 和 ITerminalSymbolsTokenNameIdentifier 這樣的例子它們不是保留的關鍵字)
  
  上述代碼片段中向 scannersetSource 方法提供了編譯單元的完整源代碼即 Java 源文件中的所有內容正如前面提到的掃描程序並不非常適合於大型分析所以我們必須將它限制用於只有以目標方法的第一個字符開始一直到調用 setSourceRange 方法作為結束的那部分源代碼IMember 接口繼承了 ISourceReferenceISourceReference 是一個允許您查詢包含編譯單元內的源代碼字符串和源代碼位置的接口這使我們不必確定目標方法在 Java 源代碼內開始和結束的位置原本可以用 AST 實現這一點而 ISourceReference 接口使 AST 成了多余的工具由於 Java 方法特征符易於解析所以 IScanner 接口的解析能力和它很匹配我們必須做的就是查找 public 關鍵字它出現在方法聲明的前一個字符之後參數聲明的左圓括號之前用 private 關鍵字替換它當然在該解決方案中這個接口將處理所有的可能情況不管該方法最初是 publicprivateprotected 還是 package(缺省)
  
  下一步是什麼?
  
  本文設定的目標是向您提供一個對 Eclipse 的 Java 開發環境頗具價值的擴展這樣的擴展增強了這個開發環境的生產率坦率地說出於簡潔性考慮我多次跳過了一些細節該解決方案本身就作了一些簡化假設象只允許在編輯器中對已打開的 Java 源代碼進行修改您可能希望在更完整的實現中取消這個限制
  
  雖然如此但我還是希望您能感受到什麼是可能的並確信這樣做不是特別困難本文中我們討論的是 The Java Developers Guide to Eclipse 一書某一高級章節的部分內容該書中有十一個比較淺顯的章節討論了插件開發的基礎象本文一樣大多數章節都包含了一個已文檔化的工作解決方案它可以強化您所學到的知識大多數內容是以本文中您已看到的相同風格編寫的(不過可能沒有以這麼快的節奏進行討論!)
  
  重要您可能需要向工作空間添加必要的插件這樣解決方案才能編譯和運行選擇 Window > Preferences > Plugin Development > Target Platform然後選擇 Not in Workspace這將確保解決方案所依賴的基礎插件在導入和重新編譯過程中可用
  
  一旦導入完成您可能需要切換至 Plugin Development 透視圖在 comibmlabsolnjdtexcerpt 項目中選擇 pluginxml然後選擇 Update Classpath這將修改由於 Eclipse 安裝路徑和解決方案的安裝路徑不同所引起的編譯錯誤
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28318.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.