8158123: NPE when the annotations is used in export-to of module-info
authorshinyafox
Sat, 11 Jun 2016 09:47:59 +0900
changeset 38916 d118cb2cffab
parent 38915 12b5c35d4fd7
child 38917 f7cfae16c87e
8158123: NPE when the annotations is used in export-to of module-info Reviewed-by: mcimadamore
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
langtools/test/tools/javac/modules/ModuleInfoTest.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Jun 10 13:52:03 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Sat Jun 11 09:47:59 2016 +0900
@@ -3216,7 +3216,7 @@
                 List<JCExpression> moduleNames = null;
                 if (token.kind == IDENTIFIER && token.name() == names.to) {
                     nextToken();
-                    moduleNames = qualidentList();
+                    moduleNames = qualidentList(false);
                 }
                 accept(SEMI);
                 defs.append(toP(F.at(pos).Exports(pkgName, moduleNames)));
@@ -3635,7 +3635,7 @@
             List<JCExpression> thrown = List.nil();
             if (token.kind == THROWS) {
                 nextToken();
-                thrown = qualidentList();
+                thrown = qualidentList(true);
             }
             JCBlock body = null;
             JCExpression defaultValue;
@@ -3672,11 +3672,11 @@
 
     /** QualidentList = [Annotations] Qualident {"," [Annotations] Qualident}
      */
-    List<JCExpression> qualidentList() {
+    List<JCExpression> qualidentList(boolean allowAnnos) {
         ListBuffer<JCExpression> ts = new ListBuffer<>();
 
-        List<JCAnnotation> typeAnnos = typeAnnotationsOpt();
-        JCExpression qi = qualident(true);
+        List<JCAnnotation> typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
+        JCExpression qi = qualident(allowAnnos);
         if (!typeAnnos.isEmpty()) {
             JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
             ts.append(at);
@@ -3686,8 +3686,8 @@
         while (token.kind == COMMA) {
             nextToken();
 
-            typeAnnos = typeAnnotationsOpt();
-            qi = qualident(true);
+            typeAnnos = allowAnnos ? typeAnnotationsOpt() : List.nil();
+            qi = qualident(allowAnnos);
             if (!typeAnnos.isEmpty()) {
                 JCExpression at = insertAnnotationsToMostInner(qi, typeAnnos, false);
                 ts.append(at);
--- a/langtools/test/tools/javac/modules/ModuleInfoTest.java	Fri Jun 10 13:52:03 2016 -0700
+++ b/langtools/test/tools/javac/modules/ModuleInfoTest.java	Sat Jun 11 09:47:59 2016 +0900
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8158123
  * @summary tests for module declarations
  * @library /tools/lib
  * @modules
@@ -35,6 +36,7 @@
 
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.util.Arrays;
 
 import toolbox.JavacTask;
 import toolbox.Task;
@@ -323,4 +325,46 @@
         if (!log.contains("module-info.java:1:30: compiler.err.duplicate.exports: m1"))
             throw new Exception("expected output not found");
     }
+
+    /**
+     * Verify that annotations are not permitted at
+     * any of the module names or the package names.
+     */
+    @Test
+    public void testAnnotations(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1.sub");
+        Path classes = base.resolve("classes");
+        Files.createDirectories(classes);
+
+        String code = "module @m1.@sub { " +
+                "requires @p1.@p2; " +
+                "exports @p1.@p2; " +
+                "exports @p1.@p2 to @m2.@sub; " +
+                "exports @p1.@p2 to @m2.@sub, @m3.@sub; " +
+                "uses @p1.@Interface; " +
+                "provides @p1.@Interface with @p2.@Concrete; " +
+                "}";
+        String[] splittedCode = code.split("@");
+        int length = splittedCode.length;
+        String anno = "@Anno ";
+
+        for (int i = 1; i < length; i++) {
+            String preAnno = String.join("", Arrays.copyOfRange(splittedCode, 0, i));
+            String postAnno = String.join("", Arrays.copyOfRange(splittedCode, i, length));
+            String moduleInfo = preAnno + anno + postAnno;
+            tb.writeFile(src_m1.resolve("module-info.java"), moduleInfo);
+
+            String log = new JavacTask(tb)
+                    .options("-XDrawDiagnostics", "-modulesourcepath", src.toString())
+                    .outdir(classes)
+                    .files(findJavaFiles(src))
+                    .run(Task.Expect.FAIL)
+                    .writeAll()
+                    .getOutput(Task.OutputKind.DIRECT);
+
+            if (!log.matches("(?s)^module\\-info\\.java:\\d+:\\d+: compiler\\.err\\.expected: token\\.identifier.*"))
+                throw new Exception("expected output not found");
+        }
+    }
 }