--- 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
--- 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<ModuleSymbol> roots = enterModules(trees, c);
- setCompilationUnitModules(trees, roots);
+ setCompilationUnitModules(trees, roots, c);
init.accept(roots);
@@ -351,7 +351,7 @@
}
}
- private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules) {
+ private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> 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;
}
--- 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<AttrContext> 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.
--- 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 extends Symbol> S doGetElement(ModuleElement module, CharSequence name, Class<S> 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 extends Symbol> S unboundNameToSymbol(String nameStr, Class<S> 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<S> 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;
}
--- 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;
}
--- 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);
--- 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);
--- 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
--- 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);
--- 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]
--- 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<? extends TypeElement> 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<String, Element> 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<String, Element> 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<? extends TypeElement> 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);
+ }
+
}