-
Bug
-
Resolution: Fixed
-
P4
-
6
-
b81
-
generic
-
generic
-
Verified
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);
}
}
}
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);
}
}
}
- relates to
-
JDK-6567414 javac compiler reports no source file or line on enum constant declaration error
-
- Closed
-
-
JDK-6471599 Type of rhs cannot be obtained when assigning to erroneous symbol
-
- Closed
-