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 0fab7e01949..988cd5d6e8c 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -1641,7 +1641,10 @@ else if (field != null && enclosingTypes.contains(current) && storeField(field, foundGetterOrSetter = (foundGetterOrSetter || getter != null || !setters.isEmpty()); } - if (readMode && !isMapProperty(pexp, receiverType)) { // GROOVY-11369, GROOVY-11370, GROOVY-11372 + // GROOVY-11369, GROOVY-11370, GROOVY-11372, GROOVY-11401: map entry + if (isMapProperty(pexp, receiverType)) break; + + if (readMode) { // GROOVY-5568, GROOVY-9115, GROOVY-9123: the property may be provided by an extension method for (ClassNode dgmReceiver : isPrimitiveType(receiverType) ? new ClassNode[]{receiverType, getWrapper(receiverType)} : new ClassNode[]{receiverType}) { Set methods = findDGMMethodsForClassNode(getSourceUnit().getClassLoader(), dgmReceiver, getterName); @@ -1669,7 +1672,7 @@ else if (field != null && enclosingTypes.contains(current) && storeField(field, } } - // GROOVY-7996: check if receiver implements get(String)/set(String,Object) or propertyMissing(String) or $static_propertyMissing(String)? + // GROOVY-7996: check if receiver implements get(String)/set(String,Object) or propertyMissing(String) if (!receiverType.isArray() && !isPrimitiveType(getUnwrapper(receiverType)) && pexp.isImplicitThis() && typeCheckingContext.getEnclosingClosure() != null) { MethodNode mopMethod; diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy index 03b4e72ff65..89890ba6840 100644 --- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy +++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy @@ -1037,6 +1037,25 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { ''' } + // GROOVY-11401 + void testMapPropertyAccess13() { + assertScript ''' + class C { + private Object obj = 'field' + def m() { + Map map = [:].withDefault{'entry'} + map.with { + @ASTTest(phase=INSTRUCTION_SELECTION, value={ + assert node.getNodeMetaData(INFERRED_TYPE) == STRING_TYPE + }) + def xxx = obj + } + } + } + assert new C().m() == 'entry' + ''' + } + void testTypeCheckerDoesNotThinkPropertyIsReadOnly() { assertScript ''' // a base class defining a read-only property