Java代碼分析器(一): JDT入門

另載於 http://www.qingjingjie.com/blogs/2java

這是一個關於抽象語法樹(Abstract Syntax Tree, AST)的故事。git

抽象語法樹是對程序代碼的結構化表示,是對代碼進行詞法分析、語法分析後獲得的產物。編譯器要用到它,不少生產力工具也要用它,例如:github

IDE能夠自動重構、自動生成一些代碼、自動對不規範代碼發出警告。這是很強很實惠的功能。

一個大型軟件項目經常有幾百人合做,幾百萬行代碼。不少代碼規範難以百分百落實,不少編程錯誤潛藏在項目中。這時候咱們會考慮Sonar, FindBug, Checkstyle之類的代碼分析工具來幫助咱們掃描出巨量代碼中存在的問題。

國內有位老兄就作了個自動生成測試代碼的工具。(但不要生成功能代碼,咱們要構建良好的抽象和簡潔的代碼)

我司的系統要進行架構遷移,其中有百萬行代碼須要修改,用人力來作是很可怕的。我作了個工具來自動完成這件事。

它們利用AST來對大量程序代碼作自動化處理,給了咱們莫大的幫助。甚至自動寫代碼也不是不可能。那麼咱們本身能玩一玩AST這種高大上的東西嗎?編程

能。Eclipse這個開源的Java IDE就提供了一個庫來幫助咱們達到目的,它的名字是JDT(Java Development Tools)。咱們使用它的核心模塊JDT Core。設計模式

這個項目歷史悠久,功能強力,早期開發者有《設計模式》GoF的做者。架構

它提供了一套關於AST的API,能解析Java代碼,生成、分析和操做AST結構。有了它,咱們就不用本身實現高難度的詞法分析和語法分析了。框架

動手搞起

(嫌麻煩能夠看這個小框架 https://github.com/sorra/exia)
首先準備好庫文件——打開你的Eclipse安裝目錄,在搜索框中搜索如下jar文件(*是通配符):
org.eclipse.jdt.core_*
org.eclipse.core.contenttype_*
org.eclipse.core.jobs_*
org.eclipse.core.resources_*
org.eclipse.core.runtime_*
org.eclipse.equinox.common_*
org.eclipse.equinox.preferences_*
org.eclipse.equinox.registry_*
org.eclipse.osgi_*
org.eclipse.text_*
若是有多個版本,取最新版本。通通copy出來,添加到你的項目中。
源代碼包是org.eclipse.jdt.core.source_* 用Eclipse的Attach source功能把它連到第一個jar上,能夠閱讀源代碼。dom

先來溜一段起步代碼,把一段Java代碼解析成AST。eclipse

import java.util.Map;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.JavaCore;
......
public static void main(String[] args) {
    ASTParser parser = ASTParser.newParser(AST.JLS4); //設置Java語言規範版本
    parser.setKind(ASTParser.K_COMPILATION_UNIT);

    Map<String, String> compilerOptions = JavaCore.getOptions();
    compilerOptions.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7); //設置Java語言版本
    compilerOptions.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
    compilerOptions.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
    parser.setCompilerOptions(compilerOptions); //設置編譯選項

    char[] src = "class A { void method1(int b){;} }".toCharArray();
    parser.setSource(src);

    CompilationUnit cu = (CompilationUnit) parser.createAST(null); //這個參數是IProgessMonitor,用於GUI的進度顯示,咱們不須要,填個null. 返回值是AST的根結點

    System.out.println(cu); //把AST直接輸出看看啥樣
}

AST做爲抽象語法樹,它就是一棵樹,有點像XML的DOM樹。
例子中的樹大概長這樣:ide

CompilationUnit
       |
     class
    |     |
    A   method1
       |   |   |
     void []   {}
           |   |
          arg  ;
         |  |
        int b

延伸閱讀:http://help.eclipse.org/ 點擊JDT Plug-in User Guide -> Programmer's Guide -> JDT Core。

相關文章
相關標籤/搜索