Obtain AST from JavaCompiler
I would like to use the javax.tools API in jdk 6.0 to obtain the AST from a Java source file and then visit the AST. I'm pretty sure the class JavaCompiler and ClassTree can help me, but I have not been able to find any information (or examples) on how to do this, or work it out myself.
If someboby out there could give me some pointers that would be great (I'll continue on my own of course, and post the answer here once I find it).
I'm in the process of creating a Java to C compiler to run Java on our small embedded devices. I want to translate the Java source (not the class file) to C. Mostly for fun, but also because I think the result will be much more readable and compact than translating from bytescodes.
# 2
Thank you very much! That helped a lot. I have included below a small HelloWorld type of example. It is basically the same as yours. This example illustrates how the framework can be used to visit the AST obtained from a single (simple) Java source file.
I think it's a brilliant idea to make this framework publicly available :-)
package main;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementScanner6;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
public class Main {
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
private static class MyProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnvironment) {
class Scan extends ElementScanner6<Void, Void> {
@Override
public Void visitExecutable(ExecutableElement e, Void p) {
System.out.println("method : " + e.toString());
return super.visitExecutable(e, p);
}
@Override
public Void visitPackage(PackageElement e, Void p) {
System.out.println("package : " + e.toString());
return super.visitPackage(e, p);
}
@Override
public Void visitType(TypeElement e, Void p) {
System.out.println("Type: " + e.toString());
return super.visitType(e, p);
}
@Override
public Void visitTypeParameter(TypeParameterElement e, Void p) {
System.out.println("param: "+ e.toString());
return super.visitTypeParameter(e, p);
}
@Override
public Void visitVariable(VariableElement e, Void p) {
System.out.println("variable: " + e.toString());
return super.visitVariable(e, p);
}
}
Scan scan = new Scan();
for (Element e : roundEnvironment.getRootElements()) {
scan.scan(e);
}
return true;
}
}
public static void main(String[] args) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
try {
StandardJavaFileManager fileManager = compiler
.getStandardFileManager(null, null, null);
List<File> files = new LinkedList<File>();
files.add(new File(
"C:\\home\\workspace\\JavaC\\main\\HelloWorld.java"));
Iterable<? extends JavaFileObject> compilationUnits1 = fileManager
.getJavaFileObjectsFromFiles(files);
CompilationTask task = compiler.getTask(null, fileManager, null,
null, null, compilationUnits1);
LinkedList<MyProcessor> processors = new LinkedList<MyProcessor>();
processors.add(new MyProcessor());
task.setProcessors(processors);
task.call();
try {
fileManager.close();
} catch (IOException e) {
}
} catch (Throwable t) {
System.out.println(t.getLocalizedMessage());
}
}
}