langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
changeset 42815 050370edaade
parent 41255 72fcbd6294cb
child 42824 89b14017e8d6
equal deleted inserted replaced
42814:058fc03646d9 42815:050370edaade
    32 import java.lang.reflect.Method;
    32 import java.lang.reflect.Method;
    33 import java.net.MalformedURLException;
    33 import java.net.MalformedURLException;
    34 import java.net.URL;
    34 import java.net.URL;
    35 import java.nio.file.Path;
    35 import java.nio.file.Path;
    36 import java.util.*;
    36 import java.util.*;
       
    37 import java.util.Map.Entry;
    37 import java.util.regex.*;
    38 import java.util.regex.*;
    38 import java.util.stream.Collectors;
    39 import java.util.stream.Collectors;
    39 
    40 
    40 import javax.annotation.processing.*;
    41 import javax.annotation.processing.*;
    41 import javax.lang.model.SourceVersion;
    42 import javax.lang.model.SourceVersion;
   825         }
   826         }
   826     }
   827     }
   827 
   828 
   828     private void discoverAndRunProcs(Set<TypeElement> annotationsPresent,
   829     private void discoverAndRunProcs(Set<TypeElement> annotationsPresent,
   829                                      List<ClassSymbol> topLevelClasses,
   830                                      List<ClassSymbol> topLevelClasses,
   830                                      List<PackageSymbol> packageInfoFiles) {
   831                                      List<PackageSymbol> packageInfoFiles,
       
   832                                      List<ModuleSymbol> moduleInfoFiles) {
   831         Map<String, TypeElement> unmatchedAnnotations = new HashMap<>(annotationsPresent.size());
   833         Map<String, TypeElement> unmatchedAnnotations = new HashMap<>(annotationsPresent.size());
   832 
   834 
   833         for(TypeElement a  : annotationsPresent) {
   835         for(TypeElement a  : annotationsPresent) {
   834                 unmatchedAnnotations.put(a.getQualifiedName().toString(),
   836             ModuleElement mod = elementUtils.getModuleOf(a);
   835                                          a);
   837             unmatchedAnnotations.put((mod != null ? mod.getSimpleName() + "/" : "") + a.getQualifiedName().toString(),
       
   838                                      a);
   836         }
   839         }
   837 
   840 
   838         // Give "*" processors a chance to match
   841         // Give "*" processors a chance to match
   839         if (unmatchedAnnotations.size() == 0)
   842         if (unmatchedAnnotations.size() == 0)
   840             unmatchedAnnotations.put("", null);
   843             unmatchedAnnotations.put("", null);
   847         // are not doing processing in that case.
   850         // are not doing processing in that case.
   848 
   851 
   849         Set<Element> rootElements = new LinkedHashSet<>();
   852         Set<Element> rootElements = new LinkedHashSet<>();
   850         rootElements.addAll(topLevelClasses);
   853         rootElements.addAll(topLevelClasses);
   851         rootElements.addAll(packageInfoFiles);
   854         rootElements.addAll(packageInfoFiles);
       
   855         rootElements.addAll(moduleInfoFiles);
   852         rootElements = Collections.unmodifiableSet(rootElements);
   856         rootElements = Collections.unmodifiableSet(rootElements);
   853 
   857 
   854         RoundEnvironment renv = new JavacRoundEnvironment(false,
   858         RoundEnvironment renv = new JavacRoundEnvironment(false,
   855                                                           false,
   859                                                           false,
   856                                                           rootElements,
   860                                                           rootElements,
   984         /** The ASTs to be compiled. */
   988         /** The ASTs to be compiled. */
   985         List<JCCompilationUnit> roots;
   989         List<JCCompilationUnit> roots;
   986         /** The trees that need to be cleaned - includes roots and implicitly parsed trees. */
   990         /** The trees that need to be cleaned - includes roots and implicitly parsed trees. */
   987         Set<JCCompilationUnit> treesToClean;
   991         Set<JCCompilationUnit> treesToClean;
   988         /** The classes to be compiler that have were generated. */
   992         /** The classes to be compiler that have were generated. */
   989         Map<String, JavaFileObject> genClassFiles;
   993         Map<ModuleSymbol, Map<String, JavaFileObject>> genClassFiles;
   990 
   994 
   991         /** The set of annotations to be processed this round. */
   995         /** The set of annotations to be processed this round. */
   992         Set<TypeElement> annotationsPresent;
   996         Set<TypeElement> annotationsPresent;
   993         /** The set of top level classes to be processed this round. */
   997         /** The set of top level classes to be processed this round. */
   994         List<ClassSymbol> topLevelClasses;
   998         List<ClassSymbol> topLevelClasses;
   995         /** The set of package-info files to be processed this round. */
   999         /** The set of package-info files to be processed this round. */
   996         List<PackageSymbol> packageInfoFiles;
  1000         List<PackageSymbol> packageInfoFiles;
       
  1001         /** The set of module-info files to be processed this round. */
       
  1002         List<ModuleSymbol> moduleInfoFiles;
   997 
  1003 
   998         /** Create a round (common code). */
  1004         /** Create a round (common code). */
   999         private Round(int number, Set<JCCompilationUnit> treesToClean,
  1005         private Round(int number, Set<JCCompilationUnit> treesToClean,
  1000                 Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
  1006                 Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
  1001             this.number = number;
  1007             this.number = number;
  1009             }
  1015             }
  1010 
  1016 
  1011             // the following will be populated as needed
  1017             // the following will be populated as needed
  1012             topLevelClasses  = List.nil();
  1018             topLevelClasses  = List.nil();
  1013             packageInfoFiles = List.nil();
  1019             packageInfoFiles = List.nil();
       
  1020             moduleInfoFiles = List.nil();
  1014             this.treesToClean = treesToClean;
  1021             this.treesToClean = treesToClean;
  1015         }
  1022         }
  1016 
  1023 
  1017         /** Create the first round. */
  1024         /** Create the first round. */
  1018         Round(List<JCCompilationUnit> roots,
  1025         Round(List<JCCompilationUnit> roots,
  1029             topLevelClasses =
  1036             topLevelClasses =
  1030                 getTopLevelClasses(roots).prependList(classSymbols.reverse());
  1037                 getTopLevelClasses(roots).prependList(classSymbols.reverse());
  1031 
  1038 
  1032             packageInfoFiles = getPackageInfoFiles(roots);
  1039             packageInfoFiles = getPackageInfoFiles(roots);
  1033 
  1040 
       
  1041             moduleInfoFiles = getModuleInfoFiles(roots);
       
  1042 
  1034             findAnnotationsPresent();
  1043             findAnnotationsPresent();
  1035         }
  1044         }
  1036 
  1045 
  1037         /** Create a new round. */
  1046         /** Create a new round. */
  1038         private Round(Round prev,
  1047         private Round(Round prev,
  1039                 Set<JavaFileObject> newSourceFiles, Map<String,JavaFileObject> newClassFiles) {
  1048                 Set<JavaFileObject> newSourceFiles, Map<ModuleSymbol, Map<String,JavaFileObject>> newClassFiles) {
  1040             this(prev.number+1, prev.treesToClean, null);
  1049             this(prev.number+1, prev.treesToClean, null);
  1041             prev.newRound();
  1050             prev.newRound();
  1042             this.genClassFiles = prev.genClassFiles;
  1051             this.genClassFiles = prev.genClassFiles;
  1043 
  1052 
  1044             List<JCCompilationUnit> parsedFiles = compiler.parseFiles(newSourceFiles);
  1053             List<JCCompilationUnit> parsedFiles = compiler.parseFiles(newSourceFiles);
  1046 
  1055 
  1047             // Check for errors after parsing
  1056             // Check for errors after parsing
  1048             if (unrecoverableError())
  1057             if (unrecoverableError())
  1049                 return;
  1058                 return;
  1050 
  1059 
       
  1060             roots = compiler.initModules(roots);
       
  1061 
  1051             enterClassFiles(genClassFiles);
  1062             enterClassFiles(genClassFiles);
  1052             List<ClassSymbol> newClasses = enterClassFiles(newClassFiles);
  1063             List<ClassSymbol> newClasses = enterClassFiles(newClassFiles);
  1053             genClassFiles.putAll(newClassFiles);
  1064             for (Entry<ModuleSymbol, Map<String, JavaFileObject>> moduleAndClassFiles : newClassFiles.entrySet()) {
       
  1065                 genClassFiles.computeIfAbsent(moduleAndClassFiles.getKey(), m -> new LinkedHashMap<>()).putAll(moduleAndClassFiles.getValue());
       
  1066             }
  1054             enterTrees(roots);
  1067             enterTrees(roots);
  1055 
  1068 
  1056             if (unrecoverableError())
  1069             if (unrecoverableError())
  1057                 return;
  1070                 return;
  1058 
  1071 
  1062 
  1075 
  1063             packageInfoFiles = join(
  1076             packageInfoFiles = join(
  1064                     getPackageInfoFiles(parsedFiles),
  1077                     getPackageInfoFiles(parsedFiles),
  1065                     getPackageInfoFilesFromClasses(newClasses));
  1078                     getPackageInfoFilesFromClasses(newClasses));
  1066 
  1079 
       
  1080             moduleInfoFiles = List.nil(); //module-info cannot be generated
       
  1081 
  1067             findAnnotationsPresent();
  1082             findAnnotationsPresent();
  1068         }
  1083         }
  1069 
  1084 
  1070         /** Create the next round to be used. */
  1085         /** Create the next round to be used. */
  1071         Round next(Set<JavaFileObject> newSourceFiles, Map<String, JavaFileObject> newClassFiles) {
  1086         Round next(Set<JavaFileObject> newSourceFiles, Map<ModuleSymbol, Map<String, JavaFileObject>> newClassFiles) {
  1072             return new Round(this, newSourceFiles, newClassFiles);
  1087             return new Round(this, newSourceFiles, newClassFiles);
  1073         }
  1088         }
  1074 
  1089 
  1075         /** Prepare the compiler for the final compilation. */
  1090         /** Prepare the compiler for the final compilation. */
  1076         void finalCompiler() {
  1091         void finalCompiler() {
  1119             annotationsPresent = new LinkedHashSet<>();
  1134             annotationsPresent = new LinkedHashSet<>();
  1120             for (ClassSymbol classSym : topLevelClasses)
  1135             for (ClassSymbol classSym : topLevelClasses)
  1121                 annotationComputer.scan(classSym, annotationsPresent);
  1136                 annotationComputer.scan(classSym, annotationsPresent);
  1122             for (PackageSymbol pkgSym : packageInfoFiles)
  1137             for (PackageSymbol pkgSym : packageInfoFiles)
  1123                 annotationComputer.scan(pkgSym, annotationsPresent);
  1138                 annotationComputer.scan(pkgSym, annotationsPresent);
       
  1139             for (ModuleSymbol mdlSym : moduleInfoFiles)
       
  1140                 annotationComputer.scan(mdlSym, annotationsPresent);
  1124         }
  1141         }
  1125 
  1142 
  1126         /** Enter a set of generated class files. */
  1143         /** Enter a set of generated class files. */
  1127         private List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) {
  1144         private List<ClassSymbol> enterClassFiles(Map<ModuleSymbol, Map<String, JavaFileObject>> modulesAndClassFiles) {
  1128             List<ClassSymbol> list = List.nil();
  1145             List<ClassSymbol> list = List.nil();
  1129 
  1146 
  1130             for (Map.Entry<String,JavaFileObject> entry : classFiles.entrySet()) {
  1147             for (Entry<ModuleSymbol, Map<String, JavaFileObject>> moduleAndClassFiles : modulesAndClassFiles.entrySet()) {
  1131                 Name name = names.fromString(entry.getKey());
  1148                 for (Map.Entry<String,JavaFileObject> entry : moduleAndClassFiles.getValue().entrySet()) {
  1132                 JavaFileObject file = entry.getValue();
  1149                     Name name = names.fromString(entry.getKey());
  1133                 if (file.getKind() != JavaFileObject.Kind.CLASS)
  1150                     JavaFileObject file = entry.getValue();
  1134                     throw new AssertionError(file);
  1151                     if (file.getKind() != JavaFileObject.Kind.CLASS)
  1135                 ClassSymbol cs;
  1152                         throw new AssertionError(file);
  1136                 // TODO: for now, we assume that generated code is in a default module;
  1153                     ClassSymbol cs;
  1137                 // in time, we need a way to be able to specify the module for generated code
  1154                     if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
  1138                 if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
  1155                         Name packageName = Convert.packagePart(name);
  1139                     Name packageName = Convert.packagePart(name);
  1156                         PackageSymbol p = symtab.enterPackage(moduleAndClassFiles.getKey(), packageName);
  1140                     PackageSymbol p = symtab.enterPackage(defaultModule, packageName);
  1157                         if (p.package_info == null)
  1141                     if (p.package_info == null)
  1158                             p.package_info = symtab.enterClass(moduleAndClassFiles.getKey(), Convert.shortName(name), p);
  1142                         p.package_info = symtab.enterClass(defaultModule, Convert.shortName(name), p);
  1159                         cs = p.package_info;
  1143                     cs = p.package_info;
  1160                         cs.reset();
  1144                     cs.reset();
  1161                         if (cs.classfile == null)
  1145                     if (cs.classfile == null)
  1162                             cs.classfile = file;
       
  1163                         cs.completer = initialCompleter;
       
  1164                     } else {
       
  1165                         cs = symtab.enterClass(moduleAndClassFiles.getKey(), name);
       
  1166                         cs.reset();
  1146                         cs.classfile = file;
  1167                         cs.classfile = file;
  1147                     cs.completer = initialCompleter;
  1168                         cs.completer = initialCompleter;
  1148                 } else {
  1169                         cs.owner.members().enter(cs); //XXX - OverwriteBetweenCompilations; syms.getClass is not sufficient anymore
  1149                     cs = symtab.enterClass(defaultModule, name);
  1170                     }
  1150                     cs.reset();
  1171                     list = list.prepend(cs);
  1151                     cs.classfile = file;
  1172                 }
  1152                     cs.completer = initialCompleter;
       
  1153                     cs.owner.members().enter(cs); //XXX - OverwriteBetweenCompilations; syms.getClass is not sufficient anymore
       
  1154                 }
       
  1155                 list = list.prepend(cs);
       
  1156             }
  1173             }
  1157             return list.reverse();
  1174             return list.reverse();
  1158         }
  1175         }
  1159 
  1176 
  1160         /** Enter a set of syntax trees. */
  1177         /** Enter a set of syntax trees. */
  1161         private void enterTrees(List<JCCompilationUnit> roots) {
  1178         private void enterTrees(List<JCCompilationUnit> roots) {
  1162             compiler.enterTrees(compiler.initModules(roots));
  1179             compiler.enterTrees(roots);
  1163         }
  1180         }
  1164 
  1181 
  1165         /** Run a processing round. */
  1182         /** Run a processing round. */
  1166         void run(boolean lastRound, boolean errorStatus) {
  1183         void run(boolean lastRound, boolean errorStatus) {
  1167             printRoundInfo(lastRound);
  1184             printRoundInfo(lastRound);
  1177                             errorStatus,
  1194                             errorStatus,
  1178                             emptyRootElements,
  1195                             emptyRootElements,
  1179                             JavacProcessingEnvironment.this);
  1196                             JavacProcessingEnvironment.this);
  1180                     discoveredProcs.iterator().runContributingProcs(renv);
  1197                     discoveredProcs.iterator().runContributingProcs(renv);
  1181                 } else {
  1198                 } else {
  1182                     discoverAndRunProcs(annotationsPresent, topLevelClasses, packageInfoFiles);
  1199                     discoverAndRunProcs(annotationsPresent, topLevelClasses, packageInfoFiles, moduleInfoFiles);
  1183                 }
  1200                 }
  1184             } catch (Throwable t) {
  1201             } catch (Throwable t) {
  1185                 // we're specifically expecting Abort here, but if any Throwable
  1202                 // we're specifically expecting Abort here, but if any Throwable
  1186                 // comes by, we should flush all deferred diagnostics, rather than
  1203                 // comes by, we should flush all deferred diagnostics, rather than
  1187                 // drop them on the ground.
  1204                 // drop them on the ground.
  1416             }
  1433             }
  1417         }
  1434         }
  1418         return packages.reverse();
  1435         return packages.reverse();
  1419     }
  1436     }
  1420 
  1437 
       
  1438     private List<ModuleSymbol> getModuleInfoFiles(List<? extends JCCompilationUnit> units) {
       
  1439         List<ModuleSymbol> modules = List.nil();
       
  1440         for (JCCompilationUnit unit : units) {
       
  1441             if (isModuleInfo(unit.sourcefile, JavaFileObject.Kind.SOURCE) &&
       
  1442                 unit.defs.nonEmpty() &&
       
  1443                 unit.defs.head.hasTag(Tag.MODULEDEF)) {
       
  1444                 modules = modules.prepend(unit.modle);
       
  1445             }
       
  1446         }
       
  1447         return modules.reverse();
       
  1448     }
       
  1449 
  1421     // avoid unchecked warning from use of varargs
  1450     // avoid unchecked warning from use of varargs
  1422     private static <T> List<T> join(List<T> list1, List<T> list2) {
  1451     private static <T> List<T> join(List<T> list1, List<T> list2) {
  1423         return list1.appendList(list2);
  1452         return list1.appendList(list2);
  1424     }
  1453     }
  1425 
  1454 
  1427         return fo.isNameCompatible("package-info", kind);
  1456         return fo.isNameCompatible("package-info", kind);
  1428     }
  1457     }
  1429 
  1458 
  1430     private boolean isPkgInfo(ClassSymbol sym) {
  1459     private boolean isPkgInfo(ClassSymbol sym) {
  1431         return isPkgInfo(sym.classfile, JavaFileObject.Kind.CLASS) && (sym.packge().package_info == sym);
  1460         return isPkgInfo(sym.classfile, JavaFileObject.Kind.CLASS) && (sym.packge().package_info == sym);
       
  1461     }
       
  1462 
       
  1463     private boolean isModuleInfo(JavaFileObject fo, JavaFileObject.Kind kind) {
       
  1464         return fo.isNameCompatible("module-info", kind);
  1432     }
  1465     }
  1433 
  1466 
  1434     /*
  1467     /*
  1435      * Called retroactively to determine if a class loader was required,
  1468      * Called retroactively to determine if a class loader was required,
  1436      * after we have failed to create one.
  1469      * after we have failed to create one.
  1623      * Convert import-style string for supported annotations into a
  1656      * Convert import-style string for supported annotations into a
  1624      * regex matching that string.  If the string is not a valid
  1657      * regex matching that string.  If the string is not a valid
  1625      * import-style string, return a regex that won't match anything.
  1658      * import-style string, return a regex that won't match anything.
  1626      */
  1659      */
  1627     private static Pattern importStringToPattern(String s, Processor p, Log log) {
  1660     private static Pattern importStringToPattern(String s, Processor p, Log log) {
  1628         if (MatchingUtils.isValidImportString(s)) {
  1661         String module;
  1629             return MatchingUtils.validImportStringToPattern(s);
  1662         String pkg;
       
  1663         int slash = s.indexOf('/');
       
  1664         if (slash == (-1)) {
       
  1665             if (s.equals("*")) {
       
  1666                 return MatchingUtils.validImportStringToPattern(s);
       
  1667             }
       
  1668             module = ".*/";
       
  1669             pkg = s;
       
  1670         } else {
       
  1671             module = Pattern.quote(s.substring(0, slash + 1));
       
  1672             pkg = s.substring(slash + 1);
       
  1673         }
       
  1674         if (MatchingUtils.isValidImportString(pkg)) {
       
  1675             return Pattern.compile(module + MatchingUtils.validImportStringToPatternString(pkg));
  1630         } else {
  1676         } else {
  1631             log.warning("proc.malformed.supported.string", s, p.getClass().getName());
  1677             log.warning("proc.malformed.supported.string", s, p.getClass().getName());
  1632             return noMatches; // won't match any valid identifier
  1678             return noMatches; // won't match any valid identifier
  1633         }
  1679         }
  1634     }
  1680     }