You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/03/30 22:22:18 UTC
[groovy] branch GROOVY_3_0_X updated: GROOVY-10282: `GenericsUtils`: do not mix type parameter contexts
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
new 2ab6c68 GROOVY-10282: `GenericsUtils`: do not mix type parameter contexts
2ab6c68 is described below
commit 2ab6c6852002031bf2a9939d4f3cc32e7232a407
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Oct 5 11:59:35 2021 -0500
GROOVY-10282: `GenericsUtils`: do not mix type parameter contexts
collect for BiFunction<U, ? super T, U> yields [T:U, U:? super T, R:U]
not [T:? super T, U:? super T, R:? super T]
---
.../codehaus/groovy/ast/tools/GenericsUtils.java | 170 ++---
.../groovy/transform/stc/GenericsSTCTest.groovy | 567 +++++++++------
src/test/groovy/transform/stc/LambdaTest.groovy | 805 ++++++++++-----------
3 files changed, 799 insertions(+), 743 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 3142345..ff571ac 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -40,7 +40,6 @@ import org.codehaus.groovy.runtime.memoize.ConcurrentSoftCache;
import org.codehaus.groovy.runtime.memoize.EvictableCache;
import java.lang.ref.SoftReference;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -142,50 +141,48 @@ public class GenericsUtils {
return gt;
}
- public static Map<GenericsType.GenericsTypeName, GenericsType> extractPlaceholders(ClassNode cn) {
- Map<GenericsType.GenericsTypeName, GenericsType> ret = new HashMap<>();
- extractPlaceholders(cn, ret);
- return ret;
+ public static Map<GenericsType.GenericsTypeName, GenericsType> extractPlaceholders(final ClassNode type) {
+ Map<GenericsType.GenericsTypeName, GenericsType> placeholders = new HashMap<>();
+ extractPlaceholders(type, placeholders);
+ return placeholders;
}
/**
* For a given classnode, fills in the supplied map with the parameterized
* types it defines.
*
- * @param node the class node to check
- * @param map the generics type information collector
+ * @param type the class node to check
+ * @param placeholders the generics type information collector
*/
- public static void extractPlaceholders(ClassNode node, Map<GenericsType.GenericsTypeName, GenericsType> map) {
- if (node == null) return;
+ public static void extractPlaceholders(final ClassNode type, final Map<GenericsType.GenericsTypeName, GenericsType> placeholders) {
+ if (type == null) return;
- if (node.isArray()) {
- extractPlaceholders(node.getComponentType(), map);
+ if (type.isArray()) {
+ extractPlaceholders(type.getComponentType(), placeholders);
return;
}
- if (!node.isUsingGenerics() || !node.isRedirectNode()) return;
- GenericsType[] parameterized = node.getGenericsTypes();
+ if (!type.isUsingGenerics() || !type.isRedirectNode()) return;
+ GenericsType[] parameterized = type.getGenericsTypes();
if (parameterized == null || parameterized.length == 0) return;
- GenericsType[] redirectGenericsTypes = node.redirect().getGenericsTypes();
- if (redirectGenericsTypes == null || (node.isGenericsPlaceHolder() // GROOVY-8609
+ GenericsType[] redirectGenericsTypes = type.redirect().getGenericsTypes();
+ if (redirectGenericsTypes == null || (type.isGenericsPlaceHolder() // GROOVY-8609
&& redirectGenericsTypes.length != parameterized.length)) {
redirectGenericsTypes = parameterized;
- }
- if (redirectGenericsTypes.length != parameterized.length) {
+ } else if (redirectGenericsTypes.length != parameterized.length) {
throw new GroovyBugError("Expected earlier checking to detect generics parameter arity mismatch" +
- "\nExpected: " + node.getName() + toGenericTypesString(redirectGenericsTypes) +
- "\nSupplied: " + node.getName() + toGenericTypesString(parameterized));
+ "\nExpected: " + type.getName() + toGenericTypesString(redirectGenericsTypes) +
+ "\nSupplied: " + type.getName() + toGenericTypesString(parameterized));
}
List<GenericsType> valueList = new LinkedList<>();
- for (int i = 0; i < redirectGenericsTypes.length; i++) {
- GenericsType redirectType = redirectGenericsTypes[i];
- if (redirectType.isPlaceholder()) {
- GenericsType.GenericsTypeName name = new GenericsType.GenericsTypeName(redirectType.getName());
- if (!map.containsKey(name)) {
+ for (int i = 0, n = redirectGenericsTypes.length; i < n; i += 1) {
+ GenericsType rgt = redirectGenericsTypes[i];
+ if (rgt.isPlaceholder()) {
+ GenericsType.GenericsTypeName name = new GenericsType.GenericsTypeName(rgt.getName());
+ if (!placeholders.containsKey(name)) {
GenericsType value = parameterized[i];
- map.put(name, value);
-
+ placeholders.put(name, value);
valueList.add(value);
}
}
@@ -195,16 +192,16 @@ public class GenericsUtils {
if (value.isWildcard()) {
ClassNode lowerBound = value.getLowerBound();
if (lowerBound != null) {
- extractPlaceholders(lowerBound, map);
+ extractPlaceholders(lowerBound, placeholders);
}
ClassNode[] upperBounds = value.getUpperBounds();
if (upperBounds != null) {
for (ClassNode upperBound : upperBounds) {
- extractPlaceholders(upperBound, map);
+ extractPlaceholders(upperBound, placeholders);
}
}
} else if (!value.isPlaceholder()) {
- extractPlaceholders(value.getType(), map);
+ extractPlaceholders(value.getType(), placeholders);
}
}
}
@@ -318,12 +315,15 @@ public class GenericsUtils {
if (type.isArray()) {
return makeClassSafeWithGenerics(type.getComponentType(), genericTypes).makeArray();
}
- GenericsType[] gtypes = EMPTY_GENERICS_ARRAY;
- if (genericTypes != null) {
- gtypes = new GenericsType[genericTypes.length];
- System.arraycopy(genericTypes, 0, gtypes, 0, gtypes.length);
+ int nTypes = (genericTypes == null ? 0 : genericTypes.length);
+ GenericsType[] gTypes;
+ if (nTypes == 0) {
+ gTypes = EMPTY_GENERICS_ARRAY;
+ } else {
+ gTypes = new GenericsType[nTypes];
+ System.arraycopy(genericTypes, 0, gTypes, 0, nTypes);
}
- return makeClassSafe0(type, gtypes);
+ return makeClassSafe0(type, gTypes);
}
public static MethodNode correctToGenericsSpec(Map<String, ClassNode> genericsSpec, MethodNode mn) {
@@ -342,7 +342,7 @@ public class GenericsUtils {
}
public static ClassNode correctToGenericsSpecRecurse(Map<String, ClassNode> genericsSpec, ClassNode type) {
- return correctToGenericsSpecRecurse(genericsSpec, type, new ArrayList<String>());
+ return correctToGenericsSpecRecurse(genericsSpec, type, Collections.emptyList());
}
/**
@@ -353,7 +353,7 @@ public class GenericsUtils {
ClassNode[] newTypes = new ClassNode[types.length];
boolean modified = false;
for (int i = 0; i < types.length; i++) {
- newTypes[i] = correctToGenericsSpecRecurse(genericsSpec, types[i], new ArrayList<String>());
+ newTypes[i] = correctToGenericsSpecRecurse(genericsSpec, types[i], Collections.emptyList());
modified = modified || (types[i] != newTypes[i]);
}
if (!modified) return types;
@@ -364,8 +364,8 @@ public class GenericsUtils {
if (type.isArray()) {
return correctToGenericsSpecRecurse(genericsSpec, type.getComponentType(), exclusions).makeArray();
}
- if (type.isGenericsPlaceHolder() && !exclusions.contains(type.getUnresolvedName())) {
- String name = type.getGenericsTypes()[0].getName();
+ String name = type.getUnresolvedName();
+ if (type.isGenericsPlaceHolder() && !exclusions.contains(name)) {
exclusions = plus(exclusions, name); // GROOVY-7722
type = genericsSpec.get(name);
if (type != null && type.isGenericsPlaceHolder()) {
@@ -538,16 +538,8 @@ public class GenericsUtils {
}
}
- public static ClassNode getSuperClass(ClassNode type, ClassNode target) {
- ClassNode superClass = ClassHelper.getNextSuperClass(type, target);
-
- if (superClass == null) {
- if (ClassHelper.isPrimitiveType(type)) {
- superClass = ClassHelper.getNextSuperClass(ClassHelper.getWrapper(type), target);
- }
- }
-
- return superClass;
+ public static ClassNode getSuperClass(final ClassNode type, final ClassNode target) {
+ return ClassHelper.getNextSuperClass(ClassHelper.isPrimitiveType(type) ? ClassHelper.getWrapper(type) : type, target);
}
private static void extractSuperClassGenerics(final GenericsType[] usage, final GenericsType[] declaration, final Map<String, ClassNode> spec) {
@@ -806,7 +798,7 @@ public class GenericsUtils {
* so we need actual types: T: String, S: Long
*/
public static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTypeMap(final ClassNode declaringClass, final ClassNode actualReceiver) {
- return doMakeDeclaringAndActualGenericsTypeMap(declaringClass, actualReceiver, false).getV1();
+ return doMakeDeclaringAndActualGenericsTypeMap(declaringClass, actualReceiver, false);
}
/**
@@ -821,79 +813,25 @@ public class GenericsUtils {
* @since 3.0.0
*/
public static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTypeMapOfExactType(final ClassNode declaringClass, final ClassNode actualReceiver) {
- return makeDeclaringAndActualGenericsTypeMapOfExactType(declaringClass, actualReceiver, new HashSet<>());
+ return doMakeDeclaringAndActualGenericsTypeMap(declaringClass, actualReceiver, true);
}
- private static Map<GenericsType, GenericsType> makeDeclaringAndActualGenericsTypeMapOfExactType(final ClassNode declaringClass, final ClassNode actualReceiver, final Set<ClassNode> parameterizedTypes) {
- Tuple2<Map<GenericsType, GenericsType>, ClassNode> tuple = doMakeDeclaringAndActualGenericsTypeMap(declaringClass, actualReceiver, true);
- Map<GenericsType, GenericsType> result = tuple.getV1();
- ClassNode parameterizedType = tuple.getV2();
-
- if (parameterizedTypes.add(parameterizedType) && hasPlaceHolders(parameterizedType)) {
- result.putAll(makeDeclaringAndActualGenericsTypeMapOfExactType(parameterizedType, actualReceiver, parameterizedTypes));
- result = connectGenericsTypes(result);
- }
-
- return result;
- }
-
- private static Tuple2<Map<GenericsType, GenericsType>, ClassNode> doMakeDeclaringAndActualGenericsTypeMap(final ClassNode declaringClass, final ClassNode actualReceiver, final boolean tryToFindExactType) {
+ private static Map<GenericsType, GenericsType> doMakeDeclaringAndActualGenericsTypeMap(final ClassNode declaringClass, final ClassNode actualReceiver, final boolean tryToFindExactType) {
+ Map<GenericsType, GenericsType> map = Collections.emptyMap();
ClassNode parameterizedType = findParameterizedTypeFromCache(declaringClass, actualReceiver, tryToFindExactType);
- if (parameterizedType == null) {
- return tuple(Collections.emptyMap(), parameterizedType);
- }
-
- Map<GenericsType, GenericsType> result = new LinkedHashMap<>();
- result.putAll(makePlaceholderAndParameterizedTypeMap(declaringClass));
- result.putAll(makePlaceholderAndParameterizedTypeMap(parameterizedType));
-
- result = connectGenericsTypes(result);
-
- return tuple(result, parameterizedType);
- }
-
- private static Map<GenericsType, GenericsType> makePlaceholderAndParameterizedTypeMap(final ClassNode declaringClass) {
- if (null == declaringClass) {
- return Collections.emptyMap();
- }
-
- Map<GenericsType, GenericsType> result = new LinkedHashMap<>();
-
- ClassNode redirectDeclaringClass = declaringClass.redirect();
- GenericsType[] declaringGenericsTypes = declaringClass.getGenericsTypes();
- GenericsType[] redirectDeclaringGenericsTypes = redirectDeclaringClass.getGenericsTypes();
-
- if (null != declaringGenericsTypes && null != redirectDeclaringGenericsTypes) {
- for (int i = 0, n = declaringGenericsTypes.length; i < n; i++) {
- result.put(redirectDeclaringGenericsTypes[i], declaringGenericsTypes[i]);
- }
- }
-
- return result;
- }
-
- private static Map<GenericsType, GenericsType> connectGenericsTypes(final Map<GenericsType, GenericsType> genericsTypeMap) {
- Map<GenericsType, GenericsType> result = new LinkedHashMap<>();
-
- outer:
- for (Map.Entry<GenericsType, GenericsType> entry : genericsTypeMap.entrySet()) {
- GenericsType key = entry.getKey();
- GenericsType value = entry.getValue();
-
- if (value.isPlaceholder()) {
- for (Map.Entry<GenericsType, GenericsType> genericsTypeMapEntry : genericsTypeMap.entrySet()) {
- GenericsType genericsTypeMapEntryValue = genericsTypeMapEntry.getValue();
- if (!genericsTypeMapEntryValue.isPlaceholder() && (genericsTypeMapEntry.getKey().getName().equals(value.getName()))) {
- result.put(key, genericsTypeMapEntryValue); // connected to actual type
- continue outer;
- }
+ if (parameterizedType != null && parameterizedType.isRedirectNode() && !parameterizedType.isGenericsPlaceHolder()) { // GROOVY-10166
+ // declaringClass may be "List<T> -> List<E>" and parameterizedType may be "List<String> -> List<E>" or "List<> -> List<E>"
+ GenericsType[] targetGenericsTypes = parameterizedType.redirect().getGenericsTypes();
+ if (targetGenericsTypes != null) {
+ GenericsType[] sourceGenericsTypes = parameterizedType.getGenericsTypes();
+ if (sourceGenericsTypes == null) sourceGenericsTypes = EMPTY_GENERICS_ARRAY;
+ map = new LinkedHashMap<>();
+ for (int i = 0, m = sourceGenericsTypes.length, n = targetGenericsTypes.length; i < n; i += 1) {
+ map.put(targetGenericsTypes[i], i < m ? sourceGenericsTypes[i] : targetGenericsTypes[i]);
}
}
-
- result.put(key, value);
}
-
- return result;
+ return map;
}
/**
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 545c892..2ad5bfb 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1000,10 +1000,11 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
C.m(new A<>(new B()))
C.m(new A<>(new E()))
C.m(flag ? new A<>(new B()) : new A<>(new B()))
- C.m(flag ? new A<>(new B()) : new A<>(new E())) // Cannot call m(A<B>) with arguments [A<? extends B>]
+ C.m(flag ? new A<>(new B()) : new A<>((B)null))
+ C.m(flag ? new A<>(new B()) : new A<>((B)new E())) // Cannot call m(A<B>) with arguments [A<? extends B>]
'''
-
- /*shouldFailWithMessages types + '''
+/*
+ shouldFailWithMessages types + '''
A<B> x = new A<>(new Object())
A<B> y = true ? new A<>(new B()) : new A<>(new Object())
@@ -1013,7 +1014,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'Cannot assign A<java.lang.Object> to: A<B>',
'Cannot assign A<? extends java.lang.Object> to: A<B>',
'Cannot call C#m(A<B>) with arguments [A<java.lang.Object>]',
- 'Cannot call C#m(A<B>) with arguments [A<? extends java.lang.Object>]'*/
+ 'Cannot call C#m(A<B>) with arguments [A<? extends java.lang.Object>]'
+*/
}
@NotYetImplemented // GROOVY-10114
@@ -1286,7 +1288,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages '''
List<String> elements = ['a','b', 1]
''',
- 'Incompatible generic argument types. Cannot assign java.util.List <java.io.Serializable> to: java.util.List <String>'
+ 'Cannot assign java.util.List <java.io.Serializable> to: java.util.List <String>'
}
void testGenericAssignmentWithSubClass() {
@@ -1400,7 +1402,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
class FooBound {
}
new Foo()
- ''', 'Cannot find matching method FooWithGenerics#say(java.lang.Object)'
+ ''',
+ 'Cannot find matching method FooWithGenerics#say(java.lang.Object)'
}
// GROOVY-5237
@@ -1522,7 +1525,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
A<String, Integer> a = new B()
a.test()
- ''', 'Cannot call A <String, Integer>#<init>(java.lang.Class <String>, java.lang.Class <Integer>) with arguments [java.lang.Class <java.lang.Integer>, java.lang.Class <java.lang.String>]'
+ ''',
+ 'Cannot call A <String, Integer>#<init>(java.lang.Class <String>, java.lang.Class <Integer>) with arguments [java.lang.Class <java.lang.Integer>, java.lang.Class <java.lang.String>]'
}
void testMethodCallWithMapParameterUnbounded() {
@@ -1589,14 +1593,14 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testPutMethodWithPrimitiveValue1() {
+ void testPutMethodWithPrimitiveValue() {
assertScript '''
def map = new HashMap<String, Integer>()
map.put('hello', 1)
'''
}
- void testPutMethodWithPrimitiveValue2() {
+ void testPutAtMethodWithPrimitiveValue() {
assertScript '''
def map = new HashMap<String, Integer>()
map['hello'] = 1
@@ -1607,7 +1611,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages '''
def map = new HashMap<String, Integer>()
map.put('hello', new Object())
- ''', '[Static type checking] - Cannot find matching method java.util.HashMap#put(java.lang.String, java.lang.Object). Please check if the declared type is correct and if the method exists.'
+ ''',
+ 'Cannot find matching method java.util.HashMap#put(java.lang.String, java.lang.Object). Please check if the declared type is correct and if the method exists.'
}
void testShouldComplainAboutToInteger() {
@@ -1635,11 +1640,12 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
if (config.pluginFactory instanceof AntlrParserPluginFactory) {
- shouldFailWithMessages code, 'Cannot find matching method java.lang.Object#getAt(int)'
+ shouldFailWithMessages code,
+ 'Cannot find matching method java.lang.Object#getAt(int)'
} else {
shouldFailWithMessages code,
- 'Cannot find matching method java.lang.Object#getAt(int)',
- 'Cannot find matching method java.lang.Object#toInteger()'
+ 'Cannot find matching method java.lang.Object#getAt(int)',
+ 'Cannot find matching method java.lang.Object#toInteger()'
}
}
@@ -1680,44 +1686,46 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
}
}
new ClassB()
- ''', 'Cannot call <X> groovy.transform.stc.GenericsSTCTest$ClassA <Long>#bar(java.lang.Class <Long>) with arguments [java.lang.Class <? extends java.lang.Object>]'
+ ''',
+ 'Cannot call <X> groovy.transform.stc.GenericsSTCTest$ClassA <Long>#bar(java.lang.Class <Long>) with arguments [java.lang.Class <? extends java.lang.Object>]'
}
// GROOVY-8961, GROOVY-9915
void testShouldUseMethodGenericType3() {
['', 'static'].each { mods ->
assertScript """
- $mods void setM(List<String> strings) {
+ $mods void setX(List<String> strings) {
}
void test() {
- m = Collections.emptyList() // Cannot assign value of type List<T> to variable of List<String>
+ x = Collections.emptyList()
}
test()
"""
assertScript """
- $mods void setM(Collection<String> strings) {
+ $mods void setX(Collection<String> strings) {
}
void test() {
- m = Collections.emptyList()
+ x = Collections.emptyList()
}
test()
"""
assertScript """
- $mods void setM(Iterable<String> strings) {
+ $mods void setX(Iterable<String> strings) {
}
void test() {
- m = Collections.emptyList()
+ x = Collections.emptyList()
}
test()
"""
shouldFailWithMessages """
- $mods void setM(List<String> strings) {
+ $mods void setX(List<String> strings) {
}
void test() {
- m = Collections.<Integer>emptyList()
+ x = Collections.<Integer>emptyList()
}
- """, '[Static type checking] - Cannot assign value of type java.util.List <Integer> to variable of type java.util.List <String>'
+ """,
+ 'Cannot assign value of type java.util.List <Integer> to variable of type java.util.List <String>'
}
}
@@ -1728,7 +1736,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
$mods void m(List<String> strings) {
}
void test() {
- m(Collections.emptyList()) // Cannot call m(List<String>) with arguments [List<T>]
+ m(Collections.emptyList())
}
test()
"""
@@ -1736,7 +1744,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
$mods void m(Collection<String> strings) {
}
void test() {
- m(Collections.emptyList())
+ m(Collections.emptyList())
}
test()
"""
@@ -1744,7 +1752,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
$mods void m(Iterable<String> strings) {
}
void test() {
- m(Collections.emptyList())
+ m(Collections.emptyList())
}
test()
"""
@@ -1811,31 +1819,33 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
assert opt.get() == 42
'''
// same as above but with separate type parameter name for each location
- assertScript '''
- abstract class A<I,O> {
- abstract O apply(I input)
- }
- class C<T> {
- static <U> C<U> of(U item) {
- new C<U>()
+ ['D.&wrap', 'Collections.&singleton', '{x -> [x].toSet()}', '{Collections.singleton(it)}'].each { toSet ->
+ assertScript """
+ abstract class A<I,O> {
+ abstract O apply(I input)
}
- def <V> C<V> map(A<? super T, ? super V> func) {
- new C<V>()
+ class C<T> {
+ static <U> C<U> of(U item) {
+ new C<U>()
+ }
+ def <V> C<V> map(A<? super T, ? super V> func) {
+ new C<V>()
+ }
}
- }
- class D {
- static <W> Set<W> wrap(W o) {
+ class D {
+ static <W> Set<W> wrap(W o) {
+ }
}
- }
- void test() {
- def c = C.of(42)
- def d = c.map(D.&wrap)
- def e = d.map(x -> x.first().intValue())
- }
+ void test() {
+ def c = C.of(42)
+ def d = c.map($toSet)
+ def e = d.map(x -> x.first().intValue())
+ }
- test()
- '''
+ test()
+ """
+ }
}
// GROOVY-9945
@@ -1875,7 +1885,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
List<String> list = ['a','b','c']
Collection<Integer> e = (Collection<Integer>) [1,2,3]
boolean r = list.addAll(e)
- ''', 'Cannot call java.util.List <java.lang.String>#addAll(java.util.Collection <? extends java.lang.String>) with arguments [java.util.Collection <Integer>]'
+ ''',
+ 'Cannot call java.util.List <java.lang.String>#addAll(java.util.Collection <? extends java.lang.String>) with arguments [java.util.Collection <Integer>]'
}
// GROOVY-5528
@@ -1906,7 +1917,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type instanceof LUB
})
List<String> list = ["foo", "$bar"]
- ''', 'You are trying to use a GString in place of a String'
+ ''',
+ 'You are trying to use a GString in place of a String'
shouldFailWithMessages base + '''
@ASTTest(phase=INSTRUCTION_SELECTION, value={
@@ -1914,12 +1926,14 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type == GSTRING_TYPE // single element means no LUB
})
List<String> list = ["$bar"]
- ''', 'You are trying to use a GString in place of a String'
+ ''',
+ 'You are trying to use a GString in place of a String'
shouldFailWithMessages base + '''
void m(List<String> list) {}
m(["foo", "$bar"])
- ''', 'You are trying to use a GString in place of a String'
+ ''',
+ 'You are trying to use a GString in place of a String'
}
// GROOVY-5559, GROOVY-10010
@@ -1928,17 +1942,20 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages base + '''
Map<String,String> map = [x:"foo", y:"$bar"]
- ''', 'You are trying to use a GString in place of a String'
+ ''',
+ 'You are trying to use a GString in place of a String'
shouldFailWithMessages base + '''
void m(Map<?,String> map) {}
m([x:"foo", y:"$bar"])
- ''', 'You are trying to use a GString in place of a String'
+ ''',
+ 'You are trying to use a GString in place of a String'
shouldFailWithMessages base + '''
void m(Map<?,String> map) {}
m(x:"foo", y:"$bar")
- ''', 'You are trying to use a GString in place of a String'
+ ''',
+ 'You are trying to use a GString in place of a String'
}
// GROOVY-5559: related behaviour
@@ -1956,49 +1973,49 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-5594
void testMapEntryUsingPropertyNotation() {
assertScript '''
- Map.Entry<Date, Integer> entry = null
+ Map.Entry<Date, Integer> entry = null
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == make(Date)
- })
- def k = entry?.key
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == make(Date)
+ })
+ def k = entry?.key
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
- })
- def v = entry?.value
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
+ })
+ def v = entry?.value
'''
}
void testInferenceFromMap() {
assertScript '''
- Map<Date, Integer> map = [:]
+ Map<Date, Integer> map = [:]
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- def infType = node.getNodeMetaData(INFERRED_TYPE)
- assert infType == make(Set)
- def entryInfType = infType.genericsTypes[0].type
- assert entryInfType == make(Map.Entry)
- assert entryInfType.genericsTypes[0].type == make(Date)
- assert entryInfType.genericsTypes[1].type == Integer_TYPE
- })
- def entries = map?.entrySet()
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def infType = node.getNodeMetaData(INFERRED_TYPE)
+ assert infType == make(Set)
+ def entryInfType = infType.genericsTypes[0].type
+ assert entryInfType == make(Map.Entry)
+ assert entryInfType.genericsTypes[0].type == make(Date)
+ assert entryInfType.genericsTypes[1].type == Integer_TYPE
+ })
+ def entries = map?.entrySet()
'''
}
void testInferenceFromListOfMaps() {
assertScript '''
- List<Map<Date, Integer>> maps = []
+ List<Map<Date, Integer>> maps = []
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- def listType = node.getNodeMetaData(INFERRED_TYPE)
- assert listType == Iterator_TYPE
- def infType = listType.genericsTypes[0].type
- assert infType == make(Map)
- assert infType.genericsTypes[0].type == make(Date)
- assert infType.genericsTypes[1].type == Integer_TYPE
- })
- def iter = maps?.iterator()
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def listType = node.getNodeMetaData(INFERRED_TYPE)
+ assert listType == Iterator_TYPE
+ def infType = listType.genericsTypes[0].type
+ assert infType == make(Map)
+ assert infType.genericsTypes[0].type == make(Date)
+ assert infType.genericsTypes[1].type == Integer_TYPE
+ })
+ def iter = maps?.iterator()
'''
}
@@ -2050,7 +2067,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
void testInferDiamondUsingAIC() {
shouldFailWithMessages '''
Map<String,Date> map = new HashMap<>() {}
- ''', 'Cannot use diamond <> with anonymous inner classes'
+ ''',
+ 'Cannot use diamond <> with anonymous inner classes'
}
// GROOVY-5614
@@ -2082,7 +2100,6 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
r.bindings2['a'] = 'A'
r.bindings2.put('b', 'B')
-
'''
}
void testInferDiamondForAssignment() {
@@ -2137,7 +2154,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
})
Map<Date, Date> map = new HashMap<>()
map.put('foo', new Date())
- ''', '[Static type checking] - Cannot find matching method java.util.HashMap#put(java.lang.String, java.util.Date). Please check if the declared type is correct and if the method exists.'
+ ''',
+ 'Cannot find matching method java.util.HashMap#put(java.lang.String, java.util.Date). Please check if the declared type is correct and if the method exists.'
}
void testInferDiamondForAssignmentWithDatesAndIllegalKeyUsingSquareBracket() {
shouldFailWithMessages '''
@@ -2156,7 +2174,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
})
Map<Date, Date> map = new HashMap<>()
map['foo'] = new Date()
- ''', 'Cannot call <K,V> java.util.HashMap <java.util.Date, java.util.Date>#putAt(java.util.Date, java.util.Date) with arguments [java.lang.String, java.util.Date]'
+ ''',
+ 'Cannot call <K,V> java.util.HashMap <java.util.Date, java.util.Date>#putAt(java.util.Date, java.util.Date) with arguments [java.lang.String, java.util.Date]'
}
void testInferDiamondForAssignmentWithDatesAndIllegalValueUsingPut() {
shouldFailWithMessages '''
@@ -2175,7 +2194,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
})
Map<Date, Date> map = new HashMap<>()
map.put(new Date(), 'foo')
- ''', '[Static type checking] - Cannot find matching method java.util.HashMap#put(java.util.Date, java.lang.String). Please check if the declared type is correct and if the method exists.'
+ ''',
+ 'Cannot find matching method java.util.HashMap#put(java.util.Date, java.lang.String). Please check if the declared type is correct and if the method exists.'
}
void testInferDiamondForAssignmentWithDatesAndIllegalValueUsingSquareBracket() {
shouldFailWithMessages '''
@@ -2194,21 +2214,22 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
})
Map<Date, Date> map = new HashMap<>()
map[new Date()] = 'foo'
- ''', 'Cannot call <K,V> java.util.HashMap <java.util.Date, java.util.Date>#putAt(java.util.Date, java.util.Date) with arguments [java.util.Date, java.lang.String]'
+ ''',
+ 'Cannot call <K,V> java.util.HashMap <java.util.Date, java.util.Date>#putAt(java.util.Date, java.util.Date) with arguments [java.util.Date, java.lang.String]'
}
void testCallMethodWithParameterizedArrayList() {
assertScript '''
- class MyUtility {
- def methodOne() {
- def someFiles = new ArrayList<File>()
- def someString = ''
- methodTwo someString, someFiles
- }
+ class MyUtility {
+ def methodOne() {
+ def someFiles = new ArrayList<File>()
+ def someString = ''
+ methodTwo someString, someFiles
+ }
- def methodTwo(String s, List<File> files) {}
- }
- new MyUtility()
+ def methodTwo(String s, List<File> files) {}
+ }
+ new MyUtility()
'''
}
@@ -2222,35 +2243,35 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-5617
void testIntermediateListAssignmentOfGStrings() {
assertScript '''
- def test() {
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- def type = node.getNodeMetaData(INFERRED_TYPE)
- assert type == make(List)
- assert type.genericsTypes.length==1
- assert type.genericsTypes[0].type == GSTRING_TYPE
- })
- List<GString> dates = ["${new Date()-1}", "${new Date()}", "${new Date()+1}"]
- dates*.toUpperCase()
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- def type = node.getNodeMetaData(INFERRED_TYPE)
- assert type == make(List)
- assert type.genericsTypes.length==1
- assert type.genericsTypes[0].type == GSTRING_TYPE
- })
- List<GString> copied = []
- copied.addAll(dates)
- List<String> upper = copied*.toUpperCase()
- }
- test()
+ def test() {
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def type = node.getNodeMetaData(INFERRED_TYPE)
+ assert type == make(List)
+ assert type.genericsTypes.length==1
+ assert type.genericsTypes[0].type == GSTRING_TYPE
+ })
+ List<GString> dates = ["${new Date()-1}", "${new Date()}", "${new Date()+1}"]
+ dates*.toUpperCase()
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def type = node.getNodeMetaData(INFERRED_TYPE)
+ assert type == make(List)
+ assert type.genericsTypes.length==1
+ assert type.genericsTypes[0].type == GSTRING_TYPE
+ })
+ List<GString> copied = []
+ copied.addAll(dates)
+ List<String> upper = copied*.toUpperCase()
+ }
+ test()
'''
}
// GROOVY-5650
void testRegressionInGenericsTypeInference() {
assertScript '''import groovy.transform.stc.GenericsSTCTest.JavaClassSupport as JavaClass
- List<JavaClass.StringContainer> containers = new ArrayList<>();
- containers.add(new JavaClass.StringContainer());
- List<String> strings = JavaClass.unwrap(containers);
+ List<JavaClass.StringContainer> containers = new ArrayList<>();
+ containers.add(new JavaClass.StringContainer());
+ List<String> strings = JavaClass.unwrap(containers);
'''
}
@@ -2276,18 +2297,73 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
assertScript '''
@ASTTest(phase=INSTRUCTION_SELECTION, value={
def ift = node.getNodeMetaData(INFERRED_TYPE)
- assert ift == make(List)
- assert ift.isUsingGenerics()
+ assert ift == LIST_TYPE
def gts = ift.genericsTypes
- assert gts.length==1
+ assert gts != null
+ assert gts.length == 1
assert gts[0].type == STRING_TYPE
})
Iterable<String> list = (List) null
'''
}
+ @NotYetImplemented // GROOVY-5692, GROOVY-10006
void testCompatibleArgumentsForPlaceholders1() {
assertScript '''
+ def <T> T test(T one, T two) { }
+ def result = test(1,"II")
+ '''
+ assertScript '''
+ def <T> T test(T one, T two, T three) { }
+ def result = test(1,"II",Class)
+ '''
+ assertScript '''
+ def <T extends Number> T test(T one, T two) { }
+ def result = test(1L,2G)
+ '''
+ }
+
+ @NotYetImplemented // GROOVY-5692
+ void testCompatibleArgumentsForPlaceholders2() {
+ assertScript '''
+ def <T> boolean test(T one, List<T> many) { }
+ test(1,["II","III"])
+ '''
+ }
+
+ // GROOVY-10220
+ void testCompatibleArgumentsForPlaceholders3() {
+ assertScript '''
+ class C<S, T extends Number> {
+ }
+ class D<T> {
+ C<? extends T, Integer> f
+ D(C<? extends T, Integer> p) {
+ f = p
+ }
+ }
+
+ assert new D<String>(null).f == null
+ '''
+ }
+
+ // GROOVY-10235
+ void testCompatibleArgumentsForPlaceholders4() {
+ assertScript '''
+ import static java.util.concurrent.ConcurrentHashMap.newKeySet
+
+ void accept(Collection<Integer> integers) {
+ assert integers
+ }
+
+ Set<Integer> integers = newKeySet()
+ integers.add(42)
+ accept(integers)
+ '''
+ }
+
+ void testCompatibleArgumentsForPlaceholders5() {
+ assertScript '''
def <X> X foo(X x) {
}
def <Y> Y bar() {
@@ -2300,7 +2376,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
}
// GROOVY-10482
- void testCompatibleArgumentsForPlaceholders2() {
+ void testCompatibleArgumentsForPlaceholders6() {
['', 'def', 'public', 'static', '@Deprecated'].each {
assertScript """
class Foo<X> {
@@ -2339,28 +2415,95 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
}
}
- void testIncompatibleGenericsForTwoArguments() {
- shouldFailWithMessages '''
- public <T> void printEqual(T arg1, T arg2) {
- println arg1 == arg2
+ // GROOVY-10100
+ void testCompatibleArgumentsForPlaceholders8() {
+ assertScript '''
+ import java.util.function.Function
+
+ class C<T> {
+ T m(Object... args) {
+ }
+ }
+ def <T extends Number> void test() {
+ C<T> c = new C<>()
+ Function<String[], T> f = c::m
+ T t = f.apply(new String[]{"string"}) // Cannot assign value of type java.lang.String[] to variable of type T
}
- printEqual(1, 'foo')
+ test()
+ '''
+ }
+
+ // GROOVY-10115
+ void testCompatibleArgumentsForPlaceholders9() {
+ assertScript '''
+ class C<X, T extends X> {
+ T t
+ C(T t) {
+ this.t = t
+ }
+ }
+ new C(null)
+ '''
+ }
+
+ @NotYetImplemented // GROOVY-10116
+ void testCompatibleArgumentsForPlaceholders10() {
+ assertScript '''
+ class Foo<X,T> {
+ Foo(Bar<X,T> bar) {
+ }
+ }
+ class Bar<X,T> {
+ }
+ class Baz<T> {
+ void test() {
+ Foo<T,Long> x = new Foo<T,Long>(new Bar<T,Long>()) // Cannot call Foo#<init>(Bar<T,Long>) with arguments [Bar<T,Long>]
+ }
+ }
+ new Baz().test()
+ '''
+ }
+
+ void testIncompatibleArgumentsForPlaceholders1() {
+ shouldFailWithMessages '''
+ def <T extends Number> T test(T one, T two) { }
+ test(1,"II")
''',
- '#printEqual(T, T) with arguments [int, java.lang.String]'
+ '#test(int, java.lang.String). Please check if the declared type is correct and if the method exists.'
}
- void testIncompatibleGenericsForTwoArgumentsUsingEmbeddedPlaceholder() {
+ @NotYetImplemented // GROOVY-7720
+ void testIncompatibleArgumentsForPlaceholders2() {
+ shouldFailWithMessages '''
+ class Consumer<T> {
+ <U> void accept(U param) {
+ T local = param
+ }
+ }
+ ''',
+ 'Cannot assign value of type U to variable of type T'
+
shouldFailWithMessages '''
- public <T> void printEqual(T arg1, List<T> arg2) {
- println arg1 == arg2
+ class Converter<T, U> {
+ U convert(T param) {
+ return param
+ }
+ }
+ ''',
+ 'Cannot return value of type T for method returning U'
+
+ shouldFailWithMessages '''
+ class C<X, Y> {
+ }
+ def <X extends C<Number, String>> X[] m() {
+ new X[]{new C<Object, String>()}
}
- printEqual(1, ['foo'])
''',
- '#printEqual(T, java.util.List <T>) with arguments [int, java.util.List <java.lang.String>]'
+ 'Cannot convert from C<java.lang.Object, java.lang.String> to X'
}
- // GROOVY-9902
- void testIncompatibleArgumentsForGenericArgument_IncludingDelegation() {
+ // GROOVY-9902: incomplete generics should not stop type checking
+ void testIncompatibleArgumentsForPlaceholders3() {
shouldFailWithMessages '''
class Holder<Unknown> {
TypedProperty<Number, Unknown> numberProperty = prop(Number)
@@ -2399,7 +2542,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'Cannot call TypedProperty <Number, Unknown>#eq(java.lang.Number) with arguments [java.lang.String]'
}
- void testGroovy5748() {
+ // GROOVY-5748
+ void testPlaceholdersAndWildcards() {
assertScript '''
interface IStack<T> {
INonEmptyStack<T, ? extends IStack<T>> push(T x)
@@ -2455,7 +2599,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
assert twoIntegers.getTop() == 2
def oneIntegerAgain = stack.push(1).push(2).pop()
- assert oneIntegerAgain.getTop() == 1 // BOOM!!!!
+ assert oneIntegerAgain.getTop() == 1 // Cannot find matching method IStack#getTop()
'''
}
@@ -2472,14 +2616,14 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-5735
void testCorrespondingParameterType() {
assertScript '''
- public <T> void someMethod (java.lang.Class<T> clazz, T object) {}
+ public <T> void someMethod (java.lang.Class<T> clazz, T object) {}
- void method() {
- List<String> list = null
- someMethod(java.util.List.class, list)
- }
+ void method() {
+ List<String> list = null
+ someMethod(java.util.List.class, list)
+ }
- method()
+ method()
'''
}
@@ -2929,7 +3073,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
def cl = node.rightExpression.arguments[0]
assert cl instanceof ClosureExpression
def type = cl.getNodeMetaData(INFERRED_TYPE)
- assert type == make(Closure)
+ assert type == CLOSURE_TYPE
assert type.isUsingGenerics()
assert type.genericsTypes
assert type.genericsTypes[0].type.name == 'CTypeTest'
@@ -3187,66 +3331,57 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-5839
void testMethodShadowGenerics() {
shouldFailWithMessages '''
- public class GoodCodeRed<T> {
- Collection<GoodCodeRed<T>> attached = []
- public <T> void attach(GoodCodeRed<T> toAttach) {
- attached.add(toAttach)
- }
- static void foo() {
- def g1 = new GoodCodeRed<Long>()
- def g2 = new GoodCodeRed<Integer>()
- g1.attach(g2);
+ class C<T> {
+ Collection<C<T>> attached = []
+ def <T> void attach(C<T> toAttach) {
+ attached.add(toAttach) // TODO: GROOVY-7719
}
}
- GoodCodeRed.foo()
- ''', 'Cannot call <T> GoodCodeRed <Long>#attach(GoodCodeRed <Long>) with arguments [GoodCodeRed <Integer>]'
+ def c1 = new C<Short>()
+ def c2 = new C<Long>()
+ c1.attach(c2)
+ ''',
+ 'Cannot call <T> C <Short>#attach(C <Short>) with arguments [C <Long>]'
}
- void testHiddenGenerics() {
- // Groovy-6237
+ void testSuperClassGenerics() {
+ // GROOVY-6237
assertScript '''
- class MyList extends LinkedList<Object> {}
+ class MyList extends LinkedList<Object> {
+ }
List<Object> o = new MyList()
'''
shouldFailWithMessages '''
- class Blah {}
- class MyList extends LinkedList<Object> {}
- List<Blah> o = new MyList()
- ''', 'Incompatible generic argument types. Cannot assign MyList to: java.util.List <Blah>'
+ class MyList extends LinkedList<Object> {
+ }
+ List<String> o = new MyList()
+ ''',
+ 'Incompatible generic argument types. Cannot assign MyList to: java.util.List <String>'
- // Groovy-5873
- assertScript """
- abstract class Parent<T> {
+ // GROOVY-5873
+ assertScript '''
+ abstract class A<T> {
public T value
}
- class Impl extends Parent<Integer> {}
- Impl impl = new Impl()
- Integer i = impl.value
- """
+ class C extends A<Integer> {
+ }
+ C c = new C()
+ Integer i = c.value
+ '''
// GROOVY-5920
- assertScript """
+ assertScript '''
class Data<T> {
- T value
+ T value
}
-
class StringDataIterator implements Iterator<Data<String>> {
- boolean hasNext() { true }
- void remove() {}
- Data<String> next() {
- new Data<String>( value: 'tim' )
- }
+ boolean hasNext() { true }
+ Data<String> next() { new Data<String>(value: 'tim') }
}
-
- class Runner {
- static main( args ) {
- Data<String> elem = new StringDataIterator().next()
- assert elem.value.length() == 3
- }
- }
- Runner.main(null);
- """
+ Data<String> elem = new StringDataIterator().next()
+ assert elem.value.length() == 3
+ '''
}
void testReturnTypeInferenceRemovalWithGenerics() {
@@ -3346,7 +3481,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- //GROOVY-6723, GROOVY-6415
+ // GROOVY-6723, GROOVY-6415
void testIndirectMethodLevelGenerics() {
assertScript '''
class C1<A> {
@@ -3355,6 +3490,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
}
new C1().m1(null) // the call does not really matter
'''
+
assertScript '''
class Test1 {
static <A, B> void pair1(A a, B b) {}
@@ -3514,7 +3650,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- void testGROOVY5981() {
+ // GROOVY-5981
+ void testCovariantAssignment() {
assertScript '''
import javax.swing.*
import java.awt.*
@@ -3522,16 +3659,12 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
class ComponentFixture<T extends Component> {}
class JButtonFixture extends ComponentFixture<JButton> {}
class ContainerFixture<T extends Container> extends ComponentFixture<T> {}
- abstract class ComponentAdapter<Fixture extends ComponentFixture> {
- Fixture getFixture() {
- return fixture
- }
- }
+ abstract class ComponentAdapter<Fixture extends ComponentFixture> { Fixture getFixture() {} }
abstract class ContainerAdapter<Fixture extends ContainerFixture> extends ComponentAdapter<Fixture> {}
class ButtonComponent extends ComponentAdapter<JButtonFixture> {
- void setFixtureResolver(final ContainerAdapter<? extends ContainerFixture> containerAdapter) {
- final ContainerFixture containerFixture = containerAdapter.getFixture()
+ void setFixtureResolver(ContainerAdapter<? extends ContainerFixture> containerAdapter) {
+ ContainerFixture containerFixture = containerAdapter.getFixture() // Cannot assign value of type ComponentFixture to variable of type ContainerFixture
}
}
@@ -3678,12 +3811,18 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
void testReturnTypeChecking() {
shouldFailWithMessages '''
- class Foo {
- List<String> run() {
- [11, 12]
- }
+ List<String> test() {
+ return [1,2,3]
}
- ''', 'Incompatible generic argument types. Cannot assign java.util.List <java.lang.Integer> to: java.util.List <String>'
+ ''',
+ 'Cannot assign java.util.List <java.lang.Integer> to: java.util.List <String>'
+
+ shouldFailWithMessages '''
+ List<CharSequence> test() {
+ return [1,2,3]
+ }
+ ''',
+ 'Cannot assign java.util.List <java.lang.Integer> to: java.util.List <CharSequence>'
}
void testBoundedReturnTypeChecking() {
@@ -3739,7 +3878,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
class Foo<T extends Bar> {
T method(T t) {
def c = { -> t }
- return c() // Cannot return value of type Object on method returning type T
+ return c() // Cannot return value of type Object for method returning T
}
}
def bar = new Bar()
@@ -3747,7 +3886,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- // GROOVY-9981
+ // GROOVY-9891
void testBoundedReturnTypeChecking3() {
assertScript '''
class Pogo {
@@ -3887,11 +4026,9 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
// GROOVY-7804
void testParameterlessClosureToGenericSAMTypeArgumentCoercion() {
assertScript '''
- interface Supplier<T> {
- public <T> T get()
- }
+ interface Supplier<T> { def <T> T get() }
- static <T> T doGet(Supplier<T> supplier) { supplier.get() }
+ def <T> T doGet(Supplier<T> supplier) { supplier.get() }
assert doGet { -> 'foo' } == 'foo'
'''
@@ -3909,6 +4046,20 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-10528
+ void testRawTypeGuard() {
+ assertScript '''
+ void test(... args) {
+ args.each { object ->
+ if (object instanceof Iterable) {
+ object.each { test(it) }
+ }
+ }
+ }
+ test(1,[2,3])
+ '''
+ }
+
//--------------------------------------------------------------------------
static class MyList
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index 202ab7d..f01c511 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -32,70 +32,43 @@ final class LambdaTest {
assertScript '''
import groovy.transform.CompileStatic
import java.util.stream.Collectors
- import java.util.stream.Stream
@CompileStatic
- public class Test1 {
- public static void main(String[] args) {
- p();
- }
-
- public static void p() {
- assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus 1).collect(Collectors.toList());
- }
+ def f() {
+ [1, 2, 3].stream().map(e -> e + 1).collect(Collectors.toList())
}
- '''
- }
-
- @Test
- void testFunction2() {
- assertScript '''
- import groovy.transform.CompileStatic
- import java.util.stream.Collectors
- import java.util.stream.Stream
-
- public class Test1 {
- public static void main(String[] args) {
- p();
- }
- @CompileStatic
- public static void p() {
- assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus 1).collect(Collectors.toList());
- }
- }
+ assert f() == [2, 3, 4]
'''
}
@Test
- void testFunctionScript() {
+ void testFunction2() {
assertScript '''
import groovy.transform.CompileStatic
import java.util.stream.Collectors
- import java.util.stream.Stream
@CompileStatic
- void p() {
- assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e + 1).collect(Collectors.toList());
+ def f() {
+ [1, 2, 3].stream().map(e -> e.plus(1)).collect(Collectors.toList())
}
- p()
+ assert f() == [2, 3, 4]
'''
}
@Test
- void testFunctionScript2() {
+ void testFunctionWithTypeArgument() {
assertScript '''
import groovy.transform.CompileStatic
import java.util.stream.Collectors
- import java.util.stream.Stream
@CompileStatic
- void p() {
- assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus 1).collect(Collectors.toList());
+ List<String> f() {
+ [1, 2, 3].stream().<String>map(i -> null).collect(Collectors.toList())
}
- p()
+ assert f() == [null, null, null]
'''
}
@@ -103,94 +76,57 @@ final class LambdaTest {
void testBinaryOperator() {
assertScript '''
import groovy.transform.CompileStatic
- import java.util.stream.Collectors
- import java.util.stream.Stream
@CompileStatic
- public class Test1 {
- public static void main(String[] args) {
- p();
- }
-
- public static void p() {
- assert 13 == [1, 2, 3].stream().reduce(7, (Integer r, Integer e) -> r + e);
- }
+ int f() {
+ [1, 2, 3].stream().reduce(7, (Integer r, Integer e) -> r + e)
}
+
+ assert f() == 13
'''
}
- @Test // GROOVY-8917: Failed to infer parameter type of some SAM, e.g. BinaryOperator
- void testBinaryOperatorWithoutExplicitTypeDef() {
+ @Test // GROOVY-8917
+ void testBinaryOperatorWithoutExplicitTypes() {
assertScript '''
import groovy.transform.CompileStatic
- import java.util.stream.Collectors
- import java.util.stream.Stream
@CompileStatic
- public class Test1 {
- public static void main(String[] args) {
- p();
- }
-
- public static void p() {
- assert 13 == [1, 2, 3].stream().reduce(7, (r, e) -> r + e);
- }
+ int f() {
+ [1, 2, 3].stream().reduce(7, (r, e) -> r + e)
}
+
+ assert f() == 13
'''
}
@Test
- void testBinaryOperatorWithoutExplicitTypeDef2() {
+ void testBinaryOperatorWithoutExplicitTypes2() {
assertScript '''
import groovy.transform.CompileStatic
- import java.util.stream.Collectors
- import java.util.stream.Stream
import java.util.function.BinaryOperator
@CompileStatic
- public class Test1 {
- public static void main(String[] args) {
- p();
- }
-
- public static void p() {
- BinaryOperator<Integer> accumulator = (r, e) -> r + e
- assert 13 == [1, 2, 3].stream().reduce(7, accumulator);
- }
+ int f() {
+ BinaryOperator<Integer> accumulator = (r, e) -> r + e
+ return [1, 2, 3].stream().reduce(7, accumulator)
}
- '''
- }
-
- @Test
- void testConsumer() {
- assertScript '''
- @groovy.transform.CompileStatic
- class Test1 {
- static main(args) {
- p()
- }
- static void p() {
- [1, 2, 3].stream().forEach(e -> { System.out.println(e + 1); })
- }
- }
+ assert f() == 13
'''
}
- @Test // GROOVY-9340
- void testConsumerWithSelfType() {
+ @Test // GROOVY-10282
+ void testBiFunctionAndBinaryOperatorWithSharedTypeParameter() {
assertScript '''
- @groovy.transform.CompileStatic
- class Test1 {
- static main(args) {
- p()
- }
+ import groovy.transform.CompileStatic
+ import java.util.stream.IntStream
- static void p() {
- java.util.function.Consumer<Test1> c = t -> null
- c.accept(this.newInstance())
- }
+ @CompileStatic
+ def f() {
+ IntStream.range(0, 10).boxed().reduce('', (s, i) -> s + '-', String::concat)
}
+ assert f() == '----------'
'''
}
@@ -294,7 +230,7 @@ final class LambdaTest {
}
@Test
- void testComparator1() {
+ void testComparator() {
assertScript '''
@groovy.transform.CompileStatic class T {
Comparator<Integer> c = (Integer a, Integer b) -> Integer.compare(a, b)
@@ -302,26 +238,29 @@ final class LambdaTest {
def t = new T()
assert t.c.compare(0,0) == 0
'''
+ }
+ @Test // GROOVY-10372
+ void testComparator2() {
def err = shouldFail '''
@groovy.transform.CompileStatic class T {
- Comparator<Integer> c = (int a, int b) -> Integer.compare(a, b)
+ Comparator<Integer> c = (int a, String b) -> 42
}
'''
- assert err =~ /Cannot assign java.util.Comparator <int> to: java.util.Comparator <Integer>/
+ assert err =~ /Cannot assign java.util.Comparator <java.lang.String> to: java.util.Comparator <Integer>/
}
@Test // GROOVY-9977
- void testComparator2() {
+ void testComparator3() {
assertScript '''
@groovy.transform.CompileStatic
class T {
Comparator<Integer> c = (a, b) -> Integer.compare(a, b)
- static void m1() {
+ void m1() {
Comparator<Integer> x = (a, b) -> Integer.compare(a, b)
}
- void m2() {
+ static void m2() {
Comparator<Integer> y = (a, b) -> Integer.compare(a, b)
}
}
@@ -331,7 +270,7 @@ final class LambdaTest {
}
@Test // GROOVY-9997
- void testComparator3() {
+ void testComparator4() {
assertScript '''
@groovy.transform.TypeChecked
void test() {
@@ -388,7 +327,8 @@ final class LambdaTest {
'''
}
- void testFunctionWithLocalVariables4() {
+ @Test
+ void testFunctionWithLocalVariables3() {
assertScript '''
import groovy.transform.CompileStatic
import java.util.stream.Collectors
@@ -410,7 +350,7 @@ final class LambdaTest {
}
@Test
- void testFunctionWithLocalVariables5() {
+ void testFunctionWithLocalVariables4() {
assertScript '''
import groovy.transform.CompileStatic
import java.util.stream.Collectors
@@ -434,7 +374,7 @@ final class LambdaTest {
}
@Test
- void testFunctionWithLocalVariables6() {
+ void testFunctionWithLocalVariables5() {
assertScript '''
import groovy.transform.CompileStatic
import java.util.stream.Collectors
@@ -807,6 +747,58 @@ final class LambdaTest {
'''
}
+ @Test // GROOVY-9340
+ void testConsumer8() {
+ assertScript '''
+ @groovy.transform.CompileStatic
+ class Test1 {
+ static main(args) {
+ p()
+ }
+
+ static void p() {
+ java.util.function.Consumer<Test1> c = t -> null
+ c.accept(this.newInstance())
+ }
+ }
+ '''
+ }
+
+ @Test
+ void testConsumer9() {
+ assertScript '''
+ @groovy.transform.CompileStatic
+ class Test1 {
+ static main(args) {
+ p()
+ }
+
+ static void p() {
+ [1, 2, 3].stream().forEach(e -> { System.out.println(e + 1); })
+ }
+ }
+ '''
+ }
+
+ @Test // GROOVY-10056
+ void testConsumer10() {
+ ['CompileStatic', 'TypeChecked'].each { xform ->
+ assertScript """
+ @groovy.transform.${xform}
+ void test() {
+ String[][] arrayArray = new String[][] {
+ new String[] {'a','b','c'},
+ new String[] {'d','e','f'}
+ }
+ Arrays.stream(arrayArray).limit(1).forEach(array -> {
+ assert Arrays.asList(array) == ['a','b','c']
+ })
+ }
+ test()
+ """
+ }
+ }
+
@Test
void testFunctionalInterface1() {
assertScript '''
@@ -973,7 +965,7 @@ final class LambdaTest {
Function<Integer, String> f = (Integer e) -> 'a' + e
assert ['a1', 'a2', 'a3'] == [1, 2, 3].stream().map(f).collect(Collectors.toList())
- assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus 1).collect(Collectors.toList());
+ assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus(1)).collect(Collectors.toList());
}
}
'''
@@ -1068,7 +1060,7 @@ final class LambdaTest {
@groovy.transform.CompileStatic
void p() {
assert ['1', '2', '3'] == [1, 2, 3].stream().map(Object::toString).collect(Collectors.toList())
- assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus 1).collect(Collectors.toList())
+ assert [2, 3, 4] == [1, 2, 3].stream().map(e -> e.plus(1)).collect(Collectors.toList())
assert ['1', '2', '3'] == [1, 2, 3].stream().map(Object::toString).collect(Collectors.toList())
}
@@ -1232,23 +1224,21 @@ final class LambdaTest {
@Test
void testSerialize1() {
assertScript '''
- import java.util.function.Function
-
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
@groovy.transform.CompileStatic
- class Test1 {
- def p() {
- def out = new ByteArrayOutputStream()
+ byte[] test() {
+ try (def out = new ByteArrayOutputStream()) {
out.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> 'a' + e)
+ SerializableFunction<Integer, String> f = ((Integer i) -> 'a' + i)
it.writeObject(f)
}
- return out.toByteArray()
+ out.toByteArray()
}
}
- assert new Test1().p().length > 0
+ assert test().length > 0
'''
}
@@ -1258,18 +1248,17 @@ final class LambdaTest {
import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- def p() {
- def out = new ByteArrayOutputStream()
+ byte[] test() {
+ try (def out = new ByteArrayOutputStream()) {
out.withObjectOutputStream {
- Function<Integer, String> f = ((Integer e) -> 'a' + e)
+ Function<Integer, String> f = ((Integer i) -> 'a' + i)
it.writeObject(f)
}
- return out.toByteArray()
+ out.toByteArray()
}
}
- new Test1().p()
+ test()
'''
assert err.message.contains('$Lambda$')
@@ -1279,415 +1268,403 @@ final class LambdaTest {
void testDeserialize1() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- byte[] p() {
+ class C {
+ byte[] test() {
def out = new ByteArrayOutputStream()
- out.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> 'a' + e)
+ out.withObjectOutputStream { it ->
+ SerializableFunction<Integer, String> f = (Integer i) -> 'a' + i
it.writeObject(f)
}
- return out.toByteArray()
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize1_InitializeBlock() {
+ void testDeserialize2() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 implements Serializable {
- private static final long serialVersionUID = -1L;
- String a = 'a'
+ class C implements Serializable {
+ private static final long serialVersionUID = -1L
+ String s = 'a'
SerializableFunction<Integer, String> f
{
- f = ((Integer e) -> a + e)
+ f = (Integer i) -> s + i
}
- byte[] p() {
+ byte[] test() {
def out = new ByteArrayOutputStream()
out.withObjectOutputStream {
it.writeObject(f)
}
-
- return out.toByteArray()
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize1_InitializeBlockShouldFail() {
+ void testDeserialize3() {
def err = shouldFail NotSerializableException, '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- String a = 'a'
+ class C {
+ String s = 'a'
SerializableFunction<Integer, String> f
{
- f = ((Integer e) -> a + e)
+ f = (Integer i) -> s + i
}
- byte[] p() {
+ byte[] test() {
def out = new ByteArrayOutputStream()
out.withObjectOutputStream {
it.writeObject(f)
}
-
- return out.toByteArray()
+ out.toByteArray()
}
- static void main(String[] args) {
- new Test1().p()
+ static main(args) {
+ this.newInstance().test()
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
-
- assert err.message.contains('tests.lambda.Test1')
+ assert err.message.contains('tests.lambda.C')
}
@Test
- void testDeserialize2() {
+ void testDeserialize4() {
assertScript '''
- import java.util.function.Function
-
@groovy.transform.CompileStatic
- class Test1 {
- static byte[] p() {
- def out = new ByteArrayOutputStream()
- out.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> 'a' + e)
- it.writeObject(f)
- }
-
- return out.toByteArray()
+ class C {
+ static byte[] test() {
+ def out = new ByteArrayOutputStream()
+ out.withObjectOutputStream { it ->
+ SerializableFunction<Integer, String> f = (Integer i) -> 'a' + i
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(Test1.p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize3() {
+ void testDeserialize5() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- byte[] p() {
- def out = new ByteArrayOutputStream()
- out.withObjectOutputStream {
- String c = 'a'
- SerializableFunction<Integer, String> f = (Integer e) -> c + e
- it.writeObject(f)
- }
-
- return out.toByteArray()
+ class C {
+ byte[] test() {
+ def out = new ByteArrayOutputStream()
+ out.withObjectOutputStream {
+ String s = 'a'
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize4() {
+ void testDeserialize6() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- byte[] p() {
- def out = new ByteArrayOutputStream()
- String c = 'a'
- SerializableFunction<Integer, String> f = (Integer e) -> c + e
- out.withObjectOutputStream {
- it.writeObject(f)
- }
-
- return out.toByteArray()
+ class C {
+ byte[] test() {
+ def out = new ByteArrayOutputStream()
+ String s = 'a'
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
+ out.withObjectOutputStream {
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize5() {
+ void testDeserialize7() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- static byte[] p() {
- def out = new ByteArrayOutputStream()
- String c = 'a'
- SerializableFunction<Integer, String> f = (Integer e) -> c + e
- out.withObjectOutputStream {
- it.writeObject(f)
- }
-
- return out.toByteArray()
+ class C {
+ static byte[] test() {
+ def out = new ByteArrayOutputStream()
+ String s = 'a'
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
+ out.withObjectOutputStream {
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(Test1.p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize6_InstanceFields() {
+ void testDeserialize8() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 implements Serializable {
+ class C implements Serializable {
private static final long serialVersionUID = -1L;
- private String c = 'a'
+ private String s = 'a'
- byte[] p() {
- def out = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f = (Integer e) -> c + e
- out.withObjectOutputStream {
- it.writeObject(f)
- }
-
- return out.toByteArray()
+ byte[] test() {
+ def out = new ByteArrayOutputStream()
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
+ out.withObjectOutputStream {
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize6_InstanceFieldsShouldFail() {
+ void testDeserialize9() {
def err = shouldFail NotSerializableException, '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- private String c = 'a'
-
- byte[] p() {
- def out = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f = (Integer e) -> c + e
- out.withObjectOutputStream {
- it.writeObject(f)
- }
+ class C {
+ private String s = 'a'
- return out.toByteArray()
+ byte[] test() {
+ def out = new ByteArrayOutputStream()
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
+ out.withObjectOutputStream {
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
- assert err.message.contains('tests.lambda.Test1')
+ assert err.message.contains('tests.lambda.C')
}
@Test
- void testDeserialize6_InstanceMethods() {
+ void testDeserialize10() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 implements Serializable {
+ class C implements Serializable {
private static final long serialVersionUID = -1L;
- private String c() { 'a' }
+ private String getS() { 'a' }
- byte[] p() {
+ byte[] test() {
def out = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f = (Integer i) -> c() + i
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
out.withObjectOutputStream {
it.writeObject(f)
}
out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize6_InstanceMethodsShouldFail() {
+ void testDeserialize11() {
def err = shouldFail NotSerializableException, '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- private String c() { 'a' }
+ class C {
+ private String getS() { 'a' }
- byte[] p() {
+ byte[] test() {
def out = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f = (Integer i) -> c() + i
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
out.withObjectOutputStream {
it.writeObject(f)
}
out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(new Test1().p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.newInstance().test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
- assert err.message.contains('tests.lambda.Test1')
+ assert err.message.contains('tests.lambda.C')
}
@Test
- void testDeserialize7_StaticFields() {
+ void testDeserialize12() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- private static final String c = 'a'
- static byte[] p() {
- def out = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f = (Integer e) -> c + e
- out.withObjectOutputStream {
- it.writeObject(f)
- }
-
- return out.toByteArray()
+ class C {
+ private static final String s = 'a'
+ static byte[] test() {
+ def out = new ByteArrayOutputStream()
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
+ out.withObjectOutputStream {
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(Test1.p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@Test
- void testDeserialize7_StaticMethods() {
+ void testDeserialize13() {
assertScript '''
package tests.lambda
- import java.util.function.Function
@groovy.transform.CompileStatic
- class Test1 {
- private static String c() { 'a' }
- static byte[] p() {
- def out = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f = (Integer e) -> c() + e
- out.withObjectOutputStream {
- it.writeObject(f)
- }
-
- return out.toByteArray()
+ class C {
+ private static String getS() { 'a' }
+ static byte[] test() {
+ def out = new ByteArrayOutputStream()
+ SerializableFunction<Integer, String> f = (Integer i) -> s + i
+ out.withObjectOutputStream {
+ it.writeObject(f)
+ }
+ out.toByteArray()
}
- static void main(String[] args) {
- new ByteArrayInputStream(Test1.p()).withObjectInputStream(Test1.class.classLoader) {
+ static main(args) {
+ new ByteArrayInputStream(this.test()).withObjectInputStream(this.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
}
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
}
'''
}
@@ -1695,56 +1672,53 @@ final class LambdaTest {
@Test
void testDeserializeNestedLambda1() {
assertScript '''
- import java.util.function.Function
-
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
@groovy.transform.CompileStatic
- class Test1 {
- def p() {
- def out1 = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f1 = (Integer e) -> 'a' + e
- out1.withObjectOutputStream {
- it.writeObject(f1)
- }
- def result1 = out1.toByteArray()
+ class C {
+ def test() {
+ def out1 = new ByteArrayOutputStream()
+ SerializableFunction<Integer, String> f1 = (Integer i) -> 'a' + i
+ out1.withObjectOutputStream {
+ it.writeObject(f1)
+ }
- def out2 = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f2 = (Integer e) -> 'b' + e
- out2.withObjectOutputStream {
- it.writeObject(f2)
- }
- def result2 = out2.toByteArray()
+ def out2 = new ByteArrayOutputStream()
+ SerializableFunction<Integer, String> f2 = (Integer i) -> 'b' + i
+ out2.withObjectOutputStream {
+ it.writeObject(f2)
+ }
- // nested lambda expression
- def out3 = new ByteArrayOutputStream()
- SerializableFunction<Integer, String> f3 = (Integer e) -> {
- SerializableFunction<Integer, String> nf = ((Integer ne) -> 'n' + ne)
- 'c' + nf(e)
- }
- out3.withObjectOutputStream {
- it.writeObject(f3)
- }
- def result3 = out3.toByteArray()
+ // nested lambda expression
+ def out3 = new ByteArrayOutputStream()
+ SerializableFunction<Integer, String> f3 = (Integer i) -> {
+ SerializableFunction<Integer, String> nf = (Integer j) -> 'c' + j
+ nf(i) + 'c'
+ }
+ out3.withObjectOutputStream {
+ it.writeObject(f3)
+ }
- return [result1, result2, result3]
+ [out1.toByteArray(), out2.toByteArray(), out3.toByteArray()]
}
}
- def (byte[] serializedLambdaBytes1, byte[] serializedLambdaBytes2, byte[] serializedLambdaBytes3) = new Test1().p()
- new ByteArrayInputStream(serializedLambdaBytes1).withObjectInputStream(Test1.class.classLoader) {
+ def (serializedLambdaBytes1, serializedLambdaBytes2, serializedLambdaBytes3) = new C().test()
+
+ new ByteArrayInputStream(serializedLambdaBytes1).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
- new ByteArrayInputStream(serializedLambdaBytes2).withObjectInputStream(Test1.class.classLoader) {
+ new ByteArrayInputStream(serializedLambdaBytes2).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'b1' == f.apply(1)
+ assert f.apply(1) == 'b1'
}
- new ByteArrayInputStream(serializedLambdaBytes3).withObjectInputStream(Test1.class.classLoader) {
+ new ByteArrayInputStream(serializedLambdaBytes3).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'cn1' == f.apply(1)
+ assert f.apply(1) == 'c1c'
}
'''
}
@@ -1752,56 +1726,53 @@ final class LambdaTest {
@Test
void testDeserializeNestedLambda2() {
assertScript '''
- import java.util.function.Function
-
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
@groovy.transform.CompileStatic
- class Test1 {
- def p() {
- def out1 = new ByteArrayOutputStream()
- out1.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> 'a' + e)
- it.writeObject(f)
- }
- def result1 = out1.toByteArray()
+ class C {
+ def test() {
+ def out1 = new ByteArrayOutputStream()
+ out1.withObjectOutputStream {
+ SerializableFunction<Integer, String> f = ((Integer i) -> 'a' + i)
+ it.writeObject(f)
+ }
- def out2 = new ByteArrayOutputStream()
- out2.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> 'b' + e)
- it.writeObject(f)
- }
- def result2 = out2.toByteArray()
-
- // nested lambda expression
- def out3 = new ByteArrayOutputStream()
- out3.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> {
- SerializableFunction<Integer, String> nf = ((Integer ne) -> 'n' + ne)
- 'c' + nf(e)
- })
- it.writeObject(f)
+ def out2 = new ByteArrayOutputStream()
+ out2.withObjectOutputStream {
+ SerializableFunction<Integer, String> f = ((Integer i) -> 'b' + i)
+ it.writeObject(f)
+ }
+
+ // nested lambda expression
+ def out3 = new ByteArrayOutputStream()
+ out3.withObjectOutputStream { it ->
+ SerializableFunction<Integer, String> f = (Integer i) -> {
+ SerializableFunction<Integer, String> nf = (Integer j) -> 'c' + j
+ nf(i) + 'c'
}
- def result3 = out3.toByteArray()
+ it.writeObject(f)
+ }
- return [result1, result2, result3]
+ [out1.toByteArray(), out2.toByteArray(), out3.toByteArray()]
}
}
- def (byte[] serializedLambdaBytes1, byte[] serializedLambdaBytes2, byte[] serializedLambdaBytes3) = new Test1().p()
- new ByteArrayInputStream(serializedLambdaBytes1).withObjectInputStream(Test1.class.classLoader) {
+ def (serializedLambdaBytes1, serializedLambdaBytes2, serializedLambdaBytes3) = new C().test()
+
+ new ByteArrayInputStream(serializedLambdaBytes1).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
- new ByteArrayInputStream(serializedLambdaBytes2).withObjectInputStream(Test1.class.classLoader) {
+ new ByteArrayInputStream(serializedLambdaBytes2).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'b1' == f.apply(1)
+ assert f.apply(1) == 'b1'
}
- new ByteArrayInputStream(serializedLambdaBytes3).withObjectInputStream(Test1.class.classLoader) {
+ new ByteArrayInputStream(serializedLambdaBytes3).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'cn1' == f.apply(1)
+ assert f.apply(1) == 'c1c'
}
'''
}
@@ -1809,56 +1780,53 @@ final class LambdaTest {
@Test
void testDeserializeNestedLambda3() {
assertScript '''
- import java.util.function.Function
-
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
@groovy.transform.CompileStatic
- class Test1 {
- static p() {
- def out1 = new ByteArrayOutputStream()
- out1.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> 'a' + e)
- it.writeObject(f)
- }
- def result1 = out1.toByteArray()
+ class C {
+ static test() {
+ def out1 = new ByteArrayOutputStream()
+ out1.withObjectOutputStream {
+ SerializableFunction<Integer, String> f = ((Integer i) -> 'a' + i)
+ it.writeObject(f)
+ }
- def out2 = new ByteArrayOutputStream()
- out2.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> 'b' + e)
- it.writeObject(f)
- }
- def result2 = out2.toByteArray()
-
- // nested lambda expression
- def out3 = new ByteArrayOutputStream()
- out3.withObjectOutputStream {
- SerializableFunction<Integer, String> f = ((Integer e) -> {
- SerializableFunction<Integer, String> nf = ((Integer ne) -> 'n' + ne)
- 'c' + nf(e)
- })
- it.writeObject(f)
+ def out2 = new ByteArrayOutputStream()
+ out2.withObjectOutputStream {
+ SerializableFunction<Integer, String> f = ((Integer i) -> 'b' + i)
+ it.writeObject(f)
+ }
+
+ // nested lambda expression
+ def out3 = new ByteArrayOutputStream()
+ out3.withObjectOutputStream { it ->
+ SerializableFunction<Integer, String> f = (Integer i) -> {
+ SerializableFunction<Integer, String> nf = (Integer j) -> 'c' + j
+ nf(i) + 'c'
}
- def result3 = out3.toByteArray()
+ it.writeObject(f)
+ }
- return [result1, result2, result3]
+ [out1.toByteArray(), out2.toByteArray(), out3.toByteArray()]
}
}
- def (byte[] serializedLambdaBytes1, byte[] serializedLambdaBytes2, byte[] serializedLambdaBytes3) = Test1.p()
- new ByteArrayInputStream(serializedLambdaBytes1).withObjectInputStream(Test1.class.classLoader) {
+ def (serializedLambdaBytes1, serializedLambdaBytes2, serializedLambdaBytes3) = C.test()
+
+ new ByteArrayInputStream(serializedLambdaBytes1).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'a1' == f.apply(1)
+ assert f.apply(1) == 'a1'
}
- new ByteArrayInputStream(serializedLambdaBytes2).withObjectInputStream(Test1.class.classLoader) {
+ new ByteArrayInputStream(serializedLambdaBytes2).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'b1' == f.apply(1)
+ assert f.apply(1) == 'b1'
}
- new ByteArrayInputStream(serializedLambdaBytes3).withObjectInputStream(Test1.class.classLoader) {
+ new ByteArrayInputStream(serializedLambdaBytes3).withObjectInputStream(this.class.classLoader) {
SerializableFunction<Integer, String> f = (SerializableFunction<Integer, String>) it.readObject()
- assert 'cn1' == f.apply(1)
+ assert f.apply(1) == 'c1c'
}
'''
}
@@ -1866,9 +1834,8 @@ final class LambdaTest {
@Test
void testDeserializeNestedLambda4() {
assertScript '''
- import java.util.function.Function
-
- interface SerializableFunction<T, R> extends Function<T, R>, Serializable {}
+ interface SerializableFunction<I,O> extends Serializable, java.util.function.Function<I,O> {
+ }
@groovy.transform.CompileStatic
class C {