You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2024/04/24 18:55:53 UTC

(groovy) branch GROOVY_4_0_X updated: GROOVY-11360: STC: add warning for field hidden by dynamic property

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

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


The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
     new 1f34705744 GROOVY-11360: STC: add warning for field hidden by dynamic property
1f34705744 is described below

commit 1f34705744c39d80ce1f695fd241683b0d177a08
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Apr 24 13:19:38 2024 -0500

    GROOVY-11360: STC: add warning for field hidden by dynamic property
    
    4_0_X backport
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 12 +++++-
 .../groovy/transform/stc/ClosuresSTCTest.groovy    | 49 ++++++++++++++++++++++
 2 files changed, 60 insertions(+), 1 deletion(-)

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 20d3b885a2..8d8ab524ec 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -108,6 +108,7 @@ import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.ErrorCollector;
 import org.codehaus.groovy.control.ResolveVisitor;
 import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.control.messages.WarningMessage;
 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.codehaus.groovy.syntax.Token;
 import org.codehaus.groovy.syntax.TokenUtil;
@@ -641,6 +642,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
                 if (declaredInScope) {
                     checkOrMarkPrivateAccess(vexp, accessedField, typeCheckingContext.isTargetOfEnclosingAssignment(vexp));
+                } else if (vexp.getAccessedVariable() != accessedField) { // GROOVY-11360: field hidden by dynamic property
+                    if (vexp.getLineNumber() > 0 && !typeCheckingContext.reportedErrors.contains(((long) vexp.getLineNumber()) << 16 + vexp.getColumnNumber())) {
+                        String text = "The field: " + accessedField.getName() + " of class: " + prettyPrintTypeName(accessedField.getDeclaringClass()) +
+                                                " is hidden by a dynamic property. A qualifier is required to reference it.";
+                        Token token = new Token(0, name, vexp.getLineNumber(), vexp.getColumnNumber()); // ASTNode to CSTNode
+                        typeCheckingContext.getErrorCollector().addWarning(new WarningMessage(WarningMessage.POSSIBLE_ERRORS, text, token, getSourceUnit()));
+                    }
                 }
             } else if (!extension.handleUnresolvedVariableExpression(vexp)) { // GROOVY-11356
                 addStaticTypeError("No such property: " + name + " for class: " + prettyPrintTypeName(typeCheckingContext.getEnclosingClassNode()), vexp);
@@ -1650,7 +1658,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     pexp.putNodeMetaData(DYNAMIC_RESOLUTION, Boolean.TRUE);
                     pexp.removeNodeMetaData(DECLARATION_INFERRED_TYPE);
                     pexp.removeNodeMetaData(INFERRED_TYPE);
-                    visitor.visitMethod(mopMethod);
+                    if (visitor != null) {
+                        visitor.visitMethod(mopMethod);
+                    }
                     return true;
                 }
             }
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index 19785b01a2..819fd21aa5 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -710,6 +710,55 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-11360
+    void testLexicalScopeVersusGetDynamicProperty() {
+        config.warningLevel = org.codehaus.groovy.control.messages.WarningMessage.POSSIBLE_ERRORS
+        config.targetDirectory = File.createTempDir()
+        def parentDir = File.createTempDir()
+        try {
+            def c = new File(parentDir, 'C.groovy')
+            c.write '''
+                class C {
+                    private static final value = "C"
+
+                    def m(D d) {
+                        d.with {
+                            return value
+                        }
+                    }
+                }
+            '''
+            def d = new File(parentDir, 'D.groovy')
+            d.write '''
+                class D {
+                    def get(String name) {
+                        if (name == "value") "D"
+                    }
+                }
+            '''
+            def e = new File(parentDir, 'E.groovy')
+            e.write '''
+                String result = new C().m(new D())
+                assert result == 'D'
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            new org.codehaus.groovy.control.CompilationUnit(config, null, loader).with {
+                addSources(c, d, e)
+                compile()
+
+                assert errorCollector.hasWarnings()
+                assert errorCollector.warnings[0].message.startsWith(
+                        'The field: value of class: C is hidden by a dynamic property.')
+            }
+            loader.addClasspath(config.targetDirectory.absolutePath)
+            loader.loadClass('E', true).main()
+        } finally {
+            config.targetDirectory.deleteDir()
+            parentDir.deleteDir()
+        }
+    }
+
     // GROOVY-9089
     void testOwnerVersusDelegateFromNestedClosure() {
         String declarations = '''