# HG changeset patch # User jlahoda # Date 1481886150 -3600 # Node ID 89b14017e8d6de622610254f4f746e8a69bcd8c2 # Parent 58864b03c7b93800d83a3543b628f7844792e547 8133896: Update javax.lang.model APIs Reviewed-by: darcy, jjg diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java --- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Fri Dec 16 12:02:30 2016 +0100 @@ -47,10 +47,11 @@ public interface Elements { /** - * Returns a package given its fully qualified name. + * Returns a package given its fully qualified name if the package is unique in the environment. + * If running with modules, all modules in the modules graph are searched for matching packages. * * @param name fully qualified package name, or an empty string for an unnamed package - * @return the named package, or {@code null} if it cannot be found + * @return the named package, or {@code null} if it cannot be uniquely found */ PackageElement getPackageElement(CharSequence name); @@ -65,10 +66,12 @@ PackageElement getPackageElement(ModuleElement module, CharSequence name); /** - * Returns a type element given its canonical name. + * Returns a type element given its canonical name if the type element is unique in the environment. + * If running with modules, all modules in the modules graph are searched for matching + * type elements. * * @param name the canonical name - * @return the named type element, or {@code null} if it cannot be found + * @return the named type element, or {@code null} if it cannot be uniquely found */ TypeElement getTypeElement(CharSequence name); @@ -84,6 +87,10 @@ /** * Returns a module element given its fully qualified name. + * If the named module cannot be found, null is returned. One situation where a module + * cannot be found is if the environment does not include modules, such as + * an annotation processing environment configured for + * a {@linkplain ProcessingEnvironment#getSourceVersion source version} without modules. * * * @param name the name * @return the named module element, or {@code null} if it cannot be found @@ -159,6 +166,10 @@ /** * Returns the module of an element. The module of a module is * itself. + * If there is no module for the element, null is returned. One situation where there is + * no module for an element is if the environment does not include modules, such as + * an annotation processing environment configured for + * a {@linkplain ProcessingEnvironment#getSourceVersion source version} without modules. * * * @param type the element being examined * @return the module of an element diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Fri Dec 16 12:02:30 2016 +0100 @@ -262,7 +262,7 @@ // scan trees for module defs Set roots = enterModules(trees, c); - setCompilationUnitModules(trees, roots); + setCompilationUnitModules(trees, roots, c); init.accept(roots); @@ -351,7 +351,7 @@ } } - private void setCompilationUnitModules(List trees, Set rootModules) { + private void setCompilationUnitModules(List trees, Set rootModules, ClassSymbol c) { // update the module for each compilation unit if (multiModuleMode) { checkNoAllModulePath(); @@ -385,6 +385,8 @@ } tree.modle = msym; rootModules.add(msym); + } else if (c != null && c.packge().modle == syms.unnamedModule) { + tree.modle = syms.unnamedModule; } else { log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules); tree.modle = syms.errModule; @@ -451,9 +453,6 @@ if (defaultModule != syms.unnamedModule) { syms.unnamedModule.completer = getUnnamedModuleCompleter(); - if (moduleOverride == null) { - syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH; - } syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH; } diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Dec 16 12:02:30 2016 +0100 @@ -1983,22 +1983,42 @@ } catch (ClassFinder.BadClassFile err) { throw err; } catch (CompletionFailure ex) { - //even if a class cannot be found in the current module and packages in modules it depends on that - //are exported for any or this module, the class may exist internally in some of these modules, - //or may exist in a module on which this module does not depend. Provide better diagnostic in - //such cases by looking for the class in any module: - for (ModuleSymbol ms : syms.getAllModules()) { - //do not load currently unloaded classes, to avoid too eager completion of random things in other modules: - ClassSymbol clazz = syms.getClass(ms, name); - - if (clazz != null) { - return new AccessError(clazz); - } + Symbol candidate = recoveryLoadClass.loadClass(env, name); + + if (candidate != null) { + return candidate; } + return typeNotFound; } } + public static interface RecoveryLoadClass { + Symbol loadClass(Env env, Name name); + } + + private RecoveryLoadClass recoveryLoadClass = (env, name) -> { + //even if a class cannot be found in the current module and packages in modules it depends on that + //are exported for any or this module, the class may exist internally in some of these modules, + //or may exist in a module on which this module does not depend. Provide better diagnostic in + //such cases by looking for the class in any module: + for (ModuleSymbol ms : syms.getAllModules()) { + //do not load currently unloaded classes, to avoid too eager completion of random things in other modules: + ClassSymbol clazz = syms.getClass(ms, name); + + if (clazz != null) { + return new AccessError(clazz); + } + } + return null; + }; + + public RecoveryLoadClass setRecoveryLoadClass(RecoveryLoadClass recovery) { + RecoveryLoadClass prev = recoveryLoadClass; + recoveryLoadClass = recovery; + return prev; + } + /** * Find a type declared in a scope (not inherited). Return null * if none is found. diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacElements.java Fri Dec 16 12:02:30 2016 +0100 @@ -25,7 +25,9 @@ package com.sun.tools.javac.model; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import javax.lang.model.SourceVersion; import javax.lang.model.element.*; @@ -54,9 +56,9 @@ import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; import static com.sun.tools.javac.code.TypeTag.CLASS; -import com.sun.tools.javac.comp.CompileStates; -import com.sun.tools.javac.comp.CompileStates.CompileState; import com.sun.tools.javac.comp.Modules; +import com.sun.tools.javac.comp.Resolve; +import com.sun.tools.javac.comp.Resolve.RecoveryLoadClass; import static com.sun.tools.javac.tree.JCTree.Tag.*; /** @@ -75,8 +77,8 @@ private final Names names; private final Types types; private final Enter enter; + private final Resolve resolve; private final JavacTaskImpl javacTaskImpl; - private final CompileStates compileStates; public static JavacElements instance(Context context) { JavacElements instance = context.get(JavacElements.class); @@ -93,14 +95,16 @@ names = Names.instance(context); types = Types.instance(context); enter = Enter.instance(context); + resolve = Resolve.instance(context); JavacTask t = context.get(JavacTask.class); javacTaskImpl = t instanceof JavacTaskImpl ? (JavacTaskImpl) t : null; - compileStates = CompileStates.instance(context); } @Override @DefinedBy(Api.LANGUAGE_MODEL) public ModuleSymbol getModuleElement(CharSequence name) { ensureEntered("getModuleElement"); + if (modules.getDefaultModule() == syms.noModule) + return null; String strName = name.toString(); if (strName.equals("")) return syms.unnamedModule; @@ -109,32 +113,77 @@ @Override @DefinedBy(Api.LANGUAGE_MODEL) public PackageSymbol getPackageElement(CharSequence name) { - ensureEntered("getPackageElement"); - return getPackageElement(modules.getDefaultModule(), name); + return doGetPackageElement(null, name); } @Override @DefinedBy(Api.LANGUAGE_MODEL) public PackageSymbol getPackageElement(ModuleElement module, CharSequence name) { - String strName = name.toString(); - if (strName.equals("")) + module.getClass(); + return doGetPackageElement(module, name); + } + + private PackageSymbol doGetPackageElement(ModuleElement module, CharSequence name) { + ensureEntered("getPackageElement"); + if (name.length() == 0) return syms.unnamedModule.unnamedPackage; - return SourceVersion.isName(strName) - ? nameToSymbol((ModuleSymbol) module, strName, PackageSymbol.class) - : null; + return doGetElement(module, name, PackageSymbol.class); } @Override @DefinedBy(Api.LANGUAGE_MODEL) public ClassSymbol getTypeElement(CharSequence name) { - ensureEntered("getTypeElement"); - return getTypeElement(modules.getDefaultModule(), name); + return doGetTypeElement(null, name); } @Override @DefinedBy(Api.LANGUAGE_MODEL) public ClassSymbol getTypeElement(ModuleElement module, CharSequence name) { + module.getClass(); + + return doGetTypeElement(module, name); + } + + private ClassSymbol doGetTypeElement(ModuleElement module, CharSequence name) { + ensureEntered("getTypeElement"); + return doGetElement(module, name, ClassSymbol.class); + } + + private S doGetElement(ModuleElement module, CharSequence name, Class clazz) { String strName = name.toString(); - return SourceVersion.isName(strName) - ? nameToSymbol((ModuleSymbol) module, strName, ClassSymbol.class) - : null; + if (!SourceVersion.isName(strName)) { + return null; + } + if (module == null) { + return unboundNameToSymbol(strName, clazz); + } else { + return nameToSymbol((ModuleSymbol) module, strName, clazz); + } + } + + private S unboundNameToSymbol(String nameStr, Class clazz) { + if (modules.getDefaultModule() == syms.noModule) { //not a modular mode: + return nameToSymbol(syms.noModule, nameStr, clazz); + } + + RecoveryLoadClass prevRecoveryLoadClass = resolve.setRecoveryLoadClass((env, name) -> null); + try { + Set found = new LinkedHashSet<>(); + + for (ModuleSymbol msym : modules.allModules()) { + S sym = nameToSymbol(msym, nameStr, clazz); + + if (sym != null) { + found.add(sym); + } + } + + if (found.size() == 1) { + return found.iterator().next(); + } else { + //not found, or more than one element found: + return null; + } + } finally { + resolve.setRecoveryLoadClass(prevRecoveryLoadClass); + } } /** @@ -369,6 +418,8 @@ @DefinedBy(Api.LANGUAGE_MODEL) public ModuleElement getModuleOf(Element e) { Symbol sym = cast(Symbol.class, e); + if (modules.getDefaultModule() == syms.noModule) + return null; return (sym.kind == MDL) ? ((ModuleElement) e) : sym.packge().modle; } diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Dec 16 12:02:30 2016 +0100 @@ -1363,15 +1363,15 @@ // Free resources this.close(); - if (!taskListener.isEmpty()) - taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); - if (errorStatus && compiler.errorCount() == 0) { compiler.log.nerrors++; } compiler.enterTreesIfNeeded(roots); + if (!taskListener.isEmpty()) + taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); + return true; } diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java Fri Dec 16 12:02:30 2016 +0100 @@ -203,8 +203,8 @@ bodyTree.addContent(HtmlConstants.START_OF_CLASS_DATA); HtmlTree div = new HtmlTree(HtmlTag.DIV); div.addStyle(HtmlStyle.header); - ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement); if (configuration.showModules) { + ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement); Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, contents.moduleLabel); Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); moduleNameDiv.addContent(Contents.SPACE); diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java Fri Dec 16 12:02:30 2016 +0100 @@ -125,8 +125,8 @@ } HtmlTree div = new HtmlTree(HtmlTag.DIV); div.addStyle(HtmlStyle.header); - ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement); if (configuration.showModules) { + ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement); Content classModuleLabel = HtmlTree.SPAN(HtmlStyle.moduleLabelInClass, contents.moduleLabel); Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel); moduleNameDiv.addContent(Contents.SPACE); diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java Fri Dec 16 12:02:30 2016 +0100 @@ -349,7 +349,12 @@ } protected Location getLocationForPackage(PackageElement pd) { - return getLocationForModule(configuration.docEnv.getElementUtils().getModuleOf(pd)); + ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(pd); + + if (mdle == null) + return defaultLocation(); + + return getLocationForModule(mdle); } protected Location getLocationForModule(ModuleElement mdle) { @@ -357,6 +362,10 @@ if (loc != null) return loc; + return defaultLocation(); + } + + private Location defaultLocation() { JavaFileManager fm = configuration.docEnv.getJavaFileManager(); return fm.hasLocation(StandardLocation.SOURCE_PATH) ? StandardLocation.SOURCE_PATH diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java Fri Dec 16 12:02:30 2016 +0100 @@ -620,7 +620,8 @@ // add all specified packages specifiedPackageElements.forEach(pkg -> { ModuleElement mdle = toolEnv.elements.getModuleOf(pkg); - imodules.add(mdle); + if (mdle != null) + imodules.add(mdle); ipackages.add(pkg); }); @@ -633,7 +634,7 @@ // add all types and its nested types specifiedTypeElements.forEach((klass) -> { ModuleElement mdle = toolEnv.elements.getModuleOf(klass); - if (!mdle.isUnnamed()) + if (mdle != null && !mdle.isUnnamed()) imodules.add(mdle); PackageElement pkg = toolEnv.elements.getPackageOf(klass); ipackages.add(pkg); diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/test/tools/javac/T6403466.out --- a/langtools/test/tools/javac/T6403466.out Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/test/tools/javac/T6403466.out Fri Dec 16 12:02:30 2016 +0100 @@ -20,11 +20,11 @@ Finished TaskEvent[ENTER,T6403466Wrapper.java,null] Started TaskEvent[ANNOTATION_PROCESSING_ROUND,null,null] Finished TaskEvent[ANNOTATION_PROCESSING_ROUND,null,null] -Finished TaskEvent[ANNOTATION_PROCESSING,null,null] Started TaskEvent[ENTER,T6403466.java,null] Started TaskEvent[ENTER,T6403466Wrapper.java,null] Finished TaskEvent[ENTER,T6403466.java,null] Finished TaskEvent[ENTER,T6403466Wrapper.java,null] +Finished TaskEvent[ANNOTATION_PROCESSING,null,null] Started TaskEvent[ANALYZE,T6403466.java,T6403466] Finished TaskEvent[ANALYZE,T6403466.java,T6403466] Started TaskEvent[GENERATE,T6403466.java,T6403466] diff -r 58864b03c7b9 -r 89b14017e8d6 langtools/test/tools/javac/modules/AnnotationProcessing.java --- a/langtools/test/tools/javac/modules/AnnotationProcessing.java Fri Dec 16 08:17:55 2016 +0000 +++ b/langtools/test/tools/javac/modules/AnnotationProcessing.java Fri Dec 16 12:02:30 2016 +0100 @@ -23,7 +23,7 @@ /** * @test - * @bug 8133884 8162711 + * @bug 8133884 8162711 8133896 * @summary Verify that annotation processing works. * @library /tools/lib * @modules @@ -49,6 +49,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; +import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.processing.AbstractProcessor; @@ -1012,6 +1013,168 @@ } } + @Test + public void testUnboundLookup(Path base) throws Exception { + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + "package impl.conflict.src; public class Impl { }"); + + Path moduleSrc = base.resolve("module-src"); + Path m1 = moduleSrc.resolve("m1x"); + Path m2 = moduleSrc.resolve("m2x"); + + Path classes = base.resolve("classes"); + Path cpClasses = base.resolve("cpClasses"); + + Files.createDirectories(classes); + Files.createDirectories(cpClasses); + + tb.writeJavaFiles(m1, + "module m1x { }", + "package impl1; public class Impl { }", + "package impl.conflict.module; class Impl { }", + "package impl.conflict.clazz; public class pkg { public static class I { } }", + "package impl.conflict.src; public class Impl { }"); + + tb.writeJavaFiles(m2, + "module m2x { }", + "package impl2; public class Impl { }", + "package impl.conflict.module; class Impl { }", + "package impl.conflict; public class clazz { public static class pkg { } }"); + + //from source: + new JavacTask(tb) + .options("--module-source-path", moduleSrc.toString(), + "--source-path", src.toString(), + "-processorpath", System.getProperty("test.class.path"), + "-processor", UnboundLookup.class.getName()) + .outdir(classes) + .files(findJavaFiles(moduleSrc)) + .run() + .writeAll(); + + new JavacTask(tb) + .options("--source-path", src.toString()) + .outdir(cpClasses) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + //from classfiles: + new JavacTask(tb) + .options("--module-path", classes.toString(), + "--class-path", cpClasses.toString(), + "--add-modules", "m1x,m2x", + "-processorpath", System.getProperty("test.class.path"), + "-processor", UnboundLookup.class.getName(), + "-proc:only") + .classes("java.lang.Object") + .run() + .writeAll(); + + //source 8: + new JavacTask(tb) + .options("--source-path", src.toString(), + "-source", "8", + "-processorpath", System.getProperty("test.class.path"), + "-processor", UnboundLookup8.class.getName()) + .outdir(cpClasses) + .files(findJavaFiles(src)) + .run() + .writeAll(); + + } + + @SupportedAnnotationTypes("*") + public static final class UnboundLookup extends AbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + assertTypeElementExists("impl1.Impl", "m1x"); + assertPackageElementExists("impl1", "m1x"); + assertTypeElementExists("impl2.Impl", "m2x"); + assertTypeElementExists("impl.conflict.clazz.pkg.I", "m1x"); + assertTypeElementExists("impl.conflict.clazz", "m2x"); + assertPackageElementExists("impl.conflict.clazz", "m1x"); + assertPackageElementExists("impl2", "m2x"); + assertTypeElementNotFound("impl.conflict.module.Impl"); + assertPackageElementNotFound("impl.conflict.module"); + assertTypeElementNotFound("impl.conflict.src.Impl"); + assertPackageElementNotFound("impl.conflict.src"); + assertTypeElementNotFound("impl.conflict.clazz.pkg"); + + return false; + } + + private void assertTypeElementExists(String name, String expectedModule) { + assertElementExists(name, "class", processingEnv.getElementUtils() :: getTypeElement, expectedModule); + } + + private void assertPackageElementExists(String name, String expectedModule) { + assertElementExists(name, "package", processingEnv.getElementUtils() :: getPackageElement, expectedModule); + } + + private void assertElementExists(String name, String type, Function getter, String expectedModule) { + Element clazz = getter.apply(name); + + if (clazz == null) { + throw new AssertionError("No " + name + " " + type + " found."); + } + + ModuleElement mod = processingEnv.getElementUtils().getModuleOf(clazz); + + if (!mod.getQualifiedName().contentEquals(expectedModule)) { + throw new AssertionError(name + " found in an unexpected module: " + mod.getQualifiedName()); + } + } + + private void assertTypeElementNotFound(String name) { + assertElementNotFound(name, processingEnv.getElementUtils() :: getTypeElement); + } + + private void assertPackageElementNotFound(String name) { + assertElementNotFound(name, processingEnv.getElementUtils() :: getPackageElement); + } + + private void assertElementNotFound(String name, Function getter) { + Element found = getter.apply(name); + + if (found != null) { + fail("Element found unexpectedly: " + found); + } + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + } + + @SupportedAnnotationTypes("*") + public static final class UnboundLookup8 extends AbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (processingEnv.getElementUtils().getTypeElement("impl.conflict.src.Impl") == null) { + throw new AssertionError("impl.conflict.src.Impl."); + } + + if (processingEnv.getElementUtils().getModuleElement("java.base") != null) { + throw new AssertionError("getModuleElement != null for -source 8"); + } + + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + } + private static void assertNonNull(String msg, Object val) { if (val == null) { throw new AssertionError(msg); @@ -1048,4 +1211,8 @@ return file; } + private static void fail(String msg) { + throw new AssertionError(msg); + } + }