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