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/08/18 20:01:56 UTC
[groovy] branch GROOVY_3_0_X updated: GROOVY-7247: STC: support spread-map expression
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 c660480dc0 GROOVY-7247: STC: support spread-map expression
c660480dc0 is described below
commit c660480dc0b88815be5171b2ce76936fe1410f96
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 18 14:06:53 2022 -0500
GROOVY-7247: STC: support spread-map expression
---
.../transform/stc/StaticTypeCheckingVisitor.java | 22 +++++++++----
.../transform/stc/TypeInferenceSTCTest.groovy | 36 ++++++++++++++++++++--
2 files changed, 50 insertions(+), 8 deletions(-)
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 532457bbe4..7bf168fae1 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -79,6 +79,7 @@ import org.codehaus.groovy.ast.expr.PrefixExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.RangeExpression;
import org.codehaus.groovy.ast.expr.SpreadExpression;
+import org.codehaus.groovy.ast.expr.SpreadMapExpression;
import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
import org.codehaus.groovy.ast.expr.TernaryExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
@@ -5200,16 +5201,25 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (genericsTypes == null
|| genericsTypes.length < 2
|| (genericsTypes.length == 2 && OBJECT_TYPE.equals(genericsTypes[0].getType()) && OBJECT_TYPE.equals(genericsTypes[1].getType()))) {
+ ClassNode keyType;
+ ClassNode valueType;
List<ClassNode> keyTypes = new ArrayList<>(nExpressions);
List<ClassNode> valueTypes = new ArrayList<>(nExpressions);
for (MapEntryExpression entryExpression : entryExpressions) {
- keyTypes.add(getType(entryExpression.getKeyExpression()));
- valueTypes.add(getType(entryExpression.getValueExpression()));
- }
- ClassNode keyType = lowestUpperBound(keyTypes);
- ClassNode valueType = lowestUpperBound(valueTypes);
+ valueType = getType(entryExpression.getValueExpression());
+ if (!(entryExpression.getKeyExpression() instanceof SpreadMapExpression)) {
+ keyType = getType(entryExpression.getKeyExpression());
+ } else { // GROOVY-7247
+ valueType = GenericsUtils.parameterizeType(valueType, MAP_TYPE);
+ keyType = getCombinedBoundType(valueType.getGenericsTypes()[0]);
+ valueType = getCombinedBoundType(valueType.getGenericsTypes()[1]);
+ }
+ keyTypes.add(keyType);
+ valueTypes.add(valueType);
+ }
+ keyType = lowestUpperBound(keyTypes);
+ valueType = lowestUpperBound(valueTypes);
if (!OBJECT_TYPE.equals(keyType) || !OBJECT_TYPE.equals(valueType)) {
- mapType = mapType.getPlainNodeReference();
mapType.setGenericsTypes(new GenericsType[]{new GenericsType(wrapTypeIfNecessary(keyType)), new GenericsType(wrapTypeIfNecessary(valueType))});
}
}
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index 02113fe08f..eec1cddce0 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -813,7 +813,8 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages '''
List values = [x:1,y:2,z:3]*.value
values*.toUpperCase()
- ''', 'Cannot find matching method java.lang.Integer#toUpperCase()'
+ ''',
+ 'Cannot find matching method java.lang.Integer#toUpperCase()'
}
void testStarOperatorOnMap3() {
@@ -827,7 +828,38 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages '''
def values = [x:1,y:2,z:3]*.value
values*.toUpperCase()
- ''', 'Cannot find matching method java.lang.Integer#toUpperCase()'
+ ''',
+ 'Cannot find matching method java.lang.Integer#toUpperCase()'
+ }
+
+ // GROOVY-7247
+ void testStarOperatorOnMapKey() {
+ assertScript '''
+ Map<String, Integer> map = [*:[A:1], *:[B:2]]
+ assert map == [A:1, B:2]
+ '''
+
+ assertScript '''
+ Map<String, Integer> one = [A:1]
+ Map<String, Integer> two = [B:2]
+ def map = [*:one, *:two]
+ assert map == [A:1, B:2]
+ '''
+
+ assertScript '''
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def type = node.getNodeMetaData(INFERRED_TYPE)
+ assert type.genericsTypes[0].type == STRING_TYPE
+ assert type.genericsTypes[1].type != Integer_TYPE
+ assert type.genericsTypes[1].type.isDerivedFrom(Number_TYPE)
+ })
+ def map = [*:[A:1], *:[B:2.3]]
+ '''
+
+ shouldFailWithMessages '''
+ Map<String, Integer> map = [*:[A:1], *:[B:2.3]]
+ ''',
+ 'Cannot assign java.util.LinkedHashMap <java.lang.String, java.lang.Number> to: java.util.Map <String, Integer>'
}
void testFlowTypingWithStringVariable() {