JDK-6472751 : SourcePositions.getStartPos returns incorrect value for enum constants
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-09-20
  • Updated: 2012-01-13
  • Resolved: 2012-01-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b81Fixed
Related Reports
Relates :  
Relates :  
Description
SourcePositions.getStartPos() incorrectly returns -1 for enum constants. TreeInfo.java line 288 has:

	case(JCTree.VARDEF): {
	    JCVariableDecl node = (JCVariableDecl)tree;
	    if (node.mods.pos != Position.NOPOS) {
		return node.mods.pos;
	    } else {
		return getStartPos(node.vartype);
	    }

and you can see why it doesn't work for enum constants.
I'm lazy, so let me try to explain the problem one more time. If you still think you need a test case, I'll consider writing one.

The problem happens when I'm looking at the tree of enum constant declaration, like "ABC" of:

  enum E { ABC, DEF; }

Javac creates JCTree.JCVariableDecl node for 'ABC' (and 'DEF') Unlike other 'ordinary' field declarations or local variable declarations, this JCVariableDecl doesn't have the JCVariableDecl#vartype set. So when I try to access the start position of this JCVariableDecl, the following code runs:

	case(JCTree.VARDEF): {
	    JCVariableDecl node = (JCVariableDecl)tree;
	    if (node.mods.pos != Position.NOPOS) {
		return node.mods.pos;
	    } else {
		return getStartPos(node.vartype);
	    }

and I get NOPOS. The correct code should be: 

	case(JCTree.VARDEF): {
	    JCVariableDecl node = (JCVariableDecl)tree;
	    if (node.mods.pos != Position.NOPOS) {
		return node.mods.pos;
	    }
            if(node.vartype!=null) {
		return getStartPos(node.vartype);
	    }
            return node.sym.pos;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.Tree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreeScanner;
import com.sun.source.util.Trees;
import com.sun.tools.javac.util.List;
import java.io.IOException;
import java.net.URI;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;

public class T6472751 {
    static class MyFileObject extends SimpleJavaFileObject {
        public MyFileObject() {
            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
        }
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return "public enum Test { ABC, DEF; }";
        }
    }
    static Trees trees;
    static SourcePositions positions;
    public static void main(String[] args) throws IOException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        JavacTask task = (JavacTask) compiler.getTask(null, null, null, null, null, List.of(new MyFileObject()));
        trees = Trees.instance(task);
        positions = trees.getSourcePositions();
        Iterable<? extends CompilationUnitTree> asts = task.parse();
        for (CompilationUnitTree ast : asts) {
            new MyVisitor().scan(ast, null);
        }
    }
    
    static class MyVisitor extends TreeScanner<Void,Void> {
        @Override
        public Void scan(Tree node, Void ignored) {
            if (node == null)
                return null;
            System.out.format("%s: %s%n", node.getKind(), positions.getStartPosition(null,node));
            return super.scan(node, ignored);
        }

    }
}

Comments
EVALUATION The synopsis is valid, but the reasoning in the Description is incorrect. The vartype is set in the JCVariableDecl but the position of the vartype is incorrectly set to NOPOS. See 6567414. Fixing that fixes this problem.
14-01-2010