diff --git a/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java b/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java index e9eaccea321..8bc339c6dab 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/ExpressionToTypeInfo.java @@ -71,7 +71,8 @@ import jdk.jshell.TypePrinter.AnonymousTypeKind; */ class ExpressionToTypeInfo { - private static final String OBJECT_TYPE_NAME = "Object"; + //only used in erroneous/non-standard circumstances; OK to use a FQN: + private static final String OBJECT_TYPE_NAME = "java.lang.Object"; final AnalyzeTask at; final CompilationUnitTree cu; @@ -394,8 +395,8 @@ class ExpressionToTypeInfo { break; case NULL: ei.isNonVoid = true; - ei.typeName = OBJECT_TYPE_NAME; - ei.accessibleTypeName = OBJECT_TYPE_NAME; + ei.typeName = varTypeName(syms.objectType, false, AnonymousTypeKind.SUPER); + ei.accessibleTypeName = ei.typeName; break; default: { ei.isNonVoid = true; diff --git a/src/jdk.jshell/share/classes/jdk/jshell/KeyMap.java b/src/jdk.jshell/share/classes/jdk/jshell/KeyMap.java index a2011a111bf..e350cf4a7d7 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/KeyMap.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/KeyMap.java @@ -99,4 +99,8 @@ class KeyMap { Stream importKeys() { return importMap.values().stream(); } + + Stream typeDeclKeys() { + return classMap.values().stream(); + } } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java index c801e489e20..0bbf2a5dceb 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java @@ -158,6 +158,15 @@ final class SnippetMaps { if (mat.lookingAt()) { return full.substring(mat.end()); } + String simpleName = full.substring(full.lastIndexOf(".") + 1); + Stream declaredInSnippets = state.keyMap.typeDeclKeys() + .map(key -> (TypeDeclSnippet) getSnippet(key)) + .map(decl -> decl.name()); + if (declaredInSnippets.anyMatch(clazz -> simpleName.equals(clazz))) { + //simple name of full clashes with a name of a user-defined class, + //use the fully-qualified name: + return full; + } state.debug(DBG_DEP, "SM %s %s\n", full, pkg); List klasses = importSnippets() .filter(isi -> !isi.isStar) @@ -165,7 +174,7 @@ final class SnippetMaps { .toList(); for (String k : klasses) { if (k.equals(full)) { - return full.substring(full.lastIndexOf(".")+1); + return simpleName; } } if (pkg.isEmpty()) { diff --git a/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java b/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java index 36d3e882f38..76f2e929e34 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java @@ -47,7 +47,8 @@ import java.util.stream.Collectors; */ class TypePrinter extends Printer { - private static final String OBJECT = "Object"; + //only used in erroneous/non-standard circumstances; OK to use a FQN: + private static final String OBJECT = "java.lang.Object"; private final JavacMessages messages; private final Types types; diff --git a/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java b/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java index f9ae63b9cde..57ed543ce25 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java @@ -113,9 +113,9 @@ abstract class Wrap implements GeneralWrap { scratchName += "$"; } Wrap waux = new CompoundWrap( - " private static <" + scratchName + "> " + scratchName +" ", DOIT_METHOD_NAME + "Aux", "() throws Throwable {\n", + " private static <" + scratchName + "> " + scratchName +" ", DOIT_METHOD_NAME + "Aux", "() throws java.lang.Throwable {\n", wtype, brackets + " ", scratchName, "_ =\n ", winit, semi(winit), - " @SuppressWarnings(\"unchecked\") ", scratchName, " ", scratchName, "__ = (", scratchName, ")", scratchName, "_;\n", + " @java.lang.SuppressWarnings(\"unchecked\") ", scratchName, " ", scratchName, "__ = (", scratchName, ")", scratchName, "_;\n", " return ", scratchName, "__;\n", "}" ); @@ -550,7 +550,7 @@ abstract class Wrap implements GeneralWrap { private static class DoitMethodWrap extends CompoundWrap { DoitMethodWrap(Wrap w) { - super(" public static Object " + DOIT_METHOD_NAME + "() throws Throwable {\n" + super(" public static java.lang.Object " + DOIT_METHOD_NAME + "() throws java.lang.Throwable {\n" + " ", w, " }\n"); } diff --git a/test/langtools/jdk/jshell/JLCollisionTest.java b/test/langtools/jdk/jshell/JLCollisionTest.java new file mode 100644 index 00000000000..2859c1a49f7 --- /dev/null +++ b/test/langtools/jdk/jshell/JLCollisionTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024, 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 8327512 + * @summary Clashes between java.lang classes and custom-defined classes with + * the same simple names + * @modules jdk.jshell/jdk.jshell + * @build KullaTesting + * @run testng JLCollisionTest + */ + +import org.testng.annotations.Test; + +@Test +public class JLCollisionTest extends KullaTesting { + + public void testObject() { + assertEval("class Object {}"); + assertEval("1"); + assertEval("null"); + assertEval("$2 = \"\""); + } + + public void testThrowable() { + assertEval("class Throwable {}"); + assertEval("1"); + //var with an "enhanced" (non-denotable) type: + assertEval("var _ = new Object() {};"); + } + + public void testSuppressWarnings() { + assertEval("class SuppressWarnings {}"); + //var with an "enhanced" (non-denotable) type: + assertEval("var _ = new Object() {};"); + } + +}