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 0c08d52ee2 GROOVY-11387: STC: entry before field for outside map 
property reference
0c08d52ee2 is described below

commit 0c08d52ee2fcd820e197a49d3e531dd8ace1d464
Author: Eric Milles <[email protected]>
AuthorDate: Tue May 28 11:28:19 2024 -0500

    GROOVY-11387: STC: entry before field for outside map property reference
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 19 +++++++++++++------
 .../stc/FieldsAndPropertiesSTCTest.groovy          | 22 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 6 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 bf9d94ee49..f09578e068 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1562,11 +1562,16 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
                     continue;
                 }
 
-                // skip property/accessor checks for "field", "this.field", 
"this.with { field }", etc. in declaring class of field
-                if (field != null && enclosingTypes.contains(current)) {
-                    if (storeField(field, pexp, receiverType, visitor, 
receiver.getData(), !readMode)) {
-                        return true;
-                    }
+                if (field != null // GROOVY-11387: entry before field for 
indirect or non-this property expressions
+                        && (!receiverType.equals(field.getDeclaringClass()) || 
!(isThisExpression(objectExpression)
+                            && !(pexp.isImplicitThis() && 
typeCheckingContext.getEnclosingClosure() != null)))
+                        && (readMode || !(field.isPublic() || 
field.isProtected()))
+                        && isMapProperty(pexp, receiverType)) {
+                    field = null;
+                }
+                // skip property/accessor checks for "field", "this.field", 
"this.with { field }", etc. within the declaring class of the field
+                else if (field != null && enclosingTypes.contains(current) && 
storeField(field, pexp, receiverType, visitor, receiver.getData(), !readMode)) {
+                    return true;
                 }
 
                 PropertyNode property = current.getProperty(propertyName);
@@ -1584,7 +1589,7 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
                         visitor.visitMethod(getter);
                     }
                 } else if (readMode) { // GROOVY-5001, GROOVY-5491, GROOVY-8555
-                    if (property != null) { property = null; field = null; }
+                    if (property != null) { property = null; assert field == 
null; }
                 }
 
                 // prefer explicit getter or setter over property if receiver 
is not 'this'
@@ -1772,6 +1777,8 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
             };
 
             if (!pexp.isSpreadSafe()) {
+                if (pexp.isImplicitThis() && 
isThisExpression(pexp.getObjectExpression()))
+                    pexp.putNodeMetaData(DYNAMIC_RESOLUTION,Boolean.TRUE); // 
GROOVY-11387
                 return getCombinedBoundType(gts[1]);
             } else {
                 // map*.property syntax acts on Entry
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy 
b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 9da6508290..cea091f780 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -970,6 +970,28 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-11387
+    void testMapPropertyAccess12() {
+        assertScript '''
+            def map = new HashMap<String,String>()
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                assert node.getNodeMetaData(INFERRED_TYPE) == STRING_TYPE
+            })
+            def xxx = map.table
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                assert node.getNodeMetaData(INFERRED_TYPE) == STRING_TYPE
+            })
+            def yyy = map.with{
+                @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                    assert node.getNodeMetaData(INFERRED_TYPE) == STRING_TYPE
+                })
+                def zzz = table
+            }
+            assert xxx == null
+            assert yyy == null
+        '''
+    }
+
     void testTypeCheckerDoesNotThinkPropertyIsReadOnly() {
         assertScript '''
             // a base class defining a read-only property

Reply via email to