# HG changeset patch # User jjg # Date 1493071183 25200 # Node ID f260f1a2acf616509a4ee5a29bc7f2acca3853e3 # Parent 3248e421620b865fed233ff7960f812a5bdd3c18 8176327: javac produces wrong module-info 8178518: Add method JavaFileManager.contains Reviewed-by: jlahoda diff -r 3248e421620b -r f260f1a2acf6 src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java --- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java Mon Apr 24 18:58:50 2017 +0200 +++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java Mon Apr 24 14:59:43 2017 -0700 @@ -204,4 +204,11 @@ public Iterable> 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); + } } diff -r 3248e421620b -r f260f1a2acf6 src/java.compiler/share/classes/javax/tools/JavaFileManager.java --- a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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. + * + *

For a package-oriented location, a file object is contained in the location if there exist + * values for packageName and relativeName such that either of the following + * calls would return the {@link #isSameFile same} file object: + *

+     *     getFileForInput(location, packageName, relativeName)
+     *     getFileForOutput(location, packageName, relativeName, null)
+     * 
+ * + *

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: + *

+     *     getLocationForModule(location, moduleName)
+     * 
+ * 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(); + } + } diff -r 3248e421620b -r f260f1a2acf6 src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java --- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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)); diff -r 3248e421620b -r f260f1a2acf6 src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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(); diff -r 3248e421620b -r f260f1a2acf6 src/jdk.compiler/share/classes/com/sun/tools/javac/api/WrappingJavaFileManager.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/WrappingJavaFileManager.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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)); + } + } diff -r 3248e421620b -r f260f1a2acf6 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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 trees) { if (!fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) { return legacyModuleOverride; diff -r 3248e421620b -r f260f1a2acf6 src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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); } diff -r 3248e421620b -r f260f1a2acf6 src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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 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> 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 = } 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 nameMap = new LinkedHashMap<>(); private final Map pathMap = new LinkedHashMap<>(); @@ -1008,6 +1073,10 @@ return nameMap.isEmpty(); } + boolean contains(Path file) throws IOException { + return Locations.this.contains(pathMap.keySet(), file); + } + Set 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> 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 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> listLocationsForModules() throws IOException { return Collections.singleton(moduleTable.locations()); } + + @Override + boolean contains(Path file) throws IOException { + return moduleTable.contains(file); + } } Map 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) diff -r 3248e421620b -r f260f1a2acf6 src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Apr 24 18:58:50 2017 +0200 +++ b/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 diff -r 3248e421620b -r f260f1a2acf6 src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java --- a/src/jdk.jshell/share/classes/jdk/jshell/MemoryFileManager.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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 diff -r 3248e421620b -r f260f1a2acf6 test/tools/doclint/ProvidesTest.java --- a/test/tools/doclint/ProvidesTest.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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 { } } diff -r 3248e421620b -r f260f1a2acf6 test/tools/doclint/ProvidesTest.out --- a/test/tools/doclint/ProvidesTest.out Mon Apr 24 18:58:50 2017 +0200 +++ b/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 diff -r 3248e421620b -r f260f1a2acf6 test/tools/doclint/UsesTest.java --- a/test/tools/doclint/UsesTest.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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 { } } diff -r 3248e421620b -r f260f1a2acf6 test/tools/doclint/UsesTest.out --- a/test/tools/doclint/UsesTest.out Mon Apr 24 18:58:50 2017 +0200 +++ b/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 diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/api/TestClientCodeWrapper.java --- a/test/tools/javac/api/TestClientCodeWrapper.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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; diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/diags/examples/FileShouldBeOnSourcePathOrPatchPath/FileShouldBeOnSourcePathOrModulePath.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 { +} + diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/diags/examples/FileShouldBeOnSourcePathOrPatchPath/sourcepath/module-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 { } + diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/file/ModuleAndPackageLocations.java --- a/test/tools/javac/file/ModuleAndPackageLocations.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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)); diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/modules/ContainsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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()); + } + } + } +} diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/modules/SourcePathTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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 showFiles(Path dir) throws IOException { + List files = new ArrayList<>(); + Files.walkFileTree(dir, new SimpleFileVisitor() { + @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; + } +} + diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/modules/T8158224/T8158224.java --- a/test/tools/javac/modules/T8158224/T8158224.java Mon Apr 24 18:58:50 2017 +0200 +++ b/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 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"); + } + } +} diff -r 3248e421620b -r f260f1a2acf6 test/tools/javac/modules/T8158224/T8158224.out --- a/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