-
Bug
-
Resolution: Fixed
-
P3
-
6u20
-
b130
-
x86
-
linux
-
Verified
FULL PRODUCT VERSION :
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux <hostname> 2.6.24-gg804011-generic #1 SMP Tue Mar 30 18:11:30 UTC 2010 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
JCCompilationUnit.getImports does not report all imports if there is an extra semicolon after one of the import statements.
getImports stops after the first non-import statement. Empty statement makes it think there would be no other import statements to follow.
$ cat A.java
import java.util.List;; // note an extra semicolon here
import java.util.ArrayList;
public class A {}
$ cat Driver.java
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.util.JavacTask;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Driver {
public static void main(String[] args) throws Exception {
if (args.length < 1) return;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
JavacTask task = (JavacTask) compiler.getTask(null, fileManager, null, null, null,
fileManager.getJavaFileObjects(args[0]));
CompilationUnitTree tree = task.parse().iterator().next();
for (ImportTree importTree : tree.getImports()) {
System.out.println(importTree);
}
}
}
$ javac A.java accepts the source file as valid
$ javac -cp /java/lib/tools.jar Driver.java
$ java -cp /java/lib/tools.jar:. Driver A.java
produces only the first import statement
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
$ javac -cp /java/lib/tools.jar Driver.java
$ java -cp /java/lib/tools.jar:. Driver A.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
import java.util.List;
import java.util.ArrayList;
ACTUAL -
import java.util.List;
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
$ cat A.java
import java.util.List;; // note an extra semicolon here
import java.util.ArrayList;
public class A {}
$ cat Driver.java
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.util.JavacTask;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Driver {
public static void main(String[] args) throws Exception {
if (args.length < 1) return;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
JavacTask task = (JavacTask) compiler.getTask(null, fileManager, null, null, null,
fileManager.getJavaFileObjects(args[0]));
CompilationUnitTree tree = task.parse().iterator().next();
for (ImportTree importTree : tree.getImports()) {
System.out.println(importTree);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
My current workaround is to cast CompilationUnitTree to JCTree.JCCompilationUnit and filter the defs myself.
The getImports could be fixed for example by adding if (tree.getTag() == SKIP) continue;
public List<JCImport> getImports() {
ListBuffer<JCImport> imports = new ListBuffer<JCImport>();
for (JCTree tree : defs) {
if (tree.getTag() == SKIP) continue;
else if (tree.getTag() == IMPORT)
imports.append((JCImport)tree);
else
break;
}
return imports.toList();
}
java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) 64-Bit Server VM (build 16.3-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux <hostname> 2.6.24-gg804011-generic #1 SMP Tue Mar 30 18:11:30 UTC 2010 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
JCCompilationUnit.getImports does not report all imports if there is an extra semicolon after one of the import statements.
getImports stops after the first non-import statement. Empty statement makes it think there would be no other import statements to follow.
$ cat A.java
import java.util.List;; // note an extra semicolon here
import java.util.ArrayList;
public class A {}
$ cat Driver.java
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.util.JavacTask;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Driver {
public static void main(String[] args) throws Exception {
if (args.length < 1) return;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
JavacTask task = (JavacTask) compiler.getTask(null, fileManager, null, null, null,
fileManager.getJavaFileObjects(args[0]));
CompilationUnitTree tree = task.parse().iterator().next();
for (ImportTree importTree : tree.getImports()) {
System.out.println(importTree);
}
}
}
$ javac A.java accepts the source file as valid
$ javac -cp /java/lib/tools.jar Driver.java
$ java -cp /java/lib/tools.jar:. Driver A.java
produces only the first import statement
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
$ javac -cp /java/lib/tools.jar Driver.java
$ java -cp /java/lib/tools.jar:. Driver A.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
import java.util.List;
import java.util.ArrayList;
ACTUAL -
import java.util.List;
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
$ cat A.java
import java.util.List;; // note an extra semicolon here
import java.util.ArrayList;
public class A {}
$ cat Driver.java
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.util.JavacTask;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Driver {
public static void main(String[] args) throws Exception {
if (args.length < 1) return;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
JavacTask task = (JavacTask) compiler.getTask(null, fileManager, null, null, null,
fileManager.getJavaFileObjects(args[0]));
CompilationUnitTree tree = task.parse().iterator().next();
for (ImportTree importTree : tree.getImports()) {
System.out.println(importTree);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
My current workaround is to cast CompilationUnitTree to JCTree.JCCompilationUnit and filter the defs myself.
The getImports could be fixed for example by adding if (tree.getTag() == SKIP) continue;
public List<JCImport> getImports() {
ListBuffer<JCImport> imports = new ListBuffer<JCImport>();
for (JCTree tree : defs) {
if (tree.getTag() == SKIP) continue;
else if (tree.getTag() == IMPORT)
imports.append((JCImport)tree);
else
break;
}
return imports.toList();
}
- relates to
-
JDK-8027682 javac wrongly accepts semicolons in package and import decls
- Resolved