From c1033edca894411b3af79aadb6a7af95f76d1f20 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 21 Sep 2018 12:29:31 +0200 Subject: [PATCH] 8209865: Incorrect 'multiple elements' notes with Elements#getTypeElement and --release Changing ct.sym to be module-path oriented, rather than class-path oriented. Reviewed-by: jjg --- .../tools/symbolgenerator/CreateSymbols.java | 111 +++++++++++------- .../javac/platform/JDKPlatformProvider.java | 83 +++++++------ .../ReleaseModulesAndTypeElement.java | 71 +++++++++++ 3 files changed, 187 insertions(+), 78 deletions(-) create mode 100644 test/langtools/tools/javac/platform/ReleaseModulesAndTypeElement.java diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index efcc4020d5d..3ca12f5195a 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -209,13 +209,15 @@ public class CreateSymbols { * {@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> package2Version2Module = new HashMap<>(); + for (ModuleDescription md : data.modules.values()) { for (ModuleHeaderDescription mhd : md.header) { List versionsList = @@ -224,26 +226,41 @@ public class CreateSymbols { 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 version2Module = package2Version2Module.getOrDefault(classDescription.packge().replace('.', '/'), Collections.emptyMap()); for (ClassHeaderDescription header : classDescription.header) { - switch (ctSymKind) { - case JOINED_VERSIONS: - Set jointVersions = new HashSet<>(); - jointVersions.add(header.versions); - limitJointVersion(jointVersions, classDescription.fields); - limitJointVersion(jointVersions, classDescription.methods); - writeClassesForVersions(ctSymLocation, classDescription, header, jointVersions); - break; - case SEPARATE: - Set versions = new HashSet<>(); - for (char v : header.versions.toCharArray()) { - versions.add("" + v); + Set jointVersions = new HashSet<>(); + jointVersions.add(header.versions); + limitJointVersion(jointVersions, classDescription.fields); + limitJointVersion(jointVersions, classDescription.methods); + Map 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 e : module2Versions.entrySet()) { + Set 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 @@ public class CreateSymbols { 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 @@ public class CreateSymbols { void limitJointVersion(Set jointVersions, List 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 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 @@ public class CreateSymbols { void writeClassesForVersions(String ctSymLocation, ClassDescription classDescription, ClassHeaderDescription header, + String module, Iterable versions) throws IOException { for (String ver : versions) { - writeClass(ctSymLocation, classDescription, header, ver); + writeClass(ctSymLocation, classDescription, header, module, ver); } } @@ -663,11 +685,6 @@ public class CreateSymbols { } } - public enum CtSymKind { - JOINED_VERSIONS, - SEPARATE; - } - // void writeModule(String ctSymLocation, ModuleDescription moduleDescription, @@ -697,7 +714,7 @@ public class CreateSymbols { attributes); Path outputClassFile = Paths.get(ctSymLocation, - version + "-modules", + version, moduleDescription.name, "module-info" + EXTENSION); @@ -713,6 +730,7 @@ public class CreateSymbols { void writeClass(String ctSymLocation, ClassDescription classDescription, ClassHeaderDescription header, + String module, String version) throws IOException { List constantPool = new ArrayList<>(); constantPool.add(null); @@ -765,7 +783,13 @@ public class CreateSymbols { 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 @@ public class CreateSymbols { new CreateSymbols().createSymbols(ctDescriptionFileExtra, ctDescriptionFile, - ctSymLocation, - CtSymKind.JOINED_VERSIONS); + ctSymLocation); break; } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java index 22fa43c991d..c8b25dc581a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java @@ -45,6 +45,7 @@ import java.util.HashMap; 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.StandardJavaFileManager; 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 @@ public class JDKPlatformProvider implements PlatformProvider { ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, null)); } - List 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 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 (!hasModules) { + List paths = new ArrayList<>(); - if (Files.isRegularFile(systemModules)) { - fm.handleOption("--system", Arrays.asList("none").iterator()); - - Path jrtModules = - FileSystems.getFileSystem(URI.create("jrt:/")) - .getPath("modules"); - try (Stream lines = - Files.lines(systemModules, utf8)) { - lines.map(line -> jrtModules.resolve(line)) - .filter(mod -> Files.exists(mod)) - .forEach(mod -> setModule(fm, mod)); + try (DirectoryStream dir = Files.newDirectoryStream(root)) { + for (Path section : dir) { + if (section.getFileName().toString().contains(ctSymVersion) && + !section.getFileName().toString().contains("-")) { + try (DirectoryStream modules = Files.newDirectoryStream(section)) { + for (Path module : modules) { + paths.add(module); + } } - pathsSet = true; - } else { - paths.add(section); } } } - } - if (Files.isDirectory(modules)) { - try (DirectoryStream 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 lines = + Files.lines(systemModules, utf8)) { + lines.map(line -> jrtModules.resolve(line)) + .filter(mod -> Files.exists(mod)) + .forEach(mod -> setModule(fm, mod)); + } + } else { + Map> module2Paths = new HashMap<>(); + + try (DirectoryStream dir = Files.newDirectoryStream(root)) { + for (Path section : dir) { + if (section.getFileName().toString().contains(ctSymVersion) && + !section.getFileName().toString().contains("-")) { + try (DirectoryStream 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> e : module2Paths.entrySet()) { + fm.setLocationForModule(StandardLocation.SYSTEM_MODULES, + e.getKey(), + e.getValue()); + } } return fm; diff --git a/test/langtools/tools/javac/platform/ReleaseModulesAndTypeElement.java b/test/langtools/tools/javac/platform/ReleaseModulesAndTypeElement.java new file mode 100644 index 00000000000..3806c2ca048 --- /dev/null +++ b/test/langtools/tools/javac/platform/ReleaseModulesAndTypeElement.java @@ -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 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(); + } + +}