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
This commit is contained in:
Jan Lahoda 2018-09-21 12:29:31 +02:00
parent 33c9c89bf0
commit c1033edca8
3 changed files with 187 additions and 78 deletions

View File

@ -209,13 +209,15 @@ public class CreateSymbols {
* {@code ctDescriptionFile}, using the file as a recipe to create the sigfiles. * {@code ctDescriptionFile}, using the file as a recipe to create the sigfiles.
*/ */
@SuppressWarnings("unchecked") @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) LoadDescriptions data = load(ctDescriptionFileExtra != null ? Paths.get(ctDescriptionFileExtra)
: null, : null,
Paths.get(ctDescriptionFile), null); Paths.get(ctDescriptionFile), null);
splitHeaders(data.classes); splitHeaders(data.classes);
Map<String, Map<Character, String>> package2Version2Module = new HashMap<>();
for (ModuleDescription md : data.modules.values()) { for (ModuleDescription md : data.modules.values()) {
for (ModuleHeaderDescription mhd : md.header) { for (ModuleHeaderDescription mhd : md.header) {
List<String> versionsList = List<String> versionsList =
@ -224,26 +226,41 @@ public class CreateSymbols {
md, md,
mhd, mhd,
versionsList); 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) { for (ClassDescription classDescription : data.classes) {
Map<Character, String> version2Module = package2Version2Module.getOrDefault(classDescription.packge().replace('.', '/'), Collections.emptyMap());
for (ClassHeaderDescription header : classDescription.header) { for (ClassHeaderDescription header : classDescription.header) {
switch (ctSymKind) { Set<String> jointVersions = new HashSet<>();
case JOINED_VERSIONS: jointVersions.add(header.versions);
Set<String> jointVersions = new HashSet<>(); limitJointVersion(jointVersions, classDescription.fields);
jointVersions.add(header.versions); limitJointVersion(jointVersions, classDescription.methods);
limitJointVersion(jointVersions, classDescription.fields); Map<String, StringBuilder> module2Versions = new HashMap<>();
limitJointVersion(jointVersions, classDescription.methods); for (char v : header.versions.toCharArray()) {
writeClassesForVersions(ctSymLocation, classDescription, header, jointVersions); String module = version2Module.get(v);
break; if (module == null) {
case SEPARATE: if (v >= '9') {
Set<String> versions = new HashSet<>(); throw new AssertionError("No module for " + classDescription.name +
for (char v : header.versions.toCharArray()) { " and version " + v);
versions.add("" + v);
} }
writeClassesForVersions(ctSymLocation, classDescription, header, versions); module = version2Module.get('9');
break; 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 @@ public class CreateSymbols {
newHeader.innerClasses = header.innerClasses; newHeader.innerClasses = header.innerClasses;
newHeader.runtimeAnnotations = header.runtimeAnnotations; newHeader.runtimeAnnotations = header.runtimeAnnotations;
newHeader.signature = header.signature; newHeader.signature = header.signature;
newHeader.versions = reduce(versions, header.versions); newHeader.versions = reduce(header.versions, versions);
newHeaders.add(newHeader); newHeaders.add(newHeader);
} }
@ -603,26 +620,30 @@ public class CreateSymbols {
void limitJointVersion(Set<String> jointVersions, List<? extends FeatureDescription> features) { void limitJointVersion(Set<String> jointVersions, List<? extends FeatureDescription> features) {
for (FeatureDescription feature : features) { for (FeatureDescription feature : features) {
for (String version : jointVersions) { limitJointVersion(jointVersions, feature.versions);
if (!containsAll(feature.versions, version) && }
!disjoint(feature.versions, version)) { }
StringBuilder featurePart = new StringBuilder();
StringBuilder otherPart = new StringBuilder(); void limitJointVersion(Set<String> jointVersions, String versions) {
for (char v : version.toCharArray()) { for (String version : jointVersions) {
if (feature.versions.indexOf(v) != (-1)) { if (!containsAll(versions, version) &&
featurePart.append(v); !disjoint(versions, version)) {
} else { StringBuilder featurePart = new StringBuilder();
otherPart.append(v); 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, void writeClassesForVersions(String ctSymLocation,
ClassDescription classDescription, ClassDescription classDescription,
ClassHeaderDescription header, ClassHeaderDescription header,
String module,
Iterable<String> versions) Iterable<String> versions)
throws IOException { throws IOException {
for (String ver : versions) { 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;
}
//<editor-fold defaultstate="collapsed" desc="Class Writing"> //<editor-fold defaultstate="collapsed" desc="Class Writing">
void writeModule(String ctSymLocation, void writeModule(String ctSymLocation,
ModuleDescription moduleDescription, ModuleDescription moduleDescription,
@ -697,7 +714,7 @@ public class CreateSymbols {
attributes); attributes);
Path outputClassFile = Paths.get(ctSymLocation, Path outputClassFile = Paths.get(ctSymLocation,
version + "-modules", version,
moduleDescription.name, moduleDescription.name,
"module-info" + EXTENSION); "module-info" + EXTENSION);
@ -713,6 +730,7 @@ public class CreateSymbols {
void writeClass(String ctSymLocation, void writeClass(String ctSymLocation,
ClassDescription classDescription, ClassDescription classDescription,
ClassHeaderDescription header, ClassHeaderDescription header,
String module,
String version) throws IOException { String version) throws IOException {
List<CPInfo> constantPool = new ArrayList<>(); List<CPInfo> constantPool = new ArrayList<>();
constantPool.add(null); constantPool.add(null);
@ -765,7 +783,13 @@ public class CreateSymbols {
methods.toArray(new Method[0]), methods.toArray(new Method[0]),
attributes); 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()); Files.createDirectories(outputClassFile.getParent());
@ -3652,8 +3676,7 @@ public class CreateSymbols {
new CreateSymbols().createSymbols(ctDescriptionFileExtra, new CreateSymbols().createSymbols(ctDescriptionFileExtra,
ctDescriptionFile, ctDescriptionFile,
ctSymLocation, ctSymLocation);
CtSymKind.JOINED_VERSIONS);
break; break;
} }
} }

View File

@ -45,6 +45,7 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
@ -61,6 +62,8 @@ import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation; import javax.tools.StandardLocation;
import com.sun.source.util.Plugin; 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.CacheFSInfo;
import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.jvm.Target;
@ -252,52 +255,64 @@ public class JDKPlatformProvider implements PlatformProvider {
ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, null)); 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(); 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"); Charset utf8 = Charset.forName("UTF-8");
try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) { if (!hasModules) {
for (Path section : dir) { List<Path> paths = new ArrayList<>();
if (section.getFileName().toString().contains(ctSymVersion) &&
!section.getFileName().toString().contains("-")) {
Path systemModules = section.resolve("system-modules");
if (Files.isRegularFile(systemModules)) { try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) {
fm.handleOption("--system", Arrays.asList("none").iterator()); for (Path section : dir) {
if (section.getFileName().toString().contains(ctSymVersion) &&
Path jrtModules = !section.getFileName().toString().contains("-")) {
FileSystems.getFileSystem(URI.create("jrt:/")) try (DirectoryStream<Path> modules = Files.newDirectoryStream(section)) {
.getPath("modules"); for (Path module : modules) {
try (Stream<String> lines = paths.add(module);
Files.lines(systemModules, utf8)) { }
lines.map(line -> jrtModules.resolve(line))
.filter(mod -> Files.exists(mod))
.forEach(mod -> setModule(fm, mod));
} }
pathsSet = true;
} else {
paths.add(section);
} }
} }
} }
}
if (Files.isDirectory(modules)) { fm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, paths);
try (DirectoryStream<Path> dir = Files.newDirectoryStream(modules)) { } else if (Files.isRegularFile(systemModules)) {
fm.handleOption("--system", Arrays.asList("none").iterator()); fm.handleOption("--system", Arrays.asList("none").iterator());
for (Path module : dir) { Path jrtModules =
fm.setLocationForModule(StandardLocation.SYSTEM_MODULES, FileSystems.getFileSystem(URI.create("jrt:/"))
module.getFileName().toString(), .getPath("modules");
Stream.concat(paths.stream(), try (Stream<String> lines =
Stream.of(module)) Files.lines(systemModules, utf8)) {
.collect(Collectors.toList())); 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; return fm;

View File

@ -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();
}
}