langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
changeset 42815 050370edaade
parent 41255 72fcbd6294cb
child 42824 89b14017e8d6
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Tue Dec 13 10:48:18 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Tue Dec 13 10:49:28 2016 +0100
@@ -34,6 +34,7 @@
 import java.net.URL;
 import java.nio.file.Path;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.regex.*;
 import java.util.stream.Collectors;
 
@@ -827,12 +828,14 @@
 
     private void discoverAndRunProcs(Set<TypeElement> annotationsPresent,
                                      List<ClassSymbol> topLevelClasses,
-                                     List<PackageSymbol> packageInfoFiles) {
+                                     List<PackageSymbol> packageInfoFiles,
+                                     List<ModuleSymbol> moduleInfoFiles) {
         Map<String, TypeElement> unmatchedAnnotations = new HashMap<>(annotationsPresent.size());
 
         for(TypeElement a  : annotationsPresent) {
-                unmatchedAnnotations.put(a.getQualifiedName().toString(),
-                                         a);
+            ModuleElement mod = elementUtils.getModuleOf(a);
+            unmatchedAnnotations.put((mod != null ? mod.getSimpleName() + "/" : "") + a.getQualifiedName().toString(),
+                                     a);
         }
 
         // Give "*" processors a chance to match
@@ -849,6 +852,7 @@
         Set<Element> rootElements = new LinkedHashSet<>();
         rootElements.addAll(topLevelClasses);
         rootElements.addAll(packageInfoFiles);
+        rootElements.addAll(moduleInfoFiles);
         rootElements = Collections.unmodifiableSet(rootElements);
 
         RoundEnvironment renv = new JavacRoundEnvironment(false,
@@ -986,7 +990,7 @@
         /** The trees that need to be cleaned - includes roots and implicitly parsed trees. */
         Set<JCCompilationUnit> treesToClean;
         /** The classes to be compiler that have were generated. */
-        Map<String, JavaFileObject> genClassFiles;
+        Map<ModuleSymbol, Map<String, JavaFileObject>> genClassFiles;
 
         /** The set of annotations to be processed this round. */
         Set<TypeElement> annotationsPresent;
@@ -994,6 +998,8 @@
         List<ClassSymbol> topLevelClasses;
         /** The set of package-info files to be processed this round. */
         List<PackageSymbol> packageInfoFiles;
+        /** The set of module-info files to be processed this round. */
+        List<ModuleSymbol> moduleInfoFiles;
 
         /** Create a round (common code). */
         private Round(int number, Set<JCCompilationUnit> treesToClean,
@@ -1011,6 +1017,7 @@
             // the following will be populated as needed
             topLevelClasses  = List.nil();
             packageInfoFiles = List.nil();
+            moduleInfoFiles = List.nil();
             this.treesToClean = treesToClean;
         }
 
@@ -1031,12 +1038,14 @@
 
             packageInfoFiles = getPackageInfoFiles(roots);
 
+            moduleInfoFiles = getModuleInfoFiles(roots);
+
             findAnnotationsPresent();
         }
 
         /** Create a new round. */
         private Round(Round prev,
-                Set<JavaFileObject> newSourceFiles, Map<String,JavaFileObject> newClassFiles) {
+                Set<JavaFileObject> newSourceFiles, Map<ModuleSymbol, Map<String,JavaFileObject>> newClassFiles) {
             this(prev.number+1, prev.treesToClean, null);
             prev.newRound();
             this.genClassFiles = prev.genClassFiles;
@@ -1048,9 +1057,13 @@
             if (unrecoverableError())
                 return;
 
+            roots = compiler.initModules(roots);
+
             enterClassFiles(genClassFiles);
             List<ClassSymbol> newClasses = enterClassFiles(newClassFiles);
-            genClassFiles.putAll(newClassFiles);
+            for (Entry<ModuleSymbol, Map<String, JavaFileObject>> moduleAndClassFiles : newClassFiles.entrySet()) {
+                genClassFiles.computeIfAbsent(moduleAndClassFiles.getKey(), m -> new LinkedHashMap<>()).putAll(moduleAndClassFiles.getValue());
+            }
             enterTrees(roots);
 
             if (unrecoverableError())
@@ -1064,11 +1077,13 @@
                     getPackageInfoFiles(parsedFiles),
                     getPackageInfoFilesFromClasses(newClasses));
 
+            moduleInfoFiles = List.nil(); //module-info cannot be generated
+
             findAnnotationsPresent();
         }
 
         /** Create the next round to be used. */
-        Round next(Set<JavaFileObject> newSourceFiles, Map<String, JavaFileObject> newClassFiles) {
+        Round next(Set<JavaFileObject> newSourceFiles, Map<ModuleSymbol, Map<String, JavaFileObject>> newClassFiles) {
             return new Round(this, newSourceFiles, newClassFiles);
         }
 
@@ -1121,45 +1136,47 @@
                 annotationComputer.scan(classSym, annotationsPresent);
             for (PackageSymbol pkgSym : packageInfoFiles)
                 annotationComputer.scan(pkgSym, annotationsPresent);
+            for (ModuleSymbol mdlSym : moduleInfoFiles)
+                annotationComputer.scan(mdlSym, annotationsPresent);
         }
 
         /** Enter a set of generated class files. */
