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 5eeb6b15473280dc78df1b574bfc444751ab379f Author: Eric Milles <[email protected]> AuthorDate: Wed May 14 11:06:45 2025 -0500 GROOVY-11663: STC: resolve `$self.pack_Type__name` to a static access --- .../transform/stc/TraitTypeCheckingExtension.java | 32 ++++++++++++++++++++++ .../traitx/TraitASTTransformationTest.groovy | 10 +++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java b/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java index f0b2b9157e..926582a967 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java @@ -25,6 +25,8 @@ import org.codehaus.groovy.ast.Parameter; import org.codehaus.groovy.ast.expr.ArgumentListExpression; import org.codehaus.groovy.ast.expr.MethodCall; import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.expr.PropertyExpression; +import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.transform.trait.TraitASTTransformation; import org.codehaus.groovy.transform.trait.Traits; @@ -93,4 +95,34 @@ public class TraitTypeCheckingExtension extends AbstractTypeCheckingExtension { return Collections.emptyList(); } + + @Override + public boolean handleUnresolvedProperty(final PropertyExpression pexp) { + var objectExpression = pexp.getObjectExpression(); + if (objectExpression instanceof VariableExpression + && objectExpression.getText().endsWith(Traits.THIS_OBJECT)) { + String propertyName = pexp.getPropertyAsString(); + if (propertyName != null) { + ClassNode objectExpressionType = getType(objectExpression); + if (isClassClassNodeWrappingConcreteType(objectExpressionType)) { + objectExpressionType = objectExpressionType.getGenericsTypes()[0].getType(); + } + for (ClassNode trait : Traits.findTraits(objectExpressionType)) { + if (propertyName.startsWith(trait.getName().replace('.', '_') + "__")) { + ClassNode staticFieldHelper = Traits.findStaticFieldHelper(trait); + if (staticFieldHelper != null) { + MethodNode getter = staticFieldHelper.getDeclaredMethod(propertyName + "$get", Parameter.EMPTY_ARRAY); + if (getter != null) { // GROOVY-11663: resolve "$self.pack_Type__name" to a static field access method + ClassNode returnType = typeCheckingVisitor.inferReturnTypeGenerics(objectExpressionType, getter, ArgumentListExpression.EMPTY_ARGUMENTS); + pexp.putNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION, returnType); + storeType(pexp, returnType); + return true; + } + } + } + } + } + } + return false; + } } 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 7caea44797..32a21c5cdb 100644 --- a/src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy +++ b/src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy @@ -3787,20 +3787,20 @@ final class TraitASTTransformationTest { $mode trait B extends A { static one(String string) { - string// + A__BANG + string + A__BANG } Object two(String string) { - string// + A__BANG + string + A__BANG } } $mode class C implements B { static test1() { - assert A__BANG + one('works') == '!works' + assert A__BANG + one('works') == '!works!' } void test2() { - assert A__BANG + one('works') == '!works' - assert A__BANG + two('works') == '!works' + assert A__BANG + one('works') == '!works!' + assert A__BANG + two('works') == '!works!' } }
