8144903: JShell: determine incorrectly the type of the expression which is array type of captured type
authorrfield
Fri, 11 Dec 2015 11:20:10 -0800
changeset 34750 36d62753f5da
parent 34572 4edcff1b9a88
child 34751 32ee3b176042
8144903: JShell: determine incorrectly the type of the expression which is array type of captured type Summary: Fix and clean-up the processing of types (esp. captured types) into type names for use in generated temp vars Reviewed-by: mcimadamore, jlahoda, rfield Contributed-by: bitterfoxc@gmail.com
langtools/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java
langtools/test/jdk/jshell/TypeNameTest.java
langtools/test/jdk/jshell/VariablesTest.java
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java	Wed Jul 05 21:07:43 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java	Fri Dec 11 11:20:10 2015 -0800
@@ -41,15 +41,15 @@
  * Print types in source form.
  */
 class TypePrinter extends Printer {
+    private static final String OBJECT = "Object";
 
     private final JavacMessages messages;
     private final BinaryOperator<String> fullClassNameAndPackageToClass;
-    private final Type typeToPrint;
+    private boolean useWildCard = false;
 
     TypePrinter(JavacMessages messages, BinaryOperator<String> fullClassNameAndPackageToClass, Type typeToPrint) {
         this.messages = messages;
         this.fullClassNameAndPackageToClass = fullClassNameAndPackageToClass;
-        this.typeToPrint = typeToPrint;
     }
 
     @Override
@@ -64,21 +64,40 @@
 
     @Override
     public String visitCapturedType(Type.CapturedType t, Locale locale) {
-        if (t == typeToPrint) {
-            return visit(t.getUpperBound(), locale);
-        } else {
-            return visit(t.wildcard, locale);
+        return visit(t.wildcard, locale);
+    }
+
+    @Override
+    public String visitWildcardType(Type.WildcardType wt, Locale locale) {
+        if (useWildCard) { // at TypeArgument(ex: List<? extends T>)
+            return super.visitWildcardType(wt, locale);
+        } else { // at TopLevelType(ex: ? extends List<T>, ? extends Number[][])
+            Type extendsBound = wt.getExtendsBound();
+            return extendsBound == null
+                    ? OBJECT
+                    : visit(extendsBound, locale);
         }
     }
 
     @Override
     public String visitType(Type t, Locale locale) {
         String s = (t.tsym == null || t.tsym.name == null)
-                ? "Object" // none
+                ? OBJECT // none
                 : t.tsym.name.toString();
         return s;
     }
 
+    @Override
+    public String visitClassType(ClassType ct, Locale locale) {
+        boolean prevUseWildCard = useWildCard;
+        try {
+            useWildCard = true;
+            return super.visitClassType(ct, locale);
+        } finally {
+            useWildCard = prevUseWildCard;
+        }
+    }
+
     /**
      * Converts a class name into a (possibly localized) string. Anonymous
      * inner classes get converted into a localized string.
@@ -101,7 +120,7 @@
             }
             return s.toString();
             ***/
-            return "Object";
+            return OBJECT;
         } else if (sym.name.length() == 0) {
             // Anonymous
             String s;
--- a/langtools/test/jdk/jshell/TypeNameTest.java	Wed Jul 05 21:07:43 2017 +0200
+++ b/langtools/test/jdk/jshell/TypeNameTest.java	Fri Dec 11 11:20:10 2015 -0800
@@ -23,7 +23,8 @@
 
 /*
  * @test
- * @summary null test
+ * @bug 8144903
+ * @summary Tests for determining the type from the expression
  * @build KullaTesting TestingInputStream
  * @run testng TypeNameTest
  */
@@ -34,7 +35,6 @@
 
 import static jdk.jshell.Snippet.Status.VALID;
 import static org.testng.Assert.assertEquals;
-import static jdk.jshell.Snippet.Status.OVERWRITTEN;
 
 @Test
 public class TypeNameTest extends KullaTesting {
@@ -62,6 +62,11 @@
         assertEquals(sn.typeName(), "Class<? extends String>");
     }
 
+    public void testArrayTypeOfCapturedTypeName() {
+        VarSnippet sn = (VarSnippet) varKey(assertEval("\"\".getClass().getEnumConstants();"));
+        assertEquals(sn.typeName(), "String[]");
+    }
+
     public void testJavaLang() {
         VarSnippet sn = (VarSnippet) varKey(assertEval("\"\";"));
         assertEquals(sn.typeName(), "String");
@@ -83,14 +88,16 @@
         VarSnippet sn3 = (VarSnippet) varKey(assertEval("list3.iterator().next()"));
         assertEquals(sn3.typeName(), "Object");
         assertEval("class Test1<X extends CharSequence> { public X get() { return null; } }");
-        Snippet x = varKey(assertEval("Test1<?> x = new Test1<>();"));
-        VarSnippet sn4 = (VarSnippet) varKey(assertEval("x.get()"));
-        assertEquals(sn4.typeName(), "CharSequence");
-        assertEval("class Foo<X extends Number & CharSequence> { public X get() { return null; } }");
-        assertEval("Foo<?> x = new Foo<>();",
-                ste(MAIN_SNIPPET, VALID, VALID, true, null),
-                ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        VarSnippet sn5 = (VarSnippet) varKey(assertEval("x.get()"));
+        Snippet x = varKey(assertEval("Test1<?> test1 = new Test1<>();"));
+        VarSnippet sn4 = (VarSnippet) varKey(assertEval("test1.get()"));
+        assertEquals(sn4.typeName(), "Object");
+        assertEval("class Test2<X extends Number & CharSequence> { public X get() { return null; } }");
+        assertEval("Test2<?> test2 = new Test2<>();");
+        VarSnippet sn5 = (VarSnippet) varKey(assertEval("test2.get()"));
         assertEquals(sn5.typeName(), "Object");
+        assertEval("class Test3<T> { T[][] get() { return null; } }", added(VALID));
+        assertEval("Test3<? extends String> test3 = new Test3<>();");
+        VarSnippet sn6 = (VarSnippet) varKey(assertEval("test3.get()"));
+        assertEquals(sn6.typeName(), "String[][]");
     }
 }
--- a/langtools/test/jdk/jshell/VariablesTest.java	Wed Jul 05 21:07:43 2017 +0200
+++ b/langtools/test/jdk/jshell/VariablesTest.java	Fri Dec 11 11:20:10 2015 -0800
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8144903
  * @summary Tests for EvaluationState.variables
  * @build KullaTesting TestingInputStream ExpectedDiagnostic
  * @run testng VariablesTest
@@ -184,6 +185,16 @@
         assertActiveKeys();
     }
 
+    public void variablesTemporaryArrayOfCapturedType() {
+        assertEval("class Test<T> { T[][] get() { return null; } }", added(VALID));
+        assertEval("Test<? extends String> test() { return new Test<>(); }", added(VALID));
+        assertEval("test().get()", added(VALID));
+        assertVariables(variable("String[][]", "$1"));
+        assertEval("\"\".getClass().getEnumConstants()", added(VALID));
+        assertVariables(variable("String[][]", "$1"), variable("String[]", "$2"));
+        assertActiveKeys();
+    }
+
     public void variablesClassReplace() {
         assertEval("import java.util.*;", added(VALID));
         Snippet var = varKey(assertEval("List<Integer> list = new ArrayList<>();", "[]",