8133896: Update javax.lang.model APIs

Reviewed-by: darcy, jjg
This commit is contained in:
Jan Lahoda 2016-12-16 12:02:30 +01:00
parent 574ac0add6
commit e62a384eb3
11 changed files with 303 additions and 45 deletions

View File

@ -47,10 +47,11 @@ import javax.lang.model.element.*;
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 @@ public interface Elements {
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 @@ public interface Elements {
/**
* 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 @@ public interface Elements {
/**
* 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

View File

@ -262,7 +262,7 @@ public class Modules extends JCTree.Visitor {
// 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 @@ public class Modules extends JCTree.Visitor {
}
}
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 @@ public class Modules extends JCTree.Visitor {
}
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 @@ public class Modules extends JCTree.Visitor {
if (defaultModule != syms.unnamedModule) {
syms.unnamedModule.completer = getUnnamedModuleCompleter();
if (moduleOverride == null) {
syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
}
syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
}

View File

@ -1983,22 +1983,42 @@ public class Resolve {
} 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);
Symbol candidate = recoveryLoadClass.loadClass(env, name);
if (clazz != null) {
return new AccessError(clazz);
}
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.

View File

@ -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 com.sun.tools.javac.util.Name;
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 @@ public class JavacElements implements Elements {
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 @@ public class JavacElements implements Elements {
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 @@ public class JavacElements implements Elements {
@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 @@ public class JavacElements implements Elements {
@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;
}

View File

@ -1363,15 +1363,15 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
// 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;
}

View File

@ -203,8 +203,8 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite
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);

View File

@ -125,8 +125,8 @@ public class PackageWriterImpl extends HtmlDocletWriter
}
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);

View File

@ -349,7 +349,12 @@ public class Utils {
}
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 @@ public class Utils {
if (loc != null)
return loc;
return defaultLocation();
}
private Location defaultLocation() {
JavaFileManager fm = configuration.docEnv.getJavaFileManager();
return fm.hasLocation(StandardLocation.SOURCE_PATH)
? StandardLocation.SOURCE_PATH

View File

@ -620,7 +620,8 @@ public class ElementsTable {
// 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 @@ public class ElementsTable {
// 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);

View File

@ -20,11 +20,11 @@ Finished TaskEvent[ENTER,T6403466.java,null]
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]

View File

@ -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.Map;
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 @@ public class AnnotationProcessing extends ModuleTestBase {
}
}
@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 @@ public class AnnotationProcessing extends ModuleTestBase {
return file;
}
private static void fail(String msg) {
throw new AssertionError(msg);
}
}