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
--- 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<>();", "[]",