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 2019/12/02 01:41:29 UTC

[groovy] branch master updated (78525bb -> db5fc65)

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

paulk pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from 78525bb  fix style items
     new 4e28d41  GROOVY-9183: use property initial value as default for map.getOrDefault
     new e03f8a5  GROOVY-9183: add support for boolean properties
     new db5fc65  GROOVY-9183: refactor to simplify (closes #1109)

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../transform/NamedVariantASTTransformation.java   | 78 ++++++++++--------
 .../transform/NamedVariantTransformTest.groovy     | 92 +++++++++++++++++++---
 2 files changed, 127 insertions(+), 43 deletions(-)


[groovy] 03/03: GROOVY-9183: refactor to simplify (closes #1109)

Posted by pa...@apache.org.
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

commit db5fc65ca489685ba246d14d80bc1132cd566ba5
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Dec 2 11:41:16 2019 +1000

    GROOVY-9183: refactor to simplify (closes #1109)
---
 .../codehaus/groovy/transform/NamedVariantASTTransformation.java | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
index 9316a07..146ad7f 100644
--- a/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
@@ -49,6 +49,7 @@ import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedConstructor
 import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedMethod;
 import static org.apache.groovy.ast.tools.ClassNodeUtils.isInnerClass;
 import static org.apache.groovy.ast.tools.VisibilityUtils.getVisibility;
+import static org.codehaus.groovy.antlr.PrimitiveHelper.getDefaultValueForPrimitive;
 import static org.codehaus.groovy.ast.ClassHelper.MAP_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.boolean_TYPE;
@@ -205,13 +206,7 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
     }
 
     private Expression getDefaultExpression(ClassNode pType) {
-        if (isPrimitiveType(pType)) {
-            if (boolean_TYPE.equals(pType)) {
-                return constX(Boolean.FALSE);
-            }
-            return castX(getWrapper(pType), constX(0));
-        }
-        return nullX();
+        return Optional.ofNullable(getDefaultValueForPrimitive(pType)).orElse(nullX());
     }
 
     private boolean hasDuplicates(final MethodNode mNode, final List<String> propNames, final String next) {


[groovy] 02/03: GROOVY-9183: add support for boolean properties

Posted by pa...@apache.org.
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

commit e03f8a53ac72d1f14b3173047f0e4d348acfdb4c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Dec 1 12:56:35 2019 -0600

    GROOVY-9183: add support for boolean properties
---
 .../transform/NamedVariantASTTransformation.java       | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
index ae9ea5c..9316a07 100644
--- a/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
@@ -51,8 +51,9 @@ import static org.apache.groovy.ast.tools.ClassNodeUtils.isInnerClass;
 import static org.apache.groovy.ast.tools.VisibilityUtils.getVisibility;
 import static org.codehaus.groovy.ast.ClassHelper.MAP_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.boolean_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
-import static org.codehaus.groovy.ast.ClassHelper.isNumberType;
+import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveType;
 import static org.codehaus.groovy.ast.ClassHelper.make;
 import static org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
@@ -190,8 +191,7 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
         for (PropertyNode pNode : props) {
             String name = pNode.getName();
             // create entry [name: __namedArgs.getOrDefault('name', initialValue)]
-            Expression defaultValue = Optional.ofNullable(pNode.getInitialExpression()).orElseGet(() ->
-                    isNumberType(pNode.getType()) ? castX(getWrapper(pNode.getType()), constX(0)) : nullX());
+            Expression defaultValue = Optional.ofNullable(pNode.getInitialExpression()).orElseGet(() -> getDefaultExpression(pNode.getType()));
             entries.add(entryX(constX(name), callX(varX(mapParam), "getOrDefault", args(constX(name), defaultValue))));
             // create annotation @NamedParam(value='name', type=DelegateType)
             AnnotationNode namedParam = new AnnotationNode(NAMED_PARAM_TYPE);
@@ -204,6 +204,16 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
         return true;
     }
 
+    private Expression getDefaultExpression(ClassNode pType) {
+        if (isPrimitiveType(pType)) {
+            if (boolean_TYPE.equals(pType)) {
+                return constX(Boolean.FALSE);
+            }
+            return castX(getWrapper(pType), constX(0));
+        }
+        return nullX();
+    }
+
     private boolean hasDuplicates(final MethodNode mNode, final List<String> propNames, final String next) {
         if (propNames.contains(next)) {
             addError("Error during " + NAMED_VARIANT + " processing. Duplicate property '" + next + "' found.", mNode);
@@ -255,4 +265,4 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
             );
         }
     }
-}
\ No newline at end of file
+}


