views:

814

answers:

3

Is it possible to access the Abstract Syntax Tree(AST) inside the javac.exe programmatically? Could you provide an example?

+7  A: 

Yes, it is possible, but only since Java 6. Peter von der Ahé talks about the two JSRs in this interview. Of JSR 199:

The JSR 199 Compiler API consists of three things: The first one basically allows you to invoke a compiler via the API. Second, the API allows you to customize how the compiler finds and writes out files. I mean files in the abstract sense, since the files the compiler deals with aren't necessarily on the file system. JSR 199's file abstraction allows you to have files in a database, and to generate output directly to memory, for example. Finally, the JSR 199 API lets you collect diagnostics from the compiler in a structured way so that you can easily transform error messages, for instance, into lines in an IDE's editor.

JSR 269 is the annotation processing API.

This article gives an excellent overview of accessing the Compiler Tree API. The section "Accessing the Abstract Syntax Tree: The Compiler Tree API" seems particularly suitable for your question.

Depending on what you're doing, you may also want to look at the Jackpot Rule Language, which is a standalone refactoring engine that plugins into the Compiler Tree.

jamesh
+3  A: 

Compile and run this with -cp tools.jar (where you have to specify the location of your tools.jar, obviously).

import com.sun.source.util.Trees;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class JCTreeTest {
    private static final JavaCompiler javac
            = ToolProvider.getSystemJavaCompiler();

    public static void main(String[] args) {
        final StandardJavaFileManager jfm
                = javac.getStandardFileManager(null, null, null);
        final JavaCompiler.CompilationTask task
                = javac.getTask(null, jfm, null, null, null,
                  jfm.getJavaFileObjects(args));
        final Trees trees = Trees.instance(task);
        // Do stuff with "trees"
    }
}

It compiles and runs for me, though I have not played with the trees stuff myself, so you'll have to read the javadoc yourself. :-) Good luck!

Chris Jester-Young
A: 

If you want to rewrite the AST from within javac, take a look at this hack where an annotation processor is used to rewrite code.

Limitation being that it works with Sun's javac only.

Adrian