8152911: javac assertion error when compiling overlay sources
Avoid creating ModuleSymbols with unspecified name, to avoid conflicts with predefined ModuleSymbol for the java.base module. Reviewed-by: jjg
This commit is contained in:
parent
16bf17a9a7
commit
c58a8aae3e
@ -31,6 +31,7 @@ import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
@ -38,10 +39,14 @@ import javax.tools.JavaFileObject;
|
||||
import javax.tools.JavaFileObject.Kind;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol.Completer;
|
||||
import com.sun.tools.javac.code.Symbol.CompletionFailure;
|
||||
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||
import com.sun.tools.javac.jvm.ModuleNameReader;
|
||||
import com.sun.tools.javac.jvm.ModuleNameReader.BadClassFile;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.JCDiagnostic;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.Fragment;
|
||||
@ -50,7 +55,6 @@ import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Log;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
import com.sun.tools.javac.util.Names;
|
||||
import com.sun.tools.javac.util.StringUtils;
|
||||
|
||||
import static com.sun.tools.javac.code.Kinds.Kind.*;
|
||||
|
||||
@ -84,6 +88,10 @@ public class ModuleFinder {
|
||||
|
||||
private final JCDiagnostic.Factory diags;
|
||||
|
||||
private ModuleNameReader moduleNameReader;
|
||||
|
||||
public ModuleInfoSourceFileCompleter sourceFileCompleter;
|
||||
|
||||
/** Get the ModuleFinder instance for this invocation. */
|
||||
public static ModuleFinder instance(Context context) {
|
||||
ModuleFinder instance = context.get(moduleFinderKey);
|
||||
@ -182,6 +190,8 @@ public class ModuleFinder {
|
||||
return list;
|
||||
}
|
||||
|
||||
private boolean inFindSingleModule;
|
||||
|
||||
public ModuleSymbol findSingleModule() {
|
||||
try {
|
||||
JavaFileObject src_fo = getModuleInfoFromLocation(StandardLocation.SOURCE_PATH, Kind.SOURCE);
|
||||
@ -194,26 +204,41 @@ public class ModuleFinder {
|
||||
if (fo == null) {
|
||||
msym = syms.unnamedModule;
|
||||
} else {
|
||||
// Note: the following may trigger a re-entrant call to Modules.enter
|
||||
// msym = new ModuleSymbol();
|
||||
// ClassSymbol info = new ClassSymbol(Flags.MODULE, names.module_info, msym);
|
||||
// info.modle = msym;
|
||||
// info.classfile = fo;
|
||||
// info.members_field = WriteableScope.create(info);
|
||||
// msym.module_info = info;
|
||||
msym = ModuleSymbol.create(null, names.module_info);
|
||||
msym.module_info.classfile = fo;
|
||||
msym.completer = sym -> classFinder.fillIn(msym.module_info);
|
||||
// // TODO: should we do the following here, or as soon as we find the name in
|
||||
// // the source or class file?
|
||||
// // Consider the case when the class/source path module shadows one on the
|
||||
// // module source path
|
||||
// if (syms.modules.get(msym.name) != null) {
|
||||
// // error: module already defined
|
||||
// System.err.println("ERROR: module already defined: " + msym);
|
||||
// } else {
|
||||
// syms.modules.put(msym.name, msym);
|
||||
// }
|
||||
switch (fo.getKind()) {
|
||||
case SOURCE:
|
||||
if (!inFindSingleModule) {
|
||||
try {
|
||||
inFindSingleModule = true;
|
||||
// Note: the following will trigger a re-entrant call to Modules.enter
|
||||
msym = sourceFileCompleter.complete(fo);
|
||||
msym.module_info.classfile = fo;
|
||||
} finally {
|
||||
inFindSingleModule = false;
|
||||
}
|
||||
} else {
|
||||
//the module-info.java does not contain a module declaration,
|
||||
//avoid infinite recursion:
|
||||
msym = syms.unnamedModule;
|
||||
}
|
||||
break;
|
||||
case CLASS:
|
||||
Name name;
|
||||
try {
|
||||
name = names.fromString(readModuleName(fo));
|
||||
} catch (BadClassFile | IOException ex) {
|
||||
//fillIn will report proper errors:
|
||||
name = names.error;
|
||||
}
|
||||
msym = syms.enterModule(name);
|
||||
msym.module_info.classfile = fo;
|
||||
msym.completer = Completer.NULL_COMPLETER;
|
||||
classFinder.fillIn(msym.module_info);
|
||||
break;
|
||||
default:
|
||||
Assert.error();
|
||||
msym = syms.unnamedModule;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msym.classLocation = StandardLocation.CLASS_OUTPUT;
|
||||
@ -224,6 +249,12 @@ public class ModuleFinder {
|
||||
}
|
||||
}
|
||||
|
||||
private String readModuleName(JavaFileObject jfo) throws IOException, ModuleNameReader.BadClassFile {
|
||||
if (moduleNameReader == null)
|
||||
moduleNameReader = new ModuleNameReader();
|
||||
return moduleNameReader.readModuleName(jfo);
|
||||
}
|
||||
|
||||
private JavaFileObject getModuleInfoFromLocation(Location location, Kind kind) throws IOException {
|
||||
if (!fileManager.hasLocation(location))
|
||||
return null;
|
||||
@ -332,4 +363,8 @@ public class ModuleFinder {
|
||||
}
|
||||
}
|
||||
|
||||
public interface ModuleInfoSourceFileCompleter {
|
||||
public ModuleSymbol complete(JavaFileObject file);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -916,7 +916,6 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
||||
|
||||
/**
|
||||
* Create a ModuleSymbol with an associated module-info ClassSymbol.
|
||||
* The name of the module may be null, if it is not known yet.
|
||||
*/
|
||||
public static ModuleSymbol create(Name name, Name module_info) {
|
||||
ModuleSymbol msym = new ModuleSymbol(name, null);
|
||||
@ -930,6 +929,7 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
||||
|
||||
public ModuleSymbol(Name name, Symbol owner) {
|
||||
super(MDL, 0, name, null, owner);
|
||||
Assert.checkNonNull(name);
|
||||
this.type = new ModuleType(this);
|
||||
}
|
||||
|
||||
|
@ -764,17 +764,6 @@ public class Symtab {
|
||||
return msym;
|
||||
}
|
||||
|
||||
public void enterModule(ModuleSymbol msym, Name name) {
|
||||
Assert.checkNull(modules.get(name));
|
||||
Assert.checkNull(msym.name);
|
||||
msym.name = name;
|
||||
addRootPackageFor(msym);
|
||||
ClassSymbol info = msym.module_info;
|
||||
info.fullname = msym.name.append('.', names.module_info);
|
||||
info.flatname = info.fullname;
|
||||
modules.put(name, msym);
|
||||
}
|
||||
|
||||
public ModuleSymbol getModule(Name name) {
|
||||
return modules.get(name);
|
||||
}
|
||||
|
@ -292,15 +292,12 @@ public class Modules extends JCTree.Visitor {
|
||||
Name name = TreeInfo.fullName(decl.qualId);
|
||||
ModuleSymbol sym;
|
||||
if (c != null) {
|
||||
sym = (ModuleSymbol) c.owner;
|
||||
if (sym.name == null) {
|
||||
//ModuleFinder.findSingleModule creates a stub of a ModuleSymbol without a name,
|
||||
//fill the name here after the module-info.java has been parsed
|
||||
//also enter the ModuleSymbol among modules:
|
||||
syms.enterModule(sym, name);
|
||||
} else {
|
||||
// TODO: validate name
|
||||
}
|
||||
sym = (ModuleSymbol) c.owner;
|
||||
Assert.checkNonNull(sym.name);
|
||||
Name treeName = TreeInfo.fullName(decl.qualId);
|
||||
if (sym.name != treeName) {
|
||||
log.error(decl.pos(), Errors.ModuleNameMismatch(name, sym.name));
|
||||
}
|
||||
} else {
|
||||
sym = syms.enterModule(name);
|
||||
if (sym.module_info.sourcefile != null && sym.module_info.sourcefile != toplevel.sourcefile) {
|
||||
@ -1006,6 +1003,10 @@ public class Modules extends JCTree.Visitor {
|
||||
return new Symbol.Completer() {
|
||||
@Override
|
||||
public void complete(Symbol sym) throws CompletionFailure {
|
||||
if (inInitModules) {
|
||||
sym.completer = this;
|
||||
return ;
|
||||
}
|
||||
ModuleSymbol msym = (ModuleSymbol) sym;
|
||||
Set<ModuleSymbol> allModules = allModules();
|
||||
for (ModuleSymbol m : allModules) {
|
||||
|
@ -80,6 +80,7 @@ import com.sun.tools.javac.util.DefinedBy;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Log;
|
||||
import com.sun.tools.javac.jvm.ModuleNameReader;
|
||||
import com.sun.tools.javac.util.Pair;
|
||||
import com.sun.tools.javac.util.StringUtils;
|
||||
|
||||
|
@ -2396,12 +2396,15 @@ public class ClassReader {
|
||||
} else {
|
||||
c.flags_field = flags;
|
||||
Name modInfoName = readModuleInfoName(nextChar());
|
||||
if (c.owner.name == null) {
|
||||
syms.enterModule((ModuleSymbol) c.owner, Convert.packagePart(modInfoName));
|
||||
} else {
|
||||
// TODO: validate name
|
||||
}
|
||||
currentModule = (ModuleSymbol) c.owner;
|
||||
if (currentModule.name.append('.', names.module_info) != modInfoName) {
|
||||
//strip trailing .module-info, if exists:
|
||||
int modInfoStart = modInfoName.length() - names.module_info.length();
|
||||
modInfoName = modInfoName.subName(modInfoStart, modInfoName.length()) == names.module_info &&
|
||||
modInfoName.charAt(modInfoStart - 1) == '.' ?
|
||||
modInfoName.subName(0, modInfoStart - 1) : modInfoName;
|
||||
throw badClassFile("module.name.mismatch", modInfoName, currentModule.name);
|
||||
}
|
||||
}
|
||||
|
||||
// class attributes must be read before class
|
||||
|
@ -22,13 +22,15 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.tools.javac.file;
|
||||
package com.sun.tools.javac.jvm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.jvm.ClassFile;
|
||||
|
||||
import static com.sun.tools.javac.jvm.ClassFile.*;
|
||||
@ -44,7 +46,7 @@ import static com.sun.tools.javac.jvm.ClassFile.*;
|
||||
* notice.</b>
|
||||
*/
|
||||
public class ModuleNameReader {
|
||||
static class BadClassFile extends Exception {
|
||||
public static class BadClassFile extends Exception {
|
||||
private static final long serialVersionUID = 0;
|
||||
BadClassFile(String msg) {
|
||||
super(msg);
|
||||
@ -61,37 +63,43 @@ public class ModuleNameReader {
|
||||
*/
|
||||
private int bp;
|
||||
|
||||
/** The objects of the constant pool.
|
||||
*/
|
||||
private Object[] poolObj;
|
||||
|
||||
/** For every constant pool entry, an index into buf where the
|
||||
* defining section of the entry is found.
|
||||
*/
|
||||
private int[] poolIdx;
|
||||
|
||||
ModuleNameReader() {
|
||||
public ModuleNameReader() {
|
||||
}
|
||||
|
||||
String readModuleName(Path p) throws IOException, BadClassFile {
|
||||
public String readModuleName(Path p) throws IOException, BadClassFile {
|
||||
try (InputStream in = Files.newInputStream(p)) {
|
||||
bp = 0;
|
||||
buf = readInputStream(buf, in);
|
||||
|
||||
int magic = nextInt();
|
||||
if (magic != JAVA_MAGIC)
|
||||
throw new BadClassFile("illegal.start.of.class.file");
|
||||
|
||||
int minorVersion = nextChar();
|
||||
int majorVersion = nextChar();
|
||||
|
||||
indexPool();
|
||||
|
||||
int accessflags = nextChar();
|
||||
return readModuleInfoName(nextChar());
|
||||
return readModuleName(in);
|
||||
}
|
||||
}
|
||||
|
||||
public String readModuleName(JavaFileObject jfo) throws IOException, BadClassFile {
|
||||
try (InputStream in = jfo.openInputStream()) {
|
||||
return readModuleName(in);
|
||||
}
|
||||
}
|
||||
|
||||
public String readModuleName(InputStream in) throws IOException, BadClassFile {
|
||||
bp = 0;
|
||||
buf = readInputStream(buf, in);
|
||||
|
||||
int magic = nextInt();
|
||||
if (magic != JAVA_MAGIC)
|
||||
throw new BadClassFile("illegal.start.of.class.file");
|
||||
|
||||
int minorVersion = nextChar();
|
||||
int majorVersion = nextChar();
|
||||
|
||||
indexPool();
|
||||
|
||||
int accessflags = nextChar();
|
||||
return readModuleInfoName(nextChar());
|
||||
}
|
||||
|
||||
/** Extract a character at position bp from buf.
|
||||
*/
|
||||
char getChar(int bp) {
|
||||
@ -120,7 +128,6 @@ public class ModuleNameReader {
|
||||
*/
|
||||
void indexPool() throws BadClassFile {
|
||||
poolIdx = new int[nextChar()];
|
||||
poolObj = new Object[poolIdx.length];
|
||||
int i = 1;
|
||||
while (i < poolIdx.length) {
|
||||
poolIdx[i++] = bp;
|
@ -37,6 +37,7 @@ import java.util.MissingResourceException;
|
||||
import java.util.Queue;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.annotation.processing.Processor;
|
||||
import javax.lang.model.SourceVersion;
|
||||
@ -67,7 +68,9 @@ import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCLambda;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMemberReference;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.Tag;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.Factory;
|
||||
@ -341,6 +344,13 @@ public class JavaCompiler {
|
||||
}
|
||||
};
|
||||
|
||||
protected final ModuleFinder.ModuleInfoSourceFileCompleter moduleInfoSourceFileCompleter =
|
||||
fo -> (ModuleSymbol) readSourceFile(parseImplicitFile(fo), null, tl -> {
|
||||
return tl.defs.nonEmpty() && tl.defs.head.hasTag(Tag.MODULEDEF) ?
|
||||
((JCModuleDecl) tl.defs.head).sym.module_info :
|
||||
syms.defineClass(names.module_info, syms.errModule);
|
||||
}).owner;
|
||||
|
||||
/**
|
||||
* Command line options.
|
||||
*/
|
||||
@ -411,6 +421,7 @@ public class JavaCompiler {
|
||||
diags = Factory.instance(context);
|
||||
|
||||
finder.sourceCompleter = sourceCompleter;
|
||||
moduleFinder.sourceFileCompleter = moduleInfoSourceFileCompleter;
|
||||
|
||||
options = Options.instance(context);
|
||||
|
||||
@ -779,6 +790,19 @@ public class JavaCompiler {
|
||||
readSourceFile(null, c);
|
||||
}
|
||||
|
||||
private JCTree.JCCompilationUnit parseImplicitFile(JavaFileObject filename) {
|
||||
JavaFileObject prev = log.useSource(filename);
|
||||
try {
|
||||
JCTree.JCCompilationUnit t = parse(filename, filename.getCharContent(false));
|
||||
return t;
|
||||
} catch (IOException e) {
|
||||
log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
|
||||
return make.TopLevel(List.<JCTree>nil());
|
||||
} finally {
|
||||
log.useSource(prev);
|
||||
}
|
||||
}
|
||||
|
||||
/** Compile a ClassSymbol from source, optionally using the given compilation unit as
|
||||
* the source tree.
|
||||
* @param tree the compilation unit in which the given ClassSymbol resides,
|
||||
@ -789,20 +813,20 @@ public class JavaCompiler {
|
||||
if (completionFailureName == c.fullname) {
|
||||
throw new CompletionFailure(c, "user-selected completion failure by class name");
|
||||
}
|
||||
JavaFileObject filename = c.classfile;
|
||||
JavaFileObject prev = log.useSource(filename);
|
||||
|
||||
if (tree == null) {
|
||||
try {
|
||||
tree = parse(filename, filename.getCharContent(false));
|
||||
} catch (IOException e) {
|
||||
log.error("error.reading.file", filename, JavacFileManager.getMessage(e));
|
||||
tree = make.TopLevel(List.<JCTree>nil());
|
||||
} finally {
|
||||
log.useSource(prev);
|
||||
}
|
||||
tree = parseImplicitFile(c.classfile);
|
||||
}
|
||||
|
||||
readSourceFile(tree, c, cut -> c);
|
||||
}
|
||||
|
||||
private ClassSymbol readSourceFile(JCCompilationUnit tree,
|
||||
ClassSymbol expectedSymbol,
|
||||
Function<JCCompilationUnit, ClassSymbol> symbolGetter)
|
||||
throws CompletionFailure {
|
||||
Assert.checkNonNull(tree);
|
||||
|
||||
if (!taskListener.isEmpty()) {
|
||||
TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
|
||||
taskListener.started(e);
|
||||
@ -814,18 +838,20 @@ public class JavaCompiler {
|
||||
// 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"));
|
||||
if (!modules.enter(List.of(tree), expectedSymbol)) {
|
||||
throw new CompletionFailure(symbolGetter.apply(tree),
|
||||
diags.fragment("cant.resolve.modules"));
|
||||
}
|
||||
|
||||
enter.complete(List.of(tree), c);
|
||||
enter.complete(List.of(tree), expectedSymbol);
|
||||
|
||||
if (!taskListener.isEmpty()) {
|
||||
TaskEvent e = new TaskEvent(TaskEvent.Kind.ENTER, tree);
|
||||
taskListener.finished(e);
|
||||
}
|
||||
|
||||
if (enter.getEnv(c) == null) {
|
||||
ClassSymbol sym = symbolGetter.apply(tree);
|
||||
if (sym == null || enter.getEnv(sym) == null) {
|
||||
boolean isPkgInfo =
|
||||
tree.sourcefile.isNameCompatible("package-info",
|
||||
JavaFileObject.Kind.SOURCE);
|
||||
@ -836,24 +862,26 @@ public class JavaCompiler {
|
||||
if (enter.getEnv(tree.modle) == null) {
|
||||
JCDiagnostic diag =
|
||||
diagFactory.fragment("file.does.not.contain.module");
|
||||
throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
|
||||
throw new ClassFinder.BadClassFile(sym, tree.sourcefile, diag, diagFactory);
|
||||
}
|
||||
} else if (isPkgInfo) {
|
||||
if (enter.getEnv(tree.packge) == null) {
|
||||
JCDiagnostic diag =
|
||||
diagFactory.fragment("file.does.not.contain.package",
|
||||
c.location());
|
||||
throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
|
||||
sym.location());
|
||||
throw new ClassFinder.BadClassFile(sym, tree.sourcefile, diag, diagFactory);
|
||||
}
|
||||
} else {
|
||||
JCDiagnostic diag =
|
||||
diagFactory.fragment("file.doesnt.contain.class",
|
||||
c.getQualifiedName());
|
||||
throw new ClassFinder.BadClassFile(c, filename, diag, diagFactory);
|
||||
sym.getQualifiedName());
|
||||
throw new ClassFinder.BadClassFile(sym, tree.sourcefile, diag, diagFactory);
|
||||
}
|
||||
}
|
||||
|
||||
implicitSourceFilesRead = true;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
/** Track when the JavaCompiler has been used to compile something. */
|
||||
|
@ -2770,6 +2770,10 @@ compiler.err.unnamed.pkg.not.allowed.named.modules=\
|
||||
compiler.err.module.name.mismatch=\
|
||||
module name {0} does not match expected name {1}
|
||||
|
||||
# 0: name, 1: name
|
||||
compiler.misc.module.name.mismatch=\
|
||||
module name {0} does not match expected name {1}
|
||||
|
||||
compiler.err.module.decl.sb.in.module-info.java=\
|
||||
module declarations should be in a file named module-info.java
|
||||
|
||||
|
@ -66,6 +66,7 @@ compiler.misc.kindname.type.variable
|
||||
compiler.misc.kindname.type.variable.bound
|
||||
compiler.misc.kindname.value
|
||||
compiler.misc.incompatible.eq.lower.bounds # cannot happen?
|
||||
compiler.misc.module.name.mismatch
|
||||
compiler.misc.no.unique.minimal.instance.exists
|
||||
compiler.misc.no.unique.maximal.instance.exists # cannot happen?
|
||||
compiler.misc.resume.abort # prompt for a response
|
||||
|
@ -58,6 +58,8 @@ import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||
import toolbox.JarTask;
|
||||
import toolbox.JavacTask;
|
||||
import toolbox.Task;
|
||||
import toolbox.Task.Expect;
|
||||
import toolbox.Task.OutputKind;
|
||||
|
||||
public class EdgeCases extends ModuleTestBase {
|
||||
|
||||
@ -304,4 +306,147 @@ public class EdgeCases extends ModuleTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitJavaBase(Path base) throws Exception {
|
||||
Path src = base.resolve("src");
|
||||
Path src_java_base = src.resolve("java.base");
|
||||
Files.createDirectories(src_java_base);
|
||||
tb.writeJavaFiles(src_java_base, "module java.base { exports java.lang; }");
|
||||
tb.writeJavaFiles(src_java_base,
|
||||
"package java.lang; public class Object {}");
|
||||
Path classes = base.resolve("classes");
|
||||
tb.createDirectories(classes);
|
||||
|
||||
//module-info from source:
|
||||
new JavacTask(tb)
|
||||
.options("-sourcepath", src_java_base.toString())
|
||||
.outdir(classes)
|
||||
.files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java")))
|
||||
.run()
|
||||
.writeAll();
|
||||
|
||||
//module-info from class:
|
||||
if (!Files.exists(classes.resolve("module-info.class"))) {
|
||||
throw new AssertionError("module-info.class not created!");
|
||||
}
|
||||
|
||||
new JavacTask(tb)
|
||||
.outdir(classes)
|
||||
.files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java")))
|
||||
.run()
|
||||
.writeAll();
|
||||
|
||||
//broken module-info.class:
|
||||
Files.newOutputStream(classes.resolve("module-info.class")).close();
|
||||
|
||||
List<String> log = new JavacTask(tb)
|
||||
.options("-XDrawDiagnostics")
|
||||
.outdir(classes)
|
||||
.files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java")))
|
||||
.run(Expect.FAIL)
|
||||
.writeAll()
|
||||
.getOutputLines(OutputKind.DIRECT);
|
||||
|
||||
List<String> expected = Arrays.asList(
|
||||
"- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.illegal.start.of.class.file))",
|
||||
"1 error");
|
||||
|
||||
if (!expected.equals(log)) {
|
||||
throw new AssertionError("Unexpected output: " + log);
|
||||
}
|
||||
|
||||
//broken module-info.java:
|
||||
Files.delete(classes.resolve("module-info.class"));
|
||||
|
||||
try (Writer out = Files.newBufferedWriter(src_java_base.resolve("module-info.java"))) {
|
||||
out.write("class Broken {}");
|
||||
}
|
||||
|
||||
log = new JavacTask(tb)
|
||||
.options("-sourcepath", src_java_base.toString(),
|
||||
"-XDrawDiagnostics")
|
||||
.outdir(classes)
|
||||
.files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java")))
|
||||
.run(Expect.FAIL)
|
||||
.writeAll()
|
||||
.getOutputLines(OutputKind.DIRECT);
|
||||
|
||||
expected = Arrays.asList("X");
|
||||
|
||||
if (expected.equals(log)) {
|
||||
throw new AssertionError("Unexpected output: " + log);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModuleInfoNameMismatchSource(Path base) throws Exception {
|
||||
Path src = base.resolve("src");
|
||||
Path m1 = src.resolve("m1");
|
||||
Files.createDirectories(m1);
|
||||
tb.writeJavaFiles(m1, "module other { }",
|
||||
"package test; public class Test {}");
|
||||
Path classes = base.resolve("classes");
|
||||
tb.createDirectories(classes);
|
||||
|
||||
List<String> log = new JavacTask(tb)
|
||||
.options("--module-source-path", src.toString(),
|
||||
"-XDrawDiagnostics")
|
||||
.outdir(classes)
|
||||
.files(findJavaFiles(m1.resolve("test").resolve("Test.java")))
|
||||
.run(Expect.FAIL)
|
||||
.writeAll()
|
||||
.getOutputLines(OutputKind.DIRECT);
|
||||
|
||||
List<String> expected = Arrays.asList(
|
||||
"module-info.java:1:1: compiler.err.module.name.mismatch: other, m1",
|
||||
"- compiler.err.cant.access: m1.module-info, (compiler.misc.cant.resolve.modules)",
|
||||
"2 errors");
|
||||
|
||||
if (!expected.equals(log)) {
|
||||
throw new AssertionError("Unexpected output: " + log);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModuleInfoNameMismatchClass(Path base) throws Exception {
|
||||
Path src = base.resolve("src");
|
||||
Files.createDirectories(src);
|
||||
tb.writeJavaFiles(src, "module other { }",
|
||||
"package test; public class Test {}");
|
||||
Path classes = base.resolve("classes");
|
||||
Path m1Classes = classes.resolve("m1");
|
||||
tb.createDirectories(m1Classes);
|
||||
|
||||
new JavacTask(tb)
|
||||
.outdir(m1Classes)
|
||||
.files(findJavaFiles(src))
|
||||
.run()
|
||||
.writeAll()
|
||||
.getOutputLines(OutputKind.DIRECT);
|
||||
|
||||
Path src2 = base.resolve("src2");
|
||||
Files.createDirectories(src2);
|
||||
tb.writeJavaFiles(src2, "module use { requires m1; }");
|
||||
|
||||
Path classes2 = base.resolve("classes2");
|
||||
tb.createDirectories(classes2);
|
||||
|
||||
List<String> log = new JavacTask(tb)
|
||||
.options("--module-path", classes.toString(),
|
||||
"-XDrawDiagnostics")
|
||||
.outdir(classes2)
|
||||
.files(findJavaFiles(src2))
|
||||
.run(Expect.FAIL)
|
||||
.writeAll()
|
||||
.getOutputLines(OutputKind.DIRECT);
|
||||
|
||||
List<String> expected = Arrays.asList(
|
||||
"- compiler.err.cant.access: m1.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.name.mismatch: other, m1))",
|
||||
"1 error");
|
||||
|
||||
if (!expected.equals(log)) {
|
||||
throw new AssertionError("Unexpected output: " + log);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user