Skip to content

Commit

Permalink
GROOVY-10326
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Oct 23, 2021
1 parent bcb5639 commit 323bf18
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4206,4 +4206,26 @@ public void testTypeChecked10325() {

runConformTest(sources, "[foo:baz!]");
}

@Test
public void testTypeChecked10326() {
//@formatter:off
String[] sources = {
"Main.groovy",
"@groovy.transform.TypeChecked\n" +
"@SuppressWarnings('rawtypes')\n" +
"void test(Map map) {\n" +
" map*.key = null\n" +
"}\n",
};
//@formatter:on

runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 4)\n" +
"\tmap*.key = null\n" +
"\t^^^^^^^^" + (isParrotParser() ? "" : "^") + "\n" +
"Groovy:[Static type checking] - Cannot set read-only property: key\n" +
"----------\n");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2095,12 +2095,20 @@ private ClassNode getTypeForMapPropertyExpression(ClassNode testClass, ClassNode
// GRECLIPSE end
// 0 is the key, 1 is the value
GenericsType[] types = intf.getGenericsTypes();
/* GRECLIPSE edit -- GROOVY-10326
if (types == null || types.length != 2) return OBJECT_TYPE;

*/
if (types == null || types.length != 2) types = new GenericsType[] {
OBJECT_TYPE.asGenericsType(), OBJECT_TYPE.asGenericsType()
};
// GRECLIPSE end
if (pexp.isSpreadSafe()) {
// map*.property syntax
// only "key" and "value" are allowed
if ("key".equals(pexp.getPropertyAsString())) {
// GRECLIPSE add -- GROOVY-10326
pexp.putNodeMetaData(StaticTypesMarker.READONLY_PROPERTY, Boolean.TRUE);
// GRECLIPSE end
ClassNode listKey = LIST_TYPE.getPlainNodeReference();
listKey.setGenericsTypes(new GenericsType[]{types[0]});
return listKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1969,15 +1969,20 @@ private ClassNode getTypeForMapPropertyExpression(final ClassNode testClass, fin
if (isOrImplements(testClass, MAP_TYPE)) {
ClassNode mapType = testClass.equals(MAP_TYPE) ? testClass
: GenericsUtils.parameterizeType(testClass, MAP_TYPE);
GenericsType[] gts = mapType.getGenericsTypes();//<K,V>
if (gts == null || gts.length != 2) return OBJECT_TYPE;
GenericsType[] gts = mapType.getGenericsTypes();//<K,V> params
if (gts == null || gts.length != 2) gts = new GenericsType[] {
OBJECT_TYPE.asGenericsType(), OBJECT_TYPE.asGenericsType()
};

if (!pexp.isSpreadSafe()) {
return getCombinedBoundType(gts[1]);
} else {
// map*.property syntax acts on Entry
switch (pexp.getPropertyAsString()) {
case "key":
// GRECLIPSE add -- GROOVY-10326
pexp.putNodeMetaData(READONLY_PROPERTY, Boolean.TRUE);
// GRECLIPSE end
ClassNode keyList = LIST_TYPE.getPlainNodeReference();
keyList.setGenericsTypes(new GenericsType[]{gts[0]});
return keyList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1779,15 +1779,18 @@ private ClassNode getTypeForMapPropertyExpression(final ClassNode testClass, fin
if (isOrImplements(testClass, MAP_TYPE)) {
ClassNode mapType = testClass.equals(MAP_TYPE) ? testClass
: GenericsUtils.parameterizeType(testClass, MAP_TYPE);
GenericsType[] gts = mapType.getGenericsTypes();//<K,V>
if (gts == null || gts.length != 2) return OBJECT_TYPE;
GenericsType[] gts = mapType.getGenericsTypes();//<K,V> params
if (gts == null || gts.length != 2) gts = new GenericsType[] {
OBJECT_TYPE.asGenericsType(), OBJECT_TYPE.asGenericsType()
};

if (!pexp.isSpreadSafe()) {
return getCombinedBoundType(gts[1]);
} else {
// map*.property syntax acts on Entry
switch (pexp.getPropertyAsString()) {
case "key":
pexp.putNodeMetaData(READONLY_PROPERTY,Boolean.TRUE); // GROOVY-10326
return makeClassSafe0(LIST_TYPE, gts[0]);
case "value":
GenericsType v = gts[1];
Expand Down

0 comments on commit 323bf18

Please sign in to comment.