[groovy] 01/03: GROOVY-9183: use property initial value as default for map.getOrDefault

Posted by pa...@apache.org.
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

commit 4e28d41ddbaa761299127707cf33a8dcae2f407e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 28 18:00:29 2019 -0600

    GROOVY-9183: use property initial value as default for map.getOrDefault
    
    if no initial value expression was supplied:
    - primitive (or wrapper) types: zero
    - reference types: null
---
 .../transform/NamedVariantASTTransformation.java   | 71 +++++++++--------
 .../transform/NamedVariantTransformTest.groovy     | 92 +++++++++++++++++++---
 2 files changed, 121 insertions(+), 42 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
index dcd444a..ae9ea5c 100644
--- a/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/NamedVariantASTTransformation.java
@@ -24,17 +24,14 @@ import groovy.transform.NamedVariant;
 import org.apache.groovy.ast.tools.AnnotatedNodeUtils;
 import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.PropertyNode;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.MapEntryExpression;
-import org.codehaus.groovy.ast.expr.MapExpression;
 import org.codehaus.groovy.ast.stmt.AssertStatement;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.ast.stmt.ForStatement;
@@ -45,13 +42,17 @@ import org.codehaus.groovy.control.SourceUnit;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 
 import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedConstructor;
 import static org.apache.groovy.ast.tools.ClassNodeUtils.addGeneratedMethod;
 import static org.apache.groovy.ast.tools.ClassNodeUtils.isInnerClass;
 import static org.apache.groovy.ast.tools.VisibilityUtils.getVisibility;
+import static org.codehaus.groovy.ast.ClassHelper.MAP_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
+import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
+import static org.codehaus.groovy.ast.ClassHelper.isNumberType;
 import static org.codehaus.groovy.ast.ClassHelper.make;
 import static org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
