--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue Mar 15 13:48:30 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Mar 17 19:04:28 2016 +0000
@@ -27,8 +27,10 @@
import java.io.Closeable;
import java.io.File;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Path;
@@ -42,6 +44,7 @@
import javax.lang.model.util.*;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardJavaFileManager;
import static javax.tools.StandardLocation.*;
@@ -49,6 +52,7 @@
import com.sun.source.util.TaskEvent;
import com.sun.tools.javac.api.MultiTaskListener;
import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.code.Types;
@@ -56,12 +60,14 @@
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.platform.PlatformDescription;
import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.Abort;
@@ -77,10 +83,10 @@
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.MatchingUtils;
+import com.sun.tools.javac.util.ModuleHelper;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Options;
-import com.sun.tools.javac.util.ServiceLoader;
import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
import static com.sun.tools.javac.code.Kinds.Kind.*;
@@ -112,8 +118,10 @@
private final JavacMessager messager;
private final JavacElements elementUtils;
private final JavacTypes typeUtils;
+ private final JavaCompiler compiler;
+ private final Modules modules;
+ private final ModuleHelper moduleHelper;
private final Types types;
- private final JavaCompiler compiler;
/**
* Holds relevant state history of which processors have been
@@ -154,7 +162,10 @@
Source source;
private ClassLoader processorClassLoader;
- private SecurityException processorClassLoaderException;
+ private ServiceLoader<Processor> serviceLoader;
+ private SecurityException processorLoaderException;
+
+ private final JavaFileManager fileManager;
/**
* JavacMessages object used for localization
@@ -167,6 +178,7 @@
private final Enter enter;
private final Completer initialCompleter;
private final Check chk;
+ private final ModuleSymbol defaultModule;
private final Context context;
@@ -196,6 +208,7 @@
fatalErrors = options.isSet("fatalEnterError");
showResolveErrors = options.isSet("showResolveErrors");
werror = options.isSet(WERROR);
+ fileManager = context.get(JavaFileManager.class);
platformAnnotations = initPlatformAnnotations();
// Initialize services before any processors are initialized
@@ -204,6 +217,7 @@
messager = new JavacMessager(context, this);
elementUtils = JavacElements.instance(context);
typeUtils = JavacTypes.instance(context);
+ modules = Modules.instance(context);
types = Types.instance(context);
processorOptions = initProcessorOptions();
unmatchedProcessorOptions = initUnmatchedProcessorOptions();
@@ -214,7 +228,11 @@
enter = Enter.instance(context);
initialCompleter = ClassFinder.instance(context).getCompleter();
chk = Check.instance(context);
- initProcessorClassLoader();
+ moduleHelper = ModuleHelper.instance(context);
+ initProcessorLoader();
+
+ defaultModule = source.allowModules() && options.isUnset("noModules")
+ ? symtab.unnamedModule : symtab.noModule;
}
public void setProcessors(Iterable<? extends Processor> processors) {
@@ -234,19 +252,28 @@
return Collections.unmodifiableSet(platformAnnotations);
}
- private void initProcessorClassLoader() {
- JavaFileManager fileManager = context.get(JavaFileManager.class);
+ private void initProcessorLoader() {
try {
- // If processorpath is not explicitly set, use the classpath.
- processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
- ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
- : fileManager.getClassLoader(CLASS_PATH);
+ if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+ try {
+ serviceLoader = fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, Processor.class);
+ } catch (IOException e) {
+ throw new Abort(e);
+ }
+ } else {
+ // If processorpath is not explicitly set, use the classpath.
+ processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
+ ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
+ : fileManager.getClassLoader(CLASS_PATH);
- if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
- compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
+ moduleHelper.addExports(processorClassLoader);
+
+ if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
+ compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
+ }
}
} catch (SecurityException e) {
- processorClassLoaderException = e;
+ processorLoaderException = e;
}
}
@@ -266,14 +293,18 @@
} else if (processors != null) {
processorIterator = processors.iterator();
} else {
- String processorNames = options.get(PROCESSOR);
- if (processorClassLoaderException == null) {
+ if (processorLoaderException == null) {
/*
* If the "-processor" option is used, search the appropriate
* path for the named class. Otherwise, use a service
* provider mechanism to create the processor iterator.
*/
- if (processorNames != null) {
+ String processorNames = options.get(PROCESSOR);
+ if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+ processorIterator = (processorNames == null) ?
+ new ServiceIterator(serviceLoader, log) :
+ new NameServiceIterator(serviceLoader, log, processorNames);
+ } else if (processorNames != null) {
processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
} else {
processorIterator = new ServiceIterator(processorClassLoader, log);
@@ -286,7 +317,7 @@
* in service configuration file.) Otherwise, we cannot continue.
*/
processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
- processorClassLoaderException);
+ processorLoaderException);
}
}
PlatformDescription platformProvider = context.get(PlatformDescription.class);
@@ -304,6 +335,18 @@
discoveredProcs = new DiscoveredProcessors(compoundIterator);
}
+ public <S> ServiceLoader<S> getServiceLoader(Class<S> service) {
+ if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
+ try {
+ return fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, service);
+ } catch (IOException e) {
+ throw new Abort(e);
+ }
+ } else {
+ return ServiceLoader.load(service, getProcessorClassLoader());
+ }
+ }
+
/**
* Returns an empty processor iterator if no processors are on the
* relevant path, otherwise if processors are present, logs an
@@ -316,8 +359,6 @@
* @param e If non-null, pass this exception to Abort
*/
private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
- JavaFileManager fileManager = context.get(JavaFileManager.class);
-
if (fileManager instanceof JavacFileManager) {
StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
Iterable<? extends Path> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
@@ -355,9 +396,9 @@
* needed but unavailable.
*/
private class ServiceIterator implements Iterator<Processor> {
- private Iterator<Processor> iterator;
- private Log log;
- private ServiceLoader<Processor> loader;
+ Iterator<Processor> iterator;
+ Log log;
+ ServiceLoader<Processor> loader;
ServiceIterator(ClassLoader classLoader, Log log) {
this.log = log;
@@ -375,9 +416,16 @@
}
}
+ ServiceIterator(ServiceLoader<Processor> loader, Log log) {
+ this.log = log;
+ this.loader = loader;
+ this.iterator = loader.iterator();
+ }
+
+ @Override
public boolean hasNext() {
try {
- return iterator.hasNext();
+ return internalHasNext();
} catch(ServiceConfigurationError sce) {
log.error("proc.bad.config.file", sce.getLocalizedMessage());
throw new Abort(sce);
@@ -386,9 +434,14 @@
}
}
+ boolean internalHasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
public Processor next() {
try {
- return iterator.next();
+ return internalNext();
} catch (ServiceConfigurationError sce) {
log.error("proc.bad.config.file", sce.getLocalizedMessage());
throw new Abort(sce);
@@ -397,6 +450,11 @@
}
}
+ Processor internalNext() {
+ return iterator.next();
+ }
+
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -412,6 +470,58 @@
}
}
+ private class NameServiceIterator extends ServiceIterator {
+ private Map<String, Processor> namedProcessorsMap = new HashMap<>();;
+ private Iterator<String> processorNames = null;
+ private Processor nextProc = null;
+
+ public NameServiceIterator(ServiceLoader<Processor> loader, Log log, String theNames) {
+ super(loader, log);
+ this.processorNames = Arrays.asList(theNames.split(",")).iterator();
+ }
+
+ @Override
+ boolean internalHasNext() {
+ if (nextProc != null) {
+ return true;
+ }
+ if (!processorNames.hasNext()) {
+ namedProcessorsMap = null;
+ return false;
+ }
+ String processorName = processorNames.next();
+ Processor theProcessor = namedProcessorsMap.get(processorName);
+ if (theProcessor != null) {
+ namedProcessorsMap.remove(processorName);
+ nextProc = theProcessor;
+ return true;
+ } else {
+ while (iterator.hasNext()) {
+ theProcessor = iterator.next();
+ String name = theProcessor.getClass().getName();
+ if (name.equals(processorName)) {
+ nextProc = theProcessor;
+ return true;
+ } else {
+ namedProcessorsMap.put(name, theProcessor);
+ }
+ }
+ log.error(Errors.ProcProcessorNotFound(processorName));
+ return false;
+ }
+ }
+
+ @Override
+ Processor internalNext() {
+ if (hasNext()) {
+ Processor p = nextProc;
+ nextProc = null;
+ return p;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+ }
private static class NameProcessIterator implements Iterator<Processor> {
Processor nextProc = null;
@@ -437,8 +547,10 @@
Processor processor;
try {
try {
+ Class<?> processorClass = processorCL.loadClass(processorName);
+ ensureReadable(processorClass);
processor =
- (Processor) (processorCL.loadClass(processorName).newInstance());
+ (Processor) (processorClass.newInstance());
} catch (ClassNotFoundException cnfe) {
log.error("proc.processor.not.found", processorName);
return false;
@@ -473,6 +585,26 @@
public void remove () {
throw new UnsupportedOperationException();
}
+
+ /**
+ * Ensures that the module of the given class is readable to this
+ * module.
+ */
+ private void ensureReadable(Class<?> targetClass) {
+ try {
+ Method getModuleMethod = Class.class.getMethod("getModule");
+ Object thisModule = getModuleMethod.invoke(this.getClass());
+ Object targetModule = getModuleMethod.invoke(targetClass);
+
+ Class<?> moduleClass = getModuleMethod.getReturnType();
+ Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
+ addReadsMethod.invoke(thisModule, targetModule);
+ } catch (NoSuchMethodException e) {
+ // ignore
+ } catch (Exception e) {
+ throw new InternalError(e);
+ }
+ }
}
public boolean atLeastOneProcessor() {
@@ -605,7 +737,7 @@
// TODO: These two classes can probably be rewritten better...
/**
* This class holds information about the processors that have
- * been discoverd so far as well as the means to discover more, if
+ * been discovered so far as well as the means to discover more, if
* necessary. A single iterator should be used per round of
* annotation processing. The iterator first visits already
* discovered processors then fails over to the service provider
@@ -1000,21 +1132,24 @@
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(packageName);
+ PackageSymbol p = symtab.enterPackage(defaultModule, packageName);
if (p.package_info == null)
- p.package_info = symtab.enterClass(Convert.shortName(name), p);
+ p.package_info = symtab.enterClass(defaultModule, Convert.shortName(name), p);
cs = p.package_info;
cs.reset();
if (cs.classfile == null)
cs.classfile = file;
cs.completer = initialCompleter;
} else {
- cs = symtab.enterClass(name);
+ 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
}
list = list.prepend(cs);
}
@@ -1023,7 +1158,7 @@
/** Enter a set of syntax trees. */
private void enterTrees(List<JCCompilationUnit> roots) {
- compiler.enterTrees(roots);
+ compiler.enterTrees(compiler.initModules(roots));
}
/** Run a processing round. */
@@ -1099,11 +1234,12 @@
filer.newRound();
messager.newRound();
compiler.newRound();
+ modules.newRound();
types.newRound();
boolean foundError = false;
- for (ClassSymbol cs : symtab.classes.values()) {
+ for (ClassSymbol cs : symtab.getAllClasses()) {
if (cs.kind == ERR) {
foundError = true;
break;
@@ -1111,7 +1247,7 @@
}
if (foundError) {
- for (ClassSymbol cs : symtab.classes.values()) {
+ for (ClassSymbol cs : symtab.getAllClasses()) {
if (cs.classfile != null || cs.kind == ERR) {
cs.reset();
cs.type = new ClassType(cs.type.getEnclosingType(), null, cs);
@@ -1350,6 +1486,13 @@
}
node.packge.reset();
}
+ boolean isModuleInfo = node.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
+ if (isModuleInfo) {
+ node.modle.reset();
+ node.modle.completer = sym -> modules.enter(List.of(node), node.modle.module_info);
+ node.modle.module_info.reset();
+ node.modle.module_info.members_field = WriteableScope.create(node.modle.module_info);
+ }
node.packge = null;
topLevel = node;
try {