From ae6d620f1c81515c8f694c942e9db6fa30bb1fca Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 25 Feb 2025 11:38:08 +0100 Subject: [PATCH 01/12] Finalizing module imports. --- .../jdk/internal/javac/PreviewFeature.java | 3 +- .../com/sun/source/tree/ImportTree.java | 6 +- .../com/sun/tools/javac/code/Preview.java | 2 - .../com/sun/tools/javac/code/Source.java | 4 +- .../share/classes/jdk/jshell/Snippet.java | 4 +- test/langtools/tools/javac/ImportModule.java | 96 +++++-------------- .../javac/diags/examples/ImportModule.java | 4 +- .../ImportModuleDoesNotRead/module-info.java | 4 +- .../ImportModuleDoesNotReadUnnamed.java | 4 +- .../diags/examples/ImportModuleNotFound.java | 3 - .../ModifierNotAllowed/module-info.java | 3 +- .../modules/ConvenientAccessErrorsTest.java | 3 - .../tools/javac/modules/EdgeCases.java | 5 +- .../tools/javac/modules/JavaBaseTest.java | 4 +- .../tools/jdeps/listdeps/ListModuleDeps.java | 1 - 15 files changed, 42 insertions(+), 104 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java index deb786b42bd03..e5c6d1fd424c6 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -76,8 +76,7 @@ public enum Feature { STRUCTURED_CONCURRENCY, CLASSFILE_API, STREAM_GATHERERS, - @JEP(number=494, title="Module Import Declarations", status="Second Preview") - MODULE_IMPORTS, +// MODULE_IMPORTS, //remove when the boot JDK is JDK 25 @JEP(number=478, title="Key Derivation Function API", status="Preview") KEY_DERIVATION, LANGUAGE_MODEL, diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java index 83a6c3eb87b66..ac4dc6258acab 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ImportTree.java @@ -25,8 +25,6 @@ package com.sun.source.tree; -import jdk.internal.javac.PreviewFeature; - /** * A tree node for an import declaration. * @@ -49,11 +47,11 @@ public interface ImportTree extends Tree { * @return true if this is a static import */ boolean isStatic(); + /** * {@return true if this is an module import declaration.} - * @since 23 + * @since 25 */ - @PreviewFeature(feature=PreviewFeature.Feature.MODULE_IMPORTS, reflective=true) boolean isModule(); /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index 9d7b1e6535245..7572c92c4c436 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -231,8 +231,6 @@ public boolean isPreview(Feature feature) { case IMPLICIT_CLASSES -> true; case FLEXIBLE_CONSTRUCTORS -> true; case PRIMITIVE_PATTERNS -> 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). //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. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java index f1c25d032d05c..eed0ceaade090 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java @@ -267,8 +267,8 @@ public enum Feature { UNNAMED_VARIABLES(JDK22, Fragments.FeatureUnnamedVariables, DiagKind.PLURAL), PRIMITIVE_PATTERNS(JDK23, Fragments.FeaturePrimitivePatterns, DiagKind.PLURAL), FLEXIBLE_CONSTRUCTORS(JDK22, Fragments.FeatureFlexibleConstructors, DiagKind.NORMAL), - MODULE_IMPORTS(JDK23, Fragments.FeatureModuleImports, DiagKind.PLURAL), - JAVA_BASE_TRANSITIVE(JDK24, Fragments.FeatureJavaBaseTransitive, DiagKind.PLURAL), + MODULE_IMPORTS(JDK25, Fragments.FeatureModuleImports, DiagKind.PLURAL), + JAVA_BASE_TRANSITIVE(JDK25, Fragments.FeatureJavaBaseTransitive, DiagKind.PLURAL), PRIVATE_MEMBERS_IN_PERMITS_CLAUSE(JDK19), ERASE_POLY_SIG_RETURN_TYPE(JDK24), ; diff --git a/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java b/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java index 4e72fed10fc3a..8e5971bedf869 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java @@ -28,7 +28,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import jdk.internal.javac.PreviewFeature; /** * A Snippet represents a snippet of Java source code as passed to @@ -219,9 +218,8 @@ public enum SubKind { * Import Module Declaration. * An import declaration of a module. * @jls 7.5.5 Import Module Declarations - * @since 23 + * @since 25 */ - @PreviewFeature(feature=PreviewFeature.Feature.MODULE_IMPORTS, reflective=true) MODULE_IMPORT_SUBKIND(Kind.IMPORT), /** diff --git a/test/langtools/tools/javac/ImportModule.java b/test/langtools/tools/javac/ImportModule.java index a53bc92f1b03f..f088dbef6582f 100644 --- a/test/langtools/tools/javac/ImportModule.java +++ b/test/langtools/tools/javac/ImportModule.java @@ -92,7 +92,6 @@ public static void main(String... args) { {//with --release: new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.SUCCESS) @@ -101,7 +100,6 @@ public static void main(String... args) { var out = new JavaTask(tb) .classpath(classes.toString()) .className("test.Test") - .vmOptions("--enable-preview") .run() .writeAll() .getOutputLines(Task.OutputKind.STDOUT); @@ -117,7 +115,6 @@ public static void main(String... args) { {//with --source: new JavacTask(tb) - .options("--enable-preview", "--source", SOURCE_VERSION) .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.SUCCESS) @@ -126,7 +123,6 @@ public static void main(String... args) { var out = new JavaTask(tb) .classpath(classes.toString()) .className("test.Test") - .vmOptions("--enable-preview") .run() .writeAll() .getOutputLines(Task.OutputKind.STDOUT); @@ -161,7 +157,7 @@ public class Test { actualErrors = new JavacTask(tb) - .options("--release", "21", "-XDrawDiagnostics") + .options("--release", "24", "-XDrawDiagnostics") .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.FAIL) @@ -169,34 +165,22 @@ public class Test { .getOutputLines(Task.OutputKind.DIRECT); expectedErrors = List.of( - "Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)", + "Test.java:2:8: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.module.imports), 24, 25", "1 error" ); if (!Objects.equals(expectedErrors, actualErrors)) { throw new AssertionError("Incorrect Output, expected: " + expectedErrors + - ", actual: " + out); + ", actual: " + actualErrors); } - actualErrors = - new JavacTask(tb) - .options("-XDrawDiagnostics") - .outdir(classes) - .files(tb.findJavaFiles(src)) - .run(Task.Expect.FAIL) - .writeAll() - .getOutputLines(Task.OutputKind.DIRECT); - - expectedErrors = List.of( - "Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)", - "1 error" - ); - - if (!Objects.equals(expectedErrors, actualErrors)) { - throw new AssertionError("Incorrect Output, expected: " + expectedErrors + - ", actual: " + out); - } + new JavacTask(tb) + .options("-XDrawDiagnostics") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run() + .writeAll(); } @Test @@ -220,8 +204,7 @@ public class Test { List expectedErrors; new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "-XDrawDiagnostics") + .options("-XDrawDiagnostics") .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.SUCCESS) @@ -240,7 +223,6 @@ public class Test { """); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) .outdir(classes) .files(tb.findJavaFiles(src)) .run() @@ -258,7 +240,6 @@ public class Test { """); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) .outdir(classes) .files(tb.findJavaFiles(src)) .run() @@ -274,7 +255,6 @@ public class Test { """); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) .outdir(classes) .files(tb.findJavaFiles(src)) .run() @@ -292,8 +272,7 @@ public class Test { actualErrors = new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "-XDrawDiagnostics") + .options("-XDrawDiagnostics") .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.FAIL) @@ -302,8 +281,6 @@ public class Test { expectedErrors = List.of( "Test.java:5:5: compiler.err.ref.ambiguous: Date, kindname.class, java.sql.Date, java.sql, kindname.class, java.util.Date, java.util", - "- compiler.note.preview.filename: Test.java, DEFAULT", - "- compiler.note.preview.recompile", "1 error" ); @@ -325,7 +302,6 @@ public class Test { """); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) .outdir(classes) .files(tb.findJavaFiles(src)) .run() @@ -387,8 +363,7 @@ public static void main(String... args) { actualErrors = new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "-p", libClasses.toString(), + .options("-p", libClasses.toString(), "--add-modules", "lib", "-XDrawDiagnostics") .outdir(classes) @@ -399,8 +374,6 @@ public static void main(String... args) { expectedErrors = List.of( "Test.java:6:9: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.class, test.Test, null)", - "- compiler.note.preview.filename: Test.java, DEFAULT", - "- compiler.note.preview.recompile", "1 error" ); @@ -412,8 +385,7 @@ public static void main(String... args) { actualErrors = new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "-p", libClasses.toString(), + .options("-p", libClasses.toString(), "-XDdev", "-XDrawDiagnostics") .outdir(classes) @@ -425,8 +397,6 @@ public static void main(String... args) { expectedErrors = List.of( "Test.java:2:1: compiler.err.import.module.does.not.read.unnamed: lib", "Test.java:6:9: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.class, test.Test, null)", - "- compiler.note.preview.filename: Test.java, DEFAULT", - "- compiler.note.preview.recompile", "2 errors" ); @@ -444,8 +414,7 @@ public static void main(String... args) { actualErrors = new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "-p", libClasses.toString(), + .options("-p", libClasses.toString(), "-XDdev", "-XDrawDiagnostics") .outdir(classes) @@ -457,8 +426,6 @@ public static void main(String... args) { expectedErrors = List.of( "Test.java:2:1: compiler.err.import.module.does.not.read: test.module, lib", "Test.java:6:9: compiler.err.cant.resolve.location: kindname.class, Impl, , , (compiler.misc.location: kindname.class, test.Test, null)", - "- compiler.note.preview.filename: Test.java, DEFAULT", - "- compiler.note.preview.recompile", "2 errors" ); @@ -539,8 +506,7 @@ public class Impl2 { Files.createDirectories(libClasses); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "--module-source-path", libSrc.toString(), + .options("--module-source-path", libSrc.toString(), "-XDrawDiagnostics") .outdir(libClasses) .files(tb.findJavaFiles(libSrc)) @@ -591,8 +557,7 @@ public class Test2 { actualErrors = new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION, - "--module-path", libClasses.toString(), + .options("--module-path", libClasses.toString(), "-XDrawDiagnostics") .outdir(classes) .files(tb.findJavaFiles(src)) @@ -611,8 +576,6 @@ public class Test2 { "Test2.java:7:5: compiler.err.cant.resolve.location: kindname.class, Impl1, , , (compiler.misc.location: kindname.class, test.Test2, null)", "Test2.java:10:5: compiler.err.cant.resolve.location: kindname.class, Api6, , , (compiler.misc.location: kindname.class, test.Test2, null)", "Test2.java:11:5: compiler.err.cant.resolve.location: kindname.class, Impl2, , , (compiler.misc.location: kindname.class, test.Test2, null)", - "- compiler.note.preview.plural: DEFAULT", - "- compiler.note.preview.recompile", "10 errors" ); @@ -640,7 +603,6 @@ public class Test { List kinds = new ArrayList<>(); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) .outdir(classes) .callback(task -> { task.addTaskListener(new TaskListener() { @@ -699,7 +661,6 @@ public class ModuleModuleClass { List kinds = new ArrayList<>(); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.SUCCESS) @@ -721,7 +682,7 @@ void main() { Files.createDirectories(classes); new JavacTask(tb) - .options("--enable-preview", "--release", SOURCE_VERSION) + .options("--enable-preview", "--release", SOURCE_VERSION) //for implicitly declared classes .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.SUCCESS) @@ -761,8 +722,7 @@ public class C {} Files.createDirectories(classes); List actualErrors = new JavacTask(tb) - .options("-XDrawDiagnostics", - "--enable-preview", "--release", SOURCE_VERSION) + .options("-XDrawDiagnostics") .outdir(classes) .files(tb.findJavaFiles(src)) .run(Task.Expect.FAIL) @@ -772,8 +732,6 @@ public class C {} List expectedErrors = List.of( "module-info.java:3:18: compiler.warn.module.not.found: M1", "module-info.java:6:9: compiler.err.cant.resolve: kindname.class, A, , ", - "- compiler.note.preview.filename: module-info.java, DEFAULT", - "- compiler.note.preview.recompile", "1 error", "1 warning" ); @@ -816,7 +774,7 @@ public class Test { "- compiler.warn.option.obsolete.source: 8", "- compiler.warn.option.obsolete.target: 8", "- compiler.warn.option.obsolete.suppression", - "Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)", + "Test.java:2:8: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.module.imports), 8, 25", "Test.java:2:1: compiler.err.import.module.not.found: java.base", "Test.java:4:5: compiler.err.cant.resolve.location: kindname.class, List, , , (compiler.misc.location: kindname.class, test.Test, null)", "3 errors", @@ -825,7 +783,7 @@ public class Test { if (!Objects.equals(expectedErrors, actualErrors)) { throw new AssertionError("Incorrect Output, expected: " + expectedErrors + - ", actual: " + out); + ", actual: " + actualErrors); } } @@ -878,7 +836,6 @@ public class Test { List actualErrors = new JavacTask(tb) .options("-XDrawDiagnostics", - "--enable-preview", "--release", SOURCE_VERSION, "--module-source-path", src.toString()) .outdir(classes) .files(tb.findJavaFiles(src)) @@ -888,8 +845,6 @@ public class Test { List 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" ); @@ -914,7 +869,6 @@ public class Test { new JavacTask(tb) .options("-XDrawDiagnostics", - "--enable-preview", "--release", SOURCE_VERSION, "--module-source-path", src.toString()) .outdir(classes) .files(tb.findJavaFiles(src)) @@ -1001,7 +955,8 @@ public static void main(String... args) { Files.createDirectories(maClasses); List actualErrors = new JavacTask(tb) - .options("-XDrawDiagnostics") + .options("-XDrawDiagnostics", + "--release", "24") .outdir(maClasses) .files(tb.findJavaFiles(ma)) .run(Task.Expect.FAIL) @@ -1009,7 +964,7 @@ public static void main(String... args) { .getOutputLines(Task.OutputKind.DIRECT); List expectedErrors = List.of( - "module-info.java:2:4: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.java.base.transitive)", + "module-info.java:2:4: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.java.base.transitive), 24, 25", "1 error" ); @@ -1034,8 +989,7 @@ public static void main(String... args) { } new JavacTask(tb) - .options("-XDrawDiagnostics", - "--enable-preview", "--release", SOURCE_VERSION) + .options("-XDrawDiagnostics") .outdir(maClasses) .files(tb.findJavaFiles(ma)) .run() @@ -1043,7 +997,7 @@ public static void main(String... args) { Path maModuleInfo2 = maClasses.resolve("module-info.class"); - if (ClassFile.of().parse(maModuleInfo2).minorVersion() != ClassFile.PREVIEW_MINOR_VERSION) { + if (ClassFile.of().parse(maModuleInfo2).minorVersion() != 0) { throw new AssertionError("wrong minor version"); } } diff --git a/test/langtools/tools/javac/diags/examples/ImportModule.java b/test/langtools/tools/javac/diags/examples/ImportModule.java index 2a0a39f5faddb..bd2a91f493b32 100644 --- a/test/langtools/tools/javac/diags/examples/ImportModule.java +++ b/test/langtools/tools/javac/diags/examples/ImportModule.java @@ -22,8 +22,8 @@ */ // key: compiler.misc.feature.module.imports - // key: compiler.warn.preview.feature.use.plural - // options: --release ${jdk.version} --enable-preview -Xlint:preview + // key: compiler.err.feature.not.supported.in.source.plural + // options: --release 24 -Xlint:preview import module java.base; diff --git a/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java index e8f9c952fbc19..8c84bc009daa7 100644 --- a/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java +++ b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotRead/module-info.java @@ -22,7 +22,5 @@ */ // key: compiler.err.import.module.does.not.read -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --release ${jdk.version} --enable-preview + module m {} diff --git a/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java index 37ae9673cc8ef..d25e7593170c0 100644 --- a/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java +++ b/test/langtools/tools/javac/diags/examples/ImportModuleDoesNotReadUnnamed.java @@ -22,9 +22,7 @@ */ // key: compiler.err.import.module.does.not.read.unnamed -// key: compiler.note.preview.filename -// key: compiler.note.preview.recompile -// options: --release ${jdk.version} --enable-preview --limit-modules java.base +// options: --limit-modules java.base import module java.compiler; diff --git a/test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java b/test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java index 8a12fc0bd034c..7e5f98e1a369e 100644 --- a/test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java +++ b/test/langtools/tools/javac/diags/examples/ImportModuleNotFound.java @@ -22,9 +22,6 @@ */ // key: compiler.err.import.module.not.found - // key: compiler.note.preview.filename - // key: compiler.note.preview.recompile - // options: --release ${jdk.version} --enable-preview import module unknown; diff --git a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java index 02cb11f5ac257..77b05420b8c9f 100644 --- a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java +++ b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java @@ -21,8 +21,9 @@ * questions. */ -// key: compiler.err.preview.feature.disabled.plural +// key: compiler.err.feature.not.supported.in.source.plural // key: compiler.misc.feature.java.base.transitive +// options: --release 24 module m { requires transitive java.base; diff --git a/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java b/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java index 2958384ae9476..d02f781681474 100644 --- a/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java +++ b/test/langtools/tools/javac/modules/ConvenientAccessErrorsTest.java @@ -448,7 +448,6 @@ public void testInModuleImport(Path base) throws Exception { List log = new JavacTask(tb) .options("-XDrawDiagnostics", - "--enable-preview", "--source", System.getProperty("java.specification.version"), "--module-source-path", src.toString()) .outdir(classes) .files(findJavaFiles(src)) @@ -458,8 +457,6 @@ public void testInModuleImport(Path base) throws Exception { List 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)) diff --git a/test/langtools/tools/javac/modules/EdgeCases.java b/test/langtools/tools/javac/modules/EdgeCases.java index a3825d9e3a6fa..39b72dda03a6a 100644 --- a/test/langtools/tools/javac/modules/EdgeCases.java +++ b/test/langtools/tools/javac/modules/EdgeCases.java @@ -1178,7 +1178,8 @@ public class Test { log = new JavacTask(tb) .outdir(classes) - .options("-XDrawDiagnostics", "-XDshould-stop.at=FLOW") + .options("-XDrawDiagnostics", "-XDshould-stop.at=FLOW", + "--release", "24") .callback(verifyJavaSEDependency(true, seenJavaSEDependency)) .files(findJavaFiles(src)) .run(Task.Expect.FAIL) @@ -1186,7 +1187,7 @@ public class Test { .getOutputLines(Task.OutputKind.DIRECT); List expected = List.of( - "Test.java:2:8: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.module.imports)", + "Test.java:2:8: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.module.imports), 24, 25", "1 error"); if (!expected.equals(log)) diff --git a/test/langtools/tools/javac/modules/JavaBaseTest.java b/test/langtools/tools/javac/modules/JavaBaseTest.java index a888c430f5369..7a7a7f95e6123 100644 --- a/test/langtools/tools/javac/modules/JavaBaseTest.java +++ b/test/langtools/tools/javac/modules/JavaBaseTest.java @@ -129,7 +129,7 @@ void testSource(Path base, List mods, String target) throws Exception { case "current": options.add("--release"); options.add(CURRENT_VERSION); - expectOK = false; + expectOK = true; break; case "current-preview": options.add("--enable-preview"); @@ -166,7 +166,7 @@ void testSource(Path base, List mods, String target) throws Exception { for (String mod : mods) { String key = mod.equals("static") ? "compiler.err.mod.not.allowed.here: " + mod - : "compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.java.base.transitive)"; + : "compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.java.base.transitive), $(VERSION), 25".replace("$(VERSION)", target); String message = "module-info.java:1:12: " + key; if (log.contains(message)) { foundErrorMessage = true; diff --git a/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java b/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java index b3f81ca1e1e9d..52db62dd41a26 100644 --- a/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java +++ b/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java @@ -92,7 +92,6 @@ public void compileAll() throws Exception { public Object[][] jdkModules() { return new Object[][]{ {"jdk.compiler", new String[]{ - "java.base/jdk.internal.javac", "java.base/jdk.internal.jmod", "java.base/jdk.internal.misc", "java.base/jdk.internal.module", From 50fbbed93965fd30660ac58732bda828ae70cf31 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 26 Feb 2025 12:17:01 +0100 Subject: [PATCH 02/12] Cleanup. --- .../share/classes/jdk/internal/javac/PreviewFeature.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java index e5c6d1fd424c6..f799f2c183327 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -76,7 +76,7 @@ public enum Feature { STRUCTURED_CONCURRENCY, CLASSFILE_API, STREAM_GATHERERS, -// MODULE_IMPORTS, //remove when the boot JDK is JDK 25 + MODULE_IMPORTS, //remove when the boot JDK is JDK 25 @JEP(number=478, title="Key Derivation Function API", status="Preview") KEY_DERIVATION, LANGUAGE_MODEL, From 46c8454a7a9f576185c2e2a6309c799284866f26 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 26 Feb 2025 14:45:44 +0100 Subject: [PATCH 03/12] Cleanup. --- test/langtools/tools/javac/diags/examples/ImportModule.java | 2 +- .../javac/diags/examples/ModifierNotAllowed/module-info.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/langtools/tools/javac/diags/examples/ImportModule.java b/test/langtools/tools/javac/diags/examples/ImportModule.java index bd2a91f493b32..f924a59acd407 100644 --- a/test/langtools/tools/javac/diags/examples/ImportModule.java +++ b/test/langtools/tools/javac/diags/examples/ImportModule.java @@ -22,7 +22,7 @@ */ // key: compiler.misc.feature.module.imports - // key: compiler.err.feature.not.supported.in.source.plural + // key: compiler.err.feature.not.supported.in.source.plural // options: --release 24 -Xlint:preview import module java.base; diff --git a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java index 77b05420b8c9f..fd57f81117acc 100644 --- a/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java +++ b/test/langtools/tools/javac/diags/examples/ModifierNotAllowed/module-info.java @@ -21,7 +21,7 @@ * questions. */ -// key: compiler.err.feature.not.supported.in.source.plural +// key: compiler.err.feature.not.supported.in.source.plural // key: compiler.misc.feature.java.base.transitive // options: --release 24 From 1476f97031f2eb76ec9bb2b9c08bd60864751641 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 14 Mar 2025 09:14:41 +0100 Subject: [PATCH 04/12] Cleanup - updated specification will permit requires transitive java.base; for all classfile versions; java.se no longer participates in preview. --- .../classes/jdk/internal/module/ModuleInfo.java | 17 ++--------------- .../com/sun/tools/javac/code/Preview.java | 4 +--- .../com/sun/tools/javac/jvm/ClassReader.java | 5 ----- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java index ff3ffada22a75..51d738702de0a 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java @@ -408,24 +408,11 @@ private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major, throw invalidModuleDescriptor("The requires entry for java.base" + " 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 - && ((mods.contains(Requires.Modifier.TRANSITIVE) - && !isPreview - && !"java.se".equals(mn)) - || mods.contains(Requires.Modifier.STATIC))) { - String flagName; - if (mods.contains(Requires.Modifier.STATIC)) { - flagName = "ACC_STATIC_PHASE"; - } else { - flagName = "ACC_TRANSITIVE"; - } + && mods.contains(Requires.Modifier.STATIC)) { + String flagName = "ACC_STATIC_PHASE"; throw invalidModuleDescriptor("The requires entry for java.base" + " has " + flagName + " set"); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java index 7572c92c4c436..325274782efef 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java @@ -153,9 +153,7 @@ public boolean participatesInPreview(Symtab syms, ModuleSymbol m) { // s participates in the preview API return syms.java_base.exports.stream() .filter(ed -> ed.packge.fullname == names.jdk_internal_javac) - .anyMatch(ed -> ed.modules.contains(m)) || - //the specification lists the java.se module as participating in preview: - m.name == names.java_se; + .anyMatch(ed -> ed.modules.contains(m)); } /** diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 6f55903f489ab..0173ab109d7d3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1202,11 +1202,6 @@ protected void read(Symbol sym, int attrLen) { ModuleSymbol rsym = poolReader.getModule(nextChar()); Set flags = readRequiresFlags(nextChar()); if (rsym == syms.java_base && majorVersion >= V54.major) { - if (flags.contains(RequiresFlag.TRANSITIVE) && - (majorVersion != Version.MAX().major || !previewClassFile) && - !preview.participatesInPreview(syms, msym)) { - throw badClassFile("bad.requires.flag", RequiresFlag.TRANSITIVE); - } if (flags.contains(RequiresFlag.STATIC_PHASE)) { throw badClassFile("bad.requires.flag", RequiresFlag.STATIC_PHASE); } From caf0ec6c8a2c7d98547161d14b4f0b0bfead1ce7 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 14 Mar 2025 14:11:26 +0100 Subject: [PATCH 05/12] Fixing tests. --- test/jdk/java/lang/module/ClassFileVersionsTest.java | 2 +- test/jdk/java/lang/module/ModuleDescriptorTest.java | 2 -- .../langtools/tools/javac/modules/AnnotationsOnModules.java | 4 ++-- test/langtools/tools/javac/modules/JavaBaseTest.java | 6 +----- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/test/jdk/java/lang/module/ClassFileVersionsTest.java b/test/jdk/java/lang/module/ClassFileVersionsTest.java index 9e22c45d5c5fb..308df36b81de6 100644 --- a/test/jdk/java/lang/module/ClassFileVersionsTest.java +++ b/test/jdk/java/lang/module/ClassFileVersionsTest.java @@ -78,6 +78,7 @@ public Object[][] supported() { // for JDK 10 through FEATURE. for (int i = 10; i <= FEATURE; i++) { result.add(new Object[]{ 44 + i, 0, Set.of()}); + result.add(new Object[]{ 44 + i, 0, Set.of(TRANSITIVE)}); } result.add(new Object[]{ 44 + FEATURE, @@ -110,7 +111,6 @@ public Object[][] unsupported() { for (int i = 10; i <= FEATURE ; i++) { // Major class file version of JDK N is 44+n result.add(new Object[]{i + 44, 0, Set.of(STATIC)}); - result.add(new Object[]{i + 44, 0, Set.of(TRANSITIVE)}); result.add(new Object[]{i + 44, 0, Set.of(STATIC, TRANSITIVE)}); } diff --git a/test/jdk/java/lang/module/ModuleDescriptorTest.java b/test/jdk/java/lang/module/ModuleDescriptorTest.java index bf379570f5171..fd7d32cc97894 100644 --- a/test/jdk/java/lang/module/ModuleDescriptorTest.java +++ b/test/jdk/java/lang/module/ModuleDescriptorTest.java @@ -1523,7 +1523,6 @@ public void testToString() { 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") @@ -1536,7 +1535,6 @@ public void testRequiresTransitiveJavaBaseNotPermitted1() throws Exception { 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") diff --git a/test/langtools/tools/javac/modules/AnnotationsOnModules.java b/test/langtools/tools/javac/modules/AnnotationsOnModules.java index 291633b4fb240..6d9bfaad40697 100644 --- a/test/langtools/tools/javac/modules/AnnotationsOnModules.java +++ b/test/langtools/tools/javac/modules/AnnotationsOnModules.java @@ -755,7 +755,7 @@ public void testBrokenModuleInfoClassWithAnnotation(Path base) throws Exception for (ModuleRequireInfo mri : attr.requires()) { if (mri.requires().name().equalsString("java.base")) { requires.add(ModuleRequireInfo.of(mri.requires(), - List.of(AccessFlag.TRANSITIVE), + List.of(AccessFlag.STATIC_PHASE), mri.requiresVersion() .orElse(null))); } else { @@ -804,7 +804,7 @@ public class C {} .writeAll() .getOutputLines(OutputKind.DIRECT); List expectedErrors = List.of( - "- compiler.err.cant.access: m.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.requires.flag: ACC_TRANSITIVE (0x0020)))", + "- compiler.err.cant.access: m.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.requires.flag: ACC_STATIC_PHASE (0x0040)))", "1 error" ); diff --git a/test/langtools/tools/javac/modules/JavaBaseTest.java b/test/langtools/tools/javac/modules/JavaBaseTest.java index 7a7a7f95e6123..9c089982c00c1 100644 --- a/test/langtools/tools/javac/modules/JavaBaseTest.java +++ b/test/langtools/tools/javac/modules/JavaBaseTest.java @@ -179,30 +179,26 @@ void testSource(Path base, List mods, String target) throws Exception { } void testClass(Path base, List mods, String target) throws Exception { - boolean expectOK; + boolean expectOK = true; List 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; } From 1c55e5198089b1c9704b68956dbd955412158e8d Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 28 Mar 2025 10:16:08 +0100 Subject: [PATCH 06/12] Adjusting JShell defaults. --- .../jdk/internal/jshell/tool/JShellTool.java | 25 +++- .../jdk/internal/jshell/tool/Startup.java | 35 ++++-- .../jdk/jshell/tool/resources/DEFAULT.jsh | 11 +- .../jdk/jshell/tool/resources/DEFAULT_24.jsh | 10 ++ .../langtools/jdk/jshell/StartOptionTest.java | 117 ++++++++++++++++-- 5 files changed, 165 insertions(+), 33 deletions(-) create mode 100644 src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_24.jsh diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 5d95bc7c77d3f..bb466b3196349 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -131,6 +131,7 @@ import static jdk.jshell.Snippet.SubKind.TEMP_VAR_EXPRESSION_SUBKIND; import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; import static java.util.stream.Collectors.toMap; +import javax.lang.model.SourceVersion; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_COMPA; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT; @@ -642,7 +643,10 @@ Options parse(OptionSet options) { } else { String packedStartup = prefs.get(STARTUP_KEY); boolean preview = previewEnabled(options); - initialStartup = Startup.unpack(packedStartup, preview, new InitMessageHandler()); + int sourceLevel = detectSourceLevel(options.valuesOf(argC) + .toArray(String[]::new)); + initialStartup = Startup.unpack(packedStartup, sourceLevel, + preview, new InitMessageHandler()); } if (options.has(argExecution)) { executionControlSpec = options.valueOf(argExecution); @@ -2308,7 +2312,8 @@ boolean setStart(ArgTokenizer at) { } } else if (defaultOption) { boolean preview = options.hasOption(OptionKind.ENABLE_PREVIEW); - startup = Startup.defaultStartup(preview, this); + int sourceLevel = detectSourceLevel(options.compilerOptions()); + startup = Startup.defaultStartup(sourceLevel, preview, this); } else if (noneOption) { startup = Startup.noStartup(); } @@ -2326,7 +2331,8 @@ void showSetStart() { String retained = prefs.get(STARTUP_KEY); if (retained != null) { boolean preview = options.hasOption(OptionKind.ENABLE_PREVIEW); - Startup retainedStart = Startup.unpack(retained, preview, this); + int sourceLevel = detectSourceLevel(options.compilerOptions()); + Startup retainedStart = Startup.unpack(retained, sourceLevel, preview, this); boolean currentDifferent = !startup.equals(retainedStart); sb.append(retainedStart.show(true)); if (currentDifferent) { @@ -2343,6 +2349,19 @@ void showSetStart() { hard(escape(sb)); } + private int detectSourceLevel(String[] compilerOptions) { + for (int i = 0; i < compilerOptions.length; i++) { + switch (compilerOptions[i]) { + case "-source", "--source", "--release": + if (i + 1 < compilerOptions.length) { + return Integer.parseInt(compilerOptions[i + 1]); + } + } + } + + return SourceVersion.latest().runtimeVersion().feature(); + } + private void showIndent() { hard("/set indent %s", indent()); } diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java index 53c31c3568dab..e1c75afb494f9 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java @@ -118,12 +118,14 @@ public boolean equals(Object o) { } private static final String DEFAULT_STARTUP_NAME = "DEFAULT"; + private static final String DEFAULT_24_STARTUP_NAME = "DEFAULT_24"; private static final String PREVIEW_DEFAULT_STARTUP_NAME = "PREVIEW_DEFAULT"; // cached DEFAULT start-up private static Startup[] defaultStartup = new Startup[] { null, //standard startup - null //preview startup + null, //JDK 24 and older startup + null //preview startup }; // the list of entries @@ -171,6 +173,7 @@ boolean isDefault() { if (entries.size() == 1) { StartupEntry sue = entries.get(0); if (sue.isBuiltIn && (sue.name.equals(DEFAULT_STARTUP_NAME) || + sue.name.equals(DEFAULT_24_STARTUP_NAME) || sue.name.equals(PREVIEW_DEFAULT_STARTUP_NAME))) { return true; } @@ -222,7 +225,7 @@ String showDetail() { * @param mh handler for error messages * @return Startup, or default startup when error (message has been printed) */ - static Startup unpack(String storedForm, boolean preview, MessageHandler mh) { + static Startup unpack(String storedForm, int sourceLevel, boolean preview, MessageHandler mh) { if (storedForm != null) { if (storedForm.isEmpty()) { return noStartup(); @@ -243,14 +246,18 @@ static Startup unpack(String storedForm, boolean preview, MessageHandler mh) { String name = all[i + 1]; String timeStamp = all[i + 2]; String content = all[i + 3]; - if (isBuiltIn) { - // update to current definition, use stored if removed/error - String resource = getResource(name); - if (resource != null) { - content = resource; + if (isBuiltIn && DEFAULT_STARTUP_NAME.equals(name)) { + e.addAll(defaultStartup(sourceLevel, preview, mh).entries); + } else { + if (isBuiltIn) { + // update to current definition, use stored if removed/error + String resource = getResource(name); + if (resource != null) { + content = resource; + } } + e.add(new StartupEntry(isBuiltIn, name, content, timeStamp)); } - e.add(new StartupEntry(isBuiltIn, name, content, timeStamp)); } return new Startup(e); } else { @@ -260,7 +267,7 @@ static Startup unpack(String storedForm, boolean preview, MessageHandler mh) { mh.errormsg("jshell.err.corrupted.stored.startup", ex.getMessage()); } } - return defaultStartup(preview, mh); + return defaultStartup(sourceLevel, preview, mh); } /** @@ -329,18 +336,20 @@ static Startup noStartup() { * @param mh handler for error messages * @return The default Startup, or empty startup when error (message has been printed) */ - static Startup defaultStartup(boolean preview, MessageHandler mh) { - int idx = preview ? 1 : 0; + static Startup defaultStartup(int sourceLevel, boolean preview, MessageHandler mh) { + boolean startup24 = sourceLevel < 25; + int idx = preview ? 2 : startup24 ? 1 : 0; if (defaultStartup[idx] != null) { return defaultStartup[idx]; } String resourceName = preview ? PREVIEW_DEFAULT_STARTUP_NAME - : DEFAULT_STARTUP_NAME; + : startup24 ? DEFAULT_24_STARTUP_NAME + : DEFAULT_STARTUP_NAME; try { String content = readResource(resourceName); return defaultStartup[idx] = new Startup( - new StartupEntry(true, resourceName, content)); + new StartupEntry(true, DEFAULT_STARTUP_NAME, content)); } catch (AccessDeniedException e) { mh.errormsg("jshell.err.file.not.accessible", "jshell", resourceName, e.getMessage()); } catch (NoSuchFileException e) { diff --git a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh index b65aada014a9e..4644ac8638657 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh +++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT.jsh @@ -1,10 +1 @@ -import java.io.*; -import java.math.*; -import java.net.*; -import java.nio.file.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.function.*; -import java.util.prefs.*; -import java.util.regex.*; -import java.util.stream.*; +import module java.base; diff --git a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_24.jsh b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_24.jsh new file mode 100644 index 0000000000000..b65aada014a9e --- /dev/null +++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_24.jsh @@ -0,0 +1,10 @@ +import java.io.*; +import java.math.*; +import java.net.*; +import java.nio.file.*; +import java.util.*; +import java.util.concurrent.*; +import java.util.function.*; +import java.util.prefs.*; +import java.util.regex.*; +import java.util.stream.*; diff --git a/test/langtools/jdk/jshell/StartOptionTest.java b/test/langtools/jdk/jshell/StartOptionTest.java index b84b454480e5e..efd50eee33cd2 100644 --- a/test/langtools/jdk/jshell/StartOptionTest.java +++ b/test/langtools/jdk/jshell/StartOptionTest.java @@ -40,6 +40,7 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.function.Consumer; import java.util.logging.Level; @@ -64,6 +65,7 @@ public class StartOptionTest { protected ByteArrayOutputStream userout; protected ByteArrayOutputStream usererr; protected InputStream cmdInStream; + private Map testPersistence; private JavaShellToolBuilder builder() { // turn on logging of launch failures @@ -73,12 +75,19 @@ private JavaShellToolBuilder builder() { .out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout)) .err(new PrintStream(cmderr), new PrintStream(usererr)) .in(cmdInStream, null) - .persistence(new HashMap<>()) + .persistence(testPersistence != null ? testPersistence + : new HashMap<>()) .env(new HashMap<>()) .locale(Locale.ROOT); } protected int runShell(String... args) { + cmdout.reset(); + cmderr.reset(); + console.reset(); + userout.reset(); + usererr.reset(); + try { return builder() .start(Presets.addExecutionIfMissing(args)); @@ -130,6 +139,16 @@ protected void startCheckUserOutput(Consumer checkUserOutput, String... args) { runShell(args); check(userout, checkUserOutput, "userout"); + check(cmderr, null, "cmderr"); + check(usererr, null, "usererr"); + } + + protected void startCheckCommandUserOutput(Consumer checkCommandOutput, + Consumer checkUserOutput, + String... args) { + runShell(args); + check(cmdout, checkCommandOutput, "cmdout"); + check(userout, checkUserOutput, "userout"); check(usererr, null, "usererr"); } @@ -198,8 +217,12 @@ public void setUp() { } protected String writeToFile(String stuff) { + return writeToFile("doit.repl", stuff); + } + + protected String writeToFile(String fileName, String stuff) { Compiler compiler = new Compiler(); - Path p = compiler.getPath("doit.repl"); + Path p = compiler.getPath(fileName); compiler.writeToFile(p, stuff); return p.toString(); } @@ -365,7 +388,7 @@ public void testShowVersion() { "--show-version"); } - public void testPreviewEnabled() { + public void testSourceLevel() { String fn = writeToFile( """ System.out.println(\"prefix\"); @@ -373,23 +396,103 @@ public void testPreviewEnabled() { System.out.println(\"suffix\"); /exit """); - startCheckUserOutput(s -> assertEquals(s, "prefix\nsuffix\n"), + startCheckUserOutput(s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), fn); startCheckUserOutput(s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), "--enable-preview", fn); + String fn24 = writeToFile( + """ + System.out.println(\"test\"); + /exit + """); + startCheckUserOutput(s -> assertEquals(s, "test\n"), + "-C--release", "-C24", fn24); + startCheckUserOutput(s -> assertEquals(s, "test\n"), + "-C--source", "-C24", fn24); + startCheckUserOutput(s -> assertEquals(s, "test\n"), + "-C-source", "-C24", fn24); //JDK-8341631: String fn2 = writeToFile( + """ + System.out.println(\"test\"); + /exit + """); + startCheckUserOutput(s -> assertEquals(s, "test\n"), + fn2); + String fn2Preview = writeToFile( """ System.out.println(\"prefix\"); IO.println(\"test\"); System.out.println(\"suffix\"); /exit """); - startCheckUserOutput(s -> assertEquals(s, "prefix\nsuffix\n"), - fn2); startCheckUserOutput(s -> assertEquals(s, "prefix\ntest\nsuffix\n"), - "--enable-preview", fn2); + "--enable-preview", fn2Preview); + + testPersistence = new HashMap<>(); + + String newStartupScript = writeToFile("test-startup.repl", + """ + System.out.println("Custom start script"); + """); + String setStartup = writeToFile( + """ + /set start -retain {file} + /exit + """.replace("{file}", newStartupScript)); + startCheckUserOutput(s -> {}, setStartup); + String exit = writeToFile( + """ + /exit + """); + startCheckUserOutput(s -> assertEquals(s, "Custom start script\n"), + exit); + String clearStartup = writeToFile( + """ + /set start -retain -default + /exit + """); + startCheckUserOutput(s -> {}, clearStartup); + String retainTest = writeToFile( + """ + /set start + System.out.println(\"prefix\"); + System.out.println(MethodHandle.class.getName()); + System.out.println(\"suffix\"); + /exit + """); + startCheckCommandUserOutput(s -> assertEquals(s, "/set start -retain -default\n"), + s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), + retainTest); + String retainTest24 = writeToFile( + """ + System.out.println(\"test\"); + /exit + """); + startCheckUserOutput(s -> assertEquals(s, "test\n"), + "-C--release", "-C24", retainTest24); + + String set24DefaultTest = writeToFile( + """ + /set start -default -retain + /exit + """); + startCheckUserOutput(s -> {}, + "-C--release", "-C24", set24DefaultTest); + + String checkDefaultAfterSet24Test = writeToFile( + """ + /set start + System.out.println(\"prefix\"); + System.out.println(MethodHandle.class.getName()); + System.out.println(\"suffix\"); + /exit + """); + startCheckCommandUserOutput(s -> assertEquals(s, "/set start -retain -default\n"), + s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), + checkDefaultAfterSet24Test); } + public void testInput() { //readLine(String): String readLinePrompt = writeToFile( From cffcf85168c9c70d43345736d6f40cd8dff97d6e Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 31 Mar 2025 11:55:38 +0200 Subject: [PATCH 07/12] Cleanup, fixing tests. --- .../share/classes/jdk/jshell/SnippetMaps.java | 49 +++++++++++++++++++ .../langtools/jdk/jshell/ReplToolTesting.java | 15 +----- .../langtools/jdk/jshell/StartOptionTest.java | 3 ++ .../jdk/jshell/ToolCommandOptionTest.java | 4 +- .../jdk/jshell/ToolEnablePreviewTest.java | 15 +++++- .../jdk/jshell/ToolProviderTest.java | 10 ++++ test/langtools/jdk/jshell/ToolSimpleTest.java | 19 +++++-- 7 files changed, 94 insertions(+), 21 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java index da3170e39483a..116457a0f809b 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java @@ -36,6 +36,13 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.stream.Stream; +import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.ModuleElement.ExportsDirective; +import javax.lang.model.element.ModuleElement.RequiresDirective; +import javax.lang.model.util.ElementFilter; + +import jdk.jshell.Snippet.SubKind; +import jdk.jshell.TaskFactory.AnalyzeTask; import static jdk.jshell.Util.PREFIX_PATTERN; import static jdk.jshell.Util.REPL_PACKAGE; @@ -51,6 +58,7 @@ final class SnippetMaps { private final List keyIndexToSnippet = new ArrayList<>(); private final Set snippets = new LinkedHashSet<>(); private final Map> dependencies = new HashMap<>(); + private final Map> module2PackagesForImport = new HashMap<>(); private final JShell state; SnippetMaps(JShell proc) { @@ -186,6 +194,13 @@ String fullClassNameAndPackageToClass(String full, String pkg) { if (Stream.concat(Stream.of("java.lang"), pkgs).anyMatch(pkg::equals)) { return full.substring(pkg.length() + 1); } + Stream mods = importSnippets() + .filter(isi -> isi.subKind() == SubKind.MODULE_IMPORT_SUBKIND) + .map(isi -> isi.fullname) + .flatMap(this::module2PackagesForImport); + if (mods.anyMatch(pkg::equals)) { + return full.substring(pkg.length() + 1); + } return full; } @@ -198,4 +213,38 @@ private Stream importSnippets() { .map(key -> (ImportSnippet)getSnippet(key)) .filter(sn -> sn != null && state.status(sn).isDefined()); } + + private Stream module2PackagesForImport(String module) { + return module2PackagesForImport.computeIfAbsent(module, mod -> { + return state.taskFactory + .analyze(new OuterWrap(Wrap.identityWrap(" ")), + at -> computeImports(at, mod)); + }).stream(); + } + + private Set computeImports(AnalyzeTask at, String mod) { + List todo = new ArrayList<>(); + Set seenModules = new HashSet<>(); + Set exportedPackages = new HashSet<>(); + todo.add(at.getElements().getModuleElement(mod)); + while (!todo.isEmpty()) { + ModuleElement current = todo.remove(todo.size() - 1); + if (current == null || !seenModules.add(current)) { + continue; + } + for (ExportsDirective exp : ElementFilter.exportsIn(current.getDirectives())) { + if (exp.getTargetModules() != null) { + continue; + } + exportedPackages.add(exp.getPackage().getQualifiedName().toString()); + } + for (RequiresDirective req : ElementFilter.requiresIn(current.getDirectives())) { + if (!req.isTransitive()) { + continue; + } + todo.add(req.getDependency()); + } + } + return exportedPackages; + } } diff --git a/test/langtools/jdk/jshell/ReplToolTesting.java b/test/langtools/jdk/jshell/ReplToolTesting.java index d08c1008386bf..8bfae2fc39022 100644 --- a/test/langtools/jdk/jshell/ReplToolTesting.java +++ b/test/langtools/jdk/jshell/ReplToolTesting.java @@ -57,19 +57,8 @@ public class ReplToolTesting { private final static String DEFAULT_STARTUP_MESSAGE = "| Welcome to"; - final static List START_UP_IMPORTS = Stream.of( - "java.io.*", - "java.math.*", - "java.net.*", - "java.nio.file.*", - "java.util.*", - "java.util.concurrent.*", - "java.util.function.*", - "java.util.prefs.*", - "java.util.regex.*", - "java.util.stream.*") - .map(s -> new ImportInfo("import " + s + ";", "", s)) - .collect(toList()); + final static List START_UP_IMPORTS = List.of( + new ImportInfo("import module java.base;", "", "java.base")); final static List START_UP_METHODS = Stream.of() .collect(toList()); final static List START_UP_CMD_METHOD = Stream.of() diff --git a/test/langtools/jdk/jshell/StartOptionTest.java b/test/langtools/jdk/jshell/StartOptionTest.java index efd50eee33cd2..0957dd9690c32 100644 --- a/test/langtools/jdk/jshell/StartOptionTest.java +++ b/test/langtools/jdk/jshell/StartOptionTest.java @@ -145,6 +145,7 @@ protected void startCheckUserOutput(Consumer checkUserOutput, protected void startCheckCommandUserOutput(Consumer checkCommandOutput, Consumer checkUserOutput, + Consumer checkCombinedCommandUserOutput, String... args) { runShell(args); check(cmdout, checkCommandOutput, "cmdout"); @@ -463,6 +464,7 @@ public void testSourceLevel() { """); startCheckCommandUserOutput(s -> assertEquals(s, "/set start -retain -default\n"), s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), + s -> assertEquals(s, "/set start -retain -default\nprefix\njava.lang.invoke.MethodHandle\nsuffix\n"), retainTest); String retainTest24 = writeToFile( """ @@ -490,6 +492,7 @@ public void testSourceLevel() { """); startCheckCommandUserOutput(s -> assertEquals(s, "/set start -retain -default\n"), s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"), + s -> assertEquals(s, "/set start -retain -default\nprefix\njava.lang.invoke.MethodHandle\nsuffix\n"), checkDefaultAfterSet24Test); } diff --git a/test/langtools/jdk/jshell/ToolCommandOptionTest.java b/test/langtools/jdk/jshell/ToolCommandOptionTest.java index ec137a3ec6083..affeabacb7a8e 100644 --- a/test/langtools/jdk/jshell/ToolCommandOptionTest.java +++ b/test/langtools/jdk/jshell/ToolCommandOptionTest.java @@ -274,7 +274,7 @@ public void setStartTest() { (a) -> assertCommand(a, "/set start DEFAULT PRINTING", ""), (a) -> assertCommandOutputContains(a, "/set start", - "/set start DEFAULT PRINTING", "void println", "import java.util.*"), + "/set start DEFAULT PRINTING", "void println", "import module java.base;"), (a) -> assertCommand(a, "/set start " + startup.toString(), ""), (a) -> assertCommandOutputContains(a, "/set start", @@ -333,7 +333,7 @@ public void retainStartTest() { "| ---- PRINTING ----\n", "| int iAmHere = 1234;\n", "| void println(String s)", - "| import java.io.*;") + "| import module java.base;") ); } diff --git a/test/langtools/jdk/jshell/ToolEnablePreviewTest.java b/test/langtools/jdk/jshell/ToolEnablePreviewTest.java index 61a54254455ed..1825e7b39ad59 100644 --- a/test/langtools/jdk/jshell/ToolEnablePreviewTest.java +++ b/test/langtools/jdk/jshell/ToolEnablePreviewTest.java @@ -28,6 +28,11 @@ * @run testng ToolEnablePreviewTest */ +import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import org.testng.annotations.Test; import static org.testng.Assert.assertTrue; @@ -70,8 +75,14 @@ public void testCommandLineFlag() { } @Test - public void testCompilerTestFlagEnv() { - test(new String[] {"-C", "-XDforcePreview"}, + public void testCompilerTestFlagEnv() throws IOException { + Path startupFile = Paths.get("startup.repl"); + try (Writer w = Files.newBufferedWriter(startupFile)) { + w.write(""" + import java.util.function.*; + """); + } + test(new String[] {"-C", "-XDforcePreview", "-startup", startupFile.toString()}, (a) -> assertCommandOutputContains(a, "Function f = (var i) -> i + i", "Error", "preview feature"), (a) -> assertCommand(a, "/env --enable-preview", diff --git a/test/langtools/jdk/jshell/ToolProviderTest.java b/test/langtools/jdk/jshell/ToolProviderTest.java index ada5f34d8c053..edacc28c02665 100644 --- a/test/langtools/jdk/jshell/ToolProviderTest.java +++ b/test/langtools/jdk/jshell/ToolProviderTest.java @@ -66,6 +66,16 @@ protected void startCheckUserOutput(Consumer checkUserOutput, String... check(usererr, null, "usererr"); } + @Override + protected void startCheckCommandUserOutput(Consumer checkCommandOutput, + Consumer checkUserOutput, + Consumer checkCombinedCommandUserOutput, + String... args) { + runShell(args); + check(cmdout, checkCombinedCommandUserOutput, "userout"); + check(usererr, null, "usererr"); + } + @Override protected int runShell(String... args) { ServiceLoader sl = ServiceLoader.load(Tool.class); diff --git a/test/langtools/jdk/jshell/ToolSimpleTest.java b/test/langtools/jdk/jshell/ToolSimpleTest.java index 81f75a3863e2b..62ea2451fb4c1 100644 --- a/test/langtools/jdk/jshell/ToolSimpleTest.java +++ b/test/langtools/jdk/jshell/ToolSimpleTest.java @@ -33,6 +33,7 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.jdeps/com.sun.tools.javap * jdk.jshell/jdk.internal.jshell.tool + * java.desktop * @build KullaTesting TestingInputStream * @run testng ToolSimpleTest */ @@ -566,11 +567,11 @@ public void testListArgs() { s -> checkLineToList(s, START_UP)), a -> assertCommandCheckOutput(a, "/list -all", s -> checkLineToList(s, startVarList)), - a -> assertCommandOutputStartsWith(a, "/list s3", - "s3 : import"), - a -> assertCommandCheckOutput(a, "/list 1-2 s3", + a -> assertCommandOutputStartsWith(a, "/list s1", + "s1 : import"), + a -> assertCommandCheckOutput(a, "/list 1-2 s1", s -> { - assertTrue(Pattern.matches(".*aardvark.*\\R.*weevil.*\\R.*s3.*import.*", s.trim()), + assertTrue(Pattern.matches(".*aardvark.*\\R.*weevil.*\\R.*s1.*import.*", s.trim()), "No match: " + s); }), a -> assertCommandOutputStartsWith(a, "/list " + arg, @@ -977,4 +978,14 @@ public void testSelfReference() { (a) -> assertCommandOutputContains(a, "var a = a;", "cannot use 'var' on self-referencing variable") ); } + + @Test + public void testModuleImportShortenedTypes() { + test( + (a) -> assertCommandOutputContains(a, "import module java.desktop;", ""), + (a) -> assertCommandOutputContains(a, "var r1 = new JButton()", ""), + (a) -> assertCommandOutputContains(a, "/vars r1", "| JButton r1 =") + ); + } + } From 067a0444606361c1f14d8f2dd921630760c1a9ac Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 31 Mar 2025 19:06:11 +0200 Subject: [PATCH 08/12] Fixing test. --- test/langtools/jdk/jshell/ToolLocalSimpleTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/langtools/jdk/jshell/ToolLocalSimpleTest.java b/test/langtools/jdk/jshell/ToolLocalSimpleTest.java index 6221f29510360..bb6f45889680a 100644 --- a/test/langtools/jdk/jshell/ToolLocalSimpleTest.java +++ b/test/langtools/jdk/jshell/ToolLocalSimpleTest.java @@ -73,7 +73,7 @@ public void testOptionR() { public void testCompoundStart() { test(new String[]{"--startup", "DEFAULT", "--startup", "PRINTING", "--startup", "TOOLING"}, (a) -> assertCommandOutputContains(a, "/list -start", - "System.out.println", "import java.util.concurrent", "tools()") + "System.out.println", "import module java.base;", "tools()") ); } From d66703c1cb4f9f532f9a98181b598fa45e55ef73 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 2 Apr 2025 18:55:36 +0200 Subject: [PATCH 09/12] Reflecting review feedback - avoiding hardcoded constants. --- .../jdk/internal/jshell/tool/JShellTool.java | 14 ++++++------- .../jdk/internal/jshell/tool/Startup.java | 20 +++++++++++-------- ...T_24.jsh => DEFAULT_NO_MODULE_IMPORTS.jsh} | 0 3 files changed, 19 insertions(+), 15 deletions(-) rename src/jdk.jshell/share/classes/jdk/jshell/tool/resources/{DEFAULT_24.jsh => DEFAULT_NO_MODULE_IMPORTS.jsh} (100%) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index bb466b3196349..686c9772d5949 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -643,8 +643,8 @@ Options parse(OptionSet options) { } else { String packedStartup = prefs.get(STARTUP_KEY); boolean preview = previewEnabled(options); - int sourceLevel = detectSourceLevel(options.valuesOf(argC) - .toArray(String[]::new)); + String sourceLevel = detectSourceLevel(options.valuesOf(argC) + .toArray(String[]::new)); initialStartup = Startup.unpack(packedStartup, sourceLevel, preview, new InitMessageHandler()); } @@ -2312,7 +2312,7 @@ boolean setStart(ArgTokenizer at) { } } else if (defaultOption) { boolean preview = options.hasOption(OptionKind.ENABLE_PREVIEW); - int sourceLevel = detectSourceLevel(options.compilerOptions()); + String sourceLevel = detectSourceLevel(options.compilerOptions()); startup = Startup.defaultStartup(sourceLevel, preview, this); } else if (noneOption) { startup = Startup.noStartup(); @@ -2331,7 +2331,7 @@ void showSetStart() { String retained = prefs.get(STARTUP_KEY); if (retained != null) { boolean preview = options.hasOption(OptionKind.ENABLE_PREVIEW); - int sourceLevel = detectSourceLevel(options.compilerOptions()); + String sourceLevel = detectSourceLevel(options.compilerOptions()); Startup retainedStart = Startup.unpack(retained, sourceLevel, preview, this); boolean currentDifferent = !startup.equals(retainedStart); sb.append(retainedStart.show(true)); @@ -2349,17 +2349,17 @@ void showSetStart() { hard(escape(sb)); } - private int detectSourceLevel(String[] compilerOptions) { + private String detectSourceLevel(String[] compilerOptions) { for (int i = 0; i < compilerOptions.length; i++) { switch (compilerOptions[i]) { case "-source", "--source", "--release": if (i + 1 < compilerOptions.length) { - return Integer.parseInt(compilerOptions[i + 1]); + return compilerOptions[i + 1]; } } } - return SourceVersion.latest().runtimeVersion().feature(); + return Integer.toString(SourceVersion.latest().runtimeVersion().feature()); } private void showIndent() { diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java index e1c75afb494f9..aa27d65c5b7d2 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java @@ -25,6 +25,8 @@ package jdk.internal.jshell.tool; +import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.code.Source.Feature; import java.nio.file.AccessDeniedException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; @@ -118,7 +120,7 @@ public boolean equals(Object o) { } private static final String DEFAULT_STARTUP_NAME = "DEFAULT"; - private static final String DEFAULT_24_STARTUP_NAME = "DEFAULT_24"; + private static final String DEFAULT_STARTUP_NAME_NO_MODULE_IMPORTS = "DEFAULT_NO_MODULE_IMPORTS"; private static final String PREVIEW_DEFAULT_STARTUP_NAME = "PREVIEW_DEFAULT"; // cached DEFAULT start-up @@ -173,7 +175,7 @@ boolean isDefault() { if (entries.size() == 1) { StartupEntry sue = entries.get(0); if (sue.isBuiltIn && (sue.name.equals(DEFAULT_STARTUP_NAME) || - sue.name.equals(DEFAULT_24_STARTUP_NAME) || + sue.name.equals(DEFAULT_STARTUP_NAME_NO_MODULE_IMPORTS) || sue.name.equals(PREVIEW_DEFAULT_STARTUP_NAME))) { return true; } @@ -225,7 +227,7 @@ String showDetail() { * @param mh handler for error messages * @return Startup, or default startup when error (message has been printed) */ - static Startup unpack(String storedForm, int sourceLevel, boolean preview, MessageHandler mh) { + static Startup unpack(String storedForm, String sourceLevel, boolean preview, MessageHandler mh) { if (storedForm != null) { if (storedForm.isEmpty()) { return noStartup(); @@ -336,16 +338,18 @@ static Startup noStartup() { * @param mh handler for error messages * @return The default Startup, or empty startup when error (message has been printed) */ - static Startup defaultStartup(int sourceLevel, boolean preview, MessageHandler mh) { - boolean startup24 = sourceLevel < 25; - int idx = preview ? 2 : startup24 ? 1 : 0; + static Startup defaultStartup(String sourceLevel, boolean preview, MessageHandler mh) { + Source source = Source.lookup(sourceLevel); + boolean hasModuleImports = source == null || + Feature.MODULE_IMPORTS.allowedInSource(source); + int idx = preview ? 2 : !hasModuleImports ? 1 : 0; if (defaultStartup[idx] != null) { return defaultStartup[idx]; } String resourceName = preview ? PREVIEW_DEFAULT_STARTUP_NAME - : startup24 ? DEFAULT_24_STARTUP_NAME - : DEFAULT_STARTUP_NAME; + : !hasModuleImports ? DEFAULT_STARTUP_NAME_NO_MODULE_IMPORTS + : DEFAULT_STARTUP_NAME; try { String content = readResource(resourceName); return defaultStartup[idx] = new Startup( diff --git a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_24.jsh b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_NO_MODULE_IMPORTS.jsh similarity index 100% rename from src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_24.jsh rename to src/jdk.jshell/share/classes/jdk/jshell/tool/resources/DEFAULT_NO_MODULE_IMPORTS.jsh From 029e0dd59c7160f4fe043dd7191860b067ca787c Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Thu, 10 Apr 2025 19:54:43 +0200 Subject: [PATCH 10/12] Reflecting review feedback: cleanup formatting in ModuleInfo. --- .../share/classes/jdk/internal/module/ModuleInfo.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java index 51d738702de0a..ed97937e39a59 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java @@ -408,10 +408,9 @@ private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major, throw invalidModuleDescriptor("The requires entry for java.base" + " has ACC_SYNTHETIC set"); } - // requires static java.base is illegal unless: - // - the major version is 53 (JDK 9), or: - if (major >= 54 - && mods.contains(Requires.Modifier.STATIC)) { + // requires static java.base is illegal unless + // the major version is 53 (JDK 9) + if (major >= 54 && mods.contains(Requires.Modifier.STATIC)) { String flagName = "ACC_STATIC_PHASE"; throw invalidModuleDescriptor("The requires entry for java.base" + " has " + flagName + " set"); From 4c14c3b0398236c842cd664ca5044c255121e9ab Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 11 Apr 2025 13:14:45 +0200 Subject: [PATCH 11/12] Adjusting ToolProviderTest to the updated persistence handling. --- test/langtools/jdk/jshell/StartOptionTest.java | 8 ++++++-- test/langtools/jdk/jshell/ToolProviderTest.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/test/langtools/jdk/jshell/StartOptionTest.java b/test/langtools/jdk/jshell/StartOptionTest.java index 06a16519c0d0a..422432d58b112 100644 --- a/test/langtools/jdk/jshell/StartOptionTest.java +++ b/test/langtools/jdk/jshell/StartOptionTest.java @@ -75,12 +75,16 @@ private JavaShellToolBuilder builder() { .out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout)) .err(new PrintStream(cmderr), new PrintStream(usererr)) .in(cmdInStream, null) - .persistence(testPersistence != null ? testPersistence - : new HashMap<>()) + .persistence(getThisTestPersistence()) .env(new HashMap<>()) .locale(Locale.ROOT); } + protected Map getThisTestPersistence() { + return testPersistence != null ? testPersistence + : new HashMap<>(); + } + protected int runShell(String... args) { cmdout.reset(); cmderr.reset(); diff --git a/test/langtools/jdk/jshell/ToolProviderTest.java b/test/langtools/jdk/jshell/ToolProviderTest.java index 9e457fee0f305..5d5f3ae1e87f8 100644 --- a/test/langtools/jdk/jshell/ToolProviderTest.java +++ b/test/langtools/jdk/jshell/ToolProviderTest.java @@ -85,7 +85,7 @@ protected void startCheckCommandUserOutput(Consumer checkCommandOutput, protected int runShell(String... args) { //make sure the JShell running during the test is not using persisted preferences from the machine: Function prevAugmentedToolBuilder = - getAndSetAugmentedToolBuilder(builder -> builder.persistence(new HashMap<>())); + getAndSetAugmentedToolBuilder(builder -> builder.persistence(getThisTestPersistence())); try { ServiceLoader sl = ServiceLoader.load(Tool.class); for (Tool provider : sl) { From 4f9575564c3761b251288c3dec0132cbe0a16139 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 29 Apr 2025 14:28:48 +0200 Subject: [PATCH 12/12] Reflecting review feedback. --- .../jdk/internal/jshell/tool/Startup.java | 78 ++++++++++++------- .../share/classes/jdk/jshell/SnippetMaps.java | 10 +-- 2 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java index aa27d65c5b7d2..f2472ee56239a 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Startup.java @@ -34,8 +34,11 @@ import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.EnumMap; import java.util.List; +import java.util.Map; import java.util.Objects; import static java.util.stream.Collectors.joining; import static jdk.internal.jshell.tool.JShellTool.RECORD_SEPARATOR; @@ -120,15 +123,10 @@ public boolean equals(Object o) { } private static final String DEFAULT_STARTUP_NAME = "DEFAULT"; - private static final String DEFAULT_STARTUP_NAME_NO_MODULE_IMPORTS = "DEFAULT_NO_MODULE_IMPORTS"; - private static final String PREVIEW_DEFAULT_STARTUP_NAME = "PREVIEW_DEFAULT"; // cached DEFAULT start-up - private static Startup[] defaultStartup = new Startup[] { - null, //standard startup - null, //JDK 24 and older startup - null //preview startup - }; + private static Map defaultStartup = + new EnumMap<>(DefaultStartupType.class); // the list of entries private List entries; @@ -174,9 +172,10 @@ boolean isEmpty() { boolean isDefault() { if (entries.size() == 1) { StartupEntry sue = entries.get(0); - if (sue.isBuiltIn && (sue.name.equals(DEFAULT_STARTUP_NAME) || - sue.name.equals(DEFAULT_STARTUP_NAME_NO_MODULE_IMPORTS) || - sue.name.equals(PREVIEW_DEFAULT_STARTUP_NAME))) { + if (sue.isBuiltIn && + Arrays.stream(DefaultStartupType.values()) + .map(DefaultStartupType::getResourceName) + .anyMatch(sue.name::equals)) { return true; } } @@ -340,28 +339,47 @@ static Startup noStartup() { */ static Startup defaultStartup(String sourceLevel, boolean preview, MessageHandler mh) { Source source = Source.lookup(sourceLevel); - boolean hasModuleImports = source == null || - Feature.MODULE_IMPORTS.allowedInSource(source); - int idx = preview ? 2 : !hasModuleImports ? 1 : 0; + DefaultStartupType type; + if (preview) { + type = DefaultStartupType.PREVIEW_DEFAULT_STARTUP; + } else if (source == null || + Feature.MODULE_IMPORTS.allowedInSource(source)) { + type = DefaultStartupType.DEFAULT_STARTUP; + } else { + type = DefaultStartupType.DEFAULT_STARTUP_NO_MODULE_IMPORTS; + } + + return defaultStartup.computeIfAbsent(type, t -> { + String resourceName = t.getResourceName(); + + try { + String content = readResource(resourceName); + return new Startup( + new StartupEntry(true, DEFAULT_STARTUP_NAME, content)); + } catch (AccessDeniedException e) { + mh.errormsg("jshell.err.file.not.accessible", "jshell", resourceName, e.getMessage()); + } catch (NoSuchFileException e) { + mh.errormsg("jshell.err.file.not.found", "jshell", resourceName); + } catch (Exception e) { + mh.errormsg("jshell.err.file.exception", "jshell", resourceName, e); + } + return noStartup(); + }); + } + + private enum DefaultStartupType { + DEFAULT_STARTUP("DEFAULT"), + DEFAULT_STARTUP_NO_MODULE_IMPORTS("DEFAULT_NO_MODULE_IMPORTS"), + PREVIEW_DEFAULT_STARTUP("PREVIEW_DEFAULT"); - if (defaultStartup[idx] != null) { - return defaultStartup[idx]; + private final String resourceName; + + private DefaultStartupType(String resourceName) { + this.resourceName = resourceName; } - String resourceName = preview ? PREVIEW_DEFAULT_STARTUP_NAME - : !hasModuleImports ? DEFAULT_STARTUP_NAME_NO_MODULE_IMPORTS - : DEFAULT_STARTUP_NAME; - try { - String content = readResource(resourceName); - return defaultStartup[idx] = new Startup( - new StartupEntry(true, DEFAULT_STARTUP_NAME, content)); - } catch (AccessDeniedException e) { - mh.errormsg("jshell.err.file.not.accessible", "jshell", resourceName, e.getMessage()); - } catch (NoSuchFileException e) { - mh.errormsg("jshell.err.file.not.found", "jshell", resourceName); - } catch (Exception e) { - mh.errormsg("jshell.err.file.exception", "jshell", resourceName, e); + + public String getResourceName() { + return resourceName; } - return defaultStartup[idx] = noStartup(); } - } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java index 116457a0f809b..bd0c9d86db3ec 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java @@ -194,11 +194,11 @@ String fullClassNameAndPackageToClass(String full, String pkg) { if (Stream.concat(Stream.of("java.lang"), pkgs).anyMatch(pkg::equals)) { return full.substring(pkg.length() + 1); } - Stream mods = importSnippets() - .filter(isi -> isi.subKind() == SubKind.MODULE_IMPORT_SUBKIND) - .map(isi -> isi.fullname) - .flatMap(this::module2PackagesForImport); - if (mods.anyMatch(pkg::equals)) { + Stream modPkgs = importSnippets() + .filter(isi -> isi.subKind() == SubKind.MODULE_IMPORT_SUBKIND) + .map(isi -> isi.fullname) + .flatMap(this::module2PackagesForImport); + if (modPkgs.anyMatch(pkg::equals)) { return full.substring(pkg.length() + 1); } return full;