Hallo zusammen!
Ich arbeite mit dem Java Compiler aus dem javax.tools package (javax.tools.JavaCompiler), und das ganze funktioniert auch recht gut für meine Zwecke um Java Code anhand des AST (Abstract Syntax Tree) zu analysieren.
Jedoch fehlen mir noch Referenzen im Code. Also wenn auf ein Feld oder eine Variable zugegriffen wird bräuchte ich eine Referenz auf dieses Feld / Variable. Genauso bei Methodenaufrufen. Gibt es dafür eine Funktion im Java-Compiler um solche Referenzen raus zu bekommen? Zum Beispiel zugriff auf die Symboltabelle oder dergleichen?
Habe in der Hinsicht leider noch nichts gefunden und hoffe, dass hier jemand damit vertraut ist.
Mein Compiler Code:
[JAVA=42]
public class StatementsJavaParser {
// TODO: check if this directory exists; if not create it or output error message
private static final String tmp_dir = "tmp";
public void parseFromSource(File f) {
// Get the valid source files as a list
List<File> files = new ArrayList<File>();
this.getFilesRecursively(files, f);
if (files.size() > 0) {
// Gets the Java programming language compiler
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// Get a new instance of the standard file manager implementation
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
// Get the list of java file objects
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(files);
// Add options
ArrayList<String> options = new ArrayList<String>();
options.add("-d");
options.add(tmp_dir);
options.add("-g:none");
options.add("-nowarn");
options.add("-Xlint:none");
options.add("-Xmaxerrs");
options.add("1");
options.add("-Xmaxwarns");
options.add("1");
// Create the compilation task
CompilationTask task = compiler.getTask(null, fileManager, null, options, null, compilationUnits);
// Get the list of annotation processors
LinkedList<AbstractProcessor> processors = new LinkedList<AbstractProcessor>();
processors.add(new Processor());
task.setProcessors(processors);
// Perform the compilation task.
task.call();
try {
fileManager.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void getFilesRecursively(List<File> files, File dir) {
if(dir.isFile()){
if(dir.getName().endsWith(".java")){
files.add(dir);
}
return;
}
File[] filelist = dir.listFiles();
for (File f : filelist) {
if (f.isDirectory() && !f.getName().contains(".svn")) {
this.getFilesRecursively(files, f);
} else if (f.isFile()) {
if (f.getName().endsWith(".java"))
files.add(f);
}
}
}
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
private class Processor extends AbstractProcessor {
private Trees trees;
@Override
public void init(ProcessingEnvironment pe) {
super.init(pe);
trees = Trees.instance(pe);
}
@Override
public boolean process(java.util.Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
Visitor visitor = new Visitor();
for (Element e : roundEnvironment.getRootElements()) {
TreePath tp = trees.getPath(e);
// if (tp != null)
// tp.getCompilationUnit().accept(visitor, null);
if (tp != null)
visitor.scan(tp, trees);
}
return true;
}
}
private class Visitor extends TreePathScanner<Object, Trees> {
@Override
public Object visitExpressionStatement(ExpressionStatementTree arg0, Trees arg1) {
// TODO is here some way to find the used variables, fields and methods in the expression????
return super.visitExpressionStatement(arg0, arg1);
}
...
}
}
[/code]
Danke schon mal im voraus!
Ich arbeite mit dem Java Compiler aus dem javax.tools package (javax.tools.JavaCompiler), und das ganze funktioniert auch recht gut für meine Zwecke um Java Code anhand des AST (Abstract Syntax Tree) zu analysieren.
Jedoch fehlen mir noch Referenzen im Code. Also wenn auf ein Feld oder eine Variable zugegriffen wird bräuchte ich eine Referenz auf dieses Feld / Variable. Genauso bei Methodenaufrufen. Gibt es dafür eine Funktion im Java-Compiler um solche Referenzen raus zu bekommen? Zum Beispiel zugriff auf die Symboltabelle oder dergleichen?
Habe in der Hinsicht leider noch nichts gefunden und hoffe, dass hier jemand damit vertraut ist.
Mein Compiler Code:
[JAVA=42]
public class StatementsJavaParser {
// TODO: check if this directory exists; if not create it or output error message
private static final String tmp_dir = "tmp";
public void parseFromSource(File f) {
// Get the valid source files as a list
List<File> files = new ArrayList<File>();
this.getFilesRecursively(files, f);
if (files.size() > 0) {
// Gets the Java programming language compiler
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// Get a new instance of the standard file manager implementation
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
// Get the list of java file objects
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(files);
// Add options
ArrayList<String> options = new ArrayList<String>();
options.add("-d");
options.add(tmp_dir);
options.add("-g:none");
options.add("-nowarn");
options.add("-Xlint:none");
options.add("-Xmaxerrs");
options.add("1");
options.add("-Xmaxwarns");
options.add("1");
// Create the compilation task
CompilationTask task = compiler.getTask(null, fileManager, null, options, null, compilationUnits);
// Get the list of annotation processors
LinkedList<AbstractProcessor> processors = new LinkedList<AbstractProcessor>();
processors.add(new Processor());
task.setProcessors(processors);
// Perform the compilation task.
task.call();
try {
fileManager.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void getFilesRecursively(List<File> files, File dir) {
if(dir.isFile()){
if(dir.getName().endsWith(".java")){
files.add(dir);
}
return;
}
File[] filelist = dir.listFiles();
for (File f : filelist) {
if (f.isDirectory() && !f.getName().contains(".svn")) {
this.getFilesRecursively(files, f);
} else if (f.isFile()) {
if (f.getName().endsWith(".java"))
files.add(f);
}
}
}
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
private class Processor extends AbstractProcessor {
private Trees trees;
@Override
public void init(ProcessingEnvironment pe) {
super.init(pe);
trees = Trees.instance(pe);
}
@Override
public boolean process(java.util.Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
Visitor visitor = new Visitor();
for (Element e : roundEnvironment.getRootElements()) {
TreePath tp = trees.getPath(e);
// if (tp != null)
// tp.getCompilationUnit().accept(visitor, null);
if (tp != null)
visitor.scan(tp, trees);
}
return true;
}
}
private class Visitor extends TreePathScanner<Object, Trees> {
@Override
public Object visitExpressionStatement(ExpressionStatementTree arg0, Trees arg1) {
// TODO is here some way to find the used variables, fields and methods in the expression????
return super.visitExpressionStatement(arg0, arg1);
}
...
}
}
[/code]
Danke schon mal im voraus!