--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Mar 15 13:48:30 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Mar 17 19:04:28 2016 +0000
@@ -39,6 +39,7 @@
import javax.annotation.processing.Processor;
import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ElementVisitor;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
@@ -67,12 +68,20 @@
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.JCDiagnostic.Factory;
import com.sun.tools.javac.util.Log.WriterKind;
import static com.sun.tools.javac.code.Kinds.Kind.*;
+
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
+
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.main.Option.*;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
+
import static javax.tools.StandardLocation.CLASS_OUTPUT;
/** This class could be the main entry point for GJC when GJC is used as a
@@ -276,6 +285,18 @@
*/
protected Flow flow;
+ /** The modules visitor
+ */
+ protected Modules modules;
+
+ /** The module finder
+ */
+ protected ModuleFinder moduleFinder;
+
+ /** The diagnostics factory
+ */
+ protected JCDiagnostic.Factory diags;
+
/** The type eraser.
*/
protected TransTypes transTypes;
@@ -336,6 +357,8 @@
**/
protected boolean implicitSourceFilesRead;
+ protected boolean enterDone;
+
protected CompileStates compileStates;
/** Construct a new compiler using a shared context.
@@ -382,6 +405,9 @@
annotate = Annotate.instance(context);
types = Types.instance(context);
taskListener = MultiTaskListener.instance(context);
+ modules = Modules.instance(context);
+ moduleFinder = ModuleFinder.instance(context);
+ diags = Factory.instance(context);
finder.sourceCompleter = sourceCompleter;
@@ -430,6 +456,18 @@
if (platformProvider != null)
closeables = closeables.prepend(platformProvider);
+
+ silentFail = new Symbol(ABSENT_TYP, 0, names.empty, Type.noType, syms.rootPackage) {
+ @DefinedBy(Api.LANGUAGE_MODEL)
+ public <R, P> R accept(ElementVisitor<R, P> v, P p) {
+ return v.visitUnknown(this, p);
+ }
+ @Override
+ public boolean exists() {
+ return false;
+ }
+ };
+
}
/* Switches:
@@ -512,6 +550,11 @@
*/
protected Set<JavaFileObject> inputFiles = new HashSet<>();
+ /** Used by the resolveBinaryNameOrIdent to say that the given type cannot be found, and that
+ * an error has already been produced about that.
+ */
+ private final Symbol silentFail;
+
protected boolean shouldStop(CompileState cs) {
CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
? shouldStopPolicyIfError
@@ -625,18 +668,44 @@
* @param name The name to resolve
*/
public Symbol resolveBinaryNameOrIdent(String name) {
+ ModuleSymbol msym;
+ String typeName;
+ int sep = name.indexOf('/');
+ if (sep == -1) {
+ msym = modules.getDefaultModule();
+ typeName = name;
+ } else if (source.allowModules() && !options.isSet("noModules")) {
+ Name modName = names.fromString(name.substring(0, sep));
+
+ msym = moduleFinder.findModule(modName);
+ typeName = name.substring(sep + 1);
+ } else {
+ log.error(Errors.InvalidModuleSpecifier(name));
+ return silentFail;
+ }
+
+ return resolveBinaryNameOrIdent(msym, typeName);
+ }
+
+ /** Resolve an identifier which may be the binary name of a class or
+ * the Java name of a class or package.
+ * @param msym The module in which the search should be performed
+ * @param name The name to resolve
+ */
+ public Symbol resolveBinaryNameOrIdent(ModuleSymbol msym, String name) {
try {
Name flatname = names.fromString(name.replace("/", "."));
- return finder.loadClass(flatname);
+ return finder.loadClass(msym, flatname);
} catch (CompletionFailure ignore) {
- return resolveIdent(name);
+ return resolveIdent(msym, name);
}
}
/** Resolve an identifier.
+ * @param msym The module in which the search should be performed
* @param name The identifier to resolve
*/
- public Symbol resolveIdent(String name) {
+ public Symbol resolveIdent(ModuleSymbol msym, String name) {
if (name.equals(""))
return syms.errSymbol;
JavaFileObject prev = log.useSource(null);
@@ -650,7 +719,8 @@
}
JCCompilationUnit toplevel =
make.TopLevel(List.<JCTree>nil());
- toplevel.packge = syms.unnamedPackage;
+ toplevel.modle = msym;
+ toplevel.packge = msym.unnamedPackage;
return attr.attribIdent(tree, toplevel);
} finally {
log.useSource(prev);
@@ -737,6 +807,16 @@
taskListener.started(e);
}
+ // Process module declarations.
+ // If module resolution fails, ignore trees, and if trying to
+ // complete a specific symbol, throw CompletionFailure.
+ // Note that if module resolution failed, we may not even
+ // have enough modules available to access java.lang, and
+ // so risk getting FatalError("no.java.lang") from MemberEnter.
+ if (!modules.enter(List.of(tree), c)) {
+ throw new CompletionFailure(c, diags.fragment("cant.resolve.modules"));
+ }
+
enter.complete(List.of(tree), c);
if (!taskListener.isEmpty()) {
@@ -748,7 +828,16 @@
boolean isPkgInfo =
tree.sourcefile.isNameCompatible("package-info",
JavaFileObject.Kind.SOURCE);
- if (isPkgInfo) {
+ boolean isModuleInfo =
+ tree.sourcefile.isNameCompatible("module-info",
+ JavaFileObject.Kind.SOURCE);
+ if (isModuleInfo) {
+ if (enter.getEnv(tree.modle) == null) {
+ JCDiagnostic diag =
+ diagFactory.fragment("file.does.not.contain.module");
+ throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
+ }
+ } else if (isPkgInfo) {
if (enter.getEnv(tree.packge) == null) {
JCDiagnostic diag =
diagFactory.fragment("file.does.not.contain.package",
@@ -812,8 +901,12 @@
// These method calls must be chained to avoid memory leaks
processAnnotations(
- enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))),
- classnames);
+ enterTrees(
+ stopIfError(CompileState.PARSE,
+ initModules(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))))
+ ),
+ classnames
+ );
// If it's safe to do so, skip attr / flow / gen for implicit classes
if (taskListener.isEmpty() &&
@@ -912,7 +1005,20 @@
public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) {
if (shouldStop(CompileState.ATTR))
return List.nil();
- return enterTrees(roots);
+ return enterTrees(initModules(roots));
+ }
+
+ public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
+ List<JCCompilationUnit> result = initModules(roots, null);
+ if (roots.isEmpty()) {
+ enterDone = true;
+ }
+ return result;
+ }
+
+ List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots, ClassSymbol c) {
+ modules.enter(roots, c);
+ return roots;
}
/**
@@ -931,6 +1037,8 @@
enter.main(roots);
+ enterDone = true;
+
if (!taskListener.isEmpty()) {
for (JCCompilationUnit unit: roots) {
TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, unit);
@@ -1085,7 +1193,8 @@
if (sym == null ||
(sym.kind == PCK && !processPcks) ||
sym.kind == ABSENT_TYP) {
- log.error("proc.cant.find.class", nameStr);
+ if (sym != silentFail)
+ log.error(Errors.ProcCantFindClass(nameStr));
errors = true;
continue;
}
@@ -1100,10 +1209,10 @@
continue;
}
Assert.check(sym.kind == PCK);
- log.warning("proc.package.does.not.exist", nameStr);
+ log.warning(Warnings.ProcPackageDoesNotExist(nameStr));
pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
} catch (CompletionFailure e) {
- log.error("proc.cant.find.class", nameStr);
+ log.error(Errors.ProcCantFindClass(nameStr));
errors = true;
continue;
}
@@ -1154,6 +1263,7 @@
return
options.isSet(PROCESSOR) ||
options.isSet(PROCESSORPATH) ||
+ options.isSet(PROCESSORMODULEPATH) ||
options.isSet(PROC, "only") ||
options.isSet(XPRINT);
}
@@ -1388,14 +1498,14 @@
make.at(Position.FIRSTPOS);
TreeMaker localMake = make.forToplevel(env.toplevel);
- if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) {
+ if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF) || env.tree.hasTag(JCTree.Tag.MODULEDEF)) {
if (!(sourceOutput)) {
if (shouldStop(CompileState.LOWER))
- return;
- List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake);
- if (pdef.head != null) {
- Assert.check(pdef.tail.isEmpty());
- results.add(new Pair<>(env, (JCClassDecl)pdef.head));
+ return;
+ List<JCTree> def = lower.translateTopLevelClass(env, env.tree, localMake);
+ if (def.head != null) {
+ Assert.check(def.tail.isEmpty());
+ results.add(new Pair<>(env, (JCClassDecl)def.head));
}
}
return;
@@ -1589,6 +1699,10 @@
}
}
+ public boolean isEnterDone() {
+ return enterDone;
+ }
+
/** Close the compiler, flushing the logs
*/
public void close() {