@@ -62,8 +63,11 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.entryX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.getAllProperties;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.list2args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.mapX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.param;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.plusX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.propX;
@@ -72,33 +76,33 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 
 @GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
 public class NamedVariantASTTransformation extends AbstractASTTransformation {
-    private static final Class MY_CLASS = NamedVariant.class;
-    private static final ClassNode MY_TYPE = make(MY_CLASS);
-    private static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage();
+
+    private static final ClassNode NAMED_VARIANT_TYPE = make(NamedVariant.class);
+    private static final String NAMED_VARIANT = "@" + NAMED_VARIANT_TYPE.getNameWithoutPackage();
     private static final ClassNode NAMED_PARAM_TYPE = makeWithoutCaching(NamedParam.class, false);
     private static final ClassNode NAMED_DELEGATE_TYPE = makeWithoutCaching(NamedDelegate.class, false);
 
     @Override
-    public void visit(ASTNode[] nodes, SourceUnit source) {
+    public void visit(final ASTNode[] nodes, final SourceUnit source) {
         init(nodes, source);
         MethodNode mNode = (MethodNode) nodes[1];
         AnnotationNode anno = (AnnotationNode) nodes[0];
-        if (!MY_TYPE.equals(anno.getClassNode())) return;
+        if (!NAMED_VARIANT_TYPE.equals(anno.getClassNode())) return;
 
         Parameter[] fromParams = mNode.getParameters();
         if (fromParams.length == 0) {
-            addError("Error during " + MY_TYPE_NAME + " processing. No-args method not supported.", mNode);
+            addError("Error during " + NAMED_VARIANT + " processing. No-args method not supported.", mNode);
             return;
         }
 
         boolean autoDelegate = memberHasValue(anno, "autoDelegate", true);
-        Parameter mapParam = param(GenericsUtils.nonGeneric(ClassHelper.MAP_TYPE), "__namedArgs");
-        List<Parameter> genParams = new ArrayList<Parameter>();
+        Parameter mapParam = param(GenericsUtils.nonGeneric(MAP_TYPE), "__namedArgs");
+        List<Parameter> genParams = new ArrayList<>();
         genParams.add(mapParam);
         ClassNode cNode = mNode.getDeclaringClass();
-        final BlockStatement inner = new BlockStatement();
+        BlockStatement inner = new BlockStatement();
         ArgumentListExpression args = new ArgumentListExpression();
-        final List<String> propNames = new ArrayList<String>();
+        List<String> propNames = new ArrayList<>();
 
         // first pass, just check for absence of annotations of interest
         boolean annoFound = false;
@@ -129,7 +133,7 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
         createMapVariant(mNode, anno, mapParam, genParams, cNode, inner, args, propNames);
     }
 
-    private boolean processImplicitNamedParam(MethodNode mNode, Parameter mapParam, ArgumentListExpression args, List<String> propNames, Parameter fromParam) {
+    private boolean processImplicitNamedParam(final MethodNode mNode, final Parameter mapParam, final ArgumentListExpression args, final List<String> propNames, final Parameter fromParam) {
         boolean required = fromParam.hasInitialExpression();
         String name = fromParam.getName();
         if (hasDuplicates(mNode, propNames, name)) return false;
@@ -142,7 +146,7 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
         return true;
     }
 
-    private boolean processExplicitNamedParam(MethodNode mNode, Parameter mapParam, BlockStatement inner, ArgumentListExpression args, List<String> propNames, Parameter fromParam) {
+    private boolean processExplicitNamedParam(final MethodNode mNode, final Parameter mapParam, final BlockStatement inner, final ArgumentListExpression args, final List<String> propNames, final Parameter fromParam) {
         AnnotationNode namedParam = fromParam.getAnnotations(NAMED_PARAM_TYPE).get(0);
         boolean required = memberHasValue(namedParam, "required", true);
         if (getMemberStringValue(namedParam, "value") == null) {
@@ -153,15 +157,15 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
             namedParam.addMember("type", classX(fromParam.getType()));
         }
         if (hasDuplicates(mNode, propNames, name)) return false;
-        // TODO check specified type is assignable from declared param type?
-        // ClassNode type = getMemberClassValue(namedParam, "type");
+        // TODO: Check specified type is assignable from declared param type?
+        //ClassNode type = getMemberClassValue(namedParam, "type");
         if (required) {
             if (fromParam.hasInitialExpression()) {
-                addError("Error during " + MY_TYPE_NAME + " processing. A required parameter can't have an initial value.", mNode);
+                addError("Error during " + NAMED_VARIANT + " processing. A required parameter can't have an initial value.", mNode);
                 return false;
             }
             inner.addStatement(new AssertStatement(boolX(callX(varX(mapParam), "containsKey", args(constX(name)))),
-                    plusX(new ConstantExpression("Missing required named argument '" + name + "'. Keys found: "), callX(varX(mapParam), "keySet"))));
+                    plusX(constX("Missing required named argument '" + name + "'. Keys found: "), callX(varX(mapParam), "keySet"))));
         }
         args.addExpression(propX(varX(mapParam), name));
         mapParam.addAnnotation(namedParam);
@@ -169,62 +173,65 @@ public class NamedVariantASTTransformation extends AbstractASTTransformation {
         return true;
     }
 
-    private boolean processDelegateParam(MethodNode mNode, Parameter mapParam, ArgumentListExpression args, List<String> propNames, Parameter fromParam) {
+    private boolean processDelegateParam(final MethodNode mNode, final Parameter mapParam, final ArgumentListExpression args, final List<String> propNames, final Parameter fromParam) {
         if (isInnerClass(fromParam.getType())) {
             if (mNode.isStatic()) {
-                addError("Error during " + MY_TYPE_NAME + " processing. Delegate type '" + fromParam.getType().getNameWithoutPackage() + "' is an inner class which is not supported.", mNode);
+                addError("Error during " + NAMED_VARIANT + " processing. Delegate type '" + fromParam.getType().getNameWithoutPackage() + "' is an inner class which is not supported.", mNode);
                 return false;
             }
         }
 
-        Set<String> names = new HashSet<String>();
+        Set<String> names = new HashSet<>();
         List<PropertyNode> props = getAllProperties(names, fromParam.getType(), true, false, false, true, false, true);
         for (String next : names) {
             if (hasDuplicates(mNode, propNames, next)) return false;
         }
-        List<MapEntryExpression> entries = new ArrayList<MapEntryExpression>();
+        List<MapEntryExpression> entries = new ArrayList<>();
         for (PropertyNode pNode : props) {
             String name = pNode.getName();
-            entries.add(new MapEntryExpression(constX(name), propX(varX(mapParam), name)));
+            // create entry [name: __namedArgs.getOrDefault('name', initialValue)]
+            Expression defaultValue = Optional.ofNullable(pNode.getInitialExpression()).orElseGet(() ->
+                    isNumberType(pNode.getType()) ? castX(getWrapper(pNode.getType()), constX(0)) : nullX());
+            entries.add(entryX(constX(name), callX(varX(mapParam), "getOrDefault", args(constX(name), defaultValue))));
+            // create annotation @NamedParam(value='name', type=DelegateType)
             AnnotationNode namedParam = new AnnotationNode(NAMED_PARAM_TYPE);
             namedParam.addMember("value", constX(name));
             namedParam.addMember("type", classX(pNode.getType()));
             mapParam.addAnnotation(namedParam);
         }
-        Expression delegateMap = new MapExpression(entries);
+        Expression delegateMap = mapX(entries);
         args.addExpression(castX(fromParam.getType(), delegateMap));
         return true;
     }
 
-    private boolean hasDuplicates(MethodNode mNode, List<String> propNames, String next) {
+    private boolean hasDuplicates(final MethodNode mNode, final List<String> propNames, final String next) {
         if (propNames.contains(next)) {
-            addError("Error during " + MY_TYPE_NAME + " processing. Duplicate property '" + next + "' found.", mNode);
+            addError("Error during " + NAMED_VARIANT + " processing. Duplicate property '" + next + "' found.", mNode);
             return true;
         }
         propNames.add(next);
         return false;
     }
 
-    private void createMapVariant(MethodNode mNode, AnnotationNode anno, Parameter mapParam, List<Parameter> genParams, ClassNode cNode, BlockStatement inner, ArgumentListExpression args, List<String> propNames) {
+    private void createMapVariant(final MethodNode mNode, final AnnotationNode anno, final Parameter mapParam, final List<Parameter> genParams, final ClassNode cNode, final BlockStatement inner, final ArgumentListExpression args, final List<String> propNames) {
         Parameter namedArgKey = param(STRING_TYPE, "namedArgKey");
         inner.addStatement(
                 new ForStatement(
                         namedArgKey,
                         callX(varX(mapParam), "keySet"),
-                        new AssertStatement(boolX(callX(list2args(propNames), "contains", varX(namedArgKey))),
-                                plusX(new ConstantExpression("Unrecognized namedArgKey: "), varX(namedArgKey)))
+                        new AssertStatement(boolX(callX(list2args(propNames), "contains", varX(namedArgKey))), plusX(constX("Unrecognized namedArgKey: "), varX(namedArgKey)))
                 ));
 
         Parameter[] genParamsArray = genParams.toArray(Parameter.EMPTY_ARRAY);
         // TODO account for default params giving multiple signatures
         if (cNode.hasMethod(mNode.getName(), genParamsArray)) {
-            addError("Error during " + MY_TYPE_NAME + " processing. Class " + cNode.getNameWithoutPackage() +
+            addError("Error during " + NAMED_VARIANT + " processing. Class " + cNode.getNameWithoutPackage() +
                     " already has a named-arg " + (mNode instanceof ConstructorNode ? "constructor" : "method") +
                     " of type " + genParams, mNode);
             return;
         }
 
-        final BlockStatement body = new BlockStatement();
+        BlockStatement body = new BlockStatement();
         int modifiers = getVisibility(anno, mNode, mNode.getClass(), mNode.getModifiers());
         if (mNode instanceof ConstructorNode) {
             body.addStatement(stmt(ctorX(ClassNode.THIS, args)));
diff --git a/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy b/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy
index 3455a77..198f951 100644
--- a/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/NamedVariantTransformTest.groovy
@@ -18,13 +18,18 @@
  */
 package org.codehaus.groovy.transform
 
-import groovy.test.GroovyShellTestCase
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
 
 /**
  * Tests for the {@code @NamedVariant} transformation.
  */
-class NamedVariantTransformTest extends GroovyShellTestCase {
+@CompileStatic
+final class NamedVariantTransformTest {
 
+    @Test
     void testNamedParam() {
         assertScript '''
             import groovy.transform.*
@@ -43,7 +48,7 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
 
             @NamedVariant
             String foo(a, @NamedParam String b2, @NamedDelegate Color shade, int c, @NamedParam(required=true) d, @NamedDelegate Animal pet) {
-              "$a $b2 $c $d ${pet.type?.toUpperCase()}:$pet.name $shade"
+                "$a $b2 $c $d ${pet.type?.toUpperCase()}:$pet.name $shade"
             }
 
             def result = foo(b2: 'b param', g: 12, b: 42, r: 12, 'foo', 42, d:true, type: 'Dog', name: 'Rover')
@@ -51,6 +56,7 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
         '''
     }
 
+    @Test
     void testNamedParamWithRename() {
         assertScript '''
             import groovy.transform.*
@@ -69,6 +75,7 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
         '''
     }
 
+    @Test
     void testNamedParamConstructor() {
         assertScript """
             import groovy.transform.*
@@ -77,9 +84,9 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
             class Color {
                 @NamedVariant
                 Color(@NamedParam int r, @NamedParam int g, @NamedParam int b) {
-                  this.r = r
-                  this.g = g
-                  this.b = b
+                    this.r = r
+                    this.g = g
+                    this.b = b
                 }
                 private int r, g, b
             }
@@ -88,6 +95,7 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
         """
     }
 
+    @Test
     void testNamedParamConstructorVisibility() {
         assertScript """
             import groovy.transform.*
@@ -99,9 +107,9 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
                 @VisibilityOptions(PUBLIC)
                 @NamedVariant
                 private Color(@NamedParam int r, @NamedParam int g, @NamedParam int b) {
-                  this.r = r
-                  this.g = g
-                  this.b = b
+                    this.r = r
+                    this.g = g
+                    this.b = b
                 }
             }
 
@@ -111,6 +119,7 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
         """
     }
 
+    @Test
     void testNamedParamInnerClass() {
         assertScript '''
             import groovy.transform.*
@@ -145,17 +154,80 @@ class NamedVariantTransformTest extends GroovyShellTestCase {
         '''
     }
 
+    @Test
     void testGeneratedMethodsSkipped() {
         assertScript '''
             import groovy.transform.*
             import static org.codehaus.groovy.transform.NamedVariantTransformTest.*
 
             @NamedVariant
-            def baz(@NamedDelegate Storm st, @NamedDelegate Switch sw) { st.front + sw.back }
+            def baz(@NamedDelegate Storm storm_, @NamedDelegate Switch switch_) { storm_.front + switch_.back }
             assert baz(front: 'Hello', back: 'World') == 'HelloWorld'
         '''
     }
 
+    @Test // GROOVY-9183
+    void testNamedDelegateWithPrimitiveValues() {
+        assertScript '''
+            import groovy.transform.*
+
+            class Color {
+                int r, g, b
+            }
+
+            @NamedVariant
+            Color makeColor(@NamedDelegate Color color) {
+                color
+            }
+
+            def color = makeColor(r: 128, g: 128)
+            assert color.r == 128
+            assert color.g == 128
+            assert color.b == 0
+        '''
+    }
+
+    @Test // GROOVY-9183
+    void testNamedDelegateWithPropertyDefaults() {
+        assertScript '''
+            import groovy.transform.*
+
+            class RowMapper {
+                final Settings settings
+
+                @NamedVariant
+                RowMapper(Settings settings) {
+                    this.settings = settings
+                }
+
+                @NamedVariant
+                static RowMapper parse(@NamedDelegate Settings settings, Reader reader) {
+                    // settings missing the initializer values from properties not passed as named arguments
+                    new RowMapper(settings).parseImpl(reader)
+                }
+
+                private RowMapper parseImpl(Reader source) {
+                    // do work here
+                    return this
+                }
+
+                @Immutable
+                static class Settings {
+                    String separator = ','
+                    Boolean headers = true
+                    Integer headersRow = 0
+                    Integer firstDataRow = 1
+                }
+            }
+
+            def mapper = RowMapper.parse(separator: '\t', new StringReader(''))
+
+            assert mapper.settings.headers == true
+            assert mapper.settings.headersRow == 0
+            assert mapper.settings.firstDataRow == 1
+        '''
+    }
+
     static class Storm { String front }
     static class Switch { String back }
 }