8176327: javac produces wrong module-info
8178518: Add method JavaFileManager.contains
Reviewed-by: jlahoda
--- a/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java Mon Apr 24 14:59:43 2017 -0700
@@ -204,4 +204,11 @@
public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException {
return fileManager.listLocationsForModules(location);
}
+
+ /**
+ * @since 9
+ */
+ public boolean contains(Location location, FileObject fo) throws IOException {
+ return fileManager.contains(location, fo);
+ }
}
--- a/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/java.compiler/share/classes/javax/tools/JavaFileManager.java Mon Apr 24 14:59:43 2017 -0700
@@ -566,4 +566,38 @@
throw new UnsupportedOperationException();
}
+ /**
+ * Determines whether or not a given file object is "contained in" a specified location.
+ *
+ * <p>For a package-oriented location, a file object is contained in the location if there exist
+ * values for <i>packageName</i> and <i>relativeName</i> such that either of the following
+ * calls would return the {@link #isSameFile same} file object:
+ * <pre>
+ * getFileForInput(location, <i>packageName</i>, <i>relativeName</i>)
+ * getFileForOutput(location, <i>packageName</i>, <i>relativeName</i>, null)
+ * </pre>
+ *
+ * <p>For a module-oriented location, a file object is contained in the location if there exists
+ * a module that may be obtained by the call:
+ * <pre>
+ * getLocationForModule(location, <i>moduleName</i>)
+ * </pre>
+ * such that the file object is contained in the (package-oriented) location for that module.
+ *
+ * @implSpec This implementation throws {@code UnsupportedOperationException}.
+ *
+ * @param location the location
+ * @param fo the file object
+ * @return whether or not the file is contained in the location
+ *
+ * @throws IOException if there is a problem determining the result
+ * @throws UnsupportedOperationException if the method is not supported
+ *
+ * @since 9
+ */
+
+ default boolean contains(Location location, FileObject fo) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java Mon Apr 24 14:59:43 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
-import java.util.regex.Pattern;
import javax.lang.model.element.Name;
import javax.tools.StandardLocation;
@@ -148,9 +147,15 @@
JavacFileManager fm = new JavacFileManager(new Context(), false, null);
fm.setSymbolFileEnabled(false);
- fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
- fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
- fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
+ if (javacBootClassPath != null) {
+ fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, javacBootClassPath);
+ }
+ if (javacClassPath != null) {
+ fm.setLocation(StandardLocation.CLASS_PATH, javacClassPath);
+ }
+ if (javacSourcePath != null) {
+ fm.setLocation(StandardLocation.SOURCE_PATH, javacSourcePath);
+ }
JavacTask task = tool.getTask(out, fm, null, javacOpts, null,
fm.getJavaFileObjectsFromFiles(javacFiles));
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Mon Apr 24 14:59:43 2017 -0700
@@ -326,6 +326,17 @@
}
@Override @DefinedBy(Api.COMPILER)
+ public boolean contains(Location location, FileObject file) throws IOException {
+ try {
+ return clientJavaFileManager.contains(location, unwrap(file));
+ } catch (ClientCodeException e) {
+ throw e;
+ } catch (RuntimeException | Error e) {
+ throw new ClientCodeException(e);
+ }
+ }
+
+ @Override @DefinedBy(Api.COMPILER)
public void flush() throws IOException {
try {
clientJavaFileManager.flush();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/WrappingJavaFileManager.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/WrappingJavaFileManager.java Mon Apr 24 14:59:43 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@
import javax.tools.*;
import javax.tools.JavaFileObject.Kind;
+import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
@@ -214,4 +215,9 @@
unwrap(sibling)));
}
+ @Override @DefinedBy(Api.COMPILER)
+ public boolean contains(Location location, FileObject file) throws IOException {
+ return super.contains(location, unwrap(file));
+ }
+
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Mon Apr 24 14:59:43 2017 -0700
@@ -532,12 +532,52 @@
module = defaultModule;
}
- for (JCCompilationUnit tree: trees) {
+ for (JCCompilationUnit tree : trees) {
+ if (defaultModule != syms.unnamedModule
+ && defaultModule.sourceLocation == StandardLocation.SOURCE_PATH
+ && fileManager.hasLocation(StandardLocation.SOURCE_PATH)) {
+ checkSourceLocation(tree, module);
+ }
tree.modle = module;
}
}
}
+ private void checkSourceLocation(JCCompilationUnit tree, ModuleSymbol msym) {
+ // skip check if legacy module override still in use
+ if (legacyModuleOverride != null) {
+ return;
+ }
+
+ try {
+ JavaFileObject fo = tree.sourcefile;
+ if (fileManager.contains(msym.sourceLocation, fo)) {
+ return;
+ }
+ if (msym.patchLocation != null && fileManager.contains(msym.patchLocation, fo)) {
+ return;
+ }
+ if (fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT)) {
+ if (fileManager.contains(StandardLocation.SOURCE_OUTPUT, fo)) {
+ return;
+ }
+ } else {
+ if (fileManager.contains(StandardLocation.CLASS_OUTPUT, fo)) {
+ return;
+ }
+ }
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+
+ JavaFileObject prev = log.useSource(tree.sourcefile);
+ try {
+ log.error(tree.pos(), "file.sb.on.source.or.patch.path.for.module");
+ } finally {
+ log.useSource(prev);
+ }
+ }
+
private String singleModuleOverride(List<JCCompilationUnit> trees) {
if (!fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) {
return legacyModuleOverride;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Mon Apr 24 14:59:43 2017 -0700
@@ -946,6 +946,14 @@
return locations.getLocation(location);
}
+ @Override @DefinedBy(Api.COMPILER)
+ public boolean contains(Location location, FileObject fo) throws IOException {
+ nullCheck(location);
+ nullCheck(fo);
+ Path p = asPath(fo);
+ return locations.contains(location, p);
+ }
+
private Path getClassOutDir() {
return locations.getOutputLocation(CLASS_OUTPUT);
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Mon Apr 24 14:59:43 2017 -0700
@@ -85,6 +85,7 @@
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.Assert;
import com.sun.tools.javac.util.Pair;
import com.sun.tools.javac.util.StringUtils;
@@ -226,6 +227,41 @@
fsEnv = Collections.singletonMap("multi-release", multiReleaseValue);
}
+ private boolean contains(Collection<Path> searchPath, Path file) throws IOException {
+
+ if (searchPath == null) {
+ return false;
+ }
+
+ Path enclosingJar = null;
+ if (file.getFileSystem().provider() == fsInfo.getJarFSProvider()) {
+ URI uri = file.toUri();
+ if (uri.getScheme().equals("jar")) {
+ String ssp = uri.getSchemeSpecificPart();
+ int sep = ssp.lastIndexOf("!");
+ if (ssp.startsWith("file:") && sep > 0) {
+ enclosingJar = Paths.get(URI.create(ssp.substring(0, sep)));
+ }
+ }
+ }
+
+ Path nf = normalize(file);
+ for (Path p : searchPath) {
+ Path np = normalize(p);
+ if (np.getFileSystem() == nf.getFileSystem()
+ && Files.isDirectory(np)
+ && nf.startsWith(np)) {
+ return true;
+ }
+ if (enclosingJar != null
+ && Files.isSameFile(enclosingJar, np)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Utility class to help evaluate a path option. Duplicate entries are ignored, jar class paths
* can be expanded.
@@ -456,6 +492,11 @@
Iterable<Set<Location>> listLocationsForModules() throws IOException {
return null;
}
+
+ /**
+ * @see JavaFileManager#contains
+ */
+ abstract boolean contains(Path file) throws IOException;
}
/**
@@ -611,6 +652,15 @@
return Collections.singleton(moduleTable.locations());
}
+
+ @Override
+ boolean contains(Path file) throws IOException {
+ if (moduleTable != null) {
+ return moduleTable.contains(file);
+ } else {
+ return (outputDir) != null && normalize(file).startsWith(normalize(outputDir));
+ }
+ }
}
/**
@@ -660,6 +710,11 @@
protected SearchPath createPath() {
return new SearchPath();
}
+
+ @Override
+ boolean contains(Path file) throws IOException {
+ return Locations.this.contains(searchPath, file);
+ }
}
/**
@@ -879,13 +934,18 @@
private void lazy() {
if (searchPath == null) {
try {
- searchPath = Collections.unmodifiableCollection(computePath());
+ searchPath = Collections.unmodifiableCollection(computePath());
} catch (IOException e) {
// TODO: need better handling here, e.g. javac Abort?
throw new UncheckedIOException(e);
}
}
}
+
+ @Override
+ boolean contains(Path file) throws IOException {
+ return Locations.this.contains(searchPath, file);
+ }
}
/**
@@ -896,7 +956,7 @@
* The Location can be specified to accept overriding classes from the
* {@code --patch-module <module>=<path> } parameter.
*/
- private static class ModuleLocationHandler extends LocationHandler implements Location {
+ private class ModuleLocationHandler extends LocationHandler implements Location {
private final LocationHandler parent;
private final String name;
private final String moduleName;
@@ -949,6 +1009,11 @@
}
@Override
+ boolean contains(Path file) throws IOException {
+ return Locations.this.contains(searchPath, file);
+ }
+
+ @Override
public String toString() {
return name;
}
@@ -957,7 +1022,7 @@
/**
* A table of module location handlers, indexed by name and path.
*/
- private static class ModuleTable {
+ private class ModuleTable {
private final Map<String, ModuleLocationHandler> nameMap = new LinkedHashMap<>();
private final Map<Path, ModuleLocationHandler> pathMap = new LinkedHashMap<>();
@@ -1008,6 +1073,10 @@
return nameMap.isEmpty();
}
+ boolean contains(Path file) throws IOException {
+ return Locations.this.contains(pathMap.keySet(), file);
+ }
+
Set<Location> locations() {
return Collections.unmodifiableSet(nameMap.values().stream().collect(Collectors.toSet()));
}
@@ -1040,6 +1109,12 @@
}
@Override
+ public Location getLocationForModule(Path file) {
+ initModuleLocations();
+ return moduleTable.get(file);
+ }
+
+ @Override
Iterable<Set<Location>> listLocationsForModules() {
if (searchPath == null)
return Collections.emptyList();
@@ -1048,6 +1123,14 @@
}
@Override
+ boolean contains(Path file) throws IOException {
+ if (moduleTable == null) {
+ initModuleLocations();
+ }
+ return moduleTable.contains(file);
+ }
+
+ @Override
void setPaths(Iterable<? extends Path> paths) {
if (paths != null) {
for (Path p: paths) {
@@ -1592,6 +1675,11 @@
return Collections.singleton(moduleTable.locations());
}
+ @Override
+ boolean contains(Path file) throws IOException {
+ return (moduleTable == null) ? false : moduleTable.contains(file);
+ }
+
}
private class SystemModulesLocationHandler extends BasicLocationHandler {
@@ -1698,6 +1786,12 @@
return Collections.singleton(moduleTable.locations());
}
+ @Override
+ boolean contains(Path file) throws IOException {
+ initSystemModules();
+ return moduleTable.contains(file);
+ }
+
private void initSystemModules() throws IOException {
if (moduleTable != null)
return;
@@ -1828,6 +1922,11 @@
Iterable<Set<Location>> listLocationsForModules() throws IOException {
return Collections.singleton(moduleTable.locations());
}
+
+ @Override
+ boolean contains(Path file) throws IOException {
+ return moduleTable.contains(file);
+ }
}
Map<Location, LocationHandler> handlersForLocation;
@@ -1931,6 +2030,13 @@
return (h == null ? null : h.listLocationsForModules());
}
+ boolean contains(Location location, Path file) throws IOException {
+ LocationHandler h = getHandler(location);
+ if (h == null)
+ throw new IllegalArgumentException("unknown location");
+ return h.contains(file);
+ }
+
protected LocationHandler getHandler(Location location) {
Objects.requireNonNull(location);
return (location instanceof LocationHandler)
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Apr 24 14:59:43 2017 -0700
@@ -947,7 +947,7 @@
package annotations should be in file package-info.java
compiler.err.no.pkg.in.module-info.java=\
- package clauses should not be in file module-info.java
+ package declarations not allowed in file module-info.java
# 0: symbol
compiler.err.pkg.clashes.with.class.of.same.name=\
@@ -1304,6 +1304,9 @@
compiler.err.locn.invalid.arg.for.xpatch=\
invalid argument for --patch-module option: {0}
+compiler.err.file.sb.on.source.or.patch.path.for.module=\
+ file should be on source path, or on patch path for module
+
#####
# Fatal Errors
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java Mon Apr 24 14:59:43 2017 -0700
@@ -559,6 +559,11 @@
return stdFileManager.listLocationsForModules(location);
}
+ @Override
+ public boolean contains(Location location, FileObject file) throws IOException {
+ return stdFileManager.contains(location, file);
+ }
+
/**
* Flushes any resources opened for output by this file manager
* directly or indirectly. Flushing a closed file manager has no
--- a/langtools/test/tools/doclint/ProvidesTest.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/test/tools/doclint/ProvidesTest.java Mon Apr 24 14:59:43 2017 -0700
@@ -10,20 +10,20 @@
/**
* Invalid use of provides in class documentation.
*
- * @provides UsesTest
+ * @provides NotFound
*/
public class ProvidesTest {
/**
* Invalid use of provides in field documentation
*
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
*/
public int invalid_param;
/**
* Invalid use of provides in method documentation
*
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
*/
public class InvalidParam { }
}
--- a/langtools/test/tools/doclint/ProvidesTest.out Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/test/tools/doclint/ProvidesTest.out Mon Apr 24 14:59:43 2017 -0700
@@ -1,28 +1,28 @@
ProvidesTest.java:13: error: invalid use of @provides
- * @provides UsesTest
+ * @provides NotFound
^
ProvidesTest.java:13: error: service-type not found
- * @provides UsesTest
+ * @provides NotFound
^
ProvidesTest.java:13: error: reference not found
- * @provides UsesTest
+ * @provides NotFound
^
ProvidesTest.java:19: error: invalid use of @provides
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
^
ProvidesTest.java:19: error: service-type not found
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
^
ProvidesTest.java:19: error: reference not found
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
^
ProvidesTest.java:26: error: invalid use of @provides
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
^
ProvidesTest.java:26: error: service-type not found
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
^
ProvidesTest.java:26: error: reference not found
- * @provides UsesTest Test description.
+ * @provides NotFound Test description.
^
9 errors
--- a/langtools/test/tools/doclint/UsesTest.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/test/tools/doclint/UsesTest.java Mon Apr 24 14:59:43 2017 -0700
@@ -10,20 +10,20 @@
/**
* Invalid use of uses in class documentation.
*
- * @uses ProvidesTest
+ * @uses NotFound
*/
public class UsesTest {
/**
* Invalid use of uses in field documentation
*
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
*/
public int invalid_param;
/**
* Invalid use of uses in method documentation
*
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
*/
public class InvalidParam { }
}
--- a/langtools/test/tools/doclint/UsesTest.out Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/test/tools/doclint/UsesTest.out Mon Apr 24 14:59:43 2017 -0700
@@ -1,28 +1,28 @@
UsesTest.java:13: error: invalid use of @uses
- * @uses ProvidesTest
+ * @uses NotFound
^
UsesTest.java:13: error: service-type not found
- * @uses ProvidesTest
+ * @uses NotFound
^
UsesTest.java:13: error: reference not found
- * @uses ProvidesTest
+ * @uses NotFound
^
UsesTest.java:19: error: invalid use of @uses
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
^
UsesTest.java:19: error: service-type not found
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
^
UsesTest.java:19: error: reference not found
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
^
UsesTest.java:26: error: invalid use of @uses
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
^
UsesTest.java:26: error: service-type not found
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
^
UsesTest.java:26: error: reference not found
- * @uses ProvidesTest Test description.
+ * @uses NotFound Test description.
^
9 errors
--- a/langtools/test/tools/javac/api/TestClientCodeWrapper.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/test/tools/javac/api/TestClientCodeWrapper.java Mon Apr 24 14:59:43 2017 -0700
@@ -62,7 +62,7 @@
defaultFileManager = fm;
for (Method m: getMethodsExcept(JavaFileManager.class,
- "close", "getJavaFileForInput", "getLocationForModule", "getServiceLoader")) {
+ "close", "getJavaFileForInput", "getLocationForModule", "getServiceLoader", "contains")) {
test(m);
}
@@ -424,6 +424,12 @@
return super.listLocationsForModules(location);
}
+ @Override
+ public boolean contains(Location location, FileObject fo) throws IOException {
+ throwUserExceptionIfNeeded(fileManagerMethod, "contains");
+ return super.contains(location, fo);
+ }
+
public FileObject wrap(FileObject fo) {
if (fileObjectMethod == null || fo == null)
return fo;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/FileShouldBeOnSourcePathOrPatchPath/FileShouldBeOnSourcePathOrModulePath.java Mon Apr 24 14:59:43 2017 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//key: compiler.err.file.sb.on.source.or.patch.path.for.module
+
+public class FileShouldBeOnSourcePathOrModulePath {
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/FileShouldBeOnSourcePathOrPatchPath/sourcepath/module-info.java Mon Apr 24 14:59:43 2017 -0700
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module m { }
+
--- a/langtools/test/tools/javac/file/ModuleAndPackageLocations.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/test/tools/javac/file/ModuleAndPackageLocations.java Mon Apr 24 14:59:43 2017 -0700
@@ -117,7 +117,6 @@
assertRefused(() -> fm.getJavaFileForOutput(StandardLocation.MODULE_SOURCE_PATH, "", Kind.SOURCE, null));
assertRefused(() -> fm.getLocationForModule(StandardLocation.SOURCE_PATH, "test"));
JavaFileObject out = fm.getJavaFileForInput(StandardLocation.CLASS_OUTPUT, "test.Test", Kind.CLASS);
- assertRefused(() -> fm.getLocationForModule(StandardLocation.SOURCE_PATH, out));
assertRefused(() -> fm.inferBinaryName(StandardLocation.MODULE_PATH, out));
assertRefused(() -> fm.inferModuleName(StandardLocation.MODULE_SOURCE_PATH));
assertRefused(() -> fm.list(StandardLocation.MODULE_SOURCE_PATH, "test", EnumSet.allOf(Kind.class), false));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/ContainsTest.java Mon Apr 24 14:59:43 2017 -0700
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8178518
+ * @summary Add method JavaFileManager.contains
+ * @library /tools/lib
+ * @modules
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
+ * @run main ContainsTest
+ */
+
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.EnumSet;
+import java.util.List;
+
+import javax.tools.FileObject;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import toolbox.JarTask;
+import toolbox.JavacTask;
+
+public class ContainsTest extends ModuleTestBase {
+ public static void main(String... args) throws Exception {
+ ContainsTest t = new ContainsTest();
+ t.runTests();
+ }
+
+ JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+
+ @Test
+ public void testSimplePath(Path base) throws IOException {
+ // Test that we can look up in directories in the default file system.
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "package p; class C { }");
+ Path c = src.resolve("p/C.java");
+ Path x = base.resolve("src2/p/C.java");
+ try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+ fm.setLocationFromPaths(StandardLocation.SOURCE_PATH, List.of(src));
+ checkContains(fm, StandardLocation.SOURCE_PATH, c, true);
+ checkContains(fm, StandardLocation.SOURCE_PATH, x, false);
+ }
+ }
+
+ @Test
+ public void testJarPath(Path base) throws IOException {
+ // Test that we can look up in jar files on a search path.
+ // In this case, the path we look up must come from open file system
+ // as used by the file manager.
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "package p; class C { }");
+ Path classes = Files.createDirectories(base.resolve("classes"));
+ new JavacTask(tb)
+ .options("-sourcepath", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run()
+ .writeAll();
+
+ Path jar = base.resolve("classes.jar");
+ new JarTask(tb).run("cf", jar.toString(), "-C", classes.toString(), "p");
+
+ Path c = src.resolve("p/C.java");
+ Path x = base.resolve("src2/p/C.java");
+
+ try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+ fm.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(src, jar));
+
+ checkContains(fm, StandardLocation.CLASS_PATH, c, true);
+ checkContains(fm, StandardLocation.CLASS_PATH, x, false);
+
+ JavaFileObject fo = fm.list(StandardLocation.CLASS_PATH, "p",
+ EnumSet.of(JavaFileObject.Kind.CLASS), false).iterator().next();
+
+ checkContains(fm, StandardLocation.CLASS_PATH, fo, true);
+ }
+ }
+
+ @Test
+ public void testJarFSPath(Path base) throws IOException {
+ // Test that we can look up in non-default file systems on the search path,
+ // such as an open jar file system.
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "package p; class C { }");
+ Path classes = Files.createDirectories(base.resolve("classes"));
+ new JavacTask(tb)
+ .options("-sourcepath", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run()
+ .writeAll();
+
+ Path jar = base.resolve("classes.jar");
+ new JarTask(tb).run("cf", jar.toString(), "-C", classes.toString(), "p");
+
+ Path c = src.resolve("p/C.java");
+ Path x = base.resolve("src2/p/C.java");
+
+ try (FileSystem jarFS = FileSystems.newFileSystem(jar, null);
+ StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+ Path jarRoot = jarFS.getRootDirectories().iterator().next();
+ fm.setLocationFromPaths(StandardLocation.CLASS_PATH, List.of(src, jarRoot));
+
+ checkContains(fm, StandardLocation.CLASS_PATH, c, true);
+ checkContains(fm, StandardLocation.CLASS_PATH, x, false);
+
+ JavaFileObject fo = fm.list(StandardLocation.CLASS_PATH, "p",
+ EnumSet.of(JavaFileObject.Kind.CLASS), false).iterator().next();
+
+ checkContains(fm, StandardLocation.CLASS_PATH, fo, true);
+ checkContains(fm, StandardLocation.CLASS_PATH, jarRoot.resolve("p/C.class"), true);
+ }
+ }
+
+ void checkContains(StandardJavaFileManager fm, Location l, Path p, boolean expect) throws IOException {
+ JavaFileObject fo = fm.getJavaFileObjects(p).iterator().next();
+ checkContains(fm, l, fo, expect);
+ }
+
+ void checkContains(StandardJavaFileManager fm, Location l, FileObject fo, boolean expect) throws IOException {
+ boolean found = fm.contains(l, fo);
+ if (found) {
+ if (expect) {
+ out.println("file found, as expected: " + l + " " + fo.getName());
+ } else {
+ error("file not found: " + l + " " + fo.getName());
+ }
+ } else {
+ if (expect) {
+ error("file found unexpectedly: " + l + " " + fo.getName());
+ } else {
+ out.println("file not found, as expected: " + l + " " + fo.getName());
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/SourcePathTest.java Mon Apr 24 14:59:43 2017 -0700
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8176327
+ * @summary javac produces wrong module-info
+ * @library /tools/lib
+ * @modules
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @run main SourcePathTest
+ */
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.List;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+
+public class SourcePathTest extends ModuleTestBase {
+ public static void main(String... args) throws Exception {
+ SourcePathTest t = new SourcePathTest();
+ t.runTests();
+ }
+
+ @Test
+ public void test_unnamedModuleOnSourcePath_fileNotOnPath(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "package p; public class A { }");
+ Path otherSrc = base.resolve("otherSrc");
+ tb.writeJavaFiles(otherSrc, "package p2; public class B { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ new JavacTask(tb)
+ .options("-sourcepath", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(otherSrc))
+ .run()
+ .writeAll();
+
+ showFiles(classes);
+ }
+
+ @Test
+ public void test_unnamedModuleOnSourcePath_fileOnPath(Path base) throws IOException {
+ Path src = base.resolve("src");
+ tb.writeJavaFiles(src, "package p; public class A { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ new JavacTask(tb)
+ .options("-sourcepath", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(src))
+ .run()
+ .writeAll();
+
+ showFiles(classes);
+ }
+
+ @Test
+ public void test_namedModuleOnSourcePath_fileNotOnPath_1(Path base) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeFile(src.resolve("module-info.java"), "module m { exports p; }");
+ tb.writeJavaFiles(src, "package p; public class A { }");
+ Path otherSrc = base.resolve("otherSrc");
+ tb.writeJavaFiles(otherSrc, "package p2; public class B { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics=true", "-sourcepath", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(otherSrc))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ showFiles(classes);
+ checkOutputContains(log,
+ "B.java:1:1: compiler.err.file.sb.on.source.or.patch.path.for.module");
+ }
+
+ @Test
+ public void test_namedModuleOnSourcePath_fileNotOnPath_2(Path base) throws Exception {
+ // This is the original test case:
+ // the source path contains one module, but the file to be compiled appears to be
+ // in another module.
+ Path src = base.resolve("src");
+ Path src_mA = src.resolve("mA");
+ tb.writeJavaFiles(src_mA,
+ "module mA { exports p; }",
+ "package p; public class A { }");
+ Path src_mB = src.resolve("mB");
+ tb.writeJavaFiles(src_mB,
+ "module mA { exports p2; }",
+ "package p2; public class B { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics=true", "-sourcepath", src_mA.toString())
+ .outdir(classes)
+ .files(findJavaFiles(src_mB.resolve("p2")))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ showFiles(classes);
+ checkOutputContains(log,
+ "B.java:1:1: compiler.err.file.sb.on.source.or.patch.path.for.module");
+ }
+
+ @Test
+ public void test_namedModuleOnSourcePath_fileOnPath(Path base) throws Exception {
+ Path src = base.resolve("src");
+ tb.writeFile(src.resolve("module-info.java"), "module m { exports p; }");
+ tb.writeJavaFiles(src, "package p; public class A { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics=true", "-sourcepath", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(src.resolve("p")))
+ .run()
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ showFiles(classes);
+ }
+
+ @Test
+ public void test_namedModuleOnSourcePath_fileOnPatchPath(Path base) throws Exception {
+ // similar to test_namedModuleOnSourcePath_fileNotOnPath_1
+ // except that other src directory is not put on the patch path
+ Path src = base.resolve("src");
+ tb.writeFile(src.resolve("module-info.java"), "module m { exports p; }");
+ tb.writeJavaFiles(src, "package p; public class A { }");
+ Path otherSrc = base.resolve("otherSrc");
+ tb.writeJavaFiles(otherSrc, "package p2; public class B { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics=true",
+ "-sourcepath", src.toString(),
+ "--patch-module", "m=" + otherSrc)
+ .outdir(classes)
+ .files(findJavaFiles(otherSrc))
+ .run()
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ showFiles(classes);
+ }
+
+ /*
+ * The following tests are not for the source path, but they exercise similar test
+ * cases for the module source path.
+ */
+
+ @Test
+ public void test_moduleSourcePath_fileNotOnPath(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path src_mA = src.resolve("mA");
+ tb.writeJavaFiles(src_mA,
+ "module mA { exports p; }",
+ "package p; public class A { }");
+ Path src_mB = src.resolve("mB");
+ tb.writeJavaFiles(src_mB,
+ "module mB { exports p2; }",
+ "package p2; public class B { }");
+ Path otherSrc = base.resolve("otherSrc");
+ tb.writeJavaFiles(otherSrc, "package p3; public class C { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics=true",
+ "--module-source-path", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(otherSrc))
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ showFiles(classes);
+ checkOutputContains(log,
+ "C.java:1:1: compiler.err.not.in.module.on.module.source.path");
+ }
+
+ @Test
+ public void test_moduleSourcePath_fileOnPath(Path base) throws Exception {
+ Path src = base.resolve("src");
+ Path src_mA = src.resolve("mA");
+ tb.writeJavaFiles(src_mA,
+ "module mA { exports p; }",
+ "package p; public class A { }");
+ Path src_mB = src.resolve("mB");
+ tb.writeJavaFiles(src_mB,
+ "module mB { exports p2; }",
+ "package p2; public class B { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics=true",
+ "--module-source-path", src.toString())
+ .outdir(classes)
+ .files(findJavaFiles(src_mB.resolve("p2")))
+ .run()
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ showFiles(classes);
+
+ }
+
+ @Test
+ public void test_moduleSourcePath_fileOnPatchPath(Path base) throws Exception {
+ // similar to test_moduleSourcePath_fileNotOnPath
+ // except that other src directory is not put on the patch path
+ Path src = base.resolve("src");
+ Path src_mA = src.resolve("mA");
+ tb.writeJavaFiles(src_mA,
+ "module mA { exports p; }",
+ "package p; public class A { }");
+ Path src_mB = src.resolve("mB");
+ tb.writeJavaFiles(src_mB,
+ "module mB { exports p2; }",
+ "package p2; public class B { }");
+ Path otherSrc = base.resolve("otherSrc");
+ tb.writeJavaFiles(otherSrc, "package p3; public class C { }");
+
+ Path classes = base.resolve("classes");
+ Files.createDirectories(classes);
+
+ String log = new JavacTask(tb)
+ .options("-XDrawDiagnostics=true",
+ "--module-source-path", src.toString(),
+ "--patch-module", "mA=" + otherSrc)
+ .outdir(classes)
+ .files(findJavaFiles(otherSrc))
+ .run()
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ showFiles(classes);
+ }
+
+ /**
+ * This method is primarily used to give visual confirmation that a test case
+ * generated files when the compilation succeeds and so generates no other output,
+ * such as error messages.
+ */
+ List<Path> showFiles(Path dir) throws IOException {
+ List<Path> files = new ArrayList<>();
+ Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ if (Files.isRegularFile(file)) {
+ out.println("Found " + file);
+ files.add(file);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ return files;
+ }
+}
+
--- a/langtools/test/tools/javac/modules/T8158224/T8158224.java Mon Apr 24 18:58:50 2017 +0200
+++ b/langtools/test/tools/javac/modules/T8158224/T8158224.java Mon Apr 24 14:59:43 2017 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,41 @@
* @test
* @bug 8158224
* @summary NullPointerException in com.sun.tools.javac.comp.Modules.checkCyclicDependencies when module missing
+ * @library /tools/lib
+ * @modules
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask
* @build Processor
- * @compile/fail/ref=T8158224.out -XDrawDiagnostics -processor Processor mods/foo/module-info.java
+ * @run main T8158224
*/
-// No code here, this file is just to host test description.
+// previously:
+// @compile/fail/ref=T8158224.out -XDrawDiagnostics -processor Processor mods/foo/module-info.java
+
+import java.util.List;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class T8158224 {
+ public static void main(String... args) throws Exception {
+ ToolBox tb = new ToolBox();
+
+ List<String> log = new JavacTask(tb)
+ .options("-XDrawDiagnostics",
+ "-processor", "Processor",
+ "-sourcepath", tb.testSrc + "/mods/foo",
+ "-classpath", tb.testClasses)
+ .files(tb.testSrc + "/mods/foo/module-info.java")
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!log.equals(List.of(
+ "module-info.java:4:14: compiler.err.module.not.found: nonexistent",
+ "1 error"))) {
+ throw new Exception("Expected output not found");
+ }
+ }
+}
--- a/langtools/test/tools/javac/modules/T8158224/T8158224.out Mon Apr 24 18:58:50 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-module-info.java:4:14: compiler.err.module.not.found: nonexistent
-1 error