mains = new ArrayList<>();
- gatherMains(mainClass, mains, true);
-
- if (mains.isEmpty()) {
- throw new NoSuchMethodException("No main method found");
- }
-
- if (1 < mains.size()) {
- mains.sort(MainMethodFinder::compareMethods);
- }
-
- Method mainMethod = mains.get(0);
- Method traditionalMain = getTraditionalMain(mainClass);
-
- if (traditionalMain != null && !traditionalMain.equals(mainMethod)) {
- System.err.println("WARNING: \"" + mains.get(0) + "\" chosen over \"" + traditionalMain + "\"");
- }
-
- return mains.get(0);
- }
-}
diff --git a/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java b/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java
new file mode 100644
index 00000000000..970cebe74ed
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/misc/MethodFinder.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import jdk.internal.access.JavaLangAccess;
+import jdk.internal.access.SharedSecrets;
+
+/**
+ * A collection of static methods that return specific method objects of interest.
+ */
+public class MethodFinder {
+
+ private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+
+ private MethodFinder() {
+ throw new AssertionError("private constructor");
+ }
+
+ /**
+ * Return the first method that meets the requirements of an application main method
+ * {@jls 12.1.4}. The method must:
+ *
+ * - be declared in this class's hierarchy
+ * - have the name "main"
+ * - have a single argument of type {@code String[]}, {@code String...} or no argument
+ * - have the return type of void
+ * - be public, protected or package private
+ * - not be abstract
+ *
+ *
+ * The method returned would be used by a launcher to initiate the execution of an
+ * application.
+ *
+ * Searching continues until a main method is found or the search is exhausted. The
+ * primary search occurs in two phases, once for a main method with a {@code
+ * String[]} or {@code String...} argument and failing that, once for a main method
+ * with a no arguments. The search itself uses recursion to first look at methods
+ * in this class, then default methods in this class's interface hierarchy and
+ * then repeating these steps with the class's super class.
+ *
+ * @apiNote The method returned may be declared in this class, a super class
+ * or as a default method of an interface that the class or super class
+ * implements.
+ * It is not possible to declare a static main method and instance main
+ * method with the same signature in the same class. {@jls 8.4.2} states that
+ * "It is a compile-time error to declare two methods with override-equivalent
+ * signatures in a class."
+ *
{@link SecurityException SecurityExceptions} can halt
+ * the search. In this case, a null is returned.
+ *
+ * @return the main method if a method found or null if no method is found
+ *
+ * @jls 8.2 Class Members
+ * @jls 8.4 Method Declarations
+ * @jls 8.4.2 Method Signature
+ * @jls 12.1.4 Invoke a main method
+ */
+ public static Method findMainMethod(Class> cls) {
+ boolean isPreview = PreviewFeatures.isEnabled();
+ Method mainMethod = JLA.findMethod(cls, !isPreview, "main", String[].class);
+
+ if (isPreview && mainMethod == null) {
+ mainMethod = JLA.findMethod(cls, false, "main");
+ }
+
+ if (mainMethod == null) {
+ return null;
+ }
+
+ int mods = mainMethod.getModifiers();
+
+ if (Modifier.isAbstract(mods) ||
+ mainMethod.getReturnType() != void.class ||
+ (isPreview && Modifier.isPrivate(mods)) ||
+ (!isPreview && !Modifier.isStatic(mods))) {
+ return null;
+ }
+
+ return mainMethod;
+ }
+
+}
diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java
index 05f797da70f..5cda08f6009 100644
--- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java
+++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java
@@ -71,7 +71,7 @@ import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import jdk.internal.misc.MainMethodFinder;
+import jdk.internal.misc.MethodFinder;
import jdk.internal.misc.PreviewFeatures;
import jdk.internal.misc.VM;
import jdk.internal.module.ModuleBootstrap;
@@ -709,7 +709,7 @@ public final class LauncherHelper {
/**
* This method:
* 1. Loads the main class from the module or class path
- * 2. Checks the public static void main method.
+ * 2. Checks for a valid main method.
* 3. If the main class extends FX Application then call on FXHelper to
* perform the launch.
*
@@ -753,7 +753,7 @@ public final class LauncherHelper {
mainClass = FXHelper.class;
}
- validateMainClass(mainClass);
+ validateMainMethod(mainClass);
return mainClass;
}
@@ -859,7 +859,7 @@ public final class LauncherHelper {
}
}
} catch (LinkageError le) {
- abort(le, "java.launcher.cls.error6", cn,
+ abort(le, "java.launcher.cls.error4", cn,
le.getClass().getName() + ": " + le.getLocalizedMessage());
}
return mainClass;
@@ -890,54 +890,28 @@ public final class LauncherHelper {
return false;
}
- /*
- * main type flags
- */
- private static final int MAIN_WITHOUT_ARGS = 1;
- private static final int MAIN_NONSTATIC = 2;
- private static int mainType = 0;
-
- /*
- * Return type so that launcher invokes the correct main
- */
- public static int getMainType() {
- return mainType;
- }
-
- private static void setMainType(Method mainMethod) {
- int mods = mainMethod.getModifiers();
- boolean isStatic = Modifier.isStatic(mods);
- boolean noArgs = mainMethod.getParameterCount() == 0;
- mainType = (isStatic ? 0 : MAIN_NONSTATIC) | (noArgs ? MAIN_WITHOUT_ARGS : 0);
- }
-
- // Check the existence and signature of main and abort if incorrect
- static void validateMainClass(Class> mainClass) {
+ // Check the existence and signature of main and abort if incorrect.
+ private static void validateMainMethod(Class> mainClass) {
Method mainMethod = null;
try {
- mainMethod = MainMethodFinder.findMainMethod(mainClass);
- } catch (NoSuchMethodException nsme) {
- // invalid main or not FX application, abort with an error
- abort(null, "java.launcher.cls.error4", mainClass.getName(),
- JAVAFX_APPLICATION_CLASS_NAME);
+ mainMethod = MethodFinder.findMainMethod(mainClass);
+
+ if (mainMethod == null) {
+ // invalid main or not FX application, abort with an error
+ abort(null, "java.launcher.cls.error2", mainClass.getName(),
+ JAVAFX_APPLICATION_CLASS_NAME);
+ }
} catch (Throwable e) {
if (mainClass.getModule().isNamed()) {
- abort(e, "java.launcher.module.error5",
+ abort(e, "java.launcher.module.error3",
mainClass.getName(), mainClass.getModule().getName(),
e.getClass().getName(), e.getLocalizedMessage());
} else {
- abort(e, "java.launcher.cls.error7", mainClass.getName(),
+ abort(e, "java.launcher.cls.error5", mainClass.getName(),
e.getClass().getName(), e.getLocalizedMessage());
}
}
- setMainType(mainMethod);
-
- /*
- * findMainMethod (above) will choose the correct method, based
- * on its name and parameter type, however, we still have to
- * ensure that the method is static (non-preview) and returns a void.
- */
int mods = mainMethod.getModifiers();
boolean isStatic = Modifier.isStatic(mods);
boolean isPublic = Modifier.isPublic(mods);
@@ -945,32 +919,26 @@ public final class LauncherHelper {
if (!PreviewFeatures.isEnabled()) {
if (!isStatic || !isPublic || noArgs) {
- abort(null, "java.launcher.cls.error2", "static",
- mainMethod.getDeclaringClass().getName());
+ abort(null, "java.launcher.cls.error2", mainClass.getName(),
+ JAVAFX_APPLICATION_CLASS_NAME);
}
+ return;
}
if (!isStatic) {
+ String className = mainMethod.getDeclaringClass().getName();
if (mainClass.isMemberClass() && !Modifier.isStatic(mainClass.getModifiers())) {
- abort(null, "java.launcher.cls.error9",
- mainMethod.getDeclaringClass().getName());
+ abort(null, "java.launcher.cls.error7", className);
}
try {
Constructor> constructor = mainClass.getDeclaredConstructor();
if (Modifier.isPrivate(constructor.getModifiers())) {
- abort(null, "java.launcher.cls.error8",
- mainMethod.getDeclaringClass().getName());
+ abort(null, "java.launcher.cls.error6", className);
}
} catch (Throwable ex) {
- abort(null, "java.launcher.cls.error8",
- mainMethod.getDeclaringClass().getName());
+ abort(null, "java.launcher.cls.error6", className);
}
}
-
- if (mainMethod.getReturnType() != java.lang.Void.TYPE) {
- abort(null, "java.launcher.cls.error3",
- mainMethod.getDeclaringClass().getName());
- }
}
private static final String encprop = "sun.jnu.encoding";
@@ -1122,13 +1090,13 @@ public final class LauncherHelper {
// find the module with the FX launcher
Optional om = ModuleLayer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME);
if (om.isEmpty()) {
- abort(null, "java.launcher.cls.error5");
+ abort(null, "java.launcher.cls.error3");
}
// load the FX launcher class
fxLauncherClass = Class.forName(om.get(), JAVAFX_LAUNCHER_CLASS_NAME);
if (fxLauncherClass == null) {
- abort(null, "java.launcher.cls.error5");
+ abort(null, "java.launcher.cls.error3");
}
try {
@@ -1149,7 +1117,7 @@ public final class LauncherHelper {
abort(null, "java.launcher.javafx.error1");
}
} catch (NoSuchMethodException ex) {
- abort(ex, "java.launcher.cls.error5", ex);
+ abort(ex, "java.launcher.cls.error3", ex);
}
fxLaunchName = what;
diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/src/java.base/share/classes/sun/launcher/resources/launcher.properties
index 219f0d977b5..6bea2e1f51f 100644
--- a/src/java.base/share/classes/sun/launcher/resources/launcher.properties
+++ b/src/java.base/share/classes/sun/launcher/resources/launcher.properties
@@ -238,29 +238,22 @@ java.launcher.cls.error1=\
Error: Could not find or load main class {0}\n\
Caused by: {1}: {2}
java.launcher.cls.error2=\
- Error: Main method is not {0} in class {1}, please define the main method as:\n\
-\ public static void main(String[] args)
-java.launcher.cls.error3=\
- Error: Main method must return a value of type void in class {0}, please \n\
- define the main method as:\n\
-\ public static void main(String[] args)
-java.launcher.cls.error4=\
Error: Main method not found in class {0}, please define the main method as:\n\
\ public static void main(String[] args)\n\
or a JavaFX application class must extend {1}
-java.launcher.cls.error5=\
+java.launcher.cls.error3=\
Error: JavaFX runtime components are missing, and are required to run this application
-java.launcher.cls.error6=\
+java.launcher.cls.error4=\
Error: LinkageError occurred while loading main class {0}\n\
\t{1}
-java.launcher.cls.error7=\
+java.launcher.cls.error5=\
Error: Unable to initialize main class {0}\n\
Caused by: {1}: {2}
-java.launcher.cls.error8=\
+java.launcher.cls.error6=\
Error: no non-private zero argument constructor found in class {0}\n\
remove private from existing constructor or define as:\n\
\ public {0}()
-java.launcher.cls.error9=\
+java.launcher.cls.error7=\
Error: non-static inner class {0} constructor can not be invoked \n\
make inner class static or move inner class out to separate source file
java.launcher.jar.error1=\
@@ -280,7 +273,7 @@ java.launcher.module.error2=\
Error: Could not find or load main class {0} in module {1}
java.launcher.module.error3=\
Error: Unable to load main class {0} in module {1}\n\
- \t{2}
+ Caused by: {2}
java.launcher.module.error4=\
{0} not found
java.launcher.module.error5=\
diff --git a/src/java.base/share/native/libjli/java.c b/src/java.base/share/native/libjli/java.c
index 2f9d0718e93..fbc9ecb1c4e 100644
--- a/src/java.base/share/native/libjli/java.c
+++ b/src/java.base/share/native/libjli/java.c
@@ -387,6 +387,84 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */
} \
} while (JNI_FALSE)
+#define CHECK_EXCEPTION_FAIL() \
+ do { \
+ if ((*env)->ExceptionOccurred(env)) { \
+ (*env)->ExceptionClear(env); \
+ return 0; \
+ } \
+ } while (JNI_FALSE)
+
+
+#define CHECK_EXCEPTION_NULL_FAIL(mainObject) \
+ do { \
+ if ((*env)->ExceptionOccurred(env)) { \
+ (*env)->ExceptionClear(env); \
+ return 0; \
+ } else if (mainObject == NULL) { \
+ return 0; \
+ } \
+ } while (JNI_FALSE)
+
+/*
+ * Invoke a static main with arguments. Returns 1 (true) if successful otherwise
+ * processes the pending exception from GetStaticMethodID and returns 0 (false).
+ */
+int
+invokeStaticMainWithArgs(JNIEnv *env, jclass mainClass, jobjectArray mainArgs) {
+ jmethodID mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
+ "([Ljava/lang/String;)V");
+ CHECK_EXCEPTION_FAIL();
+ (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
+ return 1;
+}
+
+/*
+ * Invoke an instance main with arguments. Returns 1 (true) if successful otherwise
+ * processes the pending exception from GetMethodID and returns 0 (false).
+ */
+int
+invokeInstanceMainWithArgs(JNIEnv *env, jclass mainClass, jobjectArray mainArgs) {
+ jmethodID constructor = (*env)->GetMethodID(env, mainClass, "", "()V");
+ CHECK_EXCEPTION_FAIL();
+ jobject mainObject = (*env)->NewObject(env, mainClass, constructor);
+ CHECK_EXCEPTION_NULL_FAIL(mainObject);
+ jmethodID mainID = (*env)->GetMethodID(env, mainClass, "main",
+ "([Ljava/lang/String;)V");
+ CHECK_EXCEPTION_FAIL();
+ (*env)->CallVoidMethod(env, mainObject, mainID, mainArgs);
+ return 1;
+ }
+
+/*
+ * Invoke a static main without arguments. Returns 1 (true) if successful otherwise
+ * processes the pending exception from GetStaticMethodID and returns 0 (false).
+ */
+int
+invokeStaticMainWithoutArgs(JNIEnv *env, jclass mainClass) {
+ jmethodID mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
+ "()V");
+ CHECK_EXCEPTION_FAIL();
+ (*env)->CallStaticVoidMethod(env, mainClass, mainID);
+ return 1;
+}
+
+/*
+ * Invoke an instance main without arguments. Returns 1 (true) if successful otherwise
+ * processes the pending exception from GetMethodID and returns 0 (false).
+ */
+int
+invokeInstanceMainWithoutArgs(JNIEnv *env, jclass mainClass) {
+ jmethodID constructor = (*env)->GetMethodID(env, mainClass, "", "()V");
+ CHECK_EXCEPTION_FAIL();
+ jobject mainObject = (*env)->NewObject(env, mainClass, constructor);
+ CHECK_EXCEPTION_NULL_FAIL(mainObject);
+ jmethodID mainID = (*env)->GetMethodID(env, mainClass, "main",
+ "()V");
+ CHECK_EXCEPTION_FAIL();
+ (*env)->CallVoidMethod(env, mainObject, mainID);
+ return 1;
+}
int
JavaMain(void* _args)
@@ -403,9 +481,6 @@ JavaMain(void* _args)
jclass mainClass = NULL;
jclass appClass = NULL; // actual application class being launched
jobjectArray mainArgs;
- jmethodID mainID;
- jmethodID constructor;
- jobject mainObject;
int ret = 0;
jlong start = 0, end = 0;
@@ -491,9 +566,6 @@ JavaMain(void* _args)
ret = 1;
/*
- * Get the application's main class. It also checks if the main
- * method exists.
- *
* See bugid 5030265. The Main-Class name has already been parsed
* from the manifest, but not parsed properly for UTF-8 support.
* Hence the code here ignores the value previously extracted and
@@ -523,7 +595,7 @@ JavaMain(void* _args)
* consistent in the UI we need to track and report the application main class.
*/
appClass = GetApplicationClass(env);
- NULL_CHECK_RETURN_VALUE(appClass, -1);
+ CHECK_EXCEPTION_NULL_LEAVE(appClass);
/* Build platform specific argument array */
mainArgs = CreateApplicationArgs(env, argv, argc);
@@ -545,59 +617,15 @@ JavaMain(void* _args)
CHECK_EXCEPTION_LEAVE(1);
/*
- * The LoadMainClass not only loads the main class, it will also ensure
- * that the main method's signature is correct, therefore further checking
- * is not required. The main method is invoked here so that extraneous java
- * stacks are not in the application stack trace.
+ * The main method is invoked here so that extraneous java stacks are not in
+ * the application stack trace.
*/
-#define MAIN_WITHOUT_ARGS 1
-#define MAIN_NONSTATIC 2
-
- jclass helperClass = GetLauncherHelperClass(env);
- jmethodID getMainType = (*env)->GetStaticMethodID(env, helperClass,
- "getMainType",
- "()I");
- CHECK_EXCEPTION_NULL_LEAVE(getMainType);
- int mainType = (*env)->CallStaticIntMethod(env, helperClass, getMainType);
- CHECK_EXCEPTION_LEAVE(mainType);
-
- switch (mainType) {
- case 0: {
- mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
- "([Ljava/lang/String;)V");
- CHECK_EXCEPTION_NULL_LEAVE(mainID);
- (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
- break;
- }
- case MAIN_WITHOUT_ARGS: {
- mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
- "()V");
- CHECK_EXCEPTION_NULL_LEAVE(mainID);
- (*env)->CallStaticVoidMethod(env, mainClass, mainID);
- break;
- }
- case MAIN_NONSTATIC: {
- constructor = (*env)->GetMethodID(env, mainClass, "", "()V");
- CHECK_EXCEPTION_NULL_LEAVE(constructor);
- mainObject = (*env)->NewObject(env, mainClass, constructor);
- CHECK_EXCEPTION_NULL_LEAVE(mainObject);
- mainID = (*env)->GetMethodID(env, mainClass, "main",
- "([Ljava/lang/String;)V");
- CHECK_EXCEPTION_NULL_LEAVE(mainID);
- (*env)->CallVoidMethod(env, mainObject, mainID, mainArgs);
- break;
- }
- case MAIN_NONSTATIC | MAIN_WITHOUT_ARGS: {
- constructor = (*env)->GetMethodID(env, mainClass, "", "()V");
- CHECK_EXCEPTION_NULL_LEAVE(constructor);
- mainObject = (*env)->NewObject(env, mainClass, constructor);
- CHECK_EXCEPTION_NULL_LEAVE(mainObject);
- mainID = (*env)->GetMethodID(env, mainClass, "main",
- "()V");
- CHECK_EXCEPTION_NULL_LEAVE(mainID);
- (*env)->CallVoidMethod(env, mainObject, mainID);
- break;
- }
+ if (!invokeStaticMainWithArgs(env, mainClass, mainArgs) &&
+ !invokeInstanceMainWithArgs(env, mainClass, mainArgs) &&
+ !invokeStaticMainWithoutArgs(env, mainClass) &&
+ !invokeInstanceMainWithoutArgs(env, mainClass)) {
+ ret = 1;
+ LEAVE();
}
/*
@@ -1593,8 +1621,9 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
}
/*
- * Loads a class and verifies that the main class is present and it is ok to
- * call it for more details refer to the java implementation.
+ * Calls LauncherHelper::checkAndLoadMain to verify that the main class
+ * is present, it is ok to load the main class and then load the main class.
+ * For more details refer to the java implementation.
*/
static jclass
LoadMainClass(JNIEnv *env, int mode, char *name)
diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Filer.java b/src/java.compiler/share/classes/javax/annotation/processing/Filer.java
index 9ebcf2c5908..7487c1fb236 100644
--- a/src/java.compiler/share/classes/javax/annotation/processing/Filer.java
+++ b/src/java.compiler/share/classes/javax/annotation/processing/Filer.java
@@ -177,12 +177,11 @@ public interface Filer {
* Creating a source file in or for an unnamed package in a named
* module is not supported.
*
- *
If the environment is configured to support {@linkplain
- * TypeElement#isUnnamed unnamed classes}, the name argument is
- * used to provide the leading component of the name used for the
- * output file. For example {@code filer.createSourceFile("Foo")}
- * to create an unnamed class hosted in {@code Foo.java}. All
- * unnamed classes must be in an unnamed package.
+ *
If the environment is configured to support implicitly declared
+ * classes, the name argument is used to provide the leading component of the
+ * name used for the output file. For example {@code filer.createSourceFile("Foo")}
+ * to create an implicitly declared class hosted in {@code Foo.java}. All
+ * implicit classes must be in an unnamed package.
*
* @apiNote To use a particular {@linkplain
* java.nio.charset.Charset charset} to encode the contents of the
@@ -263,12 +262,11 @@ public interface Filer {
*
Creating a class file in or for an unnamed package in a named
* module is not supported.
*
- *
If the environment is configured to support {@linkplain
- * TypeElement#isUnnamed unnamed classes}, the name argument is
- * used to provide the leading component of the name used for the
- * output file. For example {@code filer.createClassFile("Foo")} to
- * create an unnamed class hosted in {@code Foo.class}. All unnamed
- * classes must be in an unnamed package.
+ *
If the environment is configured to support implicitly declared
+ * classes, the name argument is used to provide the leading component of the
+ * name used for the output file. For example {@code filer.createSourceFile("Foo")}
+ * to create an implicitly declared class hosted in {@code Foo.java}. All
+ * implicit classes must be in an unnamed package.
*
* @apiNote To avoid subsequent errors, the contents of the class
* file should be compatible with the {@linkplain
diff --git a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java
index d430e33e591..a8c3b91f8b5 100644
--- a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java
+++ b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java
@@ -155,7 +155,7 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable
/**
* Returns the fully qualified name of this class or interface
* element. More precisely, it returns the canonical name.
- * For local, anonymous, and {@linkplain #isUnnamed() unnamed} classes, which do not have canonical
+ * For local, and anonymous classes, which do not have canonical
* names, an {@linkplain Name##empty_name empty name} is
* returned.
*
@@ -171,7 +171,6 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable
*
* @see Elements#getBinaryName
* @jls 6.7 Fully Qualified Names and Canonical Names
- * @jls 7.3 Compilation Units
*/
Name getQualifiedName();
@@ -181,10 +180,6 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable
* For an anonymous class, an {@linkplain Name##empty_name empty
* name} is returned.
*
- * For an {@linkplain #isUnnamed() unnamed} class, a name matching
- * the base name of the hosting file, minus any extension, is
- * returned.
- *
* @return the simple name of this class or interface,
* an empty name for an anonymous class
*
@@ -192,22 +187,6 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable
@Override
Name getSimpleName();
- /**
- * {@return {@code true} if this is an unnamed class and {@code
- * false} otherwise}
- *
- * @implSpec
- * The default implementation of this method returns {@code false}.
- *
- * @jls 7.3 Compilation Units
- * @since 21
- */
- @PreviewFeature(feature=PreviewFeature.Feature.UNNAMED_CLASSES,
- reflective=true)
- default boolean isUnnamed() {
- return false;
- }
-
/**
* Returns the direct superclass of this class or interface element.
* If this class or interface element represents an interface or the class
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
index 56b692fb7cc..770adbebc2e 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
@@ -444,9 +444,6 @@ public class ClassFinder {
if (c.members_field == null) {
try {
c.complete();
- if ((c.flags_field & UNNAMED_CLASS) != 0) {
- syms.removeClass(ps.modle, flatname);
- }
} catch (CompletionFailure ex) {
if (absent) {
syms.removeClass(ps.modle, flatname);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
index 8856654aed3..c6b8f2cd44e 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
@@ -123,9 +123,9 @@ public class Flags {
*/
public static final int HASINIT = 1<<18;
- /** Class is a unnamed top level class.
+ /** Class is a implicit top level class.
*/
- public static final int UNNAMED_CLASS = 1<<19;
+ public static final int IMPLICIT_CLASS = 1<<19;
/** Flag is set for compiler-generated anonymous method symbols
* that `own' an initializer block.
@@ -499,7 +499,7 @@ public class Flags {
ANNOTATION(Flags.ANNOTATION),
DEPRECATED(Flags.DEPRECATED),
HASINIT(Flags.HASINIT),
- UNNAMED_CLASS(Flags.UNNAMED_CLASS),
+ IMPLICIT_CLASS(Flags.IMPLICIT_CLASS),
BLOCK(Flags.BLOCK),
FROM_SOURCE(Flags.FROM_SOURCE),
ENUM(Flags.ENUM),
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 ad859bb4507..3c696a3e65d 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
@@ -210,7 +210,7 @@ public class Preview {
public boolean isPreview(Feature feature) {
return switch (feature) {
case STRING_TEMPLATES -> true;
- case UNNAMED_CLASSES -> true;
+ case IMPLICIT_CLASSES -> true;
case SUPER_INIT -> 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'
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 0290f8bc752..ffff623dc4f 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
@@ -245,7 +245,7 @@ public enum Source {
UNCONDITIONAL_PATTERN_IN_INSTANCEOF(JDK21, Fragments.FeatureUnconditionalPatternsInInstanceof, DiagKind.PLURAL),
RECORD_PATTERNS(JDK21, Fragments.FeatureDeconstructionPatterns, DiagKind.PLURAL),
STRING_TEMPLATES(JDK21, Fragments.FeatureStringTemplates, DiagKind.PLURAL),
- UNNAMED_CLASSES(JDK21, Fragments.FeatureUnnamedClasses, DiagKind.PLURAL),
+ IMPLICIT_CLASSES(JDK21, Fragments.FeatureImplicitClasses, DiagKind.PLURAL),
WARN_ON_ILLEGAL_UTF8(MIN, JDK21),
UNNAMED_VARIABLES(JDK22, Fragments.FeatureUnnamedVariables, DiagKind.PLURAL),
SUPER_INIT(JDK22, Fragments.FeatureSuperInit, DiagKind.NORMAL),
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
index b3dcde6c8cf..d583a86ca3f 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
@@ -435,6 +435,10 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
return (flags_field & FINAL) != 0;
}
+ public boolean isImplicit() {
+ return (flags_field & IMPLICIT_CLASS) != 0;
+ }
+
/** Is this symbol declared (directly or indirectly) local
* to a method or variable initializer?
* Also includes fields of inner classes which are in
@@ -1256,7 +1260,6 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
/** A class for class symbols
*/
- @SuppressWarnings("preview") // isUnnamed()
public static class ClassSymbol extends TypeSymbol implements TypeElement {
/** a scope for all class members; variables, methods and inner classes
@@ -1370,7 +1373,7 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Name getQualifiedName() {
- return isUnnamed() ? fullname.subName(0, 0) /* empty name */ : fullname;
+ return fullname;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
@@ -1551,7 +1554,7 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
@DefinedBy(Api.LANGUAGE_MODEL)
public NestingKind getNestingKind() {
apiComplete();
- if (owner.kind == PCK) // Handles unnamed classes as well
+ if (owner.kind == PCK) // Handles implicit classes as well
return NestingKind.TOP_LEVEL;
else if (name.isEmpty())
return NestingKind.ANONYMOUS;
@@ -1642,11 +1645,6 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
public List getPermittedSubclasses() {
return permitted.map(s -> s.type);
}
-
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
- public boolean isUnnamed() {
- return (flags_field & Flags.UNNAMED_CLASS) != 0 ;
- }
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index b69c2156e1d..567cf0a191f 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -5507,7 +5507,7 @@ public class Attr extends JCTree.Visitor {
chk.checkFunctionalInterface((JCClassDecl) env.tree, c);
chk.checkLeaksNotAccessible(env, (JCClassDecl) env.tree);
- if ((c.flags_field & Flags.UNNAMED_CLASS) != 0) {
+ if (c.isImplicit()) {
chk.checkHasMain(env.tree.pos(), c);
}
} finally {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index ead1ecf3c63..f9b228203d4 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -452,7 +452,8 @@ public class Check {
}
}
for (Symbol sym = s.owner; sym != null; sym = sym.owner) {
- if (sym.kind == TYP && sym.name == name && sym.name != names.error) {
+ if (sym.kind == TYP && sym.name == name && sym.name != names.error &&
+ !sym.isImplicit()) {
duplicateError(pos, sym);
return true;
}
@@ -2276,7 +2277,7 @@ public class Check {
}
if (!found) {
- log.error(pos, Errors.UnnamedClassDoesNotHaveMainMethod);
+ log.error(pos, Errors.ImplicitClassDoesNotHaveMainMethod);
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
index 90d48243841..7478ef1c907 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
@@ -442,7 +442,7 @@ public class Enter extends JCTree.Visitor {
log.error(tree.pos(),
Errors.ClassPublicShouldBeInFile(topElement, tree.name));
}
- if ((tree.mods.flags & UNNAMED_CLASS) != 0) {
+ if ((tree.mods.flags & IMPLICIT_CLASS) != 0) {
syms.removeClass(env.toplevel.modle, tree.name);
}
} else {
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 51486b997d3..8d12ba5ccaa 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
@@ -3047,14 +3047,6 @@ public class ClassReader {
signatureBuffer = new byte[ns];
}
readClass(c);
- if (previewClassFile) {
- if ((c.flags_field & SYNTHETIC) != 0 &&
- c.owner.kind == PCK &&
- (c.flags_field & AUXILIARY) == 0 &&
- (c.flags_field & FINAL) != 0) {
- c.flags_field |= UNNAMED_CLASS;
- }
- }
}
public void readClassFile(ClassSymbol c) {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java
index 729d1cf2b05..cd35ccaa3b7 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/launcher/Main.java
@@ -85,7 +85,7 @@ import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.resources.LauncherProperties.Errors;
import com.sun.tools.javac.util.JCDiagnostic.Error;
-import jdk.internal.misc.MainMethodFinder;
+import jdk.internal.misc.MethodFinder;
import jdk.internal.misc.PreviewFeatures;
import jdk.internal.misc.VM;
@@ -407,8 +407,8 @@ public class Main {
throw new Fault(Errors.NoClass);
}
TypeElement mainClass = l.mainClass;
- String mainClassName = (mainClass.isUnnamed() ? mainClass.getSimpleName()
- : mainClass.getQualifiedName()).toString();
+ String mainClassName = mainClass.getQualifiedName().toString();
+
return mainClassName;
}
@@ -434,26 +434,13 @@ public class Main {
throw new Fault(Errors.CantFindClass(mainClassName));
}
- Method mainMethod;
- try {
- mainMethod = MainMethodFinder.findMainMethod(appClass);
- } catch (NoSuchMethodException e) {
+ Method mainMethod = MethodFinder.findMainMethod(appClass);
+
+ if (mainMethod == null) {
throw new Fault(Errors.CantFindMainMethod(mainClassName));
}
- int mods = mainMethod.getModifiers();
- boolean isStatic = Modifier.isStatic(mods);
- boolean isPublic = Modifier.isPublic(mods);
- boolean noArgs = mainMethod.getParameterCount() == 0;
-
- if (!PreviewFeatures.isEnabled() && (!isStatic || !isPublic)) {
- throw new Fault(Errors.MainNotPublicStatic);
- }
-
- if (!mainMethod.getReturnType().equals(void.class)) {
- throw new Fault(Errors.MainNotVoid);
- }
-
+ boolean isStatic = Modifier.isStatic(mainMethod.getModifiers());
Object instance = null;
if (!isStatic) {
@@ -478,7 +465,7 @@ public class Main {
mainMethod.setAccessible(true);
Object receiver = isStatic ? appClass : instance;
- if (noArgs) {
+ if (mainMethod.getParameterCount() == 0) {
mainMethod.invoke(receiver);
} else {
mainMethod.invoke(receiver, (Object)mainArgs);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index 0713739050a..bf124bc35bc 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -206,9 +206,9 @@ public class JavacParser implements Parser {
this.source = parser.source;
this.preview = parser.preview;
this.allowStringFolding = parser.allowStringFolding;
- this.keepDocComments = false;
+ this.keepDocComments = parser.keepDocComments;
this.parseModuleInfo = false;
- this.docComments = null;
+ this.docComments = parser.docComments;
this.errorTree = F.Erroneous();
this.endPosTable = newEndPosTable(false);
this.allowYieldStatement = Feature.SWITCH_EXPRESSION.allowedInSource(source);
@@ -3916,8 +3916,8 @@ public class JavacParser implements Parser {
defs.append(pd);
}
- boolean firstTypeDecl = true; // have we see a class, enum, or interface declaration yet?
- boolean isUnnamedClass = false;
+ boolean firstTypeDecl = true; // have we seen a class, enum, or interface declaration yet?
+ boolean isImplicitClass = false;
OUTER: while (token.kind != EOF) {
if (token.pos <= endPosTable.errorEndPos) {
// error recovery
@@ -3984,13 +3984,13 @@ public class JavacParser implements Parser {
// this code speculatively tests to see if a top level method
// or field can parse. If the method or field can parse then
// it is parsed. Otherwise, parsing continues as though
- // unnamed classes did not exist and error reporting
+ // implicit classes did not exist and error reporting
// is the same as in the past.
- if (Feature.UNNAMED_CLASSES.allowedInSource(source) && !isDeclaration()) {
+ if (Feature.IMPLICIT_CLASSES.allowedInSource(source) && !isDeclaration()) {
final JCModifiers finalMods = mods;
JavacParser speculative = new VirtualParser(this);
List speculativeResult =
- speculative.topLevelMethodOrFieldDeclaration(finalMods);
+ speculative.topLevelMethodOrFieldDeclaration(finalMods, null);
if (speculativeResult.head.hasTag(METHODDEF) ||
speculativeResult.head.hasTag(VARDEF)) {
isTopLevelMethodOrField = true;
@@ -3998,9 +3998,9 @@ public class JavacParser implements Parser {
}
if (isTopLevelMethodOrField) {
- checkSourceLevel(token.pos, Feature.UNNAMED_CLASSES);
- defs.appendList(topLevelMethodOrFieldDeclaration(mods));
- isUnnamedClass = true;
+ checkSourceLevel(token.pos, Feature.IMPLICIT_CLASSES);
+ defs.appendList(topLevelMethodOrFieldDeclaration(mods, docComment));
+ isImplicitClass = true;
} else {
JCTree def = typeDeclaration(mods, docComment);
if (def instanceof JCExpressionStatement statement)
@@ -4012,7 +4012,7 @@ public class JavacParser implements Parser {
firstTypeDecl = false;
}
}
- List topLevelDefs = isUnnamedClass ? constructUnnamedClass(defs.toList()) : defs.toList();
+ List topLevelDefs = isImplicitClass ? constructImplictClass(defs.toList()) : defs.toList();
JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(topLevelDefs);
if (!consumedToplevelDoc)
attach(toplevel, firstToken.docComment());
@@ -4027,14 +4027,14 @@ public class JavacParser implements Parser {
return toplevel;
}
- // Restructure top level to be an unnamed class.
- private List constructUnnamedClass(List origDefs) {
+ // Restructure top level to be an implicit class.
+ private List constructImplictClass(List origDefs) {
ListBuffer topDefs = new ListBuffer<>();
ListBuffer defs = new ListBuffer<>();
for (JCTree def : origDefs) {
if (def.hasTag(Tag.PACKAGEDEF)) {
- log.error(def.pos(), Errors.UnnamedClassShouldNotHavePackageDeclaration);
+ log.error(def.pos(), Errors.ImplicitClassShouldNotHavePackageDeclaration);
} else if (def.hasTag(Tag.IMPORT)) {
topDefs.append(def);
} else if (!def.hasTag(Tag.SKIP)) {
@@ -4053,12 +4053,12 @@ public class JavacParser implements Parser {
}
Name name = names.fromString(simplename);
- JCModifiers unnamedMods = F.at(Position.NOPOS)
- .Modifiers(Flags.FINAL|Flags.SYNTHETIC|Flags.UNNAMED_CLASS, List.nil());
- JCClassDecl unnamed = F.at(primaryPos).ClassDef(
- unnamedMods, name, List.nil(), null, List.nil(), List.nil(),
+ JCModifiers implicitMods = F.at(Position.NOPOS)
+ .Modifiers(Flags.FINAL|Flags.IMPLICIT_CLASS, List.nil());
+ JCClassDecl implicit = F.at(primaryPos).ClassDef(
+ implicitMods, name, List.nil(), null, List.nil(), List.nil(),
defs.toList());
- topDefs.append(unnamed);
+ topDefs.append(implicit);
return topDefs.toList();
}
@@ -4735,10 +4735,9 @@ public class JavacParser implements Parser {
return List.of(syntaxError(token.pos, err, Errors.Expected(LPAREN)));
}
- private List topLevelMethodOrFieldDeclaration(JCModifiers mods) throws AssertionError {
- int topPos = token.pos;
+ private List topLevelMethodOrFieldDeclaration(JCModifiers mods, Comment dc) throws AssertionError {
int pos = token.pos;
- Comment dc = token.docComment();
+ dc = dc == null ? token.docComment() : dc;
List typarams = typeParametersOpt();
// if there are type parameters but no modifiers, save the start
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java
index ee49a5b344d..9cb3b4992f1 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java
@@ -126,7 +126,7 @@ public class PrintingProcessor extends AbstractProcessor {
kind != INSTANCE_INIT) {
Element enclosing = e.getEnclosingElement();
- // Don't print out the constructor of an anonymous or unnamed class
+ // Don't print out the constructor of an anonymous class
if (kind == CONSTRUCTOR &&
enclosing != null &&
(NestingKind.ANONYMOUS ==
@@ -136,13 +136,6 @@ public class PrintingProcessor extends AbstractProcessor {
public NestingKind visitType(TypeElement e, Void p) {
return e.getNestingKind();
}
- }).visit(enclosing)
- || // Don't print the constructor of an unnamed class
- (new SimpleElementVisitor14(false) {
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
- public Boolean visitType(TypeElement e, Void p) {
- return e.isUnnamed();
- }
}).visit(enclosing)) ) {
return this;
}
@@ -222,14 +215,6 @@ public class PrintingProcessor extends AbstractProcessor {
printParameters(constructors.get(0));
}
writer.print(")");
- } else if (e.isUnnamed()) {
- writer.println("// Unnamed class in file whose name starts with " + e.getSimpleName());
-
- for(Element element : e.getEnclosedElements()) {
- this.visit(element);
- }
-
- return this;
} else {
if (nestingKind == TOP_LEVEL) {
PackageElement pkg = elementUtils.getPackageOf(e);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index 30756ef6fa6..975c3205a36 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -524,11 +524,11 @@ compiler.err.duplicate.class=\
compiler.err.bad.file.name=\
bad file name: {0}
-compiler.err.unnamed.class.should.not.have.package.declaration=\
- unnamed class should not have package declaration
+compiler.err.implicit.class.should.not.have.package.declaration=\
+ implicit class should not have package declaration
-compiler.err.unnamed.class.does.not.have.main.method=\
- unnamed class does not have main method in the form of void main() or void main(String[] args)
+compiler.err.implicit.class.does.not.have.main.method=\
+ implicit class does not have main method in the form of void main() or void main(String[] args)
# 0: name, 1: name
compiler.err.same.binary.name=\
@@ -3218,8 +3218,8 @@ compiler.misc.feature.string.templates=\
compiler.misc.feature.unconditional.patterns.in.instanceof=\
unconditional patterns in instanceof
-compiler.misc.feature.unnamed.classes=\
- unnamed classes
+compiler.misc.feature.implicit.classes=\
+ implicit classes
compiler.misc.feature.super.init=\
statements before super()
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
index 7cd0df9295b..21ced44c80e 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
@@ -1161,7 +1161,7 @@ public class TreeMaker implements JCTree.Factory {
!it.hasNext();
}
}
- return sym.kind == TYP && (sym.flags_field & Flags.UNNAMED_CLASS) != 0;
+ return sym.kind == TYP && sym.isImplicit();
}
/** The name of synthetic parameter number `i'.
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java
index 7f4f31844f5..b0a6b4dfdf4 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java
@@ -986,7 +986,7 @@ public class ElementsTable {
* @return true if the element is visible
*/
public boolean isSelected(Element e) {
- if (toolEnv.isSynthetic((Symbol) e) && !toolEnv.isUnnamed((Symbol) e)) {
+ if (toolEnv.isSynthetic((Symbol) e)) {
return false;
}
if (visibleElementVisitor == null) {
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java
index a8cb10651dd..4b1e1c66258 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java
@@ -174,10 +174,6 @@ public class ToolEnvironment {
return (sym.flags() & Flags.SYNTHETIC) != 0;
}
- boolean isUnnamed(Symbol sym) {
- return (sym.flags() & Flags.UNNAMED_CLASS) != 0;
- }
-
void setElementToTreePath(Element e, TreePath tree) {
if (e == null || tree == null)
return;
diff --git a/test/jdk/java/lang/Class/UnnamedClass/TestUnnamedClass.java b/test/jdk/java/lang/Class/UnnamedClass/TestUnnamedClass.java
deleted file mode 100644
index 9e4635ab932..00000000000
--- a/test/jdk/java/lang/Class/UnnamedClass/TestUnnamedClass.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8306112
- * @enablePreview
- * @build Unnamed TestUnnamedClass
- * @run main TestUnnamedClass
- * @summary Basic checks of java.lang.Class support for unnamed classes
- */
-
-import java.lang.reflect.Modifier;
-
-public class TestUnnamedClass {
- public static void main(String... args) throws Exception {
- Class> unnamedClass = Class.forName("Unnamed");
-
- /*
- * From JEP 445 JLS changes:
- *
- * "An unnamed class compilation unit implicitly declares a class that satisfies the following
- * properties:
- * It is always a top level class.
- * It is always an unnamed class (it has no canonical or fully qualified name (6.7)).
- * It is never abstract (8.1.1.1).
- * It is always final (8.1.1.2).
- * It is always a member of an unnamed package (7.4.2) and has package access.
- * Its direct superclass type is always Object (8.1.4).
- * It never has any direct superinterface types (8.1.5).
- */
-
- check(unnamedClass.isUnnamedClass(), "Unnamed class was isUnnamedClass() false");
-
- check(!(unnamedClass.isInterface() ||
- unnamedClass.isEnum() ||
- unnamedClass.isRecord() ||
- unnamedClass.isHidden()),
- "Unnamed class was not a normal class");
-
- check(!(unnamedClass.isLocalClass() ||
- unnamedClass.isMemberClass() ||
- unnamedClass.isPrimitive() ||
- unnamedClass.isArray()),
- "Unnamed class was not top-level");
-
- check("Unnamed".equals(unnamedClass.getName()), "Unexpected Class.getName result");
- check("Unnamed".equals(unnamedClass.getTypeName()), "Unexpected Class.getTypeName result");
- check("".equals(unnamedClass.getSimpleName()), "Unexpected Class.getSimpleName result");
- check(unnamedClass.getCanonicalName() == null, "Unexpected non-null Class.getCanonicalName");
-
- int modifiers = unnamedClass.getModifiers();
- check((modifiers & Modifier.ABSTRACT) == 0, "Unnamed class was abstract");
- check((modifiers & Modifier.FINAL) != 0, "Unnamed class was not final");
- check((modifiers & (Modifier.PUBLIC |
- Modifier.PRIVATE |
- Modifier.PROTECTED)) == 0, "Unnamed class was not package access");
-
- check(unnamedClass.isSynthetic(), "Unnamed class was not synthetic");
-
- check("".equals(unnamedClass.getPackage().getName()), "Unnamed class not in an unnamed package");
-
- check(unnamedClass.getSuperclass() == Object.class, "Superclass was not java.lang.Object");
-
- check(unnamedClass.getInterfaces().length == 0, "Unnamed class had super interfaces");
- }
-
- private static void check(boolean predicate, String message) {
- if (!predicate) {
- throw new RuntimeException(message);
- }
- }
-}
diff --git a/test/jdk/tools/launcher/Arrrghs.java b/test/jdk/tools/launcher/Arrrghs.java
index 11a6ab0a520..efc95052842 100644
--- a/test/jdk/tools/launcher/Arrrghs.java
+++ b/test/jdk/tools/launcher/Arrrghs.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -541,12 +541,12 @@ public class Arrrghs extends TestHelper {
createJar(new File("some.jar"), new File("Foo"),
"public static int main(String[] args){return 1;}");
tr = doExec(javaCmd, "-jar", "some.jar");
- tr.contains("Error: Main method must return a value of type void in class Foo");
+ tr.contains("Error: Main method not found in class Foo");
if (!tr.testStatus)
System.out.println(tr);
// use classpath to check
tr = doExec(javaCmd, "-cp", "some.jar", "Foo");
- tr.contains("Error: Main method must return a value of type void in class Foo");
+ tr.contains("Error: Main method not found in class Foo");
if (!tr.testStatus)
System.out.println(tr);
@@ -567,12 +567,12 @@ public class Arrrghs extends TestHelper {
createJar(new File("some.jar"), new File("Foo"),
"public void main(String[] args){}");
tr = doExec(javaCmd, "-jar", "some.jar");
- tr.contains("Error: Main method is not static in class Foo");
+ tr.contains("Error: Main method not found in class Foo");
if (!tr.testStatus)
System.out.println(tr);
// use classpath to check
tr = doExec(javaCmd, "-cp", "some.jar", "Foo");
- tr.contains("Error: Main method is not static in class Foo");
+ tr.contains("Error: Main method not found in class Foo");
if (!tr.testStatus)
System.out.println(tr);
diff --git a/test/jdk/tools/launcher/InstanceMainTest.java b/test/jdk/tools/launcher/InstanceMainTest.java
index 05973557fc3..08b5cb48dbb 100644
--- a/test/jdk/tools/launcher/InstanceMainTest.java
+++ b/test/jdk/tools/launcher/InstanceMainTest.java
@@ -42,13 +42,13 @@ public class InstanceMainTest extends TestHelper {
}
""",
- // static dominating instance
+ // instance dominating static
"""
class MainClass {
void main(String[] args) {
- throw new AssertionError();
}
static void main() {
+ throw new AssertionError();
}
}
""",
@@ -81,12 +81,12 @@ public class InstanceMainTest extends TestHelper {
}
""",
- // unnamed class static dominating instance
+ // main with args dominating main without args
"""
void main(String[] args) {
- throw new AssertionError();
}
static void main() {
+ throw new AssertionError();
}
""",
@@ -105,15 +105,15 @@ public class InstanceMainTest extends TestHelper {
}
""",
- // instance main dominating super static
+ // instance main with args dominating super
"""
class MainClass extends SuperClass {
void main() {
+ throw new AssertionError();
}
}
class SuperClass {
void main(String[] args) {
- throw new AssertionError();
}
}
""",
diff --git a/test/jdk/tools/launcher/modules/basic/LauncherErrors.java b/test/jdk/tools/launcher/modules/basic/LauncherErrors.java
index b79238218b3..dd5157fa612 100644
--- a/test/jdk/tools/launcher/modules/basic/LauncherErrors.java
+++ b/test/jdk/tools/launcher/modules/basic/LauncherErrors.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -92,9 +92,10 @@ public class LauncherErrors {
ProcessTools.executeTestJava("-Djava.security.manager", "--module-path", dir, "--module", mid)
.outputTo(System.out)
.errorTo(System.out)
- .shouldContain("Error: Unable to initialize main class " + MAIN_CLASS + " in module " + TEST_MODULE)
- .shouldContain("Caused by: java.security.AccessControlException: access denied")
+ .shouldContain("Error: Unable to load main class " + MAIN_CLASS + " in module " + TEST_MODULE)
+ .shouldContain("Caused by: java.security.AccessControlException")
.shouldNotHaveExitValue(0);
+
}
}
diff --git a/test/langtools/jdk/javadoc/doclet/testUnnamed/TestUnnamed.java b/test/langtools/jdk/javadoc/doclet/testUnnamed/TestImplicit.java
similarity index 91%
rename from test/langtools/jdk/javadoc/doclet/testUnnamed/TestUnnamed.java
rename to test/langtools/jdk/javadoc/doclet/testUnnamed/TestImplicit.java
index e9658cd4071..fa9a535902f 100644
--- a/test/langtools/jdk/javadoc/doclet/testUnnamed/TestUnnamed.java
+++ b/test/langtools/jdk/javadoc/doclet/testUnnamed/TestImplicit.java
@@ -24,11 +24,11 @@
/*
* @test
* @bug 8309595
- * @summary Allow javadoc to process unnamed classes
+ * @summary Allow javadoc to process implicit classes
* @library /tools/lib ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build toolbox.ToolBox javadoc.tester.*
- * @run main TestUnnamed
+ * @run main TestImplicit
*/
import java.io.File;
@@ -39,18 +39,18 @@ import java.nio.file.Path;
import javadoc.tester.JavadocTester;
import toolbox.ToolBox;
-public class TestUnnamed extends JavadocTester {
+public class TestImplicit extends JavadocTester {
private static final String thisVersion = System.getProperty("java.specification.version");
private static final ToolBox tb = new ToolBox();
public static void main(String... args) throws Exception {
- new TestUnnamed().runTests();
+ new TestImplicit().runTests();
}
@Test
- public void testUnnamed(Path base) throws IOException {
+ public void testImplicit(Path base) throws IOException {
String className = "Sample";
Files.createDirectories(base);
Path out = base.resolve("out");
diff --git a/test/jdk/java/lang/Class/UnnamedClass/Unnamed.java b/test/langtools/tools/javac/ImplicitClass/Implicit.java
similarity index 95%
rename from test/jdk/java/lang/Class/UnnamedClass/Unnamed.java
rename to test/langtools/tools/javac/ImplicitClass/Implicit.java
index 9545a90f0de..10e1fad007b 100644
--- a/test/jdk/java/lang/Class/UnnamedClass/Unnamed.java
+++ b/test/langtools/tools/javac/ImplicitClass/Implicit.java
@@ -23,8 +23,8 @@
/**
- * Exemplar unnamed class.
+ * Exemplar implicit class.
*/
-public void main() {
+void main() {
System.out.println("Hello, world.");
}
diff --git a/test/langtools/tools/javac/unnamed/UnnamedClassRecovery.java b/test/langtools/tools/javac/ImplicitClass/ImplicitClassRecovery.java
similarity index 53%
rename from test/langtools/tools/javac/unnamed/UnnamedClassRecovery.java
rename to test/langtools/tools/javac/ImplicitClass/ImplicitClassRecovery.java
index 2c1d533ab6c..0057d779f8c 100644
--- a/test/langtools/tools/javac/unnamed/UnnamedClassRecovery.java
+++ b/test/langtools/tools/javac/ImplicitClass/ImplicitClassRecovery.java
@@ -1,6 +1,6 @@
/**
* @test /nodynamiccopyright/
- * @compile/fail/ref=UnnamedClassRecovery.out -XDrawDiagnostics --enable-preview --source ${jdk.version} UnnamedClassRecovery.java
+ * @compile/fail/ref=ImplicitClassRecovery.out -XDrawDiagnostics --enable-preview --source ${jdk.version} ImplicitClassRecovery.java
*/
public void main() {
//the following is intentionally missing a semicolon:
diff --git a/test/langtools/tools/javac/ImplicitClass/ImplicitClassRecovery.out b/test/langtools/tools/javac/ImplicitClass/ImplicitClassRecovery.out
new file mode 100644
index 00000000000..7de6ac6b3ee
--- /dev/null
+++ b/test/langtools/tools/javac/ImplicitClass/ImplicitClassRecovery.out
@@ -0,0 +1,4 @@
+ImplicitClassRecovery.java:7:33: compiler.err.expected: ';'
+- compiler.note.preview.filename: ImplicitClassRecovery.java, DEFAULT
+- compiler.note.preview.recompile
+1 error
diff --git a/test/langtools/tools/javac/ImplicitClass/NestedClasses.java b/test/langtools/tools/javac/ImplicitClass/NestedClasses.java
new file mode 100644
index 00000000000..19f070c4d48
--- /dev/null
+++ b/test/langtools/tools/javac/ImplicitClass/NestedClasses.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8315458
+ * @enablePreview
+ * @summary Make sure nesting classes don't create symbol conflicts with implicit name.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @run main NestedClasses
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import toolbox.ToolBox;
+import toolbox.JavaTask;
+import toolbox.JavacTask;
+import toolbox.Task;
+
+public class NestedClasses {
+ private static ToolBox TOOLBOX = new ToolBox();
+ private static final String JAVA_VERSION = System.getProperty("java.specification.version");
+
+ public static void main(String... arg) throws IOException {
+ compPass("A.java", """
+ void main() {}
+ class A {} // okay
+ """);
+
+ compPass("A.java", """
+ void main() {}
+ class B {
+ class A { } // okay
+ }
+ """);
+
+ compFail("A.java", """
+ void main() {}
+ class B {
+ class B { } //error
+ }
+ """);
+ }
+
+ /*
+ * Test source for successful compile.
+ */
+ static void compPass(String fileName, String code) throws IOException {
+ Path path = Path.of(fileName);
+ Files.writeString(path, code);
+ String output = new JavacTask(TOOLBOX)
+ .files(List.of(path))
+ .classpath(".")
+ .options("-encoding", "utf8", "--enable-preview", "-source", JAVA_VERSION)
+ .run()
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ if (output.contains("compiler.err")) {
+ throw new RuntimeException("Error detected");
+ }
+ }
+
+ /*
+ * Test source for unsuccessful compile and specific error.
+ */
+ static void compFail(String fileName, String code) throws IOException {
+ Path path = Path.of(fileName);
+ Files.writeString(path, code);
+ String output = new JavacTask(TOOLBOX)
+ .files(List.of(path))
+ .classpath(".")
+ .options("-XDrawDiagnostics", "-encoding", "utf8", "--enable-preview", "-source", JAVA_VERSION)
+ .run(Task.Expect.FAIL)
+ .writeAll()
+ .getOutput(Task.OutputKind.DIRECT);
+
+ if (!output.contains("compiler.err")) {
+ throw new RuntimeException("No error detected");
+ }
+ }
+
+ }
diff --git a/test/langtools/tools/javac/unnamedclass/NestedEnum.java b/test/langtools/tools/javac/ImplicitClass/NestedEnum.java
similarity index 100%
rename from test/langtools/tools/javac/unnamedclass/NestedEnum.java
rename to test/langtools/tools/javac/ImplicitClass/NestedEnum.java
diff --git a/test/langtools/tools/javac/unnamedclass/SourceLevelErrorPosition.java b/test/langtools/tools/javac/ImplicitClass/SourceLevelErrorPosition.java
similarity index 74%
rename from test/langtools/tools/javac/unnamedclass/SourceLevelErrorPosition.java
rename to test/langtools/tools/javac/ImplicitClass/SourceLevelErrorPosition.java
index 54beb45d90b..786c228f11e 100644
--- a/test/langtools/tools/javac/unnamedclass/SourceLevelErrorPosition.java
+++ b/test/langtools/tools/javac/ImplicitClass/SourceLevelErrorPosition.java
@@ -1,7 +1,7 @@
/**
* @test /nodynamiccopyright/
* @bug 8310314
- * @summary Ensure proper error position for the "unnamed classes not supported" error
+ * @summary Ensure proper error position for the "implicit classes not supported" error
* @compile/fail/ref=SourceLevelErrorPosition.out -XDrawDiagnostics SourceLevelErrorPosition.java
*/
class Nested {}
diff --git a/test/langtools/tools/javac/unnamedclass/SourceLevelErrorPosition.out b/test/langtools/tools/javac/ImplicitClass/SourceLevelErrorPosition.out
similarity index 55%
rename from test/langtools/tools/javac/unnamedclass/SourceLevelErrorPosition.out
rename to test/langtools/tools/javac/ImplicitClass/SourceLevelErrorPosition.out
index 518350810a0..1376183d9c6 100644
--- a/test/langtools/tools/javac/unnamedclass/SourceLevelErrorPosition.out
+++ b/test/langtools/tools/javac/ImplicitClass/SourceLevelErrorPosition.out
@@ -1,2 +1,2 @@
-SourceLevelErrorPosition.java:8:1: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.unnamed.classes)
+SourceLevelErrorPosition.java:8:1: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.implicit.classes)
1 error
diff --git a/test/langtools/tools/javac/ImplicitClass/TestImplicitClass.java b/test/langtools/tools/javac/ImplicitClass/TestImplicitClass.java
new file mode 100644
index 00000000000..673c31b6215
--- /dev/null
+++ b/test/langtools/tools/javac/ImplicitClass/TestImplicitClass.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8315458
+ * @enablePreview
+ * @build Implicit TestImplicitClass
+ * @run main TestImplicitClass
+ * @summary Basic checks of java.lang.Class support for implicit classes
+ */
+
+import java.lang.reflect.Modifier;
+
+public class TestImplicitClass {
+ public static void main(String... args) throws Exception {
+ Class> implicitClass = Class.forName("Implicit");
+
+ /*
+ * From JEP 463 JLS changes:
+ *
+ * "An implicit class compilation unit implicitly declares a class that satisfies the following
+ * properties:
+ * It is always a top level class.
+ * It is never abstract (8.1.1.1).
+ * It is never synthetic (13.1.11)
+ * It is always final (8.1.1.2).
+ * It is always a member of unnamed package (7.4.2) and has package access.
+ * Its direct superclass type is always Object (8.1.4).
+ * It never has any direct superinterface types (8.1.5).
+ */
+
+ check(!(implicitClass.isInterface() ||
+ implicitClass.isEnum() ||
+ implicitClass.isRecord() ||
+ implicitClass.isHidden()),
+ "Implicit class was not a normal class");
+
+ check(!(implicitClass.isLocalClass() ||
+ implicitClass.isMemberClass() ||
+ implicitClass.isPrimitive() ||
+ implicitClass.isArray()),
+ "Implicit class was not top-level");
+
+ check("Implicit".equals(implicitClass.getName()), "Unexpected Class.getName result");
+ check("Implicit".equals(implicitClass.getTypeName()), "Unexpected Class.getTypeName result");
+ check("Implicit".equals(implicitClass.getSimpleName()), "Unexpected Class.getSimpleName result");
+ check("Implicit".equals(implicitClass.getCanonicalName()), "Unexpected Class.getCanonicalName result");
+
+ int modifiers = implicitClass.getModifiers();
+ check((modifiers & Modifier.ABSTRACT) == 0, "Implicit class was abstract");
+ check((modifiers & Modifier.FINAL) != 0, "Implicit class was not final");
+ check((modifiers & (Modifier.PUBLIC |
+ Modifier.PRIVATE |
+ Modifier.PROTECTED)) == 0, "Implicit class was not package access");
+
+ check(!implicitClass.isSynthetic(), "Implicit class was synthetic");
+
+ check("".equals(implicitClass.getPackage().getName()), "Implicit class not in an implicit package");
+
+ check(implicitClass.getSuperclass() == Object.class, "Superclass was not java.lang.Object");
+
+ check(implicitClass.getInterfaces().length == 0, "Implicit class had super interfaces");
+ }
+
+ private static void check(boolean predicate, String message) {
+ if (!predicate) {
+ throw new RuntimeException(message);
+ }
+ }
+}
diff --git a/test/langtools/tools/javac/diags/examples/UnnamedClass.java b/test/langtools/tools/javac/diags/examples/ImplicitClass.java
similarity index 96%
rename from test/langtools/tools/javac/diags/examples/UnnamedClass.java
rename to test/langtools/tools/javac/diags/examples/ImplicitClass.java
index c78dcf14e6c..c032bdefeff 100644
--- a/test/langtools/tools/javac/diags/examples/UnnamedClass.java
+++ b/test/langtools/tools/javac/diags/examples/ImplicitClass.java
@@ -21,7 +21,7 @@
* questions.
*/
- // key: compiler.misc.feature.unnamed.classes
+ // key: compiler.misc.feature.implicit.classes
// key: compiler.warn.preview.feature.use.plural
// options: -source ${jdk.version} --enable-preview -Xlint:preview
diff --git a/test/langtools/tools/javac/diags/examples/UnnamedClassBad-Filename.java b/test/langtools/tools/javac/diags/examples/ImplicitClassBad-Filename.java
similarity index 100%
rename from test/langtools/tools/javac/diags/examples/UnnamedClassBad-Filename.java
rename to test/langtools/tools/javac/diags/examples/ImplicitClassBad-Filename.java
diff --git a/test/langtools/tools/javac/diags/examples/UnnamedClassHasPackage.java b/test/langtools/tools/javac/diags/examples/ImplicitClassHasPackage.java
similarity index 92%
rename from test/langtools/tools/javac/diags/examples/UnnamedClassHasPackage.java
rename to test/langtools/tools/javac/diags/examples/ImplicitClassHasPackage.java
index 96601f9a945..c90e0f3dfbc 100644
--- a/test/langtools/tools/javac/diags/examples/UnnamedClassHasPackage.java
+++ b/test/langtools/tools/javac/diags/examples/ImplicitClassHasPackage.java
@@ -21,12 +21,12 @@
* questions.
*/
- // key: compiler.err.unnamed.class.should.not.have.package.declaration
+ // key: compiler.err.implicit.class.should.not.have.package.declaration
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: -source ${jdk.version} --enable-preview
-package unnamed.classes;
+package implicit.classes;
public static void main(String... args) {
}
diff --git a/test/langtools/tools/javac/diags/examples/UnnamedClassNoMain.java b/test/langtools/tools/javac/diags/examples/ImplicitClassNoMain.java
similarity index 95%
rename from test/langtools/tools/javac/diags/examples/UnnamedClassNoMain.java
rename to test/langtools/tools/javac/diags/examples/ImplicitClassNoMain.java
index 0caacb60e66..4c82341f5ac 100644
--- a/test/langtools/tools/javac/diags/examples/UnnamedClassNoMain.java
+++ b/test/langtools/tools/javac/diags/examples/ImplicitClassNoMain.java
@@ -21,7 +21,7 @@
* questions.
*/
- // key: compiler.err.unnamed.class.does.not.have.main.method
+ // key: compiler.err.implicit.class.does.not.have.main.method
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: -source ${jdk.version} --enable-preview
diff --git a/test/langtools/tools/javac/launcher/SourceLauncherTest.java b/test/langtools/tools/javac/launcher/SourceLauncherTest.java
index 06190546d49..9e2ef069369 100644
--- a/test/langtools/tools/javac/launcher/SourceLauncherTest.java
+++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.java
@@ -564,7 +564,7 @@ public class SourceLauncherTest extends TestRunner {
tb.writeJavaFiles(base,
"class NotStatic { public void main(String... args) { } }");
testError(base.resolve("NotStatic.java"), "",
- "error: 'main' method is not declared 'public static'");
+ "error: can't find main(String[]) method in class: NotStatic");
}
@Test
@@ -572,7 +572,7 @@ public class SourceLauncherTest extends TestRunner {
tb.writeJavaFiles(base,
"class NotVoid { public static int main(String... args) { return 0; } }");
testError(base.resolve("NotVoid.java"), "",
- "error: 'main' method is not declared with a return type of 'void'");
+ "error: can't find main(String[]) method in class: NotVoid");
}
@Test
diff --git a/test/langtools/tools/javac/parser/JavacParserTest.java b/test/langtools/tools/javac/parser/JavacParserTest.java
index 14f0c506cd1..f9ccb39c05e 100644
--- a/test/langtools/tools/javac/parser/JavacParserTest.java
+++ b/test/langtools/tools/javac/parser/JavacParserTest.java
@@ -2472,7 +2472,7 @@ public class JavacParserTest extends TestCase {
result,
"""
\n\
- /*synthetic*/ final class Test {
+ final class Test {
\n\
void main() {
(ERROR);
diff --git a/test/langtools/tools/javac/processing/model/element/TestUnnamedClass.java b/test/langtools/tools/javac/processing/model/element/TestImplicitClass.java
similarity index 61%
rename from test/langtools/tools/javac/processing/model/element/TestUnnamedClass.java
rename to test/langtools/tools/javac/processing/model/element/TestImplicitClass.java
index 13ea7e0fa6d..bad9fa15f8b 100644
--- a/test/langtools/tools/javac/processing/model/element/TestUnnamedClass.java
+++ b/test/langtools/tools/javac/processing/model/element/TestImplicitClass.java
@@ -24,19 +24,19 @@
/*
* @test
* @bug 8306112 8309568
- * @summary Test basic processing of unnamed classes.
+ * @summary Test basic processing of implicitly declared classes.
* @library /tools/javac/lib
* @modules java.compiler
* jdk.compiler
- * @build JavacTestingAbstractProcessor TestUnnamedClass
- * @compile -processor TestUnnamedClass --enable-preview --release ${jdk.version} Anonymous.java
+ * @build JavacTestingAbstractProcessor TestImplicitClass
+ * @compile -processor TestImplicitClass --enable-preview --release ${jdk.version} Anonymous.java
* @clean Nameless.java
- * @compile/process -processor TestUnnamedClass -proc:only --enable-preview --release ${jdk.version} -Xprefer:newer -AclassOnly Anonymous Nameless
+ * @compile/process -processor TestImplicitClass -proc:only --enable-preview --release ${jdk.version} -Xprefer:newer -AclassOnly Anonymous Nameless
*/
// The first @compile line processes Anonymous.java and a
-// Nameless.java class generated using the Filer. Both of those
-// unnamed classes are then compiled down to class files. The second
+// Nameless.java class generated using the Filer. Both of those implicitly
+// declared classes are then compiled down to class files. The second
// @compile line, as directed by -Xprefer:newer, builds and checks the
// language model objects constructed from those class files, ignoring
// any source files for those types.
@@ -52,12 +52,12 @@ import static javax.lang.model.util.ElementFilter.*;
import javax.tools.JavaFileObject;
/**
- * Test annotation processing representation of unnamed classes
+ * Test annotation processing representation of implicitly classes
* constructed from either a source file or a class file.
*/
@SuppressWarnings("preview")
@SupportedOptions("classOnly")
-public class TestUnnamedClass extends JavacTestingAbstractProcessor {
+public class TestImplicitClass extends JavacTestingAbstractProcessor {
private static int round = 0;
private static int checkedClassesCount = 0;
@@ -72,14 +72,14 @@ public class TestUnnamedClass extends JavacTestingAbstractProcessor {
// Don't generate any files if testing pre-existing class files
if (!classOnly) {
- generateUnnamed();
+ generateImplicitClass();
}
} else {
if (!roundEnv.processingOver()) { // Test generated file(s)
checkRoots(roundEnv);
} else { // Should have checked at least one class before processing is over
if (checkedClassesCount == 0) {
- messager.printError("No unnamed classes checked.");
+ messager.printError("No implicitly declared classes checked.");
}
}
}
@@ -95,11 +95,11 @@ public class TestUnnamedClass extends JavacTestingAbstractProcessor {
checkUnnamedClassProperties(type);
}
if (checks == 0) {
- messager.printError("No checking done of any candidate unnamed classes.");
+ messager.printError("No checking done of any candidate implicitly declared classes.");
}
}
- private void generateUnnamed() {
+ private void generateImplicitClass() {
try {
String unnamedSource = """
void main() {
@@ -117,12 +117,11 @@ public class TestUnnamedClass extends JavacTestingAbstractProcessor {
}
/*
- * From JEP 445 JLS changes:
+ * From JEP 463 JLS changes:
*
- * "An unnamed class compilation unit implicitly declares a class that satisfies the following
- * properties:
+ * "An implicitly declared class compilation unit implicitly declares a class that
+ * satisfies the following properties:
* It is always a top level class.
- * It is always an unnamed class (it has no canonical or fully qualified name (6.7)).
* It is never abstract (8.1.1.1).
* It is always final (8.1.1.2).
* It is always a member of an unnamed package (7.4.2) and has package access.
@@ -130,8 +129,8 @@ public class TestUnnamedClass extends JavacTestingAbstractProcessor {
* It never has any direct superinterface types (8.1.5).
*
* The body of the class contains every ClassMemberDeclaration
- * from the unnamed class compilation unit. It is not possible for
- * an unnamed class compilation unit to declare an instance
+ * from the implicitly declared class compilation unit. It is not possible for
+ * an implicitly declared class compilation unit to declare an instance
* initializer, static initializer, or constructor.
*
* It has an implicitly declared default constructor (8.8.9).
@@ -141,63 +140,55 @@ public class TestUnnamedClass extends JavacTestingAbstractProcessor {
*
* It is a compile-time error if this class does not declare a candidate main method (12.1.4).
*/
- void checkUnnamedClassProperties(TypeElement unnamedClass) {
+ void checkUnnamedClassProperties(TypeElement implicitClass) {
checkedClassesCount++;
- Name expectedName = unnamedClass.getSimpleName();
+ Name expectedName = implicitClass.getSimpleName();
System.out.println("Checking " + expectedName);
- if (unnamedClass.getNestingKind() != NestingKind.TOP_LEVEL) {
- messager.printError("Unnamed class is not top-level.", unnamedClass);
+ if (implicitClass.getNestingKind() != NestingKind.TOP_LEVEL) {
+ messager.printError("Implicitly declared class is not top-level.", implicitClass);
}
- if (!unnamedClass.isUnnamed()) {
- messager.printError("Unnamed class is _not_ indicated as such.", unnamedClass);
+ if (!implicitClass.getQualifiedName().equals(expectedName)) {
+ messager.printError("Implicitly declared class qualified name does not match simple name.", implicitClass);
}
- if (unnamedClass.getSimpleName().isEmpty()) {
- messager.printError("Unnamed class has an empty simple name.", unnamedClass);
- }
-
- if (!unnamedClass.getQualifiedName().isEmpty()) {
- messager.printError("Unnamed class does _not_ have an empty qualified name.", unnamedClass);
- }
-
- Name binaryName = elements.getBinaryName(unnamedClass);
+ Name binaryName = elements.getBinaryName(implicitClass);
if (!expectedName.equals(binaryName)) {
- messager.printError("Unnamed has unexpected binary name" + binaryName + ".", unnamedClass);
+ messager.printError("Implicitly declared class has unexpected binary name" + binaryName + ".", implicitClass);
}
- if (unnamedClass.getModifiers().contains(Modifier.ABSTRACT)) {
- messager.printError("Unnamed class is abstract.", unnamedClass);
+ if (implicitClass.getModifiers().contains(Modifier.ABSTRACT)) {
+ messager.printError("Implicitly declared class is abstract.", implicitClass);
}
- if (!unnamedClass.getModifiers().contains(Modifier.FINAL)) {
- messager.printError("Unnamed class is _not_ final.", unnamedClass);
+ if (!implicitClass.getModifiers().contains(Modifier.FINAL)) {
+ messager.printError("Implicitly declared class is _not_ final.", implicitClass);
}
- if (!elements.getPackageOf(unnamedClass).isUnnamed()) {
- messager.printError("Unnamed class is _not_ in an unnamed package.", unnamedClass);
+ if (!elements.getPackageOf(implicitClass).isUnnamed()) {
+ messager.printError("Implicitly declared class is _not_ in an unnamed package.", implicitClass);
}
- if (unnamedClass.getModifiers().contains(Modifier.PUBLIC) ||
- unnamedClass.getModifiers().contains(Modifier.PRIVATE) ||
- unnamedClass.getModifiers().contains(Modifier.PROTECTED)) {
- messager.printError("Unnamed class does _not_ have package access.", unnamedClass);
+ if (implicitClass.getModifiers().contains(Modifier.PUBLIC) ||
+ implicitClass.getModifiers().contains(Modifier.PRIVATE) ||
+ implicitClass.getModifiers().contains(Modifier.PROTECTED)) {
+ messager.printError("Implicitly declared class does _not_ have package access.", implicitClass);
}
- if ( !types.isSameType(unnamedClass.getSuperclass(),
+ if ( !types.isSameType(implicitClass.getSuperclass(),
elements.getTypeElement("java.lang.Object").asType())) {
- messager.printError("Unnamed class does _not_ have java.lang.Object as a superclass.", unnamedClass);
+ messager.printError("Implicitly declared class does _not_ have java.lang.Object as a superclass.", implicitClass);
}
- if (!unnamedClass.getInterfaces().isEmpty()) {
- messager.printError("Unnamed class has superinterfaces.", unnamedClass);
+ if (!implicitClass.getInterfaces().isEmpty()) {
+ messager.printError("Implicitly declared class has superinterfaces.", implicitClass);
}
- List ctors = constructorsIn(unnamedClass.getEnclosedElements());
+ List ctors = constructorsIn(implicitClass.getEnclosedElements());
if (ctors.size() != 1 ) {
- messager.printError("Did not find exactly one constructor", unnamedClass);
+ messager.printError("Did not find exactly one constructor", implicitClass);
}
if (!classOnly) {
@@ -208,7 +199,7 @@ public class TestUnnamedClass extends JavacTestingAbstractProcessor {
}
}
- List methods = methodsIn(unnamedClass.getEnclosedElements());
+ List methods = methodsIn(implicitClass.getEnclosedElements());
// Just look for a method named "main"; don't check the other details.
boolean mainFound = false;
Name mainName = elements.getName("main");
@@ -220,7 +211,7 @@ public class TestUnnamedClass extends JavacTestingAbstractProcessor {
}
if (!mainFound) {
- messager.printError("No main mehtod found", unnamedClass);
+ messager.printError("No main method found", implicitClass);
}
}
}
diff --git a/test/langtools/tools/javac/unnamed/UnnamedClassRecovery.out b/test/langtools/tools/javac/unnamed/UnnamedClassRecovery.out
deleted file mode 100644
index 0389b156f01..00000000000
--- a/test/langtools/tools/javac/unnamed/UnnamedClassRecovery.out
+++ /dev/null
@@ -1,4 +0,0 @@
-UnnamedClassRecovery.java:7:33: compiler.err.expected: ';'
-- compiler.note.preview.filename: UnnamedClassRecovery.java, DEFAULT
-- compiler.note.preview.recompile
-1 error