Search code examples
javaeclipseeclipse-jdt

Eclipse AST parser not preserving static import


I pray that you are well.

I am trying to write a QuickFix plugin in Eclipse for "not found" imports. As part of this, I am trying to generate an AST with a variety of different import statement types. I am trying to avoid setting up a full-blown Eclipse workspace to perform the test.

The code to fire up the parser and produce an AST is pretty simple. However, I have found that the parser does not honour the "static" keyword on the imports. So if I find an ImportDeclaration on the generated AST, its isStatic() property will be false even if the source contained "import static ...", and if I dump the contents of the CompilationUnit I can see that the "static" keyword has been dropped.

ASTParser parser = ASTParser.newParser(AST.JLS8);
parser.setSource("import static java.util.Collections.*;".toCharArray());
CompilationUnit cu = (CompilationUnit)parser.createAST(null);
System.err.println(cu); // prints "import java.util.Collections.*;"*

I tried to get around this problem by generating the AST directly instead of via the parser. I can then call "setStatic(true)" on the ImportDeclaration to set its static flag. This generates the correct structure:

AST ast = AST.newAST(AST.JLS8);
CompilationUnit cu = ast.newCompilationUnit();
ImportDeclaration dec = ast.newImportDeclaration();
dec.setName(ast.newName("java.util.Collections"));
dec.setStatic(true);
dec.setOnDemand(true);
cu.imports().add(dec);
System.err.println(cu); //  prints "import static java.util.Collections.*;"

However, dec.getStartPosition() is set to -1 and dec.getLength() returns 0, presumably as they don't correspond to any particular source. This messes up my QuickFix processor, which needs to know where in the source they appear to work. I can try and manually set all of the set and end positions, but I was kinda hoping that's what the parser should be doing.

Any suggestions? Is it a simple parser configuration option that I'm missing?


Solution

  • Well, wouldn't you know it - I researched this for a good day or so before posting the question on Stack Overflow and then found the answer myself a few minutes after posting...

    For the benefit of anyone else who should stumble across this question: The missing link is that the "import static" syntax only became available in Java 1.5 and higher, and by default the compiler was using a lower java version (perhaps 1.0?). Adding the following code to my first example fixed the problem:

    ASTParser parser = ASTParser.newParser(AST.JLS8);
    Map options = JavaCore.getOptions(); // New!
    JavaCore.setComplianceOptions(JavaCore.VERSION_1_5, options); // New!
    parser.setCompilerOptions(options); // New!
    parser.setSource("import static java.util.Collections.*;".toCharArray());
    CompilationUnit cu = (CompilationUnit)parser.createAST(null);
    System.err.println(cu); // prints "import static java.util.Collections.*;"
    

    I had incorrectly assumed that setting AST.JLS8 in the call to newParser() would take care of that, but apparently it doesn't.