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

commit b351c27bbbc96ca0fb9ae4ea0aff7206dadb070d
Author: Eric Milles <[email protected]>
AuthorDate: Tue May 13 09:48:07 2025 -0500

    GROOVY-11663: STC: error for class or trait property expression
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 41 ++++++++++++++--------
 .../packageScope/DifferentPackageTest.groovy       |  2 +-
 .../traitx/TraitASTTransformationTest.groovy       |  9 +++--
 3 files changed, 34 insertions(+), 18 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 f375a1ea7d..fa7df3da1e 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -763,28 +763,39 @@ public class StaticTypeCheckingVisitor extends 
ClassCodeVisitorSupport {
 
     @Override
     public void visitPropertyExpression(final PropertyExpression expression) {
-        if (existsProperty(expression, 
!typeCheckingContext.isTargetOfEnclosingAssignment(expression))) return;
-
-        if (!extension.handleUnresolvedProperty(expression)) {
-            var objectExpression = expression.getObjectExpression();
-            var objectExpressionType = (objectExpression instanceof 
ClassExpression
-                    ? objectExpression.getType() : 
wrapTypeIfNecessary(getType(objectExpression)));
-            objectExpressionType = 
findCurrentInstanceOfClass(objectExpression, objectExpressionType);
-            addStaticTypeError("No such property: " + 
expression.getPropertyAsString() + " for class: " + 
prettyPrintTypeName(objectExpressionType), expression);
+        boolean readOnly = 
!typeCheckingContext.isTargetOfEnclosingAssignment(expression);
+        if (existsProperty(expression, readOnly)
+                || extension.handleUnresolvedProperty(expression)) {
+            return; // resolved or excused
         }
+        recordMissingProperty(expression);
     }
 
     @Override
     public void visitAttributeExpression(final AttributeExpression expression) 
{
-        if (existsProperty(expression, true)) return;
+        boolean readOnly = true;
+        if (existsProperty(expression, readOnly)
+                || extension.handleUnresolvedAttribute(expression)) {
+            return; // resolved or excused
+        }
+        recordMissingProperty(expression);
+    }
 
-        if (!extension.handleUnresolvedAttribute(expression)) {
-            var objectExpression = expression.getObjectExpression();
-            var objectExpressionType = (objectExpression instanceof 
ClassExpression
-                    ? objectExpression.getType() : 
wrapTypeIfNecessary(getType(objectExpression)));
-            objectExpressionType = 
findCurrentInstanceOfClass(objectExpression, objectExpressionType);
-            addStaticTypeError("No such attribute: " + 
expression.getPropertyAsString() + " for class: " + 
prettyPrintTypeName(objectExpressionType), expression);
+    private void recordMissingProperty(final PropertyExpression expression) {
+        var objectExpression = expression.getObjectExpression();
+        var objectExpressionType = 
findCurrentInstanceOfClass(objectExpression, getType(objectExpression));
+
+        String pattern;
+        if (!isClassClassNodeWrappingConcreteType(objectExpressionType)) {
+            pattern = "No such {0,choice,1#attribute|2#property}: {1} for 
class: {2}";
+        } else {
+            objectExpressionType = 
objectExpressionType.getGenericsTypes()[0].getType();
+            pattern = "No such {0,choice,1#attribute|2#property}: {1} for 
Class or static {0,choice,1#field|2#property} for class: {2}";
         }
+
+        String error = java.text.MessageFormat.format(pattern, expression 
instanceof AttributeExpression ? 1 : 2, expression.getPropertyAsString(), 
prettyPrintTypeName(wrapTypeIfNecessary(objectExpressionType)));
+        ASTNode node = expression.getLineNumber() > 0 ? expression : 
expression.getProperty(); // GROOVY-11663
+        addStaticTypeError(error, node);
     }
 
     @Override
diff --git 
a/src/test/groovy/org/codehaus/groovy/transform/packageScope/DifferentPackageTest.groovy
 
b/src/test/groovy/org/codehaus/groovy/transform/packageScope/DifferentPackageTest.groovy
index ba1644879e..135dd8d364 100644
--- 
a/src/test/groovy/org/codehaus/groovy/transform/packageScope/DifferentPackageTest.groovy
+++ 
b/src/test/groovy/org/codehaus/groovy/transform/packageScope/DifferentPackageTest.groovy
@@ -447,6 +447,6 @@ final class DifferentPackageTest {
                 '''
             )
         }
-        assert err =~ /No such property: answer for class: p.One/ // TODO: 
Cannot access p.One#getAnswer?
+        assert err =~ /No such property: answer for Class or static property 
for class: p.One/ // TODO: Cannot access p.One#getAnswer?
     }
 }
diff --git 
a/src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
 
b/src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index e0bfd2b087..c1dd00f55e 100644
--- 
a/src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ 
b/src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -3710,10 +3710,10 @@ final class TraitASTTransformationTest {
         """
     }
 
-    // GROOVY-11641
+    // GROOVY-11641, GROOVY-11663
     @CompileModesTest
     void testTraitAccessToInheritedStaticMethods4(String mode) {
-        shouldFail shell, """
+        var err = shouldFail shell, """
             $mode
             trait Foo {
                 public static final String BANG = '!'
@@ -3739,6 +3739,11 @@ final class TraitASTTransformationTest {
             Main.test1()
             new Main().test2()
         """
+        if (mode.endsWith('Dynamic')) {
+            assert err =~ /MissingPropertyException/
+        } else {
+            assert err =~ /\[Static type checking\] - No such property: BANG 
for Class or static property for class: Bar/
+        }
     }
 
     // GROOVY-9386

Reply via email to