2010-01-07 28 views
7

我正在使用eclipse JDT AST解析器來處理一些Java代碼,並試圖提取字段和方法聲明的類型綁定。這樣做的邏輯是在我的Visitor類中(見下文)。不幸的是,我沒有任何運氣,也沒有任何綁定解決(它們始終爲空)。有趣的是,綁定可以在日食ASTView插件上使用相同的代碼。我究竟做錯了什麼?在eclipse中無法通過AST處理來解決綁定

這裏有一些相關的代碼片段,希望能幫助別人找出發生了什麼!

ASTParser parser = ASTParser.newParser(AST.JLS3); 
parser.setKind(ASTParser.K_COMPILATION_UNIT); 
parser.setSource(source); 
parser.setResolveBindings(true); 
CompilationUnit unit = (CompilationUnit) parser.createAST(null); 

GenericVisitor visitor = new GenericVisitor(outDir + "//" + file.getName() + ".xml"); 
visitor.process(unit); 


public class GenericVisitor extends ASTVisitor 
{ 
    public void endVisit(FieldDeclaration node) 
    { 
     String bindingInfo = "";  
     ITypeBinding binding = node.getType().resolveBinding(); 

     if(binding == null) 
     {      
     System.out.println("field declaration binding = null"); 
     } 
     else 
     { 
     bindingInfo = binding.getQualifiedName(); 
     } 

     endVisitNode(node, bindingInfo); 
    } 

    public void endVisit(MethodInvocation node) 
    { 
     String bindingInfo = ""; 
     IMethodBinding binding = node.resolveMethodBinding(); 

    if(binding == null) 
    {      
     System.out.println("method binding = null"); 
    } 
    else 
    { 
     bindingInfo = binding.toString(); 
    } 

    endVisitNode(node, bindingInfo); 
    } 
} 

回答

2

可能的原因是您不應直接在Visitor實例中調用方法。你應該這樣做:

unit.accept(visitor); 

父類 CompilationUnit ASTNode的,有一個accept方法,這需要一個訪問者是類型的ASTVisitor的。你寫

訪客, GenericVisitor,確實子類abstarct類的ASTVisitor和覆蓋實現你中位數的節點類型,所以我想改變你的代碼做調用上述形式將解決您的問題。

1

ASTParser只是解析器:它構建了一個AST,這是編譯的第一步。 實際的編譯器做的不止於此:它運行各種訪問者,通過附加信息增強樹。其中之一是具有約束力的解析訪問者。

尤其要看 public void process(CompilationUnitDeclaration unit,int i)方法中的org.eclipse.jdt.internal.compiler.Compiler類。

0

如果您的綁定爲空,我不完全確定您的問題已被其他解釋所覆蓋。在我們的代碼庫,我們做到以下幾點,並綁定總是在那裏:

public static ASTNode getASTNodeFromCompilationUnit(ICompilationUnit compUnit) { 
    ASTParser parser = ASTParser.newParser(AST.JLS3); 
    parser.setResolveBindings(true); 
    parser.setSource(compUnit); 
    return parser.createAST(/* passing in monitor messes up previous monitor state */ null); 
} 

所以我可以看到,唯一的區別是調用的順序來解析綁定,而事實上,我們不叫解析器上的setKind。任何機會,你可以試試這個代碼,看看會發生什麼?

8

當您使用: parser.setSource(source); 參數「源」的類型是什麼?

綁定信息從 Java模型獲得。這意味着 編譯單元必須位於相對於Java模型的 。當源 代碼來自 setSource(ICompilationUnit)或 setSource(IClassFile)時,此 會自動發生。當源爲由setSource(char [])提供的 時,必須通過調用 setProject(IJavaProject)和 setUnitName(String)明確地建立 位置 。

這是http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html 我想,也許你只需要使用的SetSource(的char []),而無需調用setProject(IJavaProject)和setUnitName(字符串)

+0

你也可以使用parser.setEnvironment(...):「設置時,沒有IJavaProject可用,可用於環境」 – roesslerj 2012-06-19 10:10:47

-1

有時候,如果你在引用的源文件有錯誤,那麼這些類型的綁定就不會被解析。例如,確保您使用了正確的編碼和Java版本的源代碼。

ASTParser parser = ASTParser.newParser(AST.JLS3); 
    parser.setKind(ASTParser.K_COMPILATION_UNIT); 
    parser.setResolveBindings(true); 
    parser.setBindingsRecovery(true); 
    Hashtable<String, String> options = JavaCore.getDefaultOptions(); 
    options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6); 
    parser.setCompilerOptions(options); 
    parser.setEnvironment(classpath, sources, new String[] { "UTF-8", "UTF-8" }, true); 
    parser.setSource(fileContents.toCharArray()); 
    CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null); 
    IProblem[] problems = compilationUnit.getProblems(); 
    if (problems != null && problems.length > 0) { 
     logger.warn("Got {} problems compiling the source file: ", problems.length); 
     for (IProblem problem : problems) { 
      logger.warn("{}", problem); 
     } 
    } 
    return compilationUnit; 
+0

我試圖實現類似這樣的東西,這裏的類路徑和源變量是什麼?你能舉一個他們的價值的例子嗎? – Braden 2012-07-17 23:49:35

+0

classpath和sources是String的數組,其實際路徑與您在java -classpath選項中給出的一樣。對不起,我花了這麼長的時間來回應... – roesslerj 2012-09-06 20:19:09

1

好的,這是我在Stack Overflow上的第一個答案。神經...

我得到了同樣的問題與你,因爲你已經這樣做了:

parser.setResolveBindings(true); 

讓我們來看看它是否工作通過檢查這一點:

if (unit.getAST().hasResolvedBindings()) { 
    System.out.println("Binding activated."); 
} 
else { 
    Ststem.out.println("Binding is not activated."); 
} 

而且我覺得結果是「綁定未激活」。這就是爲什麼你總是得到空指針的原因。

然後,我這個語句添加到我的代碼:

parser.setEnvironment(null, null, null, true); 

奇妙的是,在解決問題!我想你也可以試試這個。

+0

看起來setEnvironment只能從JDT 3.6開始提供,但Maven只能達到3.3?你是如何安裝3.6的? – 2017-01-07 16:34:56

1

問題是您的解析器尚未提供必要的信息來構建其解析綁定所需的Java模型。

如果解析器的源是從setSource(ICompilationUnit)setSource(IClassFile)獲得的,則將此信息自動提供給解析器。

但是,如果使用setSource(char[])代替,則必須爲解析器提供此上下文。這可以通過調用parser.setProject(IJavaProject)setEnvironment(String[], String[], String[], boolean)setUnitName(String)

完成來源:http://help.eclipse.org/kepler/topic/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html#setResolveBindings(boolean)

相關問題