Mit der internen Compiler-API auf den AST einer Klasse zugreifen
Der Zugriff zum Java-Compiler ist über die Java-Compiler-API standardisiert, jedoch sind alle Interna, wie die tatsächliche Repräsentation des Programmcodes verborgen. Die Compiler-API abstrahiert alles über Schnittstellen, und so kommen Entwickler nur mit JavaCompiler, StandardJavaFileManager und CompilationTask in Kontakt – alles Schnittstellen aus dem Paket javax.tools. Um etwas tiefer einzusteigen, lässt sich zum einem Trick greifen: Klassen implementieren Schnittstellen und wenn ein Programm den Schnittstellentyp auf den konkreten Klassentyp anpasst, dann stehen in der Regel mehr Methoden zur Verfügung. So lässt sich der CompilationTask auf eine com.sun.tools.javac.api.JavacTaskImpl casten und dann steht eine parse()-Methode für Verfügung. Die parse()-Methode liefert als Rückgabe eine Aufzählung von CompilationUnitTree. Um diesen Baum nun abzulaufen, lässt sich das Besuchermuster einsetzen. CompilationUnitTree bietet eine accept(…)-Methode; der übergeben wir einen TreeScanner. Die accept(…)-Methode ruft dann beim Ablaufen jedes Knotens unseren Besucher auf.
package com.tutego.tools.javac;
import java.io.*;
import java.net.*;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import com.sun.source.tree.*;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.JavacTaskImpl;
public class PrintAllMethodNames {
final static TreeScanner methodPrintingTreeVisitor = new TreeScanner() {
@Override public Void visitCompilationUnit( CompilationUnitTree unit, Void arg ) {
System.out.println( "Paket: " + unit.getPackageName() );
return super.visitCompilationUnit( unit, arg );
};
@Override public Void visitClass( ClassTree classTree, Void arg ) {
System.out.println( "Klasse: " + classTree.getSimpleName() );
return super.visitClass( classTree, arg );
}
@Override public Void visitMethod( MethodTree methodTree, Void arg ) {
System.out.println( "Methode: " + methodTree.getName() );
return super.visitMethod( methodTree, arg );
}
};
public static void main( String[] args ) throws IOException, URISyntaxException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
URI filename = PrintAllMethodNames.class.getResource( "PrintAllMethodNames.java" ).toURI();
Iterable
2 Kommentare
Mit Java für C64 entwickeln - Java Blog | Javainsel-Blog ·
\[...\] JDK bringt alles mit, um an den AST des Compilers zu kommen, wie schon im Blog hier beschrieben: http://www.tutego.de/blog/javainsel/2012/07/mit-der-internen-compiler-api-auf-den-ast-einer-klasse-z.... Von den erkannten Elementen (Ausdrücke, Variablenzugriff, Schleife, …) muss man nur C-Code \[...\]
Lars ·
Hi wirklich guter Blog und immer wieder interessante Einträge, aber bitte nutze doch endlich syntax highlighting, ist doch kein gimmick mehr, wenn man das nutzt, sonst liest sich code echt schlecht, oder schreibst du noch mit notepad deine Java-Klassen? ;) Trotzdem weiter so!
Die bisherigen Kommentare wurden aus WordPress übernommen. Neue Kommentare sind derzeit geschlossen.