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 2023/05/18 15:13:36 UTC
[groovy] branch master updated: GROOVY-10067, GROOVY-11057: better `parameterizeType` result
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 8c9e150087 GROOVY-10067, GROOVY-11057: better `parameterizeType` result
8c9e150087 is described below
commit 8c9e150087484d858e262bd0a5ade5de681d50c4
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu May 18 10:09:12 2023 -0500
GROOVY-10067, GROOVY-11057: better `parameterizeType` result
---
.../codehaus/groovy/ast/tools/GenericsUtils.java | 18 +++---
.../transform/stc/StaticTypeCheckingVisitor.java | 16 ++---
.../groovy/ast/tools/GenericsUtilsTest.groovy | 74 ++++++++++++++++++----
3 files changed, 81 insertions(+), 27 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 7b87a7aca1..1572c25915 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -442,11 +442,14 @@ public class GenericsUtils {
return makeClassSafeWithGenerics(type, newgTypes);
}
- public static ClassNode correctToGenericsSpec(Map<String, ClassNode> genericsSpec, GenericsType type) {
- ClassNode cn = null; String name = type.getName();
- if (type.isPlaceholder() && name.charAt(0) != '#') {
- cn = genericsSpec.get(name);
- } else if (type.isWildcard()) {
+ public static ClassNode correctToGenericsSpec(final Map<String, ClassNode> genericsSpec, final GenericsType type) {
+ ClassNode cn = null;
+ if (type.isPlaceholder()) {
+ String name = type.getName();
+ if (name.charAt(0) != '#') //
+ cn = genericsSpec.get(name);
+ }
+ else if (type.isWildcard()) {
if (type.getUpperBounds() != null)
cn = type.getUpperBounds()[0]; // GROOVY-9891
}
@@ -456,7 +459,7 @@ public class GenericsUtils {
return cn;
}
- public static ClassNode correctToGenericsSpec(Map<String, ClassNode> genericsSpec, ClassNode type) {
+ public static ClassNode correctToGenericsSpec(final Map<String, ClassNode> genericsSpec, ClassNode type) {
if (type.isArray()) {
return correctToGenericsSpec(genericsSpec, type.getComponentType()).makeArray();
}
@@ -468,8 +471,7 @@ public class GenericsUtils {
return correctToGenericsSpec(genericsSpec, type);
}
}
- if (type == null) type = ClassHelper.OBJECT_TYPE.getPlainNodeReference();
- return type;
+ return type != null ? type : ClassHelper.OBJECT_TYPE.getPlainNodeReference();
}
public static Map<String, ClassNode> createGenericsSpec(final ClassNode type) {
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index b63f6d9721..825bc16ea8 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -5446,14 +5446,14 @@ out: if (mn.size() != 1) {
for (GenericsType gt : methodGenericTypes) {
// GROOVY-8409, GROOVY-10067, et al.: provide "no type witness" mapping for param
resolvedPlaceholders.computeIfAbsent(new GenericsTypeName(gt.getName()), gtn -> {
- GenericsType xxx = new GenericsType(ClassHelper.makeWithoutCaching("#"),
- applyGenericsContext(resolvedPlaceholders, gt.getUpperBounds()),
- applyGenericsContext(resolvedPlaceholders, gt.getLowerBound()));
- xxx.getType().setRedirect(getCombinedBoundType(gt));
- xxx.putNodeMetaData(GenericsType.class, gt);
- xxx.setName("#" + gt.getName());
- xxx.setPlaceholder(true);
- return xxx;
+ ClassNode hash = ClassHelper.makeWithoutCaching("#" + gt.getName());
+ hash.setRedirect(getCombinedBoundType(gt));
+ hash.setGenericsPlaceHolder(true);
+
+ GenericsType gtx = new GenericsType(hash, applyGenericsContext(resolvedPlaceholders, gt.getUpperBounds()), null);
+ gtx.putNodeMetaData(GenericsType.class, gt);
+ gtx.setResolved(true);
+ return gtx;
});
}
diff --git a/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy b/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
index 3c72244f59..a1ef582a85 100644
--- a/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
+++ b/src/test/org/codehaus/groovy/ast/tools/GenericsUtilsTest.groovy
@@ -23,17 +23,18 @@ import org.codehaus.groovy.ast.ClassHelper
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.GenericsType
import org.codehaus.groovy.control.CompilePhase
+import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor
import org.junit.Test
final class GenericsUtilsTest {
private static List<ClassNode> compile(String code) {
def compiler = new org.codehaus.groovy.ast.builder.AstStringCompiler()
- compiler.compile(code, CompilePhase.SEMANTIC_ANALYSIS, false).tail()
+ compiler.compile(code, CompilePhase.INSTRUCTION_SELECTION, false).tail()
}
- private static ClassNode findClassNode(String name, List<ClassNode> list) {
- list.find { it.name == name }
+ private static ClassNode findClassNode(String name, classNodes) {
+ classNodes.find { it.name == name }
}
//--------------------------------------------------------------------------
@@ -177,7 +178,8 @@ final class GenericsUtilsTest {
assert result.redirect() === target
}
- @Test // GROOVY-9945
+ // GROOVY-9945
+ @Test
void testFindParameterizedType8() {
def classNodeList = compile '''
interface I<T> {}
@@ -198,7 +200,7 @@ final class GenericsUtilsTest {
import java.util.function.*
interface Derived extends BinaryOperator<Integer> {}
'''
- ClassNode target = ClassHelper.makeWithoutCaching(java.util.function.BiFunction.class)
+ ClassNode target = ClassHelper.makeWithoutCaching(java.util.function.BiFunction)
ClassNode source = findClassNode('Derived', classNodeList)
Map<GenericsType, GenericsType> m = GenericsUtils.makeDeclaringAndActualGenericsTypeMapOfExactType(target, source)
@@ -249,7 +251,7 @@ final class GenericsUtilsTest {
import java.util.function.*
interface T extends Function<String, Integer> {}
'''
- ClassNode samType = findClassNode('T', classNodeList).interfaces.find { it.name == 'java.util.function.Function' }
+ ClassNode samType = findClassNode('java.util.function.Function', findClassNode('T', classNodeList).interfaces)
def typeInfo = GenericsUtils.parameterizeSAM(samType)
@@ -265,7 +267,7 @@ final class GenericsUtilsTest {
import java.util.function.*
interface T extends BinaryOperator<Integer> {}
'''
- ClassNode samType = findClassNode('T', classNodeList).interfaces.find { it.name == 'java.util.function.BinaryOperator' }
+ ClassNode samType = findClassNode('java.util.function.BinaryOperator', findClassNode('T', classNodeList).interfaces)
def typeInfo = GenericsUtils.parameterizeSAM(samType)
@@ -276,13 +278,14 @@ final class GenericsUtilsTest {
assert typeInfo.v2 == ClassHelper.Integer_TYPE
}
- @Test // GROOVY-10813
+ // GROOVY-10813
+ @Test
void testParameterizeSAMWithRawType() {
def classNodeList = compile '''
interface I extends java.util.function.BinaryOperator {
}
'''
- ClassNode samType = findClassNode('I', classNodeList).interfaces.find { it.name == 'java.util.function.BinaryOperator' }
+ ClassNode samType = findClassNode('java.util.function.BinaryOperator', findClassNode('I', classNodeList).interfaces)
def typeInfo = GenericsUtils.parameterizeSAM(samType)
@@ -302,7 +305,7 @@ final class GenericsUtilsTest {
abstract class A implements I {
}
'''
- ClassNode samType = findClassNode('A', classNodeList).interfaces.find { it.name == 'I' }
+ ClassNode samType = findClassNode('I', findClassNode('A', classNodeList).interfaces)
def typeInfo = GenericsUtils.parameterizeSAM(samType)
@@ -321,7 +324,7 @@ final class GenericsUtilsTest {
abstract class A implements I {
}
'''
- ClassNode samType = findClassNode('A', classNodeList).interfaces.find { it.name == 'I' }
+ ClassNode samType = findClassNode('I', findClassNode('A', classNodeList).interfaces)
def typeInfo = GenericsUtils.parameterizeSAM(samType)
@@ -330,4 +333,53 @@ final class GenericsUtilsTest {
assert typeInfo.v2.toString(false) == 'java.lang.CharSequence'
}
+
+ // GROOVY-10067, GROOVY-11057
+ @Test
+ void testParameterizeType1() {
+ def classNodeList = compile '''
+ @groovy.transform.CompileStatic
+ void test() {
+ def map = [:]
+ }
+ '''
+ // get the intermediate type of the map literal (LinkedHashMap<#K,#V>)
+ def node = classNodeList[0].getDeclaredMethod('test').code.statements[0]
+ def type = new StaticTypeCheckingVisitor(classNodeList[0].module.context,
+ classNodeList[0]).getType(node.expression.rightExpression)
+
+ ClassNode mapType = GenericsUtils.parameterizeType(type, ClassHelper.MAP_TYPE)
+
+ assert mapType == ClassHelper.MAP_TYPE
+ assert mapType.genericsTypes.length == 2
+ assert mapType.genericsTypes[0].name == '#K'
+ assert mapType.genericsTypes[1].name == '#V'
+ assert mapType.genericsTypes[0].type.unresolvedName == '#K'
+ assert mapType.genericsTypes[1].type.unresolvedName == '#V'
+ assert mapType.genericsTypes[0].type.name == 'java.lang.Object'
+ assert mapType.genericsTypes[1].type.name == 'java.lang.Object'
+ }
+
+ // GROOVY-10067, GROOVY-11057
+ @Test
+ void testParameterizeType2() {
+ def classNodeList = compile '''
+ @groovy.transform.CompileStatic
+ void test() {
+ def list = []
+ }
+ '''
+ // get the intermediate type of the list literal (ArrayList<#E>)
+ def node = classNodeList[0].getDeclaredMethod('test').code.statements[0]
+ def type = new StaticTypeCheckingVisitor(classNodeList[0].module.context,
+ classNodeList[0]).getType(node.expression.rightExpression)
+
+ ClassNode listType = GenericsUtils.parameterizeType(type, ClassHelper.LIST_TYPE)
+
+ assert listType == ClassHelper.LIST_TYPE
+ assert listType.genericsTypes.length == 1
+ assert listType.genericsTypes[0].name == '#E'
+ assert listType.genericsTypes[0].type.unresolvedName == '#E'
+ assert listType.genericsTypes[0].type.name == 'java.lang.Object'
+ }
}