-        private List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) {
+        private List<ClassSymbol> enterClassFiles(Map<ModuleSymbol, Map<String, JavaFileObject>> modulesAndClassFiles) {
             List<ClassSymbol> list = List.nil();
 
-            for (Map.Entry<String,JavaFileObject> entry : classFiles.entrySet()) {
-                Name name = names.fromString(entry.getKey());
-                JavaFileObject file = entry.getValue();
-                if (file.getKind() != JavaFileObject.Kind.CLASS)
-                    throw new AssertionError(file);
-                ClassSymbol cs;
-                // TODO: for now, we assume that generated code is in a default module;
-                // in time, we need a way to be able to specify the module for generated code
-                if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
-                    Name packageName = Convert.packagePart(name);
-                    PackageSymbol p = symtab.enterPackage(defaultModule, packageName);
-                    if (p.package_info == null)
-                        p.package_info = symtab.enterClass(defaultModule, Convert.shortName(name), p);
-                    cs = p.package_info;
-                    cs.reset();
-                    if (cs.classfile == null)
+            for (Entry<ModuleSymbol, Map<String, JavaFileObject>> moduleAndClassFiles : modulesAndClassFiles.entrySet()) {
+                for (Map.Entry<String,JavaFileObject> entry : moduleAndClassFiles.getValue().entrySet()) {
+                    Name name = names.fromString(entry.getKey());
+                    JavaFileObject file = entry.getValue();
+                    if (file.getKind() != JavaFileObject.Kind.CLASS)
+                        throw new AssertionError(file);
+                    ClassSymbol cs;
+                    if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
+                        Name packageName = Convert.packagePart(name);
+                        PackageSymbol p = symtab.enterPackage(moduleAndClassFiles.getKey(), packageName);
+                        if (p.package_info == null)
+                            p.package_info = symtab.enterClass(moduleAndClassFiles.getKey(), Convert.shortName(name), p);
+                        cs = p.package_info;
+                        cs.reset();
+                        if (cs.classfile == null)
+                            cs.classfile = file;
+                        cs.completer = initialCompleter;
+                    } else {
+                        cs = symtab.enterClass(moduleAndClassFiles.getKey(), name);
+                        cs.reset();
                         cs.classfile = file;
-                    cs.completer = initialCompleter;
-                } else {
-                    cs = symtab.enterClass(defaultModule, name);
-                    cs.reset();
-                    cs.classfile = file;
-                    cs.completer = initialCompleter;
-                    cs.owner.members().enter(cs); //XXX - OverwriteBetweenCompilations; syms.getClass is not sufficient anymore
+                        cs.completer = initialCompleter;
+                        cs.owner.members().enter(cs); //XXX - OverwriteBetweenCompilations; syms.getClass is not sufficient anymore
+                    }
+                    list = list.prepend(cs);
                 }
-                list = list.prepend(cs);
             }
             return list.reverse();
         }
 
         /** Enter a set of syntax trees. */
         private void enterTrees(List<JCCompilationUnit> roots) {
-            compiler.enterTrees(compiler.initModules(roots));
+            compiler.enterTrees(roots);
         }
 
         /** Run a processing round. */
@@ -1179,7 +1196,7 @@
                             JavacProcessingEnvironment.this);
                     discoveredProcs.iterator().runContributingProcs(renv);
                 } else {
-                    discoverAndRunProcs(annotationsPresent, topLevelClasses, packageInfoFiles);
+                    discoverAndRunProcs(annotationsPresent, topLevelClasses, packageInfoFiles, moduleInfoFiles);
                 }
             } catch (Throwable t) {
                 // we're specifically expecting Abort here, but if any Throwable
@@ -1418,6 +1435,18 @@
         return packages.reverse();
     }
 
+    private List<ModuleSymbol> getModuleInfoFiles(List<? extends JCCompilationUnit> units) {
+        List<ModuleSymbol> modules = List.nil();
+        for (JCCompilationUnit unit : units) {
+            if (isModuleInfo(unit.sourcefile, JavaFileObject.Kind.SOURCE) &&
+                unit.defs.nonEmpty() &&
+                unit.defs.head.hasTag(Tag.MODULEDEF)) {
+                modules = modules.prepend(unit.modle);
+            }
+        }
+        return modules.reverse();
+    }
+
     // avoid unchecked warning from use of varargs
     private static <T> List<T> join(List<T> list1, List<T> list2) {
         return list1.appendList(list2);
@@ -1431,6 +1460,10 @@
         return isPkgInfo(sym.classfile, JavaFileObject.Kind.CLASS) && (sym.packge().package_info == sym);
     }
 
+    private boolean isModuleInfo(JavaFileObject fo, JavaFileObject.Kind kind) {
+        return fo.isNameCompatible("module-info", kind);
+    }
+
     /*
      * Called retroactively to determine if a class loader was required,
      * after we have failed to create one.
@@ -1625,8 +1658,21 @@
      * import-style string, return a regex that won't match anything.
      */
     private static Pattern importStringToPattern(String s, Processor p, Log log) {
-        if (MatchingUtils.isValidImportString(s)) {
-            return MatchingUtils.validImportStringToPattern(s);
+        String module;
+        String pkg;
+        int slash = s.indexOf('/');
+        if (slash == (-1)) {
+            if (s.equals("*")) {
+                return MatchingUtils.validImportStringToPattern(s);
+            }
+            module = ".*/";
+            pkg = s;
+        } else {
+            module = Pattern.quote(s.substring(0, slash + 1));
+            pkg = s.substring(slash + 1);
+        }
+        if (MatchingUtils.isValidImportString(pkg)) {
+            return Pattern.compile(module + MatchingUtils.validImportStringToPatternString(pkg));
         } else {
             log.warning("proc.malformed.supported.string", s, p.getClass().getName());
             return noMatches; // won't match any valid identifier