1 /*
   2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8144903 8171981 8191802 8191842
  27  * @summary Tests for determining the type from the expression
  28  * @build KullaTesting TestingInputStream
  29  * @run testng TypeNameTest
  30  */
  31 
  32 import org.testng.annotations.Test;
  33 
  34 import static org.testng.Assert.assertEquals;
  35 
  36 @Test
  37 public class TypeNameTest extends KullaTesting {
  38 
  39 
  40     private void assertType(String expr, String type) {
  41         assertType(expr, type, type);
  42     }
  43 
  44     private void assertType(String expr, String type, String inferType) {
  45         assertEquals(varKey(assertEval(expr)).typeName(), type);
  46         assertInferredType(expr, inferType);
  47     }
  48 
  49     public void testTypeInference() {
  50         assertEval("import java.util.List;");
  51         assertEval("import java.util.ArrayList;");
  52         assertEval("import java.util.Arrays;");
  53 
  54         assertType("new Object().getClass().getSuperclass() ", "Class<?>");
  55         assertType("new ArrayList().getClass().getSuperclass()", "Class<?>");
  56         assertType("new ArrayList().getClass()", "Class<? extends ArrayList>");
  57         assertType("ArrayList.class", "Class<ArrayList>");
  58         assertType("ArrayList.class.getSuperclass()", "Class<? super ArrayList>");
  59 
  60         assertEval("class D<T extends CharSequence> { D<? super T> getS() { return null; } }");
  61         assertEval("D<?> d = new D<String>();");
  62         assertType("d.getS()", "D<?>");
  63         assertType("null", "Object");
  64         assertType("Class.forName( \"java.util.ArrayList\" )", "Class<?>");
  65         assertType("new ArrayList<Boolean>() {}", "<anonymous class extending ArrayList<Boolean>>", "ArrayList<Boolean>");
  66         assertType("new ArrayList<String>().stream()", "java.util.stream.Stream<String>");
  67         assertType("Arrays.asList( 1, 2, 3)", "List<Integer>");
  68         assertType("new ArrayList().getClass().getClass()", "Class<? extends Class>");
  69 
  70         assertEval("interface A {}");
  71         assertEval("interface I {}");
  72         assertEval("interface J extends A, I {}");
  73         assertEval("interface K extends A, I {}");
  74         assertEval("class P<T extends A & I> {}");
  75         assertType("(P<?>) null", "P<?>");
  76     }
  77 
  78     public void testConditionals() {
  79         assertEval("import java.util.List;");
  80         assertEval("import java.util.ArrayList;");
  81         assertEval("import java.util.Arrays;");
  82 
  83         assertEval("CharSequence cs = \"hi\";");
  84         assertEval("String st = \"low\";");
  85         assertEval("boolean b;");
  86         assertType("b? cs : st", "CharSequence");
  87 
  88         assertEval("List<String> l1 = Arrays.asList(\"hi\");");
  89         assertEval("List<? extends String> l2 = Arrays.asList(\"po\");");
  90         assertType("b? l1.get(0) : l2.get(0)", "String");
  91 
  92         assertEval("class X {}");
  93         assertEval("class B extends X {}");
  94         assertEval("class C extends X {}");
  95         assertType("b? new B() : new C()", "X");
  96     }
  97 
  98     public void testJEP286NonDenotable() {
  99         assertEval("import java.util.List;");
 100         assertEval("import java.util.Arrays;");
 101         assertEval("import java.util.Iterator;");
 102 
 103         assertEval("List<? extends String> extString() { return Arrays.asList( \"hi\", \"low\" ); }");
 104         assertEval("List<? super String> supString() { return Arrays.asList( \"hi\", \"low\" ); }");
 105         assertEval("List<?> unbString() { return Arrays.asList( \"hi\", \"low\" ); }");
 106         assertEval("List<? extends String>[] extStringArr() {" +
 107                 " @SuppressWarnings(\"unchecked\") " +
 108                 "List<? extends String>[] a = new List[1]; a[0] = Arrays.asList(\"hi\"); return a; }");
 109         assertEval("List<? super String>[] supStringArr() {" +
 110                 " @SuppressWarnings(\"unchecked\") " +
 111                 "List<? super String>[] a = new List[1]; a[0] = Arrays.asList(\"hi\"); return a; }");
 112         assertEval("List<?>[] unbStringArr() {" +
 113                 " @SuppressWarnings(\"unchecked\") " +
 114                 "List<?>[] a = new List[1]; a[0] = Arrays.asList(\"hi\"); return a; }");
 115         assertEval("Iterable<? extends List<? extends String>> extStringIter() {" +
 116                 "return Arrays.asList( Arrays.asList( \"hi\" ) ); }");
 117         assertEval("Iterable<? extends List<? super String>> supStringIter() {" +
 118                 "return Arrays.asList( Arrays.asList( \"hi\" ) ); }");
 119         assertEval("Iterable<? extends List<?>> unbStringIter() {" +
 120                 "return Arrays.asList( Arrays.asList( \"hi\" ) ); }");
 121         assertType("extString()", "List<? extends String>");
 122         assertType("extString().get(0)", "String");
 123         assertType("supString()", "List<? super String>");
 124         assertType("supString().get(0)", "Object");
 125         assertType("unbString()", "List<?>");
 126         assertType("unbString().get(0)", "Object");
 127         assertType("supStringArr()", "List<? super String>[]");
 128         assertType("supStringArr()[0]", "List<? super String>");
 129         assertType("supStringArr()[0].get(0)", "Object");
 130         assertType("unbStringArr()", "List<?>[]");
 131         assertType("unbStringArr()[0]", "List<?>");
 132         assertType("unbStringArr()[0].get(0)", "Object");
 133         assertType("extStringIter()", "Iterable<? extends List<? extends String>>");
 134         assertType("extStringIter().iterator()", "Iterator<? extends List<? extends String>>");
 135         assertType("extStringIter().iterator().next()", "List<? extends String>");
 136         assertType("extStringIter().iterator().next().get(0)", "String");
 137         assertType("supStringIter()", "Iterable<? extends List<? super String>>");
 138         assertType("supStringIter().iterator()", "Iterator<? extends List<? super String>>");
 139         assertType("supStringIter().iterator().next()", "List<? super String>");
 140         assertType("supStringIter().iterator().next().get(0)", "Object");
 141         assertType("unbStringIter()", "Iterable<? extends List<?>>");
 142         assertType("unbStringIter().iterator()", "Iterator<? extends List<?>>");
 143         assertType("unbStringIter().iterator().next()", "List<?>");
 144         assertType("unbStringIter().iterator().next().get(0)", "Object");
 145     }
 146 
 147     public void testJEP286NonDenotable2() {
 148         assertEval("import java.util.List;");
 149         assertEval("import java.util.Arrays;");
 150         assertEval("import java.lang.reflect.Array;");
 151 
 152         assertEval("<Z extends Comparable<Z>> List<? extends Z> extFbound() {" +
 153                 "return Arrays.asList( (Z)null ); }");
 154         assertEval("<Z extends Comparable<Z>> List<? super Z> supFbound() {" +
 155                 "return Arrays.asList( (Z)null ); }");
 156         assertEval("<Z extends Comparable<Z>> List<? extends Z>[] extFboundArr() {" +
 157                 "@SuppressWarnings(\"unchecked\")" +
 158                 "List<? extends Z>[] a = new List[1]; a[0] = Arrays.asList( (Z)null ); return a; }");
 159         assertEval("<Z extends Comparable<Z>> List<? super Z>[] supFboundArr() {" +
 160                 "@SuppressWarnings(\"unchecked\")" +
 161                 "List<? super Z>[] a = new List[1]; a[0] = Arrays.asList( (Z)null ); return a; }");
 162         assertEval("<Z extends Comparable<Z>> Iterable<? extends List<? extends Z>> extFboundIter() {" +
 163                 "return Arrays.asList( Arrays.asList( (Z)null ) ); }");
 164         assertEval("<Z extends Comparable<Z>> Iterable<? extends List<? super Z>> supFboundIter() {" +
 165                 "return Arrays.asList( Arrays.asList( (Z)null ) ); }");
 166         assertEval("<Z> List<Z> listOf(Z z) { return Arrays.asList( z ); }");
 167         assertEval("<Z> Z[] arrayOf(Z z) {" +
 168                 "@SuppressWarnings(\"unchecked\")" +
 169                 "final Z[] a = (Z[]) Array.newInstance(z.getClass(), 1); a[0] = z; return a; }");
 170         assertType("extFbound()", "List<? extends Comparable<?>>");
 171         assertType("extFbound().get(0)", "Comparable<?>");
 172         assertType("supFbound()", "List<?>");
 173         assertType("supFbound().get(0)", "Object");
 174         assertType("extFboundArr()", "List<? extends Comparable<?>>[]");
 175         assertType("extFboundArr()[0]", "List<? extends Comparable<?>>");
 176         assertType("extFboundArr()[0].get(0)", "Comparable<?>");
 177         assertType("supFboundArr()", "List<?>[]");
 178         assertType("supFboundArr()[0]", "List<?>");
 179         assertType("supFboundArr()[0].get(0)", "Object");
 180         assertType("extFboundIter()", "Iterable<? extends List<? extends Comparable<?>>>");
 181         assertType("extFboundIter().iterator()", "java.util.Iterator<? extends List<? extends Comparable<?>>>");
 182         assertType("extFboundIter().iterator().next()", "List<? extends Comparable<?>>");
 183         assertType("extFboundIter().iterator().next().get(0)", "Comparable<?>");
 184         assertType("supFboundIter()", "Iterable<? extends List<?>>");
 185         assertType("supFboundIter().iterator()", "java.util.Iterator<? extends List<?>>");
 186         assertType("supFboundIter().iterator().next()", "List<?>");
 187         assertType("supFboundIter().iterator().next().get(0)", "Object");
 188         assertType("listOf(23)", "List<Integer>");
 189         assertType("listOf(true)", "List<Boolean>");
 190         assertType("listOf(true).get(0)", "Boolean");
 191         assertType("arrayOf(99)", "Integer[]");
 192         assertType("arrayOf(99)[0]", "Integer");
 193 
 194         assertEval("<Z> Z choose(Z z1, Z z2) { return z1; }");
 195         assertType("choose(1, 1L);",
 196                   "Number&Comparable<? extends Number&Comparable<?>&java.lang.constant.Constable&java.lang.constant.ConstantDesc>&java.lang.constant.Constable&java.lang.constant.ConstantDesc",
 197                 "Object");
 198     }
 199 
 200     public void testVariableTypeName() {
 201         assertType("\"x\"", "String");
 202 
 203         assertType("java.util.regex.Pattern.compile(\"x\")", "java.util.regex.Pattern");
 204         assertEval("import java.util.regex.*;");
 205         assertType("java.util.regex.Pattern.compile(\"x\")", "Pattern");
 206 
 207         assertType("new java.util.ArrayList()", "java.util.ArrayList");
 208         assertEval("import java.util.ArrayList;");
 209         assertType("new java.util.ArrayList()", "ArrayList");
 210 
 211         assertType("java.util.Locale.Category.FORMAT", "java.util.Locale.Category");
 212         assertEval("import static java.util.Locale.Category;");
 213         assertType("java.util.Locale.Category.FORMAT", "Category");
 214     }
 215 
 216     public void testReplNestedClassName() {
 217         assertEval("class D { static class E {} }");
 218         assertType("new D.E();", "D.E");
 219     }
 220 
 221     public void testAnonymousClassName() {
 222         assertEval("class C {}");
 223         assertType("new C();", "C");
 224         assertType("new C() { int x; };", "<anonymous class extending C>", "C");
 225     }
 226 
 227     public void testCapturedTypeName() {
 228         assertType("\"\".getClass();", "Class<? extends String>");
 229         assertType("\"\".getClass().getEnumConstants();", "String[]");
 230     }
 231 
 232     public void testJavaLang() {
 233         assertType("\"\";", "String");
 234     }
 235 
 236     public void testNotOverEagerPackageEating() {
 237         assertType("\"\".getClass().getDeclaredMethod(\"hashCode\");", "java.lang.reflect.Method");
 238     }
 239 
 240     public void testBounds() {
 241         assertEval("java.util.List<? extends String> list1 = java.util.Arrays.asList(\"\");");
 242         assertType("list1.iterator().next()", "String");
 243         assertEval("java.util.List<? super String> list2 = java.util.Arrays.asList(\"\");");
 244         assertType("list2.iterator().next()", "Object");
 245         assertEval("java.util.List<?> list3 = java.util.Arrays.asList(\"\");");
 246         assertType("list3.iterator().next()", "Object");
 247         assertEval("class Test1<X extends CharSequence> { public X get() { return null; } }");
 248         assertEval("Test1<?> test1 = new Test1<>();");
 249         assertType("test1.get()", "CharSequence");
 250         assertEval("class Test2<X extends Number & CharSequence> { public X get() { return null; } }");
 251         assertEval("Test2<?> test2 = new Test2<>();");
 252         assertType("test2.get()", "Number&CharSequence", "Object");
 253         assertEval("class Test3<T> { T[][] get() { return null; } }");
 254         assertEval("Test3<? extends String> test3 = new Test3<>();");
 255         assertType("test3.get()", "String[][]");
 256     }
 257 }