You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/03/01 04:05:50 UTC

[groovy] branch master updated: GROOVY-10484: NamedVariant: NamedParam not checked when added by transform

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

paulk 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 bc1024e  GROOVY-10484: NamedVariant: NamedParam not checked when added by transform
bc1024e is described below

commit bc1024e9ee5d7332e8f88e6b98cd5ffbd13ab9fb
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Feb 28 15:46:27 2022 +1000

    GROOVY-10484: NamedVariant: NamedParam not checked when added by transform
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 25 +++++++++++++++++-----
 .../transform/NamedVariantTransformTest.groovy     | 18 ++++++++++++++++
 2 files changed, 38 insertions(+), 5 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 bfc738f..c553189 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -347,6 +347,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected static final ClassNode DELEGATES_TO_TARGET = ClassHelper.make(DelegatesTo.Target.class);
     protected static final ClassNode CLOSUREPARAMS_CLASSNODE = ClassHelper.make(ClosureParams.class);
     protected static final ClassNode NAMED_PARAMS_CLASSNODE = ClassHelper.make(NamedParams.class);
+    protected static final ClassNode NAMED_PARAM_CLASSNODE = ClassHelper.make(NamedParam.class);
     @Deprecated protected static final ClassNode LINKEDHASHMAP_CLASSNODE = LinkedHashMap_TYPE;
     protected static final ClassNode ENUMERATION_TYPE = ClassHelper.make(Enumeration.class);
     protected static final ClassNode MAP_ENTRY_TYPE = ClassHelper.make(Map.Entry.class);
@@ -2828,6 +2829,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
             entries.put(key, entry.getValueExpression());
         }
+        List<String> collectedNames = new ArrayList<>();
         List<AnnotationNode> annotations = param.getAnnotations(NAMED_PARAMS_CLASSNODE);
         if (annotations != null && !annotations.isEmpty()) {
             AnnotationNode an = null;
@@ -2836,7 +2838,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     an = next;
                 }
             }
-            List<String> collectedNames = new ArrayList<>();
             if (an != null) {
                 Expression value = an.getMember("value");
                 if (value instanceof AnnotationConstantExpression) {
@@ -2849,10 +2850,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         }
                     }
                 }
-                for (Map.Entry<Object, Expression> entry : entries.entrySet()) {
-                    if (!collectedNames.contains(entry.getKey())) {
-                        addStaticTypeError("unexpected named arg: " + entry.getKey(), args);
-                    }
+            }
+        }
+        annotations = param.getAnnotations(NAMED_PARAM_CLASSNODE);
+        if (annotations != null && !annotations.isEmpty()) {
+            for (AnnotationNode next : annotations) {
+                if (next.getClassNode().getName().equals(NamedParam.class.getName())) {
+                    processNamedParam(next, entries, args, collectedNames);
+                }
+            }
+        }
+        if (!collectedNames.isEmpty()) {
+            for (Map.Entry<Object, Expression> entry : entries.entrySet()) {
+                if (!collectedNames.contains(entry.getKey())) {
+                    addStaticTypeError("unexpected named arg: " + entry.getKey(), args);
                 }
             }
         }
@@ -2861,6 +2872,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     private void processNamedParam(final AnnotationConstantExpression value, final Map<Object, Expression> entries, final Expression expression, final List<String> collectedNames) {
         AnnotationNode namedParam = (AnnotationNode) value.getValue();
         if (!namedParam.getClassNode().getName().equals(NamedParam.class.getName())) return;
+        processNamedParam(namedParam, entries, expression, collectedNames);
+    }
+
+    private void processNamedParam(final AnnotationNode namedParam, final Map<Object, Expression> entries, final Expression expression, final List<String> collectedNames) {
         String name = null;
         boolean required = false;
         ClassNode expectedType = null;
diff --git a/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy b/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy
index 16a364e..a98408c 100644
--- a/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy
@@ -272,6 +272,7 @@ final class NamedVariantTransformTest {
 
     @Test
     void testNamedParamRequiredVersusOptional() {
+        // check dynamic case
         def err = shouldFail '''
             import groovy.transform.*
 
@@ -287,6 +288,23 @@ final class NamedVariantTransformTest {
             m(alpha: 123)
         '''
         assert err =~ /Missing required named argument 'color'/
+
+        // also check static error (GROOVY-10484)
+        err = shouldFail '''
+            import groovy.transform.*
+            class Color {
+                int r, g, b
+            }
+            @NamedVariant
+            String m(Color color, int alpha = 0) {
+                return [color, alpha].join(' ')
+            }
+            @TypeChecked
+            void test() {
+                m(alpha: 123)
+            }
+        '''
+        assert err =~ /required named param 'color' not found/
     }
 
     @Test // GROOVY-9183