8209865: Incorrect 'multiple elements' notes with Elements#getTypeElement and --release
Summary: Changing ct.sym to be module-path oriented, rather than class-path oriented.
Reviewed-by: jjg
--- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java Fri Sep 21 16:13:49 2018 +0800
+++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java Fri Sep 21 12:29:31 2018 +0200
@@ -209,13 +209,15 @@
* {@code ctDescriptionFile}, using the file as a recipe to create the sigfiles.
*/
@SuppressWarnings("unchecked")
- public void createSymbols(String ctDescriptionFileExtra, String ctDescriptionFile, String ctSymLocation, CtSymKind ctSymKind) throws IOException {
+ public void createSymbols(String ctDescriptionFileExtra, String ctDescriptionFile, String ctSymLocation) throws IOException {
LoadDescriptions data = load(ctDescriptionFileExtra != null ? Paths.get(ctDescriptionFileExtra)
: null,
Paths.get(ctDescriptionFile), null);
splitHeaders(data.classes);
+ Map<String, Map<Character, String>> package2Version2Module = new HashMap<>();
+
for (ModuleDescription md : data.modules.values()) {
for (ModuleHeaderDescription mhd : md.header) {
List<String> versionsList =
@@ -224,26 +226,41 @@
md,
mhd,
versionsList);
+ mhd.exports.stream().forEach(pkg -> {
+ for (char v : mhd.versions.toCharArray()) {
+ package2Version2Module.computeIfAbsent(pkg, dummy -> new HashMap<>()).put(v, md.name);
+ }
+ });
}
}
for (ClassDescription classDescription : data.classes) {
+ Map<Character, String> version2Module = package2Version2Module.getOrDefault(classDescription.packge().replace('.', '/'), Collections.emptyMap());
for (ClassHeaderDescription header : classDescription.header) {
- switch (ctSymKind) {
- case JOINED_VERSIONS:
- Set<String> jointVersions = new HashSet<>();
- jointVersions.add(header.versions);
- limitJointVersion(jointVersions, classDescription.fields);
- limitJointVersion(jointVersions, classDescription.methods);
- writeClassesForVersions(ctSymLocation, classDescription, header, jointVersions);
- break;
- case SEPARATE:
- Set<String> versions = new HashSet<>();
- for (char v : header.versions.toCharArray()) {
- versions.add("" + v);
+ Set<String> jointVersions = new HashSet<>();
+ jointVersions.add(header.versions);
+ limitJointVersion(jointVersions, classDescription.fields);
+ limitJointVersion(jointVersions, classDescription.methods);
+ Map<String, StringBuilder> module2Versions = new HashMap<>();
+ for (char v : header.versions.toCharArray()) {
+ String module = version2Module.get(v);
+ if (module == null) {
+ if (v >= '9') {
+ throw new AssertionError("No module for " + classDescription.name +
+ " and version " + v);
}
- writeClassesForVersions(ctSymLocation, classDescription, header, versions);
- break;
+ module = version2Module.get('9');
+ if (module == null) {
+ module = "java.base";
+ }
+ }
+ module2Versions.computeIfAbsent(module, dummy -> new StringBuilder()).append(v);
+ }
+ for (Entry<String, StringBuilder> e : module2Versions.entrySet()) {
+ Set<String> currentVersions = new HashSet<>(jointVersions);
+ limitJointVersion(currentVersions, e.getValue().toString());
+ currentVersions = currentVersions.stream().filter(vers -> !disjoint(vers, e.getValue().toString())).collect(Collectors.toSet());
+ writeClassesForVersions(ctSymLocation, classDescription, header, e.getKey(), currentVersions);
}
}
}
@@ -591,7 +608,7 @@
newHeader.innerClasses = header.innerClasses;
newHeader.runtimeAnnotations = header.runtimeAnnotations;
newHeader.signature = header.signature;
- newHeader.versions = reduce(versions, header.versions);
+ newHeader.versions = reduce(header.versions, versions);
newHeaders.add(newHeader);
}
@@ -603,26 +620,30 @@
void limitJointVersion(Set<String> jointVersions, List<? extends FeatureDescription> features) {
for (FeatureDescription feature : features) {
- for (String version : jointVersions) {
- if (!containsAll(feature.versions, version) &&
- !disjoint(feature.versions, version)) {
- StringBuilder featurePart = new StringBuilder();
- StringBuilder otherPart = new StringBuilder();
- for (char v : version.toCharArray()) {
- if (feature.versions.indexOf(v) != (-1)) {
- featurePart.append(v);
- } else {
- otherPart.append(v);
- }
+ limitJointVersion(jointVersions, feature.versions);
+ }
+ }
+
+ void limitJointVersion(Set<String> jointVersions, String versions) {
+ for (String version : jointVersions) {
+ if (!containsAll(versions, version) &&
+ !disjoint(versions, version)) {
+ StringBuilder featurePart = new StringBuilder();
+ StringBuilder otherPart = new StringBuilder();
+ for (char v : version.toCharArray()) {
+ if (versions.indexOf(v) != (-1)) {
+ featurePart.append(v);
+ } else {
+ otherPart.append(v);
}
- jointVersions.remove(version);
- if (featurePart.length() == 0 || otherPart.length() == 0) {
- throw new AssertionError();
- }
- jointVersions.add(featurePart.toString());
- jointVersions.add(otherPart.toString());
- break;
}
+ jointVersions.remove(version);
+ if (featurePart.length() == 0 || otherPart.length() == 0) {
+ throw new AssertionError();
+ }
+ jointVersions.add(featurePart.toString());
+ jointVersions.add(otherPart.toString());
+ break;
}
}
}
@@ -646,10 +667,11 @@
void writeClassesForVersions(String ctSymLocation,
ClassDescription classDescription,
ClassHeaderDescription header,
+ String module,
Iterable<String> versions)
throws IOException {
for (String ver : versions) {
- writeClass(ctSymLocation, classDescription, header, ver);
+ writeClass(ctSymLocation, classDescription, header, module, ver);
}
}
@@ -663,11 +685,6 @@
}
}
- public enum CtSymKind {
- JOINED_VERSIONS,
- SEPARATE;
- }
-
//<editor-fold defaultstate="collapsed" desc="Class Writing">
void writeModule(String ctSymLocation,
ModuleDescription moduleDescription,
@@ -697,7 +714,7 @@
attributes);
Path outputClassFile = Paths.get(ctSymLocation,
- version + "-modules",
+ version,
moduleDescription.name,
"module-info" + EXTENSION);
@@ -713,6 +730,7 @@
void writeClass(String ctSymLocation,
ClassDescription classDescription,
ClassHeaderDescription header,
+ String module,
String version) throws IOException {
List<CPInfo> constantPool = new ArrayList<>();
constantPool.add(null);
@@ -765,7 +783,13 @@
methods.toArray(new Method[0]),
attributes);
- Path outputClassFile = Paths.get(ctSymLocation, version, classDescription.name + EXTENSION);
+ Path outputClassFile = Paths.get(ctSymLocation, version);
+
+ if (module != null) {
+ outputClassFile = outputClassFile.resolve(module);
+ }
+
+ outputClassFile = outputClassFile.resolve(classDescription.name + EXTENSION);
Files.createDirectories(outputClassFile.getParent());
@@ -3652,8 +3676,7 @@
new CreateSymbols().createSymbols(ctDescriptionFileExtra,
ctDescriptionFile,
- ctSymLocation,
- CtSymKind.JOINED_VERSIONS);
+ ctSymLocation);
break;
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java Fri Sep 21 16:13:49 2018 +0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java Fri Sep 21 12:29:31 2018 +0200
@@ -45,6 +45,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeSet;
@@ -61,6 +62,8 @@
import javax.tools.StandardLocation;
import com.sun.source.util.Plugin;
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.file.CacheFSInfo;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.jvm.Target;
@@ -252,52 +255,64 @@
ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, null));
}
- List<Path> paths = new ArrayList<>();
- Path modules = fs.getPath(ctSymVersion + "-modules");
Path root = fs.getRootDirectories().iterator().next();
- boolean pathsSet = false;
+ boolean hasModules =
+ Feature.MODULES.allowedInSource(Source.lookup(sourceVersion));
+ Path systemModules = root.resolve(ctSymVersion).resolve("system-modules");
Charset utf8 = Charset.forName("UTF-8");
- try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) {
- for (Path section : dir) {
- if (section.getFileName().toString().contains(ctSymVersion) &&
- !section.getFileName().toString().contains("-")) {
- Path systemModules = section.resolve("system-modules");
-
- if (Files.isRegularFile(systemModules)) {
- fm.handleOption("--system", Arrays.asList("none").iterator());
+ if (!hasModules) {
+ List<Path> paths = new ArrayList<>();
- Path jrtModules =
- FileSystems.getFileSystem(URI.create("jrt:/"))
- .getPath("modules");
- try (Stream<String> lines =
- Files.lines(systemModules, utf8)) {
- lines.map(line -> jrtModules.resolve(line))
- .filter(mod -> Files.exists(mod))
- .forEach(mod -> setModule(fm, mod));
+ try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) {
+ for (Path section : dir) {
+ if (section.getFileName().toString().contains(ctSymVersion) &&
+ !section.getFileName().toString().contains("-")) {
+ try (DirectoryStream<Path> modules = Files.newDirectoryStream(section)) {
+ for (Path module : modules) {
+ paths.add(module);
+ }
}
- pathsSet = true;
- } else {
- paths.add(section);
}
}
}
- }
- if (Files.isDirectory(modules)) {
- try (DirectoryStream<Path> dir = Files.newDirectoryStream(modules)) {
- fm.handleOption("--system", Arrays.asList("none").iterator());
+ fm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, paths);
+ } else if (Files.isRegularFile(systemModules)) {
+ fm.handleOption("--system", Arrays.asList("none").iterator());
- for (Path module : dir) {
- fm.setLocationForModule(StandardLocation.SYSTEM_MODULES,
- module.getFileName().toString(),
- Stream.concat(paths.stream(),
- Stream.of(module))
- .collect(Collectors.toList()));
+ Path jrtModules =
+ FileSystems.getFileSystem(URI.create("jrt:/"))
+ .getPath("modules");
+ try (Stream<String> lines =
+ Files.lines(systemModules, utf8)) {
+ lines.map(line -> jrtModules.resolve(line))
+ .filter(mod -> Files.exists(mod))
+ .forEach(mod -> setModule(fm, mod));
+ }
+ } else {
+ Map<String, List<Path>> module2Paths = new HashMap<>();
+
+ try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) {
+ for (Path section : dir) {
+ if (section.getFileName().toString().contains(ctSymVersion) &&
+ !section.getFileName().toString().contains("-")) {
+ try (DirectoryStream<Path> modules = Files.newDirectoryStream(section)) {
+ for (Path module : modules) {
+ module2Paths.computeIfAbsent(module.getFileName().toString(), dummy -> new ArrayList<>()).add(module);
+ }
+ }
+ }
}
}
- } else if (!pathsSet) {
- fm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, paths);
+
+ fm.handleOption("--system", Arrays.asList("none").iterator());
+
+ for (Entry<String, List<Path>> e : module2Paths.entrySet()) {
+ fm.setLocationForModule(StandardLocation.SYSTEM_MODULES,
+ e.getKey(),
+ e.getValue());
+ }
}
return fm;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/platform/ReleaseModulesAndTypeElement.java Fri Sep 21 12:29:31 2018 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, 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 8209865
+ * @summary Verify that when reading from ct.sym, classes are only visible from modules from which
+ * they are exported.
+ * @modules jdk.compiler
+ * @build ReleaseModulesAndTypeElement
+ * @compile -processor ReleaseModulesAndTypeElement --release 11 ReleaseModulesAndTypeElement.java
+ */
+
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+
+@SupportedAnnotationTypes("*")
+public class ReleaseModulesAndTypeElement extends AbstractProcessor {
+
+ @Override
+ public boolean process(Set<? extends TypeElement> roots, RoundEnvironment roundEnv) {
+ Elements elements = processingEnv.getElementUtils();
+ if (elements.getTypeElement(JX_A_P_GENERATED) == null) {
+ throw new AssertionError("jx.a.p.Generated not found by unqualified search!");
+ }
+ ModuleElement javaBase = elements.getModuleElement("java.base");
+ if (elements.getTypeElement(javaBase, JX_A_P_GENERATED) != null) {
+ throw new AssertionError("jx.a.p.Generated found in java.base!");
+ }
+ ModuleElement javaCompiler = elements.getModuleElement("java.compiler");
+ if (elements.getTypeElement(javaCompiler, JX_A_P_GENERATED) == null) {
+ throw new AssertionError("jx.a.p.Generated not found in java.compiler!");
+ }
+ return false;
+ }
+ //where:
+ private static final String JX_A_P_GENERATED = "javax.annotation.processing.Generated";
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+}