2010-01-07 8 views
7

Ich verwende den Eclipse JDT AST-Parser, um einige Java-Code zu verarbeiten und versuche, die Typ-Bindungen für Felder und Methodendeklarationen zu extrahieren. Die Logik hierfür liegt in meiner Besucherklasse (siehe unten). Unglücklicherweise habe ich kein Glück und keine der Bindungen löst auf (sie sind durchgängig null). Das Interessante daran ist, dass die Bindings mit dem Eclipse ASTView Plugin am gleichen Code arbeiten. Was mache ich falsch?Bindings nicht mit AST Verarbeitung in Eclipse

Hier sind einige relevante Code-Schnipsel, die hoffentlich helfen werden, herauszufinden, was vor sich geht!

Antwort

2

Der wahrscheinliche Grund ist, dass Sie die Methode in Visitor-Instanz nicht direkt aufrufen sollten. Sie sollten so etwas wie tun:

unit.accept(visitor); 

Die Elternklasse von Compilation, ASTNode, hat eine accept Methode, die einen Besucher nimmt, die von Typ ASTVisitor ist.

Die Besucher Sie geschrieben haben, GenericVisitor, tut Subklassen die abstarct Klasse ASTVisitor und überschreibt Implementierung für die Knotentypen, die Sie in intersted. So Ihren Code Ich denke, die Änderung den Aufruf in obiger Form zu tun wäre, fixieren Sie Ihre Problem.

1

ASTParser ist nur der Parser: Er erstellt einen AST, der der erste Schritt beim Kompilieren ist. Der eigentliche Compiler macht mehr als das: Es laufen verschiedene Besucher, die den Baum mit zusätzlichen Informationen erweitern. Einer von ihnen ist der bindende Resolutionsbesucher.

Insbesondere, werfen Sie einen Blick auf den Körper der öffentlichen Void-Prozess (CompilationUnitDeclaration Einheit, Int i) -Methode in der org.eclipse.jdt.internal.compiler.Compiler Klasse.

0

Wenn Ihre Bindungen null sind, bin ich mir nicht ganz sicher, ob Ihr Problem durch die anderen Erklärungen abgedeckt ist. In unserer Code-Basis, haben wir die folgenden, und die Bindungen sind immer da:

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); 
} 

Also die einzigen Unterschiede, die ich sind die Reihenfolge der Anrufe sehen kann Bindungen zu lösen, und die Tatsache, dass wir nicht nennen setKind auf dem Parser. Kannst du es mit genau diesem Code versuchen und sehen was passiert?

8

Bei Verwendung von: parser.setSource (source); Was ist die Art von Param "Quelle"?

Bindungsinformationen werden von das Java-Modell erhalten. Dies bedeutet, dass sich die Kompilierungseinheit relativ zum Java-Modell befinden muss. Diese geschieht automatisch, wenn der Quellcode entweder setSource (ICompilationUnit) oder setSource (IClassFile) stammt. Wenn die Quelle von setSource (char []) angegeben wird, muss die Position explizit durch Aufruf von setProject (IJavaProject) und setUnitName (String) aktiviert werden.

Das von http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/ASTParser.html ist Ich denke, vielleicht gerade Sie setSource (char []) ohne Aufruf setproject (IJavaProject) und setUnitName (String)

+0

One auch parser.setEnvironment verwenden können (...): „die Umgebung ein, die verwendet werden können, wenn keine IJavaProject verfügbar sind“ – roesslerj

-1

Manchmal verwenden, wenn Sie Fehler in den angegebenen Quelldateien erhalten, dann werden die Bindungen zu diesen Typen nicht aufgelöst. Stellen Sie beispielsweise sicher, dass Sie die korrekte Codierung und Java-Version der Quelle verwenden.

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

Ich versuche, etwas ähnliches zu implementieren, was sind die Classpath & sources Variablen hier? Können Sie ein Beispiel für ihre Werte geben? – Braden

+0

Klassenpfad und Quellen sind Arrays von Strings mit tatsächlichen Pfaden, wie Sie sie in der Option java -classpath angeben würden. Es hat so lange gedauert, bis ich geantwortet habe ... – roesslerj

1

Okay, das ist meine erste Antwort auf Stack Overflow. Nervous ...

bekam ich das gleiche Problem mit Ihnen, und da Sie dies getan haben:

parser.setResolveBindings(true); 

Mal sehen, ob es durch die Überprüfung dieser gearbeitet:

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

Und ich denke, das Ergebnis ist "Bindung ist nicht aktiviert.". Und deshalb hast du die ganze Zeit den Nullzeiger.

Dann füge ich diese Aussage zu meinem Code:

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

Magisch, das Problem behoben ist !!! Und ich nehme an, Sie können das auch versuchen.

+0

es scheint, dass setEnvironment erst ab JDT 3.6 verfügbar ist, aber Maven hat nur bis zu 3.3? Wie hast du 3.6 installiert? –

1

Das Problem ist, dass Ihr Parser nicht mit den notwendigen Informationen zur Verfügung gestellt wurde, um sein Java-Modell zu konstruieren, das für die Auflösung von Bindungen benötigt wird.

Wenn die Quelle des Parsers von setSource(ICompilationUnit) oder setSource(IClassFile) erreicht wird, wird diese Information dem Parser automatisch zur Verfügung gestellt. Wenn Sie stattdessen setSource(char[]) verwenden, müssen Sie diesen Kontext für den Parser bereitstellen. Dies kann erfolgen durch entweder Aufruf parser.setProject(IJavaProject) oder setEnvironment(String[], String[], String[], boolean) und setUnitName(String)

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