8335989: Implement JEP 494: Module Import Declarations (Second Preview)
Reviewed-by: vromero, abimpoudis, mcimadamore, alanb
This commit is contained in:
parent
e7d90b941f
commit
1e97c1c913
@ -1896,6 +1896,11 @@ public class CreateSymbols {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ed.packageName.equals("jdk/internal/javac")) {
|
||||||
|
//keep jdk/internal/javac untouched. It is used to determine participates in preview:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Set<String> usingModules = package2ModulesUsingIt.getOrDefault(ed.packageName(), Set.of());
|
Set<String> usingModules = package2ModulesUsingIt.getOrDefault(ed.packageName(), Set.of());
|
||||||
|
|
||||||
ed.to.retainAll(usingModules);
|
ed.to.retainAll(usingModules);
|
||||||
|
@ -77,7 +77,7 @@ public @interface PreviewFeature {
|
|||||||
@JEP(number=466, title="ClassFile API", status="Second Preview")
|
@JEP(number=466, title="ClassFile API", status="Second Preview")
|
||||||
CLASSFILE_API,
|
CLASSFILE_API,
|
||||||
STREAM_GATHERERS,
|
STREAM_GATHERERS,
|
||||||
@JEP(number=476, title="Module Import Declarations", status="Preview")
|
@JEP(number=494, title="Module Import Declarations", status="Second Preview")
|
||||||
MODULE_IMPORTS,
|
MODULE_IMPORTS,
|
||||||
@JEP(number=478, title="Key Derivation Function API", status="Preview")
|
@JEP(number=478, title="Key Derivation Function API", status="Preview")
|
||||||
KEY_DERIVATION,
|
KEY_DERIVATION,
|
||||||
|
@ -31,6 +31,7 @@ import java.io.EOFException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
|
import java.lang.classfile.ClassFile;
|
||||||
import java.lang.module.InvalidModuleDescriptorException;
|
import java.lang.module.InvalidModuleDescriptorException;
|
||||||
import java.lang.module.ModuleDescriptor;
|
import java.lang.module.ModuleDescriptor;
|
||||||
import java.lang.module.ModuleDescriptor.Builder;
|
import java.lang.module.ModuleDescriptor.Builder;
|
||||||
@ -189,6 +190,7 @@ public final class ModuleInfo {
|
|||||||
|
|
||||||
int minor_version = in.readUnsignedShort();
|
int minor_version = in.readUnsignedShort();
|
||||||
int major_version = in.readUnsignedShort();
|
int major_version = in.readUnsignedShort();
|
||||||
|
boolean isPreview = minor_version == ClassFile.PREVIEW_MINOR_VERSION;
|
||||||
if (!VM.isSupportedModuleDescriptorVersion(major_version, minor_version)) {
|
if (!VM.isSupportedModuleDescriptorVersion(major_version, minor_version)) {
|
||||||
throw invalidModuleDescriptor("Unsupported major.minor version "
|
throw invalidModuleDescriptor("Unsupported major.minor version "
|
||||||
+ major_version + "." + minor_version);
|
+ major_version + "." + minor_version);
|
||||||
@ -248,7 +250,7 @@ public final class ModuleInfo {
|
|||||||
|
|
||||||
switch (attribute_name) {
|
switch (attribute_name) {
|
||||||
case MODULE :
|
case MODULE :
|
||||||
builder = readModuleAttribute(in, cpool, major_version);
|
builder = readModuleAttribute(in, cpool, major_version, isPreview);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODULE_PACKAGES :
|
case MODULE_PACKAGES :
|
||||||
@ -344,7 +346,8 @@ public final class ModuleInfo {
|
|||||||
* Reads the Module attribute, returning the ModuleDescriptor.Builder to
|
* Reads the Module attribute, returning the ModuleDescriptor.Builder to
|
||||||
* build the corresponding ModuleDescriptor.
|
* build the corresponding ModuleDescriptor.
|
||||||
*/
|
*/
|
||||||
private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major)
|
private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major,
|
||||||
|
boolean isPreview)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
// module_name
|
// module_name
|
||||||
@ -405,14 +408,23 @@ public final class ModuleInfo {
|
|||||||
throw invalidModuleDescriptor("The requires entry for java.base"
|
throw invalidModuleDescriptor("The requires entry for java.base"
|
||||||
+ " has ACC_SYNTHETIC set");
|
+ " has ACC_SYNTHETIC set");
|
||||||
}
|
}
|
||||||
|
// requires transitive java.base is illegal unless:
|
||||||
|
// - the major version is 53 (JDK 9), or:
|
||||||
|
// - the classfile is a preview classfile, or:
|
||||||
|
// - the module is deemed to be participating in preview
|
||||||
|
// (i.e. the module is a java.* module)
|
||||||
|
// requires static java.base is illegal unless:
|
||||||
|
// - the major version is 53 (JDK 9), or:
|
||||||
if (major >= 54
|
if (major >= 54
|
||||||
&& (mods.contains(Requires.Modifier.TRANSITIVE)
|
&& ((mods.contains(Requires.Modifier.TRANSITIVE)
|
||||||
|
&& !isPreview
|
||||||
|
&& !"java.se".equals(mn))
|
||||||
|| mods.contains(Requires.Modifier.STATIC))) {
|
|| mods.contains(Requires.Modifier.STATIC))) {
|
||||||
String flagName;
|
String flagName;
|
||||||
if (mods.contains(Requires.Modifier.TRANSITIVE)) {
|
if (mods.contains(Requires.Modifier.STATIC)) {
|
||||||
flagName = "ACC_TRANSITIVE";
|
|
||||||
} else {
|
|
||||||
flagName = "ACC_STATIC_PHASE";
|
flagName = "ACC_STATIC_PHASE";
|
||||||
|
} else {
|
||||||
|
flagName = "ACC_TRANSITIVE";
|
||||||
}
|
}
|
||||||
throw invalidModuleDescriptor("The requires entry for java.base"
|
throw invalidModuleDescriptor("The requires entry for java.base"
|
||||||
+ " has " + flagName + " set");
|
+ " has " + flagName + " set");
|
||||||
|
@ -154,6 +154,7 @@ module java.base {
|
|||||||
exports jdk.internal.javac to
|
exports jdk.internal.javac to
|
||||||
java.compiler,
|
java.compiler,
|
||||||
java.desktop, // for ScopedValue
|
java.desktop, // for ScopedValue
|
||||||
|
java.se, // for ParticipatesInPreview
|
||||||
jdk.compiler,
|
jdk.compiler,
|
||||||
jdk.incubator.vector, // participates in preview features
|
jdk.incubator.vector, // participates in preview features
|
||||||
jdk.jartool, // participates in preview features
|
jdk.jartool, // participates in preview features
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import jdk.internal.javac.ParticipatesInPreview;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the API of the Java SE Platform.
|
* Defines the API of the Java SE Platform.
|
||||||
*
|
*
|
||||||
@ -38,7 +40,9 @@
|
|||||||
* @moduleGraph
|
* @moduleGraph
|
||||||
* @since 9
|
* @since 9
|
||||||
*/
|
*/
|
||||||
|
@ParticipatesInPreview
|
||||||
module java.se {
|
module java.se {
|
||||||
|
requires transitive java.base;
|
||||||
requires transitive java.compiler;
|
requires transitive java.compiler;
|
||||||
requires transitive java.datatransfer;
|
requires transitive java.datatransfer;
|
||||||
requires transitive java.desktop;
|
requires transitive java.desktop;
|
||||||
|
@ -87,12 +87,26 @@ public class JavacScope implements com.sun.source.tree.Scope {
|
|||||||
} else {
|
} else {
|
||||||
// synthesize an outermost "star-import" scope
|
// synthesize an outermost "star-import" scope
|
||||||
return new JavacScope(env) {
|
return new JavacScope(env) {
|
||||||
public boolean isStarImportScope() {
|
@Override
|
||||||
return true;
|
public ScopeType getScopeType() {
|
||||||
|
return ScopeType.STAR_IMPORT;
|
||||||
}
|
}
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
@DefinedBy(Api.COMPILER_TREE)
|
||||||
public JavacScope getEnclosingScope() {
|
public JavacScope getEnclosingScope() {
|
||||||
return null;
|
return new JavacScope(env) {
|
||||||
|
@Override
|
||||||
|
public ScopeType getScopeType() {
|
||||||
|
return ScopeType.MODULE_IMPORT;
|
||||||
|
}
|
||||||
|
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||||
|
public JavacScope getEnclosingScope() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||||
|
public Iterable<? extends Element> getLocalElements() {
|
||||||
|
return env.toplevel.moduleImportScope.getSymbols(VALIDATOR);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
@DefinedBy(Api.COMPILER_TREE)
|
||||||
public Iterable<? extends Element> getLocalElements() {
|
public Iterable<? extends Element> getLocalElements() {
|
||||||
@ -122,21 +136,27 @@ public class JavacScope implements com.sun.source.tree.Scope {
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStarImportScope() {
|
public ScopeType getScopeType() {
|
||||||
return false;
|
return ScopeType.ORDINARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
return other instanceof JavacScope javacScope
|
return other instanceof JavacScope javacScope
|
||||||
&& env.equals(javacScope.env)
|
&& env.equals(javacScope.env)
|
||||||
&& isStarImportScope() == javacScope.isStarImportScope();
|
&& getScopeType()== javacScope.getScopeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return env.hashCode() + (isStarImportScope() ? 1 : 0);
|
return env.hashCode() + getScopeType().hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "JavacScope[env=" + env + ",starImport=" + isStarImportScope() + "]";
|
return "JavacScope[env=" + env + ", scope type=" + getScopeType() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum ScopeType {
|
||||||
|
ORDINARY,
|
||||||
|
STAR_IMPORT,
|
||||||
|
MODULE_IMPORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1402,6 +1402,7 @@ public class JavacTrees extends DocTrees {
|
|||||||
jcCompilationUnit.namedImportScope = new NamedImportScope(psym);
|
jcCompilationUnit.namedImportScope = new NamedImportScope(psym);
|
||||||
jcCompilationUnit.packge = psym;
|
jcCompilationUnit.packge = psym;
|
||||||
jcCompilationUnit.starImportScope = new StarImportScope(psym);
|
jcCompilationUnit.starImportScope = new StarImportScope(psym);
|
||||||
|
jcCompilationUnit.moduleImportScope = new StarImportScope(psym);
|
||||||
jcCompilationUnit.toplevelScope = WriteableScope.create(psym);
|
jcCompilationUnit.toplevelScope = WriteableScope.create(psym);
|
||||||
return new TreePath(jcCompilationUnit);
|
return new TreePath(jcCompilationUnit);
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ package com.sun.tools.javac.code;
|
|||||||
|
|
||||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||||
import com.sun.tools.javac.code.Source.Feature;
|
import com.sun.tools.javac.code.Source.Feature;
|
||||||
|
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||||
import com.sun.tools.javac.jvm.Target;
|
import com.sun.tools.javac.jvm.Target;
|
||||||
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
||||||
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
|
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
|
||||||
@ -133,11 +134,23 @@ public class Preview {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return participatesInPreview(syms, s.packge().modle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if module {@code m} is deemed to participate in the preview, and
|
||||||
|
* therefore no warnings or errors will be produced.
|
||||||
|
*
|
||||||
|
* @param syms the symbol table
|
||||||
|
* @param m the module to check
|
||||||
|
* @return true if {@code m} is participating in the preview of {@code previewSymbol}
|
||||||
|
*/
|
||||||
|
public boolean participatesInPreview(Symtab syms, ModuleSymbol m) {
|
||||||
// If java.base's jdk.internal.javac package is exported to s's module then
|
// If java.base's jdk.internal.javac package is exported to s's module then
|
||||||
// s participates in the preview API
|
// s participates in the preview API
|
||||||
return syms.java_base.exports.stream()
|
return syms.java_base.exports.stream()
|
||||||
.filter(ed -> ed.packge.fullname == names.jdk_internal_javac)
|
.filter(ed -> ed.packge.fullname == names.jdk_internal_javac)
|
||||||
.anyMatch(ed -> ed.modules.contains(s.packge().modle));
|
.anyMatch(ed -> ed.modules.contains(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -211,6 +224,7 @@ public class Preview {
|
|||||||
case FLEXIBLE_CONSTRUCTORS -> true;
|
case FLEXIBLE_CONSTRUCTORS -> true;
|
||||||
case PRIMITIVE_PATTERNS -> true;
|
case PRIMITIVE_PATTERNS -> true;
|
||||||
case MODULE_IMPORTS -> true;
|
case MODULE_IMPORTS -> true;
|
||||||
|
case JAVA_BASE_TRANSITIVE -> true;
|
||||||
//Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
|
//Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
|
||||||
//When real preview features will be added, this method can be implemented to return 'true'
|
//When real preview features will be added, this method can be implemented to return 'true'
|
||||||
//for those selected features, and 'false' for all the others.
|
//for those selected features, and 'false' for all the others.
|
||||||
|
@ -262,6 +262,7 @@ public enum Source {
|
|||||||
PRIMITIVE_PATTERNS(JDK23, Fragments.FeaturePrimitivePatterns, DiagKind.PLURAL),
|
PRIMITIVE_PATTERNS(JDK23, Fragments.FeaturePrimitivePatterns, DiagKind.PLURAL),
|
||||||
FLEXIBLE_CONSTRUCTORS(JDK22, Fragments.FeatureFlexibleConstructors, DiagKind.NORMAL),
|
FLEXIBLE_CONSTRUCTORS(JDK22, Fragments.FeatureFlexibleConstructors, DiagKind.NORMAL),
|
||||||
MODULE_IMPORTS(JDK23, Fragments.FeatureModuleImports, DiagKind.PLURAL),
|
MODULE_IMPORTS(JDK23, Fragments.FeatureModuleImports, DiagKind.PLURAL),
|
||||||
|
JAVA_BASE_TRANSITIVE(JDK24, Fragments.FeatureJavaBaseTransitive, DiagKind.PLURAL),
|
||||||
PRIVATE_MEMBERS_IN_PERMITS_CLAUSE(JDK19),
|
PRIVATE_MEMBERS_IN_PERMITS_CLAUSE(JDK19),
|
||||||
ERASE_POLY_SIG_RETURN_TYPE(JDK24),
|
ERASE_POLY_SIG_RETURN_TYPE(JDK24),
|
||||||
;
|
;
|
||||||
|
@ -223,6 +223,7 @@ public class Enter extends JCTree.Visitor {
|
|||||||
tree.toplevelScope = WriteableScope.create(tree.packge);
|
tree.toplevelScope = WriteableScope.create(tree.packge);
|
||||||
tree.namedImportScope = new NamedImportScope(tree.packge);
|
tree.namedImportScope = new NamedImportScope(tree.packge);
|
||||||
tree.starImportScope = new StarImportScope(tree.packge);
|
tree.starImportScope = new StarImportScope(tree.packge);
|
||||||
|
tree.moduleImportScope = new StarImportScope(tree.packge);
|
||||||
localEnv.info.scope = tree.toplevelScope;
|
localEnv.info.scope = tree.toplevelScope;
|
||||||
localEnv.info.lint = lint;
|
localEnv.info.lint = lint;
|
||||||
return localEnv;
|
return localEnv;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -64,8 +64,11 @@ import com.sun.tools.javac.code.Directive.RequiresFlag;
|
|||||||
import com.sun.tools.javac.code.Directive.UsesDirective;
|
import com.sun.tools.javac.code.Directive.UsesDirective;
|
||||||
import com.sun.tools.javac.code.Flags;
|
import com.sun.tools.javac.code.Flags;
|
||||||
import com.sun.tools.javac.code.Flags.Flag;
|
import com.sun.tools.javac.code.Flags.Flag;
|
||||||
|
import com.sun.tools.javac.code.Kinds;
|
||||||
|
import com.sun.tools.javac.code.Lint;
|
||||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||||
import com.sun.tools.javac.code.ModuleFinder;
|
import com.sun.tools.javac.code.ModuleFinder;
|
||||||
|
import com.sun.tools.javac.code.Preview;
|
||||||
import com.sun.tools.javac.code.Source;
|
import com.sun.tools.javac.code.Source;
|
||||||
import com.sun.tools.javac.code.Source.Feature;
|
import com.sun.tools.javac.code.Source.Feature;
|
||||||
import com.sun.tools.javac.code.Symbol;
|
import com.sun.tools.javac.code.Symbol;
|
||||||
@ -74,6 +77,7 @@ import com.sun.tools.javac.code.Symbol.Completer;
|
|||||||
import com.sun.tools.javac.code.Symbol.CompletionFailure;
|
import com.sun.tools.javac.code.Symbol.CompletionFailure;
|
||||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||||
import com.sun.tools.javac.code.Symbol.ModuleFlags;
|
import com.sun.tools.javac.code.Symbol.ModuleFlags;
|
||||||
|
import com.sun.tools.javac.code.Symbol.ModuleResolutionFlags;
|
||||||
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||||
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
import com.sun.tools.javac.code.Symbol.PackageSymbol;
|
||||||
import com.sun.tools.javac.code.Symtab;
|
import com.sun.tools.javac.code.Symtab;
|
||||||
@ -99,6 +103,7 @@ import com.sun.tools.javac.tree.JCTree.Tag;
|
|||||||
import com.sun.tools.javac.tree.TreeInfo;
|
import com.sun.tools.javac.tree.TreeInfo;
|
||||||
import com.sun.tools.javac.util.Assert;
|
import com.sun.tools.javac.util.Assert;
|
||||||
import com.sun.tools.javac.util.Context;
|
import com.sun.tools.javac.util.Context;
|
||||||
|
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||||
import com.sun.tools.javac.util.List;
|
import com.sun.tools.javac.util.List;
|
||||||
import com.sun.tools.javac.util.ListBuffer;
|
import com.sun.tools.javac.util.ListBuffer;
|
||||||
@ -112,14 +117,9 @@ import static com.sun.tools.javac.code.Flags.ENUM;
|
|||||||
import static com.sun.tools.javac.code.Flags.PUBLIC;
|
import static com.sun.tools.javac.code.Flags.PUBLIC;
|
||||||
import static com.sun.tools.javac.code.Flags.UNATTRIBUTED;
|
import static com.sun.tools.javac.code.Flags.UNATTRIBUTED;
|
||||||
|
|
||||||
import com.sun.tools.javac.code.Kinds;
|
|
||||||
|
|
||||||
import static com.sun.tools.javac.code.Kinds.Kind.ERR;
|
import static com.sun.tools.javac.code.Kinds.Kind.ERR;
|
||||||
import static com.sun.tools.javac.code.Kinds.Kind.MDL;
|
import static com.sun.tools.javac.code.Kinds.Kind.MDL;
|
||||||
import static com.sun.tools.javac.code.Kinds.Kind.MTH;
|
import static com.sun.tools.javac.code.Kinds.Kind.MTH;
|
||||||
import com.sun.tools.javac.code.Lint;
|
|
||||||
|
|
||||||
import com.sun.tools.javac.code.Symbol.ModuleResolutionFlags;
|
|
||||||
|
|
||||||
import static com.sun.tools.javac.code.TypeTag.CLASS;
|
import static com.sun.tools.javac.code.TypeTag.CLASS;
|
||||||
|
|
||||||
@ -141,6 +141,7 @@ public class Modules extends JCTree.Visitor {
|
|||||||
private final Symtab syms;
|
private final Symtab syms;
|
||||||
private final Attr attr;
|
private final Attr attr;
|
||||||
private final Check chk;
|
private final Check chk;
|
||||||
|
private final Preview preview;
|
||||||
private final DeferredLintHandler deferredLintHandler;
|
private final DeferredLintHandler deferredLintHandler;
|
||||||
private final TypeEnvs typeEnvs;
|
private final TypeEnvs typeEnvs;
|
||||||
private final Types types;
|
private final Types types;
|
||||||
@ -150,6 +151,7 @@ public class Modules extends JCTree.Visitor {
|
|||||||
private final Target target;
|
private final Target target;
|
||||||
private final boolean allowModules;
|
private final boolean allowModules;
|
||||||
private final boolean allowAccessIntoSystem;
|
private final boolean allowAccessIntoSystem;
|
||||||
|
private final boolean allowRequiresTransitiveJavaBase;
|
||||||
|
|
||||||
public final boolean multiModuleMode;
|
public final boolean multiModuleMode;
|
||||||
|
|
||||||
@ -192,6 +194,7 @@ public class Modules extends JCTree.Visitor {
|
|||||||
syms = Symtab.instance(context);
|
syms = Symtab.instance(context);
|
||||||
attr = Attr.instance(context);
|
attr = Attr.instance(context);
|
||||||
chk = Check.instance(context);
|
chk = Check.instance(context);
|
||||||
|
preview = Preview.instance(context);
|
||||||
deferredLintHandler = DeferredLintHandler.instance(context);
|
deferredLintHandler = DeferredLintHandler.instance(context);
|
||||||
typeEnvs = TypeEnvs.instance(context);
|
typeEnvs = TypeEnvs.instance(context);
|
||||||
moduleFinder = ModuleFinder.instance(context);
|
moduleFinder = ModuleFinder.instance(context);
|
||||||
@ -203,6 +206,12 @@ public class Modules extends JCTree.Visitor {
|
|||||||
Options options = Options.instance(context);
|
Options options = Options.instance(context);
|
||||||
|
|
||||||
allowAccessIntoSystem = options.isUnset(Option.RELEASE);
|
allowAccessIntoSystem = options.isUnset(Option.RELEASE);
|
||||||
|
|
||||||
|
Preview preview = Preview.instance(context);
|
||||||
|
|
||||||
|
allowRequiresTransitiveJavaBase =
|
||||||
|
Feature.JAVA_BASE_TRANSITIVE.allowedInSource(source) &&
|
||||||
|
(!preview.isPreview(Feature.JAVA_BASE_TRANSITIVE) || preview.isEnabled());
|
||||||
lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
|
lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
|
||||||
|
|
||||||
multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
|
multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
|
||||||
@ -249,7 +258,12 @@ public class Modules extends JCTree.Visitor {
|
|||||||
|
|
||||||
public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) {
|
public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) {
|
||||||
Assert.check(rootModules != null || inInitModules || !allowModules);
|
Assert.check(rootModules != null || inInitModules || !allowModules);
|
||||||
return enter(trees, modules -> {}, c);
|
return enter(trees, modules -> {
|
||||||
|
//make sure java.base is completed in all cases before continuing.
|
||||||
|
//the next steps may query if the current module participates in preview,
|
||||||
|
//and that requires a completed java.base:
|
||||||
|
syms.java_base.complete();
|
||||||
|
}, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean enter(List<JCCompilationUnit> trees, Consumer<Set<ModuleSymbol>> init, ClassSymbol c) {
|
private boolean enter(List<JCCompilationUnit> trees, Consumer<Set<ModuleSymbol>> init, ClassSymbol c) {
|
||||||
@ -807,11 +821,16 @@ public class Modules extends JCTree.Visitor {
|
|||||||
allRequires.add(msym);
|
allRequires.add(msym);
|
||||||
Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class);
|
Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class);
|
||||||
if (tree.isTransitive) {
|
if (tree.isTransitive) {
|
||||||
if (msym == syms.java_base && source.compareTo(Source.JDK10) >= 0) {
|
if (msym == syms.java_base &&
|
||||||
log.error(tree.pos(), Errors.ModifierNotAllowedHere(names.transitive));
|
!allowRequiresTransitiveJavaBase &&
|
||||||
} else {
|
!preview.participatesInPreview(syms, sym)) {
|
||||||
flags.add(RequiresFlag.TRANSITIVE);
|
if (source.compareTo(Source.JDK10) >= 0) {
|
||||||
|
log.error(DiagnosticFlag.SOURCE_LEVEL,
|
||||||
|
tree.pos(),
|
||||||
|
Feature.JAVA_BASE_TRANSITIVE.error(source.name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
flags.add(RequiresFlag.TRANSITIVE);
|
||||||
}
|
}
|
||||||
if (tree.isStaticPhase) {
|
if (tree.isStaticPhase) {
|
||||||
if (msym == syms.java_base && source.compareTo(Source.JDK10) >= 0) {
|
if (msym == syms.java_base && source.compareTo(Source.JDK10) >= 0) {
|
||||||
|
@ -2149,23 +2149,32 @@ public class Resolve {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
private final RecoveryLoadClass starImportScopeRecovery = (env, name) -> {
|
private final RecoveryLoadClass starImportScopeRecovery =
|
||||||
Scope importScope = env.toplevel.starImportScope;
|
onDemandImportScopeRecovery(false);
|
||||||
Symbol existing = importScope.findFirst(Convert.shortName(name),
|
|
||||||
sym -> sym.kind == TYP && sym.flatName() == name);
|
|
||||||
|
|
||||||
if (existing != null) {
|
private final RecoveryLoadClass moduleImportScopeRecovery =
|
||||||
try {
|
onDemandImportScopeRecovery(true);
|
||||||
existing = finder.loadClass(existing.packge().modle, name);
|
|
||||||
|
|
||||||
return new InvisibleSymbolError(env, true, existing);
|
private RecoveryLoadClass onDemandImportScopeRecovery(boolean moduleImportScope) {
|
||||||
} catch (CompletionFailure cf) {
|
return (env, name) -> {
|
||||||
//ignore
|
Scope importScope = moduleImportScope ? env.toplevel.moduleImportScope
|
||||||
|
: env.toplevel.starImportScope;
|
||||||
|
Symbol existing = importScope.findFirst(Convert.shortName(name),
|
||||||
|
sym -> sym.kind == TYP && sym.flatName() == name);
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
try {
|
||||||
|
existing = finder.loadClass(existing.packge().modle, name);
|
||||||
|
|
||||||
|
return new InvisibleSymbolError(env, true, existing);
|
||||||
|
} catch (CompletionFailure cf) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Symbol lookupPackage(Env<AttrContext> env, Name name) {
|
Symbol lookupPackage(Env<AttrContext> env, Name name) {
|
||||||
PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, name);
|
PackageSymbol pack = syms.lookupPackage(env.toplevel.modle, name);
|
||||||
@ -2433,6 +2442,11 @@ public class Resolve {
|
|||||||
sym = findGlobalType(env, env.toplevel.starImportScope, name, starImportScopeRecovery);
|
sym = findGlobalType(env, env.toplevel.starImportScope, name, starImportScopeRecovery);
|
||||||
if (sym.exists()) return sym;
|
if (sym.exists()) return sym;
|
||||||
else bestSoFar = bestOf(bestSoFar, sym);
|
else bestSoFar = bestOf(bestSoFar, sym);
|
||||||
|
|
||||||
|
sym = findGlobalType(env, env.toplevel.moduleImportScope, name, moduleImportScopeRecovery);
|
||||||
|
if (sym.exists()) return sym;
|
||||||
|
|
||||||
|
else bestSoFar = bestOf(bestSoFar, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestSoFar;
|
return bestSoFar;
|
||||||
|
@ -220,6 +220,7 @@ public class TypeEnter implements Completer {
|
|||||||
chk.checkImportedPackagesObservable(toplevel);
|
chk.checkImportedPackagesObservable(toplevel);
|
||||||
toplevel.namedImportScope.finalizeScope();
|
toplevel.namedImportScope.finalizeScope();
|
||||||
toplevel.starImportScope.finalizeScope();
|
toplevel.starImportScope.finalizeScope();
|
||||||
|
toplevel.moduleImportScope.finalizeScope();
|
||||||
} catch (CompletionFailure cf) {
|
} catch (CompletionFailure cf) {
|
||||||
chk.completionError(toplevel.pos(), cf);
|
chk.completionError(toplevel.pos(), cf);
|
||||||
} finally {
|
} finally {
|
||||||
@ -331,7 +332,7 @@ public class TypeEnter implements Completer {
|
|||||||
throw new Abort();
|
throw new Abort();
|
||||||
}
|
}
|
||||||
importAll(make.at(tree.pos()).Import(make.Select(make.QualIdent(javaLang.owner), javaLang), false),
|
importAll(make.at(tree.pos()).Import(make.Select(make.QualIdent(javaLang.owner), javaLang), false),
|
||||||
javaLang, env);
|
javaLang, env, false);
|
||||||
|
|
||||||
List<JCTree> defs = tree.getTypeDecls();
|
List<JCTree> defs = tree.getTypeDecls();
|
||||||
boolean isImplicitClass = !defs.isEmpty() &&
|
boolean isImplicitClass = !defs.isEmpty() &&
|
||||||
@ -341,7 +342,7 @@ public class TypeEnter implements Completer {
|
|||||||
doModuleImport(make.ModuleImport(make.QualIdent(syms.java_base)));
|
doModuleImport(make.ModuleImport(make.QualIdent(syms.java_base)));
|
||||||
if (peekTypeExists(syms.ioType.tsym)) {
|
if (peekTypeExists(syms.ioType.tsym)) {
|
||||||
doImport(make.Import(make.Select(make.QualIdent(syms.ioType.tsym),
|
doImport(make.Import(make.Select(make.QualIdent(syms.ioType.tsym),
|
||||||
names.asterisk), true));
|
names.asterisk), true), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,7 +414,7 @@ public class TypeEnter implements Completer {
|
|||||||
if (imp instanceof JCModuleImport mimp) {
|
if (imp instanceof JCModuleImport mimp) {
|
||||||
doModuleImport(mimp);
|
doModuleImport(mimp);
|
||||||
} else {
|
} else {
|
||||||
doImport((JCImport) imp);
|
doImport((JCImport) imp, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,7 +439,7 @@ public class TypeEnter implements Completer {
|
|||||||
annotate.annotateLater(tree.annotations, env, env.toplevel.packge, tree.pos());
|
annotate.annotateLater(tree.annotations, env, env.toplevel.packge, tree.pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doImport(JCImport tree) {
|
private void doImport(JCImport tree, boolean fromModuleImport) {
|
||||||
JCFieldAccess imp = tree.qualid;
|
JCFieldAccess imp = tree.qualid;
|
||||||
Name name = TreeInfo.name(imp);
|
Name name = TreeInfo.name(imp);
|
||||||
|
|
||||||
@ -450,16 +451,20 @@ public class TypeEnter implements Completer {
|
|||||||
if (name == names.asterisk) {
|
if (name == names.asterisk) {
|
||||||
// Import on demand.
|
// Import on demand.
|
||||||
chk.checkCanonical(imp.selected);
|
chk.checkCanonical(imp.selected);
|
||||||
if (tree.staticImport)
|
if (tree.staticImport) {
|
||||||
|
Assert.check(!fromModuleImport);
|
||||||
importStaticAll(tree, p, env);
|
importStaticAll(tree, p, env);
|
||||||
else
|
} else {
|
||||||
importAll(tree, p, env);
|
importAll(tree, p, env, fromModuleImport);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Named type import.
|
// Named type import.
|
||||||
if (tree.staticImport) {
|
if (tree.staticImport) {
|
||||||
|
Assert.check(!fromModuleImport);
|
||||||
importNamedStatic(tree, p, name, localEnv);
|
importNamedStatic(tree, p, name, localEnv);
|
||||||
chk.checkCanonical(imp.selected);
|
chk.checkCanonical(imp.selected);
|
||||||
} else {
|
} else {
|
||||||
|
Assert.check(!fromModuleImport);
|
||||||
Type importedType = attribImportType(imp, localEnv);
|
Type importedType = attribImportType(imp, localEnv);
|
||||||
Type originalType = importedType.getOriginalType();
|
Type originalType = importedType.getOriginalType();
|
||||||
TypeSymbol c = originalType.hasTag(CLASS) ? originalType.tsym : importedType.tsym;
|
TypeSymbol c = originalType.hasTag(CLASS) ? originalType.tsym : importedType.tsym;
|
||||||
@ -506,7 +511,7 @@ public class TypeEnter implements Completer {
|
|||||||
JCImport nestedImport = make.at(tree.pos)
|
JCImport nestedImport = make.at(tree.pos)
|
||||||
.Import(make.Select(make.QualIdent(pkg), names.asterisk), false);
|
.Import(make.Select(make.QualIdent(pkg), names.asterisk), false);
|
||||||
|
|
||||||
doImport(nestedImport);
|
doImport(nestedImport, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RequiresDirective requires : currentModule.requires) {
|
for (RequiresDirective requires : currentModule.requires) {
|
||||||
@ -542,8 +547,13 @@ public class TypeEnter implements Completer {
|
|||||||
*/
|
*/
|
||||||
private void importAll(JCImport imp,
|
private void importAll(JCImport imp,
|
||||||
final TypeSymbol tsym,
|
final TypeSymbol tsym,
|
||||||
Env<AttrContext> env) {
|
Env<AttrContext> env,
|
||||||
env.toplevel.starImportScope.importAll(types, tsym.members(), typeImportFilter, imp, cfHandler);
|
boolean fromModuleImport) {
|
||||||
|
StarImportScope targetScope =
|
||||||
|
fromModuleImport ? env.toplevel.moduleImportScope
|
||||||
|
: env.toplevel.starImportScope;
|
||||||
|
|
||||||
|
targetScope.importAll(types, tsym.members(), typeImportFilter, imp, cfHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Import all static members of a class or package on demand.
|
/** Import all static members of a class or package on demand.
|
||||||
|
@ -199,6 +199,9 @@ public class ClassReader {
|
|||||||
/** The minor version number of the class file being read. */
|
/** The minor version number of the class file being read. */
|
||||||
int minorVersion;
|
int minorVersion;
|
||||||
|
|
||||||
|
/** true if the class file being read is a preview class file. */
|
||||||
|
boolean previewClassFile;
|
||||||
|
|
||||||
/** UTF-8 validation level */
|
/** UTF-8 validation level */
|
||||||
Convert.Validation utf8validation;
|
Convert.Validation utf8validation;
|
||||||
|
|
||||||
@ -1200,7 +1203,9 @@ public class ClassReader {
|
|||||||
ModuleSymbol rsym = poolReader.getModule(nextChar());
|
ModuleSymbol rsym = poolReader.getModule(nextChar());
|
||||||
Set<RequiresFlag> flags = readRequiresFlags(nextChar());
|
Set<RequiresFlag> flags = readRequiresFlags(nextChar());
|
||||||
if (rsym == syms.java_base && majorVersion >= V54.major) {
|
if (rsym == syms.java_base && majorVersion >= V54.major) {
|
||||||
if (flags.contains(RequiresFlag.TRANSITIVE)) {
|
if (flags.contains(RequiresFlag.TRANSITIVE) &&
|
||||||
|
(majorVersion != Version.MAX().major || !previewClassFile) &&
|
||||||
|
!preview.participatesInPreview(syms, msym)) {
|
||||||
throw badClassFile("bad.requires.flag", RequiresFlag.TRANSITIVE);
|
throw badClassFile("bad.requires.flag", RequiresFlag.TRANSITIVE);
|
||||||
}
|
}
|
||||||
if (flags.contains(RequiresFlag.STATIC_PHASE)) {
|
if (flags.contains(RequiresFlag.STATIC_PHASE)) {
|
||||||
@ -3185,7 +3190,7 @@ public class ClassReader {
|
|||||||
majorVersion = nextChar();
|
majorVersion = nextChar();
|
||||||
int maxMajor = Version.MAX().major;
|
int maxMajor = Version.MAX().major;
|
||||||
int maxMinor = Version.MAX().minor;
|
int maxMinor = Version.MAX().minor;
|
||||||
boolean previewClassFile =
|
previewClassFile =
|
||||||
minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
|
minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
|
||||||
if (majorVersion > maxMajor ||
|
if (majorVersion > maxMajor ||
|
||||||
majorVersion * 1000 + minorVersion <
|
majorVersion * 1000 + minorVersion <
|
||||||
|
@ -921,10 +921,6 @@ compiler.misc.unexpected.ret.val=\
|
|||||||
compiler.err.mod.not.allowed.here=\
|
compiler.err.mod.not.allowed.here=\
|
||||||
modifier {0} not allowed here
|
modifier {0} not allowed here
|
||||||
|
|
||||||
# 0: name
|
|
||||||
compiler.err.modifier.not.allowed.here=\
|
|
||||||
modifier {0} not allowed here
|
|
||||||
|
|
||||||
compiler.err.intf.not.allowed.here=\
|
compiler.err.intf.not.allowed.here=\
|
||||||
interface not allowed here
|
interface not allowed here
|
||||||
|
|
||||||
@ -3252,6 +3248,9 @@ compiler.misc.feature.flexible.constructors=\
|
|||||||
compiler.misc.feature.module.imports=\
|
compiler.misc.feature.module.imports=\
|
||||||
module imports
|
module imports
|
||||||
|
|
||||||
|
compiler.misc.feature.java.base.transitive=\
|
||||||
|
transitive modifier for java.base
|
||||||
|
|
||||||
compiler.warn.underscore.as.identifier=\
|
compiler.warn.underscore.as.identifier=\
|
||||||
as of release 9, ''_'' is a keyword, and may not be used as an identifier
|
as of release 9, ''_'' is a keyword, and may not be used as an identifier
|
||||||
|
|
||||||
|
@ -538,6 +538,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
public NamedImportScope namedImportScope;
|
public NamedImportScope namedImportScope;
|
||||||
/** A scope for all import-on-demands. */
|
/** A scope for all import-on-demands. */
|
||||||
public StarImportScope starImportScope;
|
public StarImportScope starImportScope;
|
||||||
|
/** A scope for all single module imports. */
|
||||||
|
public StarImportScope moduleImportScope;
|
||||||
/** Line starting positions, defined only if option -g is set. */
|
/** Line starting positions, defined only if option -g is set. */
|
||||||
public Position.LineMap lineMap = null;
|
public Position.LineMap lineMap = null;
|
||||||
/** A table that stores all documentation comments indexed by the tree
|
/** A table that stores all documentation comments indexed by the tree
|
||||||
|
@ -1138,26 +1138,17 @@ public class TreeMaker implements JCTree.Factory {
|
|||||||
sym.owner.kind == MTH || sym.owner.kind == VAR) {
|
sym.owner.kind == MTH || sym.owner.kind == VAR) {
|
||||||
return true;
|
return true;
|
||||||
} else if (sym.kind == TYP && toplevel != null) {
|
} else if (sym.kind == TYP && toplevel != null) {
|
||||||
Iterator<Symbol> it = toplevel.namedImportScope.getSymbolsByName(sym.name).iterator();
|
for (Scope scope : new Scope[] {toplevel.namedImportScope,
|
||||||
if (it.hasNext()) {
|
toplevel.packge.members(),
|
||||||
Symbol s = it.next();
|
toplevel.starImportScope,
|
||||||
return
|
toplevel.moduleImportScope}) {
|
||||||
s == sym &&
|
Iterator<Symbol> it = scope.getSymbolsByName(sym.name).iterator();
|
||||||
!it.hasNext();
|
if (it.hasNext()) {
|
||||||
}
|
Symbol s = it.next();
|
||||||
it = toplevel.packge.members().getSymbolsByName(sym.name).iterator();
|
return
|
||||||
if (it.hasNext()) {
|
s == sym &&
|
||||||
Symbol s = it.next();
|
!it.hasNext();
|
||||||
return
|
}
|
||||||
s == sym &&
|
|
||||||
!it.hasNext();
|
|
||||||
}
|
|
||||||
it = toplevel.starImportScope.getSymbolsByName(sym.name).iterator();
|
|
||||||
if (it.hasNext()) {
|
|
||||||
Symbol s = it.next();
|
|
||||||
return
|
|
||||||
s == sym &&
|
|
||||||
!it.hasNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sym.kind == TYP && sym.isImplicit();
|
return sym.kind == TYP && sym.isImplicit();
|
||||||
|
@ -31,10 +31,13 @@
|
|||||||
* @summary Test parsing of module-info.class with different class file versions
|
* @summary Test parsing of module-info.class with different class file versions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.lang.classfile.ClassFile;
|
||||||
import java.lang.module.InvalidModuleDescriptorException;
|
import java.lang.module.InvalidModuleDescriptorException;
|
||||||
import java.lang.module.ModuleDescriptor;
|
import java.lang.module.ModuleDescriptor;
|
||||||
import java.lang.module.ModuleDescriptor.Requires.Modifier;
|
import java.lang.module.ModuleDescriptor.Requires.Modifier;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
|
import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
|
||||||
@ -46,6 +49,8 @@ import org.testng.annotations.Test;
|
|||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
public class ClassFileVersionsTest {
|
public class ClassFileVersionsTest {
|
||||||
|
private static final int PREVIEW_MINOR_VERSION =
|
||||||
|
ClassFile.PREVIEW_MINOR_VERSION;
|
||||||
private static final int FEATURE;
|
private static final int FEATURE;
|
||||||
static {
|
static {
|
||||||
FEATURE = Runtime.version().feature();
|
FEATURE = Runtime.version().feature();
|
||||||
@ -56,26 +61,34 @@ public class ClassFileVersionsTest {
|
|||||||
@DataProvider(name = "supported")
|
@DataProvider(name = "supported")
|
||||||
public Object[][] supported() {
|
public Object[][] supported() {
|
||||||
/*
|
/*
|
||||||
* There are four test cases for JDK 9 and then one test case
|
* There are four test cases for JDK 9, one test case
|
||||||
* for each subsequent JDK version from JDK 10 to the current
|
* for each subsequent JDK version from JDK 10 to the current
|
||||||
* feature release for a total of (4 + (FEATURE - 9) ) =>
|
* feature release, and two tests for the current release with
|
||||||
* (feature - 5) rows.
|
* a preview flag set, for a total of (4 + (FEATURE - 9) + 2)
|
||||||
|
* rows.
|
||||||
*/
|
*/
|
||||||
Object[][] result = new Object[(FEATURE - 5)][];
|
List<Object[]> result = new ArrayList<>(4 + (FEATURE - 9) + 2);
|
||||||
|
|
||||||
// Class file version of JDK 9 is 53.0
|
// Class file version of JDK 9 is 53.0
|
||||||
result[0] = new Object[]{ 53, 0, Set.of()};
|
result.add(new Object[]{ 53, 0, Set.of()});
|
||||||
result[1] = new Object[]{ 53, 0, Set.of(STATIC) };
|
result.add(new Object[]{ 53, 0, Set.of(STATIC) });
|
||||||
result[2] = new Object[]{ 53, 0, Set.of(TRANSITIVE) };
|
result.add(new Object[]{ 53, 0, Set.of(TRANSITIVE) });
|
||||||
result[3] = new Object[]{ 53, 0, Set.of(STATIC, TRANSITIVE) };
|
result.add(new Object[]{ 53, 0, Set.of(STATIC, TRANSITIVE) });
|
||||||
|
|
||||||
// Major class file version of JDK N is 44 + n. Create rows
|
// Major class file version of JDK N is 44 + n. Create rows
|
||||||
// for JDK 10 through FEATURE.
|
// for JDK 10 through FEATURE.
|
||||||
for (int i = 4; i < (FEATURE - 5) ; i++) {
|
for (int i = 10; i <= FEATURE; i++) {
|
||||||
result[i] = new Object[]{i + 50, 0, Set.of()};
|
result.add(new Object[]{ 44 + i, 0, Set.of()});
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
result.add(new Object[]{ 44 + FEATURE,
|
||||||
|
PREVIEW_MINOR_VERSION,
|
||||||
|
Set.of()});
|
||||||
|
result.add(new Object[]{ 44 + FEATURE,
|
||||||
|
PREVIEW_MINOR_VERSION,
|
||||||
|
Set.of(TRANSITIVE) });
|
||||||
|
|
||||||
|
return result.toArray(s -> new Object[s][]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// major, minor, modifiers for requires java.base
|
// major, minor, modifiers for requires java.base
|
||||||
@ -84,27 +97,34 @@ public class ClassFileVersionsTest {
|
|||||||
/*
|
/*
|
||||||
* There are three test cases for releases prior to JDK 9,
|
* There are three test cases for releases prior to JDK 9,
|
||||||
* three test cases for each JDK version from JDK 10 to the
|
* three test cases for each JDK version from JDK 10 to the
|
||||||
* current feature release, plus one addition test case for
|
* current feature release, two tests for the current release with
|
||||||
* the next release for a total of (3 + (FEATURE - 9) * 3 + 1)
|
* the preview flag set, plus one addition test case for
|
||||||
|
* the next release for a total of (3 + (FEATURE - 9) * 3 + 2 + 1)
|
||||||
* rows.
|
* rows.
|
||||||
*/
|
*/
|
||||||
int unsupportedCount = 3 + (FEATURE - 9)*3 + 1;
|
List<Object[]> result = new ArrayList<>(3 + (FEATURE - 9) * 3 + 2 + 1);
|
||||||
Object[][] result = new Object[unsupportedCount][];
|
|
||||||
|
|
||||||
result[0] = new Object[]{50, 0, Set.of()}; // JDK 6
|
result.add(new Object[]{50, 0, Set.of()}); // JDK 6
|
||||||
result[1] = new Object[]{51, 0, Set.of()}; // JDK 7
|
result.add(new Object[]{51, 0, Set.of()}); // JDK 7
|
||||||
result[2] = new Object[]{52, 0, Set.of()}; // JDK 8
|
result.add(new Object[]{52, 0, Set.of()}); // JDK 8
|
||||||
|
|
||||||
for (int i = 10; i <= FEATURE ; i++) {
|
for (int i = 10; i <= FEATURE ; i++) {
|
||||||
int base = 3 + (i-10)*3;
|
|
||||||
// Major class file version of JDK N is 44+n
|
// Major class file version of JDK N is 44+n
|
||||||
result[base] = new Object[]{i + 44, 0, Set.of(STATIC)};
|
result.add(new Object[]{i + 44, 0, Set.of(STATIC)});
|
||||||
result[base + 1] = new Object[]{i + 44, 0, Set.of(TRANSITIVE)};
|
result.add(new Object[]{i + 44, 0, Set.of(TRANSITIVE)});
|
||||||
result[base + 2] = new Object[]{i + 44, 0, Set.of(STATIC, TRANSITIVE)};
|
result.add(new Object[]{i + 44, 0, Set.of(STATIC, TRANSITIVE)});
|
||||||
}
|
}
|
||||||
|
|
||||||
result[unsupportedCount - 1] = new Object[]{FEATURE+1+44, 0, Set.of()};
|
result.add(new Object[]{FEATURE + 44,
|
||||||
return result;
|
PREVIEW_MINOR_VERSION,
|
||||||
|
Set.of(STATIC)});
|
||||||
|
result.add(new Object[]{FEATURE + 44,
|
||||||
|
PREVIEW_MINOR_VERSION,
|
||||||
|
Set.of(STATIC, TRANSITIVE)});
|
||||||
|
|
||||||
|
result.add(new Object[]{FEATURE+1+44, 0, Set.of()});
|
||||||
|
|
||||||
|
return result.toArray(s -> new Object[s][]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dataProvider = "supported")
|
@Test(dataProvider = "supported")
|
||||||
|
@ -61,6 +61,8 @@ import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
|
|||||||
import jdk.internal.access.JavaLangModuleAccess;
|
import jdk.internal.access.JavaLangModuleAccess;
|
||||||
import jdk.internal.access.SharedSecrets;
|
import jdk.internal.access.SharedSecrets;
|
||||||
import java.lang.classfile.ClassFile;
|
import java.lang.classfile.ClassFile;
|
||||||
|
import java.lang.classfile.ClassFileVersion;
|
||||||
|
import java.lang.classfile.ClassTransform;
|
||||||
import java.lang.classfile.attribute.ModuleAttribute;
|
import java.lang.classfile.attribute.ModuleAttribute;
|
||||||
import java.lang.constant.PackageDesc;
|
import java.lang.constant.PackageDesc;
|
||||||
import java.lang.constant.ModuleDesc;
|
import java.lang.constant.ModuleDesc;
|
||||||
@ -1522,4 +1524,68 @@ public class ModuleDescriptorTest {
|
|||||||
assertTrue(s.contains("p1"));
|
assertTrue(s.contains("p1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = InvalidModuleDescriptorException.class)
|
||||||
|
public void testRequiresTransitiveJavaBaseNotPermitted1() throws Exception {
|
||||||
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
|
||||||
|
.requires(Set.of(Modifier.TRANSITIVE), "java.base")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ModuleInfoWriter.write(descriptor, baos);
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
|
||||||
|
|
||||||
|
ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = InvalidModuleDescriptorException.class)
|
||||||
|
public void testRequiresTransitiveJavaBaseNotPermitted2() throws Exception {
|
||||||
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
|
||||||
|
.requires(Set.of(Modifier.TRANSITIVE), "java.base")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ModuleInfoWriter.write(descriptor, baos);
|
||||||
|
byte[] bytecode = baos.toByteArray();
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap(bytecode);
|
||||||
|
setClassFileVersion(bb, ClassFile.JAVA_21_VERSION, -1);
|
||||||
|
|
||||||
|
ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRequiresTransitiveJavaBasePermitted() throws Exception {
|
||||||
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
|
||||||
|
.requires(Set.of(Modifier.TRANSITIVE), "java.base")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ModuleInfoWriter.write(descriptor, baos);
|
||||||
|
byte[] bytecode = baos.toByteArray();
|
||||||
|
ByteBuffer bb = ByteBuffer.wrap(bytecode);
|
||||||
|
setClassFileVersion(bb, -1, ClassFile.PREVIEW_MINOR_VERSION);
|
||||||
|
|
||||||
|
descriptor = ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
|
||||||
|
|
||||||
|
assertEquals(descriptor.requires().size(), 1);
|
||||||
|
Requires javaBase = descriptor.requires().iterator().next();
|
||||||
|
assertEquals(javaBase.name(), "java.base");
|
||||||
|
assertEquals(javaBase.modifiers(), Set.of(Modifier.TRANSITIVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Change the classfile versions of the provided classfile to the provided
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* @param bytecode the classfile content to modify
|
||||||
|
* @param major the major classfile version to set,
|
||||||
|
* -1 if the existing version should be kept
|
||||||
|
* @param minor the minor classfile version to set,
|
||||||
|
* -1 if the existing version should be kept
|
||||||
|
*/
|
||||||
|
private void setClassFileVersion(ByteBuffer bb, int major, int minor) {
|
||||||
|
if (minor != (-1)) {
|
||||||
|
bb.putShort(4, (short) minor);
|
||||||
|
}
|
||||||
|
if (major != (-1)) {
|
||||||
|
bb.putShort(6, (short) major);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,32 +26,32 @@
|
|||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
void m1(int m1_arg) {
|
void m1(int m1_arg) {
|
||||||
String x = "Test; 0; 0";
|
String x = "Test; 0; 0; 0";
|
||||||
String y = "Test; 0; 0";
|
String y = "Test; 0; 0; 0";
|
||||||
String z = "Test; 0; 0";
|
String z = "Test; 0; 0; 0";
|
||||||
Object o = new Object() {
|
Object o = new Object() {
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
String p = "-; Test; 0; 0";
|
String p = "-; Test; 0; 0; 0";
|
||||||
String q = "-; Test; 0; 0";
|
String q = "-; Test; 0; 0; 0";
|
||||||
String r = "-; Test; 0; 0";
|
String r = "-; Test; 0; 0; 0";
|
||||||
return (this == other);
|
return (this == other);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
String s = "Test; 0; 0";
|
String s = "Test; 0; 0; 0";
|
||||||
|
|
||||||
boolean b = new Object() {
|
boolean b = new Object() {
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
String p = "-; Test; 0; 0";
|
String p = "-; Test; 0; 0; 0";
|
||||||
String q = "-; Test; 0; 0";
|
String q = "-; Test; 0; 0; 0";
|
||||||
String r = "-; Test; 0; 0";
|
String r = "-; Test; 0; 0; 0";
|
||||||
return (this == other);
|
return (this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
}.equals(null);
|
}.equals(null);
|
||||||
|
|
||||||
class Test2 {
|
class Test2 {
|
||||||
String s = "Test.Test2; Test; 0; 0";
|
String s = "Test.Test2; Test; 0; 0; 0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,29 +23,29 @@
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
//TOPLEVEL_SCOPE:List, Test2, Test; java.io.*, java.lang.*
|
//TOPLEVEL_SCOPE:List, Test2, Test; java.io.*, java.lang.*;
|
||||||
class Test {
|
class Test {
|
||||||
void m1(int m1_arg) {
|
void m1(int m1_arg) {
|
||||||
String x = "x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String x = "x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
String y = "y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String y = "y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
String z = "z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String z = "z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
Object o = new Object() {
|
Object o = new Object() {
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
String p = "p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String p = "p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
String q = "q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String q = "q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
String r = "r, q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String r = "r, q, p, other, super, this; -, o, z, y, x, m1_arg, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
return (this == other);
|
return (this == other);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
String s = "super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String s = "super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
|
|
||||||
boolean b = new Object() {
|
boolean b = new Object() {
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
String p = "p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String p = "p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
String q = "q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String q = "q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
String r = "r, q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
|
String r = "r, q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*;";
|
||||||
return (this == other);
|
return (this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,32 +25,32 @@
|
|||||||
|
|
||||||
class Test {
|
class Test {
|
||||||
void m1(int m1_arg) {
|
void m1(int m1_arg) {
|
||||||
String x = "m1; 0; 0";
|
String x = "m1; 0; 0; 0";
|
||||||
String y = "m1; 0; 0";
|
String y = "m1; 0; 0; 0";
|
||||||
String z = "m1; 0; 0";
|
String z = "m1; 0; 0; 0";
|
||||||
Object o = new Object() {
|
Object o = new Object() {
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
String p = "equals; m1; 0; 0";
|
String p = "equals; m1; 0; 0; 0";
|
||||||
String q = "equals; m1; 0; 0";
|
String q = "equals; m1; 0; 0; 0";
|
||||||
String r = "equals; m1; 0; 0";
|
String r = "equals; m1; 0; 0; 0";
|
||||||
return (this == other);
|
return (this == other);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
String s = "0; 0; 0";
|
String s = "0; 0; 0; 0";
|
||||||
|
|
||||||
boolean b = new Object() {
|
boolean b = new Object() {
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
String p = "equals; 0; 0; 0";
|
String p = "equals; 0; 0; 0; 0";
|
||||||
String q = "equals; 0; 0; 0";
|
String q = "equals; 0; 0; 0; 0";
|
||||||
String r = "equals; 0; 0; 0";
|
String r = "equals; 0; 0; 0; 0";
|
||||||
return (this == other);
|
return (this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
}.equals(null);
|
}.equals(null);
|
||||||
|
|
||||||
class Test2 {
|
class Test2 {
|
||||||
String s = "0; 0; 0; 0";
|
String s = "0; 0; 0; 0; 0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,28 +218,14 @@ public class ImportModule extends TestRunner {
|
|||||||
List<String> actualErrors;
|
List<String> actualErrors;
|
||||||
List<String> expectedErrors;
|
List<String> expectedErrors;
|
||||||
|
|
||||||
actualErrors =
|
new JavacTask(tb)
|
||||||
new JavacTask(tb)
|
.options("--enable-preview", "--release", SOURCE_VERSION,
|
||||||
.options("--enable-preview", "--release", SOURCE_VERSION,
|
"-XDrawDiagnostics")
|
||||||
"-XDrawDiagnostics")
|
.outdir(classes)
|
||||||
.outdir(classes)
|
.files(tb.findJavaFiles(src))
|
||||||
.files(tb.findJavaFiles(src))
|
.run(Task.Expect.SUCCESS)
|
||||||
.run(Task.Expect.FAIL)
|
.writeAll()
|
||||||
.writeAll()
|
.getOutputLines(Task.OutputKind.DIRECT);
|
||||||
.getOutputLines(Task.OutputKind.DIRECT);
|
|
||||||
|
|
||||||
expectedErrors = List.of(
|
|
||||||
"Test.java:5:5: compiler.err.ref.ambiguous: Logger, kindname.interface, java.lang.System.Logger, java.lang.System, kindname.class, java.util.logging.Logger, java.util.logging",
|
|
||||||
"- compiler.note.preview.filename: Test.java, DEFAULT",
|
|
||||||
"- compiler.note.preview.recompile",
|
|
||||||
"1 error"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!Objects.equals(expectedErrors, actualErrors)) {
|
|
||||||
throw new AssertionError("Incorrect Output, expected: " + expectedErrors +
|
|
||||||
", actual: " + out);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
tb.writeJavaFiles(src,
|
tb.writeJavaFiles(src,
|
||||||
"""
|
"""
|
||||||
@ -793,7 +779,7 @@ public class ImportModule extends TestRunner {
|
|||||||
|
|
||||||
if (!Objects.equals(expectedErrors, actualErrors)) {
|
if (!Objects.equals(expectedErrors, actualErrors)) {
|
||||||
throw new AssertionError("Incorrect Output, expected: " + expectedErrors +
|
throw new AssertionError("Incorrect Output, expected: " + expectedErrors +
|
||||||
", actual: " + out);
|
", actual: " + actualErrors);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -843,4 +829,94 @@ public class ImportModule extends TestRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testPackageImportDisambiguates(Path base) throws Exception {
|
||||||
|
Path current = base.resolve(".");
|
||||||
|
Path src = current.resolve("src");
|
||||||
|
Path classes = current.resolve("classes");
|
||||||
|
Path ma = src.resolve("ma");
|
||||||
|
tb.writeJavaFiles(ma,
|
||||||
|
"""
|
||||||
|
module ma {
|
||||||
|
exports ma.p1;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
package ma.p1;
|
||||||
|
public class A {}
|
||||||
|
""");
|
||||||
|
Path mb = src.resolve("mb");
|
||||||
|
tb.writeJavaFiles(mb,
|
||||||
|
"""
|
||||||
|
module mb {
|
||||||
|
exports mb.p1;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
package mb.p1;
|
||||||
|
public class A {}
|
||||||
|
""");
|
||||||
|
Path test = src.resolve("test");
|
||||||
|
tb.writeJavaFiles(test,
|
||||||
|
"""
|
||||||
|
module test {
|
||||||
|
requires ma;
|
||||||
|
requires mb;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
package test;
|
||||||
|
import module ma;
|
||||||
|
import module mb;
|
||||||
|
public class Test {
|
||||||
|
A a;
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
Files.createDirectories(classes);
|
||||||
|
|
||||||
|
List<String> actualErrors = new JavacTask(tb)
|
||||||
|
.options("-XDrawDiagnostics",
|
||||||
|
"--enable-preview", "--release", SOURCE_VERSION,
|
||||||
|
"--module-source-path", src.toString())
|
||||||
|
.outdir(classes)
|
||||||
|
.files(tb.findJavaFiles(src))
|
||||||
|
.run(Task.Expect.FAIL)
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.DIRECT);
|
||||||
|
|
||||||
|
List<String> expectedErrors = List.of(
|
||||||
|
"Test.java:5:5: compiler.err.ref.ambiguous: A, kindname.class, mb.p1.A, mb.p1, kindname.class, ma.p1.A, ma.p1",
|
||||||
|
"- compiler.note.preview.filename: Test.java, DEFAULT",
|
||||||
|
"- compiler.note.preview.recompile",
|
||||||
|
"1 error"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Objects.equals(expectedErrors, actualErrors)) {
|
||||||
|
throw new AssertionError("Incorrect Output, expected: " + expectedErrors +
|
||||||
|
", actual: " + actualErrors);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tb.writeJavaFiles(test,
|
||||||
|
"""
|
||||||
|
package test;
|
||||||
|
import module ma;
|
||||||
|
import module mb;
|
||||||
|
import mb.p1.*;
|
||||||
|
public class Test {
|
||||||
|
A a;
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
Files.createDirectories(classes);
|
||||||
|
|
||||||
|
new JavacTask(tb)
|
||||||
|
.options("-XDrawDiagnostics",
|
||||||
|
"--enable-preview", "--release", SOURCE_VERSION,
|
||||||
|
"--module-source-path", src.toString())
|
||||||
|
.outdir(classes)
|
||||||
|
.files(tb.findJavaFiles(src))
|
||||||
|
.run(Task.Expect.SUCCESS)
|
||||||
|
.writeAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,9 @@ import com.sun.tools.javac.tree.JCTree.JCCase;
|
|||||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||||
import com.sun.tools.javac.util.Context;
|
import com.sun.tools.javac.util.Context;
|
||||||
import com.sun.tools.javac.util.Context.Factory;
|
import com.sun.tools.javac.util.Context.Factory;
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.lang.model.util.ElementFilter;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
|
||||||
import static javax.tools.JavaFileObject.Kind.SOURCE;
|
import static javax.tools.JavaFileObject.Kind.SOURCE;
|
||||||
|
|
||||||
@ -89,6 +92,7 @@ public class TestGetScopeResult {
|
|||||||
new TestGetScopeResult().testLocalRecordAnnotation();
|
new TestGetScopeResult().testLocalRecordAnnotation();
|
||||||
new TestGetScopeResult().testRuleCases();
|
new TestGetScopeResult().testRuleCases();
|
||||||
new TestGetScopeResult().testNestedSwitchExpression();
|
new TestGetScopeResult().testNestedSwitchExpression();
|
||||||
|
new TestGetScopeResult().testModuleImportScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws IOException {
|
public void run() throws IOException {
|
||||||
@ -823,6 +827,64 @@ public class TestGetScopeResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testModuleImportScope() throws IOException {
|
||||||
|
JavacTool c = JavacTool.create();
|
||||||
|
try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) {
|
||||||
|
String code = """
|
||||||
|
import module java.compiler;
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.System;
|
||||||
|
class Test {
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
Context ctx = new Context();
|
||||||
|
TestAnalyzer.preRegister(ctx);
|
||||||
|
JavaFileObject input =
|
||||||
|
SimpleJavaFileObject.forSource(URI.create("myfo:///Test.java"), code);
|
||||||
|
JavacTask t = (JavacTask) c.getTask(null, fm, null, null, null,
|
||||||
|
List.of(input),
|
||||||
|
ctx);
|
||||||
|
CompilationUnitTree cut = t.parse().iterator().next();
|
||||||
|
t.analyze();
|
||||||
|
|
||||||
|
TreePath topLevelClass = new TreePath(new TreePath(cut), cut.getTypeDecls().get(0));
|
||||||
|
Scope scope = Trees.instance(t).getScope(topLevelClass);
|
||||||
|
|
||||||
|
if (scope.getEnclosingClass() == null) {
|
||||||
|
throw new AssertionError("Expected an enclosing class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
scope = scope.getEnclosingScope();
|
||||||
|
|
||||||
|
if (scope.getEnclosingClass() != null) {
|
||||||
|
throw new AssertionError("Did not expect an enclosing class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
asssertScopeContainsTypeWithFQN(scope, "java.lang.System");
|
||||||
|
asssertScopeContainsTypeWithFQN(scope, "Test");
|
||||||
|
|
||||||
|
scope = scope.getEnclosingScope();
|
||||||
|
|
||||||
|
if (scope.getEnclosingClass() != null) {
|
||||||
|
throw new AssertionError("Did not expect an enclosing class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
asssertScopeContainsTypeWithFQN(scope, "java.util.List");
|
||||||
|
|
||||||
|
scope = scope.getEnclosingScope();
|
||||||
|
|
||||||
|
if (scope.getEnclosingClass() != null) {
|
||||||
|
throw new AssertionError("Did not expect an enclosing class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
asssertScopeContainsTypeWithFQN(scope, "javax.tools.ToolProvider");
|
||||||
|
|
||||||
|
if (scope.getEnclosingScope() != null) {
|
||||||
|
throw new AssertionError("Did not expect an enclosing scope.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<String> dumpScope(Scope scope) {
|
private List<String> dumpScope(Scope scope) {
|
||||||
List<String> content = new ArrayList<>();
|
List<String> content = new ArrayList<>();
|
||||||
while (scope.getEnclosingClass() != null) {
|
while (scope.getEnclosingClass() != null) {
|
||||||
@ -833,4 +895,17 @@ public class TestGetScopeResult {
|
|||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void asssertScopeContainsTypeWithFQN(Scope scope, String fqn) {
|
||||||
|
for (TypeElement type : ElementFilter.typesIn(scope.getLocalElements())) {
|
||||||
|
if (type.getQualifiedName().contentEquals(fqn)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AssertionError("Expected to find: " + fqn +
|
||||||
|
" in: " + scope.getLocalElements() +
|
||||||
|
", but it is missing.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// key: compiler.err.modifier.not.allowed.here
|
// key: compiler.err.feature.not.supported.in.source.plural
|
||||||
|
// key: compiler.misc.feature.java.base.transitive
|
||||||
|
|
||||||
module m {
|
module m {
|
||||||
requires transitive java.base;
|
requires transitive java.base;
|
||||||
|
@ -432,6 +432,40 @@ public class ConvenientAccessErrorsTest extends ModuleTestBase {
|
|||||||
throw new Exception("expected output not found; actual: " + log);
|
throw new Exception("expected output not found; actual: " + log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInModuleImport(Path base) throws Exception {
|
||||||
|
Path src = base.resolve("src");
|
||||||
|
Path src_m1 = src.resolve("m1x");
|
||||||
|
tb.writeJavaFiles(src_m1,
|
||||||
|
"module m1x { }",
|
||||||
|
"package api; public class Api { public String test() { return null; } }");
|
||||||
|
Path src_m2 = src.resolve("m2x");
|
||||||
|
tb.writeJavaFiles(src_m2,
|
||||||
|
"module m2x { requires m1x; }",
|
||||||
|
"package test; import module m1x; public class Test { Api api; { api.test().length(); } }");
|
||||||
|
Path classes = base.resolve("classes");
|
||||||
|
tb.createDirectories(classes);
|
||||||
|
|
||||||
|
List<String> log = new JavacTask(tb)
|
||||||
|
.options("-XDrawDiagnostics",
|
||||||
|
"--enable-preview", "--source", System.getProperty("java.specification.version"),
|
||||||
|
"--module-source-path", src.toString())
|
||||||
|
.outdir(classes)
|
||||||
|
.files(findJavaFiles(src))
|
||||||
|
.run(Task.Expect.FAIL)
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.DIRECT);
|
||||||
|
|
||||||
|
List<String> expected = Arrays.asList(
|
||||||
|
"Test.java:1:54: compiler.err.cant.resolve.location: kindname.class, Api, , , (compiler.misc.location: kindname.class, test.Test, null)",
|
||||||
|
"- compiler.note.preview.filename: Test.java, DEFAULT",
|
||||||
|
"- compiler.note.preview.recompile",
|
||||||
|
"1 error");
|
||||||
|
|
||||||
|
if (!expected.equals(log))
|
||||||
|
throw new Exception("expected output not found; actual: " + log);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnusedImportOnDemand2(Path base) throws Exception {
|
public void testUnusedImportOnDemand2(Path base) throws Exception {
|
||||||
Path src = base.resolve("src");
|
Path src = base.resolve("src");
|
||||||
|
@ -73,6 +73,9 @@ import com.sun.tools.javac.api.JavacTaskImpl;
|
|||||||
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
|
||||||
import com.sun.tools.javac.code.Symtab;
|
import com.sun.tools.javac.code.Symtab;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import javax.lang.model.element.ModuleElement.DirectiveKind;
|
||||||
|
|
||||||
import toolbox.JarTask;
|
import toolbox.JarTask;
|
||||||
import toolbox.JavacTask;
|
import toolbox.JavacTask;
|
||||||
@ -1153,4 +1156,90 @@ public class EdgeCases extends ModuleTestBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJavaSEHasRequiresTransitiveJavaBase(Path base) throws Exception {
|
||||||
|
Path src = base.resolve("src");
|
||||||
|
Path a = src.resolve("a");
|
||||||
|
tb.writeJavaFiles(a,
|
||||||
|
"module a { requires java.se; }",
|
||||||
|
"""
|
||||||
|
package test;
|
||||||
|
import module java.se;
|
||||||
|
public class Test {
|
||||||
|
ArrayList<String> l;
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
Path classes = base.resolve("classes");
|
||||||
|
tb.createDirectories(classes);
|
||||||
|
|
||||||
|
AtomicBoolean seenJavaSEDependency = new AtomicBoolean();
|
||||||
|
|
||||||
|
List<String> log;
|
||||||
|
|
||||||
|
log = new JavacTask(tb)
|
||||||
|
.outdir(classes)
|
||||||
|
.options("-XDrawDiagnostics", "-XDshould-stop.at=FLOW")
|
||||||
|
.callback(verifyJavaSEDependency(true, seenJavaSEDependency))
|
||||||
|
.files(findJavaFiles(src))
|
||||||
|
.run(Task.Expect.FAIL)
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.DIRECT);
|
||||||
|
|
||||||
|
List<String> expected = List.of(
|
||||||
|
"Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)",
|
||||||
|
"1 error");
|
||||||
|
|
||||||
|
if (!expected.equals(log))
|
||||||
|
throw new Exception("expected output not found: " + log);
|
||||||
|
|
||||||
|
if (!seenJavaSEDependency.get()) {
|
||||||
|
throw new AssertionError("Didn't find the java.se dependency!");
|
||||||
|
}
|
||||||
|
|
||||||
|
seenJavaSEDependency.set(false);
|
||||||
|
|
||||||
|
new JavacTask(tb)
|
||||||
|
.outdir(classes)
|
||||||
|
.options("--enable-preview",
|
||||||
|
"--source", System.getProperty("java.specification.version"))
|
||||||
|
.callback(verifyJavaSEDependency(true, seenJavaSEDependency))
|
||||||
|
.files(findJavaFiles(src))
|
||||||
|
.run(Task.Expect.SUCCESS)
|
||||||
|
.writeAll()
|
||||||
|
.getOutputLines(Task.OutputKind.DIRECT);
|
||||||
|
|
||||||
|
if (!seenJavaSEDependency.get()) {
|
||||||
|
throw new AssertionError("Didn't find the java.se dependency!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Consumer<com.sun.source.util.JavacTask> verifyJavaSEDependency(
|
||||||
|
boolean expectedTransitive,
|
||||||
|
AtomicBoolean seenJavaSEDependency) {
|
||||||
|
return t -> {
|
||||||
|
t.addTaskListener(new TaskListener() {
|
||||||
|
@Override
|
||||||
|
public void finished(TaskEvent e) {
|
||||||
|
if (e.getKind() == TaskEvent.Kind.ANALYZE) {
|
||||||
|
ModuleElement javaBase =
|
||||||
|
t.getElements().getModuleElement("java.base");
|
||||||
|
ModuleElement javaSE =
|
||||||
|
t.getElements().getModuleElement("java.se");
|
||||||
|
RequiresDirective requiresJavaBase =
|
||||||
|
javaSE.getDirectives()
|
||||||
|
.stream()
|
||||||
|
.filter(d -> d.getKind() == DirectiveKind.REQUIRES)
|
||||||
|
.map(d -> (RequiresDirective) d)
|
||||||
|
.filter(d -> d.getDependency() == javaBase)
|
||||||
|
.findAny()
|
||||||
|
.orElseThrow();
|
||||||
|
if (requiresJavaBase.isTransitive() != expectedTransitive) {
|
||||||
|
throw new AssertionError("Expected: " + expectedTransitive + ", " +
|
||||||
|
"but got: " + requiresJavaBase.isTransitive());
|
||||||
|
}
|
||||||
|
seenJavaSEDependency.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @bug 8193125 8196623
|
* @bug 8193125 8196623 8335989
|
||||||
* @summary test modifiers with java.base
|
* @summary test modifiers with java.base
|
||||||
* @library /tools/lib
|
* @library /tools/lib
|
||||||
* @enablePreview
|
* @enablePreview
|
||||||
@ -49,6 +49,7 @@ import java.lang.classfile.attribute.*;
|
|||||||
|
|
||||||
import com.sun.tools.javac.jvm.Target;
|
import com.sun.tools.javac.jvm.Target;
|
||||||
import com.sun.tools.javac.platform.JDKPlatformProvider;
|
import com.sun.tools.javac.platform.JDKPlatformProvider;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import toolbox.JavacTask;
|
import toolbox.JavacTask;
|
||||||
import toolbox.Task;
|
import toolbox.Task;
|
||||||
@ -56,6 +57,8 @@ import toolbox.ToolBox;
|
|||||||
|
|
||||||
public class JavaBaseTest {
|
public class JavaBaseTest {
|
||||||
|
|
||||||
|
private static final String CURRENT_VERSION = System.getProperty("java.specification.version");
|
||||||
|
|
||||||
public static void main(String... args) throws Exception {
|
public static void main(String... args) throws Exception {
|
||||||
JavaBaseTest t = new JavaBaseTest();
|
JavaBaseTest t = new JavaBaseTest();
|
||||||
t.run();
|
t.run();
|
||||||
@ -75,13 +78,11 @@ public class JavaBaseTest {
|
|||||||
|
|
||||||
void run() throws Exception {
|
void run() throws Exception {
|
||||||
Set<String> targets = new LinkedHashSet<>();
|
Set<String> targets = new LinkedHashSet<>();
|
||||||
StreamSupport.stream(new JDKPlatformProvider().getSupportedPlatformNames()
|
targets.add("9");
|
||||||
.spliterator(),
|
targets.add("10");
|
||||||
false)
|
targets.add("21");
|
||||||
.filter(p -> Integer.parseInt(p) >= 9)
|
|
||||||
.forEach(targets::add);
|
|
||||||
//run without --release:
|
|
||||||
targets.add("current");
|
targets.add("current");
|
||||||
|
targets.add("current-preview");
|
||||||
for (List<String> mods : modifiers) {
|
for (List<String> mods : modifiers) {
|
||||||
for (String target : targets) {
|
for (String target : targets) {
|
||||||
for (Mode mode : Mode.values()) {
|
for (Mode mode : Mode.values()) {
|
||||||
@ -119,15 +120,43 @@ public class JavaBaseTest {
|
|||||||
tb.writeJavaFiles(src,
|
tb.writeJavaFiles(src,
|
||||||
"module m { requires " + String.join(" ", mods) + " java.base; }");
|
"module m { requires " + String.join(" ", mods) + " java.base; }");
|
||||||
Path modules = Files.createDirectories(base.resolve("modules"));
|
Path modules = Files.createDirectories(base.resolve("modules"));
|
||||||
boolean expectOK = target.equals("9");
|
boolean expectOK;
|
||||||
|
|
||||||
JavacTask jct = new JavacTask(tb)
|
JavacTask jct = new JavacTask(tb)
|
||||||
.outdir(modules);
|
.outdir(modules);
|
||||||
|
|
||||||
if (target.equals("current"))
|
List<String> options = new ArrayList<>();
|
||||||
jct.options("-XDrawDiagnostics");
|
|
||||||
else
|
switch (target) {
|
||||||
jct.options("-XDrawDiagnostics", "--release", target);
|
case "current":
|
||||||
|
options.add("--release");
|
||||||
|
options.add(CURRENT_VERSION);
|
||||||
|
expectOK = false;
|
||||||
|
break;
|
||||||
|
case "current-preview":
|
||||||
|
options.add("--enable-preview");
|
||||||
|
options.add("--release");
|
||||||
|
options.add(CURRENT_VERSION);
|
||||||
|
expectOK = true;
|
||||||
|
break;
|
||||||
|
case "9":
|
||||||
|
options.add("--release");
|
||||||
|
options.add(target);
|
||||||
|
expectOK = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
options.add("--release");
|
||||||
|
options.add(target);
|
||||||
|
expectOK = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mods.contains("static") && !"9".equals(target)) {
|
||||||
|
expectOK = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.add("-XDrawDiagnostics");
|
||||||
|
jct.options(options);
|
||||||
|
|
||||||
String log = jct.files(tb.findJavaFiles(src))
|
String log = jct.files(tb.findJavaFiles(src))
|
||||||
.run(expectOK ? Task.Expect.SUCCESS : Task.Expect.FAIL)
|
.run(expectOK ? Task.Expect.SUCCESS : Task.Expect.FAIL)
|
||||||
@ -138,9 +167,9 @@ public class JavaBaseTest {
|
|||||||
boolean foundErrorMessage = false;
|
boolean foundErrorMessage = false;
|
||||||
for (String mod : mods) {
|
for (String mod : mods) {
|
||||||
String key = mod.equals("static")
|
String key = mod.equals("static")
|
||||||
? "compiler.err.mod.not.allowed.here"
|
? "compiler.err.mod.not.allowed.here: " + mod
|
||||||
: "compiler.err.modifier.not.allowed.here";
|
: "compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.java.base.transitive)";
|
||||||
String message = "module-info.java:1:12: " + key + ": " + mod;
|
String message = "module-info.java:1:12: " + key;
|
||||||
if (log.contains(message)) {
|
if (log.contains(message)) {
|
||||||
foundErrorMessage = true;
|
foundErrorMessage = true;
|
||||||
}
|
}
|
||||||
@ -152,18 +181,57 @@ public class JavaBaseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void testClass(Path base, List<String> mods, String target) throws Exception {
|
void testClass(Path base, List<String> mods, String target) throws Exception {
|
||||||
createClass(base, mods, target);
|
boolean expectOK;
|
||||||
|
List<String> options = new ArrayList<>();
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
case "current":
|
||||||
|
options.add("--release");
|
||||||
|
options.add(CURRENT_VERSION);
|
||||||
|
expectOK = false;
|
||||||
|
break;
|
||||||
|
case "current-preview":
|
||||||
|
options.add("--enable-preview");
|
||||||
|
options.add("--release");
|
||||||
|
options.add(CURRENT_VERSION);
|
||||||
|
expectOK = true;
|
||||||
|
break;
|
||||||
|
case "9":
|
||||||
|
options.add("--release");
|
||||||
|
options.add(target);
|
||||||
|
expectOK = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
options.add("--release");
|
||||||
|
options.add(target);
|
||||||
|
expectOK = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mods.contains("static") && !"9".equals(target)) {
|
||||||
|
expectOK = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
createClass(base, mods, options);
|
||||||
|
|
||||||
|
List<String> testOptions = new ArrayList<>();
|
||||||
|
|
||||||
|
testOptions.add("-XDrawDiagnostics");
|
||||||
|
testOptions.add("--module-path"); testOptions.add(base.resolve("test-modules").toString());
|
||||||
|
|
||||||
|
if (options.contains("--enable-preview")) {
|
||||||
|
testOptions.add("--enable-preview");
|
||||||
|
testOptions.add("--source"); testOptions.add(CURRENT_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
Path src = base.resolve("src");
|
Path src = base.resolve("src");
|
||||||
tb.writeJavaFiles(src,
|
tb.writeJavaFiles(src,
|
||||||
"module mx { requires m; }");
|
"module mx { requires m; }");
|
||||||
Path modules = Files.createDirectories(base.resolve("modules"));
|
Path modules = Files.createDirectories(base.resolve("modules"));
|
||||||
|
|
||||||
boolean expectOK = target.equals("9");
|
|
||||||
String log = new JavacTask(tb)
|
String log = new JavacTask(tb)
|
||||||
.outdir(modules)
|
.outdir(modules)
|
||||||
.options("-XDrawDiagnostics",
|
.options(testOptions)
|
||||||
"--module-path", base.resolve("test-modules").toString())
|
|
||||||
.files(tb.findJavaFiles(src))
|
.files(tb.findJavaFiles(src))
|
||||||
.run(expectOK ? Task.Expect.SUCCESS : Task.Expect.FAIL)
|
.run(expectOK ? Task.Expect.SUCCESS : Task.Expect.FAIL)
|
||||||
.writeAll()
|
.writeAll()
|
||||||
@ -188,7 +256,7 @@ public class JavaBaseTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void createClass(Path base, List<String> mods, String target) throws Exception {
|
void createClass(Path base, List<String> mods, List<String> options) throws Exception {
|
||||||
Path src1 = base.resolve("interim-src");
|
Path src1 = base.resolve("interim-src");
|
||||||
tb.writeJavaFiles(src1,
|
tb.writeJavaFiles(src1,
|
||||||
"module m { requires java.base; }");
|
"module m { requires java.base; }");
|
||||||
@ -197,9 +265,7 @@ public class JavaBaseTest {
|
|||||||
JavacTask jct = new JavacTask(tb)
|
JavacTask jct = new JavacTask(tb)
|
||||||
.outdir(modules1);
|
.outdir(modules1);
|
||||||
|
|
||||||
if (!target.equals("current")) {
|
jct.options(options);
|
||||||
jct.options("--release", target);
|
|
||||||
}
|
|
||||||
|
|
||||||
jct.files(tb.findJavaFiles(src1))
|
jct.files(tb.findJavaFiles(src1))
|
||||||
.run(Task.Expect.SUCCESS);
|
.run(Task.Expect.SUCCESS);
|
||||||
@ -226,6 +292,8 @@ public class JavaBaseTest {
|
|||||||
requires.set(i, e2);
|
requires.set(i, e2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean preview = options.contains("--enable-preview");
|
||||||
|
|
||||||
ModuleAttribute modAttr2 = ModuleAttribute.of(
|
ModuleAttribute modAttr2 = ModuleAttribute.of(
|
||||||
modAttr1.moduleName(),
|
modAttr1.moduleName(),
|
||||||
modAttr1.moduleFlagsMask(),
|
modAttr1.moduleFlagsMask(),
|
||||||
@ -237,8 +305,14 @@ public class JavaBaseTest {
|
|||||||
modAttr1.provides());
|
modAttr1.provides());
|
||||||
Path modInfo = base.resolve("test-modules").resolve("module-info.class");
|
Path modInfo = base.resolve("test-modules").resolve("module-info.class");
|
||||||
Files.createDirectories(modInfo.getParent());
|
Files.createDirectories(modInfo.getParent());
|
||||||
byte[] newBytes = ClassFile.of().transformClass(cm1, ClassTransform.dropping(ce -> ce instanceof ModuleAttribute).
|
ClassTransform replace = (builder, element) -> {
|
||||||
andThen(ClassTransform.endHandler(classBuilder -> classBuilder.with(modAttr2))));
|
switch (element) {
|
||||||
|
case ClassFileVersion cfv when preview -> builder.withVersion(cfv.majorVersion(), 0xFFFF);
|
||||||
|
case ModuleAttribute _ -> builder.with(modAttr2);
|
||||||
|
default -> builder.with(element);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
byte[] newBytes = ClassFile.of().transformClass(cm1, replace);
|
||||||
try (OutputStream out = Files.newOutputStream(modInfo)) {
|
try (OutputStream out = Files.newOutputStream(modInfo)) {
|
||||||
out.write(newBytes);
|
out.write(newBytes);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user