From 323bf1817e78f10f2da17b453adccdb993574504 Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Sat, 23 Oct 2021 12:54:47 -0500 Subject: [PATCH] GROOVY-10326 --- .../core/tests/xform/TypeCheckedTests.java | 22 +++++++++++++++++++ .../stc/StaticTypeCheckingVisitor.java | 10 ++++++++- .../stc/StaticTypeCheckingVisitor.java | 9 ++++++-- .../stc/StaticTypeCheckingVisitor.java | 7 ++++-- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java index b012107659..1631780b17 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java @@ -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"); + } } diff --git a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 54bcae3203..1e911532c1 100644 --- a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -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; diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 6ef7c37d69..465cdefeaf 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -1969,8 +1969,10 @@ 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();// - if (gts == null || gts.length != 2) return OBJECT_TYPE; + GenericsType[] gts = mapType.getGenericsTypes();// params + if (gts == null || gts.length != 2) gts = new GenericsType[] { + OBJECT_TYPE.asGenericsType(), OBJECT_TYPE.asGenericsType() + }; if (!pexp.isSpreadSafe()) { return getCombinedBoundType(gts[1]); @@ -1978,6 +1980,9 @@ private ClassNode getTypeForMapPropertyExpression(final ClassNode testClass, fin // 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; diff --git a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 93b87ef407..1f68165aaf 100644 --- a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -1779,8 +1779,10 @@ 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();// - if (gts == null || gts.length != 2) return OBJECT_TYPE; + GenericsType[] gts = mapType.getGenericsTypes();// params + if (gts == null || gts.length != 2) gts = new GenericsType[] { + OBJECT_TYPE.asGenericsType(), OBJECT_TYPE.asGenericsType() + }; if (!pexp.isSpreadSafe()) { return getCombinedBoundType(gts[1]); @@ -1788,6 +1790,7 @@ private ClassNode getTypeForMapPropertyExpression(final ClassNode testClass, fin // 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];