blob: 7d691eda8ee3599de3a78cfc5444673eebf8bdcc [file] [log] [blame]
/*
* Copyright (c) 2015, 2018, 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 8144903 8171981 8191802 8191842
* @summary Tests for determining the type from the expression
* @build KullaTesting TestingInputStream
* @run testng TypeNameTest
*/
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
@Test
public class TypeNameTest extends KullaTesting {
private void assertType(String expr, String type) {
assertType(expr, type, type);
}
private void assertType(String expr, String type, String inferType) {
assertEquals(varKey(assertEval(expr)).typeName(), type);
assertInferredType(expr, inferType);
}
public void testTypeInference() {
assertEval("import java.util.List;");
assertEval("import java.util.ArrayList;");
assertEval("import java.util.Arrays;");
assertType("new Object().getClass().getSuperclass() ", "Class<?>");
assertType("new ArrayList().getClass().getSuperclass()", "Class<?>");
assertType("new ArrayList().getClass()", "Class<? extends ArrayList>");
assertType("ArrayList.class", "Class<ArrayList>");
assertType("ArrayList.class.getSuperclass()", "Class<? super ArrayList>");
assertEval("class D<T extends CharSequence> { D<? super T> getS() { return null; } }");
assertEval("D<?> d = new D<String>();");
assertType("d.getS()", "D<?>");
assertType("null", "Object");
assertType("Class.forName( \"java.util.ArrayList\" )", "Class<?>");
assertType("new ArrayList<Boolean>() {}", "<anonymous class extending ArrayList<Boolean>>", "ArrayList<Boolean>");
assertType("new ArrayList<String>().stream()", "java.util.stream.Stream<String>");
assertType("Arrays.asList( 1, 2, 3)", "List<Integer>");
assertType("new ArrayList().getClass().getClass()", "Class<? extends Class>");
assertEval("interface A {}");
assertEval("interface I {}");
assertEval("interface J extends A, I {}");
assertEval("interface K extends A, I {}");
assertEval("class P<T extends A & I> {}");
assertType("(P<?>) null", "P<?>");
}
public void testConditionals() {
assertEval("import java.util.List;");
assertEval("import java.util.ArrayList;");
assertEval("import java.util.Arrays;");
assertEval("CharSequence cs = \"hi\";");
assertEval("String st = \"low\";");
assertEval("boolean b;");
assertType("b? cs : st", "CharSequence");
assertEval("List<String> l1 = Arrays.asList(\"hi\");");
assertEval("List<? extends String> l2 = Arrays.asList(\"po\");");
assertType("b? l1.get(0) : l2.get(0)", "String");
assertEval("class X {}");
assertEval("class B extends X {}");
assertEval("class C extends X {}");
assertType("b? new B() : new C()", "X");
}
public void testJEP286NonDenotable() {
assertEval("import java.util.List;");
assertEval("import java.util.Arrays;");
assertEval("import java.util.Iterator;");
assertEval("List<? extends String> extString() { return Arrays.asList( \"hi\", \"low\" ); }");
assertEval("List<? super String> supString() { return Arrays.asList( \"hi\", \"low\" ); }");
assertEval("List<?> unbString() { return Arrays.asList( \"hi\", \"low\" ); }");
assertEval("List<? extends String>[] extStringArr() {" +
" @SuppressWarnings(\"unchecked\") " +
"List<? extends String>[] a = new List[1]; a[0] = Arrays.asList(\"hi\"); return a; }");
assertEval("List<? super String>[] supStringArr() {" +
" @SuppressWarnings(\"unchecked\") " +
"List<? super String>[] a = new List[1]; a[0] = Arrays.asList(\"hi\"); return a; }");
assertEval("List<?>[] unbStringArr() {" +
" @SuppressWarnings(\"unchecked\") " +
"List<?>[] a = new List[1]; a[0] = Arrays.asList(\"hi\"); return a; }");
assertEval("Iterable<? extends List<? extends String>> extStringIter() {" +
"return Arrays.asList( Arrays.asList( \"hi\" ) ); }");
assertEval("Iterable<? extends List<? super String>> supStringIter() {" +
"return Arrays.asList( Arrays.asList( \"hi\" ) ); }");
assertEval("Iterable<? extends List<?>> unbStringIter() {" +
"return Arrays.asList( Arrays.asList( \"hi\" ) ); }");
assertType("extString()", "List<? extends String>");
assertType("extString().get(0)", "String");
assertType("supString()", "List<? super String>");
assertType("supString().get(0)", "Object");
assertType("unbString()", "List<?>");
assertType("unbString().get(0)", "Object");
assertType("supStringArr()", "List<? super String>[]");
assertType("supStringArr()[0]", "List<? super String>");
assertType("supStringArr()[0].get(0)", "Object");
assertType("unbStringArr()", "List<?>[]");
assertType("unbStringArr()[0]", "List<?>");
assertType("unbStringArr()[0].get(0)", "Object");
assertType("extStringIter()", "Iterable<? extends List<? extends String>>");
assertType("extStringIter().iterator()", "Iterator<? extends List<? extends String>>");
assertType("extStringIter().iterator().next()", "List<? extends String>");
assertType("extStringIter().iterator().next().get(0)", "String");
assertType("supStringIter()", "Iterable<? extends List<? super String>>");
assertType("supStringIter().iterator()", "Iterator<? extends List<? super String>>");
assertType("supStringIter().iterator().next()", "List<? super String>");
assertType("supStringIter().iterator().next().get(0)", "Object");
assertType("unbStringIter()", "Iterable<? extends List<?>>");
assertType("unbStringIter().iterator()", "Iterator<? extends List<?>>");
assertType("unbStringIter().iterator().next()", "List<?>");
assertType("unbStringIter().iterator().next().get(0)", "Object");
}
public void testJEP286NonDenotable2() {
assertEval("import java.util.List;");
assertEval("import java.util.Arrays;");
assertEval("import java.lang.reflect.Array;");
assertEval("<Z extends Comparable<Z>> List<? extends Z> extFbound() {" +
"return Arrays.asList( (Z)null ); }");
assertEval("<Z extends Comparable<Z>> List<? super Z> supFbound() {" +
"return Arrays.asList( (Z)null ); }");
assertEval("<Z extends Comparable<Z>> List<? extends Z>[] extFboundArr() {" +
"@SuppressWarnings(\"unchecked\")" +
"List<? extends Z>[] a = new List[1]; a[0] = Arrays.asList( (Z)null ); return a; }");
assertEval("<Z extends Comparable<Z>> List<? super Z>[] supFboundArr() {" +
"@SuppressWarnings(\"unchecked\")" +
"List<? super Z>[] a = new List[1]; a[0] = Arrays.asList( (Z)null ); return a; }");
assertEval("<Z extends Comparable<Z>> Iterable<? extends List<? extends Z>> extFboundIter() {" +
"return Arrays.asList( Arrays.asList( (Z)null ) ); }");
assertEval("<Z extends Comparable<Z>> Iterable<? extends List<? super Z>> supFboundIter() {" +
"return Arrays.asList( Arrays.asList( (Z)null ) ); }");
assertEval("<Z> List<Z> listOf(Z z) { return Arrays.asList( z ); }");
assertEval("<Z> Z[] arrayOf(Z z) {" +
"@SuppressWarnings(\"unchecked\")" +
"final Z[] a = (Z[]) Array.newInstance(z.getClass(), 1); a[0] = z; return a; }");
assertType("extFbound()", "List<? extends Comparable<?>>");
assertType("extFbound().get(0)", "Comparable<?>");
assertType("supFbound()", "List<?>");
assertType("supFbound().get(0)", "Object");
assertType("extFboundArr()", "List<? extends Comparable<?>>[]");
assertType("extFboundArr()[0]", "List<? extends Comparable<?>>");
assertType("extFboundArr()[0].get(0)", "Comparable<?>");
assertType("supFboundArr()", "List<?>[]");
assertType("supFboundArr()[0]", "List<?>");
assertType("supFboundArr()[0].get(0)", "Object");
assertType("extFboundIter()", "Iterable<? extends List<? extends Comparable<?>>>");
assertType("extFboundIter().iterator()", "java.util.Iterator<? extends List<? extends Comparable<?>>>");
assertType("extFboundIter().iterator().next()", "List<? extends Comparable<?>>");
assertType("extFboundIter().iterator().next().get(0)", "Comparable<?>");
assertType("supFboundIter()", "Iterable<? extends List<?>>");
assertType("supFboundIter().iterator()", "java.util.Iterator<? extends List<?>>");
assertType("supFboundIter().iterator().next()", "List<?>");
assertType("supFboundIter().iterator().next().get(0)", "Object");
assertType("listOf(23)", "List<Integer>");
assertType("listOf(true)", "List<Boolean>");
assertType("listOf(true).get(0)", "Boolean");
assertType("arrayOf(99)", "Integer[]");
assertType("arrayOf(99)[0]", "Integer");
assertEval("<Z> Z choose(Z z1, Z z2) { return z1; }");
assertType("choose(1, 1L);", "Number&Comparable<? extends Number&Comparable<?>>", "Object");
}
public void testVariableTypeName() {
assertType("\"x\"", "String");
assertType("java.util.regex.Pattern.compile(\"x\")", "java.util.regex.Pattern");
assertEval("import java.util.regex.*;");
assertType("java.util.regex.Pattern.compile(\"x\")", "Pattern");
assertType("new java.util.ArrayList()", "java.util.ArrayList");
assertEval("import java.util.ArrayList;");
assertType("new java.util.ArrayList()", "ArrayList");
assertType("java.util.Locale.Category.FORMAT", "java.util.Locale.Category");
assertEval("import static java.util.Locale.Category;");
assertType("java.util.Locale.Category.FORMAT", "Category");
}
public void testReplNestedClassName() {
assertEval("class D { static class E {} }");
assertType("new D.E();", "D.E");
}
public void testAnonymousClassName() {
assertEval("class C {}");
assertType("new C();", "C");
assertType("new C() { int x; };", "<anonymous class extending C>", "C");
}
public void testCapturedTypeName() {
assertType("\"\".getClass();", "Class<? extends String>");
assertType("\"\".getClass().getEnumConstants();", "String[]");
}
public void testJavaLang() {
assertType("\"\";", "String");
}
public void testNotOverEagerPackageEating() {
assertType("\"\".getClass().getDeclaredMethod(\"hashCode\");", "java.lang.reflect.Method");
}
public void testBounds() {
assertEval("java.util.List<? extends String> list1 = java.util.Arrays.asList(\"\");");
assertType("list1.iterator().next()", "String");
assertEval("java.util.List<? super String> list2 = java.util.Arrays.asList(\"\");");
assertType("list2.iterator().next()", "Object");
assertEval("java.util.List<?> list3 = java.util.Arrays.asList(\"\");");
assertType("list3.iterator().next()", "Object");
assertEval("class Test1<X extends CharSequence> { public X get() { return null; } }");
assertEval("Test1<?> test1 = new Test1<>();");
assertType("test1.get()", "CharSequence");
assertEval("class Test2<X extends Number & CharSequence> { public X get() { return null; } }");
assertEval("Test2<?> test2 = new Test2<>();");
assertType("test2.get()", "Number&CharSequence", "Object");
assertEval("class Test3<T> { T[][] get() { return null; } }");
assertEval("Test3<? extends String> test3 = new Test3<>();");
assertType("test3.get()", "String[][]");
}
}