This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new ba984b19e5 GROOVY-11387: STC: class field or property of map-based type
ba984b19e5 is described below

commit ba984b19e5dc5d7ddf6aae6e15f1be8e259b1781
Author: Eric Milles <[email protected]>
AuthorDate: Thu May 30 15:39:40 2024 -0500

    GROOVY-11387: STC: class field or property of map-based type
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 42 +++++++++++-----------
 .../stc/FieldsAndPropertiesSTCTest.groovy          | 10 ++++++
 2 files changed, 32 insertions(+), 20 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 3bdec7150f..2e637cf1d5 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1656,7 +1656,7 @@ out:    if ((samParameterTypes.length == 1 && 
isOrImplements(samParameterTypes[0
                     continue;
                 }
 
-                if (field != null && !(field.isPublic() || 
(field.isProtected() && !readMode)) // GROOVY-11387: map entry before 
non-public field
+                if (field != null && !staticOnly && !(field.isPublic() || 
(field.isProtected() && !readMode)) // GROOVY-11387: entry before field
                         && !(isThisExpression(objectExpression) && 
(!pexp.isImplicitThis() || typeCheckingContext.getEnclosingClosure() == null))
                         && isOrImplements(receiverType, MAP_TYPE)) {
                     field = null;
@@ -1677,6 +1677,7 @@ out:    if ((samParameterTypes.length == 1 && 
isOrImplements(samParameterTypes[0
                         && 
(!hasAccessToMember(typeCheckingContext.getEnclosingClassNode(), 
getter.getDeclaringClass(), getter.getModifiers())
                         // GROOVY-11369:
                         || (isOrImplements(receiverType, MAP_TYPE)
+                            && !staticOnly // GROOVY-10387: Map.foo
                             && !isSuperExpression(objectExpression)
                             && !(isThisExpression(objectExpression) && 
(!pexp.isImplicitThis() || typeCheckingContext.getEnclosingClosure() == null)) 
// GROOVY-11384
                             && (!getter.isPublic() || 
(propertyName.matches("empty|class|metaClass") && 
!List.of(getTypeCheckingAnnotations()).contains(COMPILESTATIC_CLASSNODE)))))) {
@@ -1791,25 +1792,26 @@ out:    if ((samParameterTypes.length == 1 && 
isOrImplements(samParameterTypes[0
             }
         }
 
-        for (Receiver<String> receiver : receivers) {
-            ClassNode receiverType = receiver.getType();
-            ClassNode propertyType = 
getTypeForMapPropertyExpression(receiverType, pexp);
-            if (propertyType == null)
-                propertyType = getTypeForListPropertyExpression(receiverType, 
pexp);
-            if (propertyType == null)
-                propertyType = getTypeForSpreadExpression(receiverType, pexp);
-            if (propertyType == null)
-                continue;
-            if (visitor != null) {
-                // TODO: type inference on maps and lists, if possible
-                PropertyNode node = new PropertyNode(propertyName, 
Opcodes.ACC_PUBLIC, propertyType, receiver.getType(), null, null, null);
-                node.setDeclaringClass(receiver.getType());
-                visitor.visitProperty(node);
-            }
-            storeType(pexp, propertyType);
-            String delegationData = receiver.getData();
-            if (delegationData != null) 
pexp.putNodeMetaData(IMPLICIT_RECEIVER, delegationData);
-            return true;
+        if (pexp.isImplicitThis() || !staticOnlyAccess) {
+            for (Receiver<String> receiver : receivers) {
+                ClassNode receiverType = receiver.getType();
+                ClassNode propertyType = 
getTypeForMapPropertyExpression(receiverType, pexp);
+                if (propertyType == null)
+                    propertyType = 
getTypeForListPropertyExpression(receiverType, pexp);
+                if (propertyType == null)
+                    propertyType = getTypeForSpreadExpression(receiverType, 
pexp);
+                if (propertyType == null)
+                    continue;
+                if (visitor != null) {
+                    PropertyNode node = new PropertyNode(propertyName, 
Opcodes.ACC_PUBLIC, propertyType, receiverType, null, null, null);
+                    node.setDeclaringClass(receiverType);
+                    visitor.visitProperty(node);
+                }
+                storeType(pexp, propertyType);
+                String delegationData = receiver.getData();
+                if (delegationData != null) 
pexp.putNodeMetaData(IMPLICIT_RECEIVER, delegationData);
+                return true;
+            }
         }
 
         if (pexp.isImplicitThis() && isThisExpression(objectExpression)) {
diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy 
b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
index 0c0481db34..71f244e7b1 100644
--- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
+++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy
@@ -842,6 +842,16 @@ class FieldsAndPropertiesSTCTest extends 
StaticTypeCheckingTestCase {
             assert xxx == null
             assert yyy == null
         '''
+        assertScript '''
+            class HttpHeaders extends HashMap<String,List<String>> {
+                protected static final String ACCEPT = 'Accept'
+            }
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                assert node.getNodeMetaData(INFERRED_TYPE) == STRING_TYPE
+            })
+            def accept = HttpHeaders.ACCEPT
+            assert accept == 'Accept'
+        '''
     }
 
     void testTypeCheckerDoesNotThinkPropertyIsReadOnly() {

Reply via email to