Skip to content

Commit bcb5639

Browse files
committed
GROOVY-10325
1 parent c66e026 commit bcb5639

File tree

4 files changed

+54
-12
lines changed

4 files changed

+54
-12
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java

+23
Original file line numberDiff line numberDiff line change
@@ -4183,4 +4183,27 @@ public void testTypeChecked10320() {
41834183

41844184
runConformTest(sources, "3.3");
41854185
}
4186+
4187+
@Test
4188+
public void testTypeChecked10325() {
4189+
//@formatter:off
4190+
String[] sources = {
4191+
"Main.groovy",
4192+
"@groovy.transform.TypeChecked\n" +
4193+
"void test(Map<String,Object> map) {\n" +
4194+
" @groovy.transform.ASTTest(phase=INSTRUCTION_SELECTION, value={\n" +
4195+
" def type = node.getNodeMetaData(org.codehaus.groovy.transform.stc.StaticTypesMarker.INFERRED_TYPE)\n" +
4196+
" assert type.toString(false) == 'java.util.List<java.lang.Object>'\n" + // should not change
4197+
" })\n" +
4198+
" def values = map*.value\n" +
4199+
" map.entrySet()[0].value = 'baz'\n" +
4200+
" map*.value = 'baz!'\n" + // Cannot assign java.util.List<java.lang.String> to: java.util.List<java.lang.Object>
4201+
" print map\n" +
4202+
"}\n" +
4203+
"test(foo:'bar')\n",
4204+
};
4205+
//@formatter:on
4206+
4207+
runConformTest(sources, "[foo:baz!]");
4208+
}
41864209
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+8
Original file line numberDiff line numberDiff line change
@@ -2105,9 +2105,17 @@ private ClassNode getTypeForMapPropertyExpression(ClassNode testClass, ClassNode
21052105
listKey.setGenericsTypes(new GenericsType[]{types[0]});
21062106
return listKey;
21072107
} else if ("value".equals(pexp.getPropertyAsString())) {
2108+
/* GRECLIPSE edit -- GROOVY-10325
21082109
ClassNode listValue = LIST_TYPE.getPlainNodeReference();
21092110
listValue.setGenericsTypes(new GenericsType[]{types[1]});
21102111
return listValue;
2112+
*/
2113+
GenericsType v = types[1];
2114+
if (!v.isWildcard() && !Modifier.isFinal(v.getType().getModifiers()) && isLHSOfEnclosingAssignment(pexp)) {
2115+
v = GenericsUtils.buildWildcardType(v.getType());
2116+
}
2117+
return GenericsUtils.makeClassSafe0(LIST_TYPE, v);
2118+
// GRECLIPSE end
21112119
} else {
21122120
addStaticTypeError("Spread operator on map only allows one of [key,value]", pexp);
21132121
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+10
Original file line numberDiff line numberDiff line change
@@ -1982,9 +1982,19 @@ private ClassNode getTypeForMapPropertyExpression(final ClassNode testClass, fin
19821982
keyList.setGenericsTypes(new GenericsType[]{gts[0]});
19831983
return keyList;
19841984
case "value":
1985+
/* GRECLIPSE edit
19851986
ClassNode valueList = LIST_TYPE.getPlainNodeReference();
19861987
valueList.setGenericsTypes(new GenericsType[]{gts[1]});
19871988
return valueList;
1989+
*/
1990+
GenericsType v = gts[1];
1991+
if (!v.isWildcard()
1992+
&& !Modifier.isFinal(v.getType().getModifiers())
1993+
&& typeCheckingContext.isTargetOfEnclosingAssignment(pexp)) {
1994+
v = GenericsUtils.buildWildcardType(v.getType()); // GROOVY-10325
1995+
}
1996+
return GenericsUtils.makeClassSafe0(LIST_TYPE, v);
1997+
// GRECLIPSE end
19881998
default:
19891999
addStaticTypeError("Spread operator on map only allows one of [key,value]", pexp);
19902000
}

base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+13-12
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@
220220
import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
221221
import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
222222
import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
223+
import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafe0;
223224
import static org.codehaus.groovy.ast.tools.WideningCategories.isBigDecCategory;
224225
import static org.codehaus.groovy.ast.tools.WideningCategories.isBigIntCategory;
225226
import static org.codehaus.groovy.ast.tools.WideningCategories.isDouble;
@@ -1204,14 +1205,12 @@ private boolean typeCheckMultipleAssignmentAndContinue(final Expression leftExpr
12041205
return true;
12051206
}
12061207

1207-
private ClassNode adjustTypeForSpreading(final ClassNode inferredRightExpressionType, final Expression leftExpression) {
1208-
// imagine we have: list*.foo = 100
1209-
// then the assignment must be checked against [100], not 100
1210-
ClassNode wrappedRHS = inferredRightExpressionType;
1208+
private ClassNode adjustTypeForSpreading(final ClassNode rightExpressionType, final Expression leftExpression) {
1209+
// given "list*.foo = 100" or "map*.value = 100", then the assignment must be checked against [100], not 100
12111210
if (leftExpression instanceof PropertyExpression && ((PropertyExpression) leftExpression).isSpreadSafe()) {
1212-
wrappedRHS = extension.buildListType(inferredRightExpressionType);
1211+
return extension.buildListType(rightExpressionType);
12131212
}
1214-
return wrappedRHS;
1213+
return rightExpressionType;
12151214
}
12161215

12171216
private boolean addedReadOnlyPropertyError(final Expression expr) {
@@ -1789,13 +1788,15 @@ private ClassNode getTypeForMapPropertyExpression(final ClassNode testClass, fin
17891788
// map*.property syntax acts on Entry
17901789
switch (pexp.getPropertyAsString()) {
17911790
case "key":
1792-
ClassNode keyList = LIST_TYPE.getPlainNodeReference();
1793-
keyList.setGenericsTypes(new GenericsType[]{gts[0]});
1794-
return keyList;
1791+
return makeClassSafe0(LIST_TYPE, gts[0]);
17951792
case "value":
1796-
ClassNode valueList = LIST_TYPE.getPlainNodeReference();
1797-
valueList.setGenericsTypes(new GenericsType[]{gts[1]});
1798-
return valueList;
1793+
GenericsType v = gts[1];
1794+
if (!v.isWildcard()
1795+
&& !Modifier.isFinal(v.getType().getModifiers())
1796+
&& typeCheckingContext.isTargetOfEnclosingAssignment(pexp)) {
1797+
v = GenericsUtils.buildWildcardType(v.getType()); // GROOVY-10325
1798+
}
1799+
return makeClassSafe0(LIST_TYPE, v);
17991800
default:
18001801
addStaticTypeError("Spread operator on map only allows one of [key,value]", pexp);
18011802
}

0 commit comments

Comments
 (0)