You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/07/08 14:24:39 UTC

[groovy] branch master updated: GROOVY-9854: STC: propagate `switch` type to `case` closure parameter

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


The following commit(s) were added to refs/heads/master by this push:
     new e21b5d41a3 GROOVY-9854: STC: propagate `switch` type to `case` closure parameter
e21b5d41a3 is described below

commit e21b5d41a3bc2e6583c6aa3615432390d1c229fa
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 8 08:25:55 2022 -0500

    GROOVY-9854: STC: propagate `switch` type to `case` closure parameter
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 15 +++++++++++++
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 26 ++++++++++++++++++++++
 2 files changed, 41 insertions(+)

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 ae0acf3d27..8c45a0b7d9 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4085,6 +4085,21 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitCaseStatement(final CaseStatement statement) {
+        Expression expression = statement.getExpression();
+        if (expression instanceof ClosureExpression) { // GROOVY-9854: propagate the switch type
+            SwitchStatement switchStatement = typeCheckingContext.getEnclosingSwitchStatement();
+            ClassNode inf = switchStatement.getExpression().getNodeMetaData(TYPE);
+            expression.putNodeMetaData(CLOSURE_ARGUMENTS, new ClassNode[]{inf});
+
+            Parameter[] params = ((ClosureExpression) expression).getParameters();
+            if (params != null && params.length == 1) {
+                boolean lambda = (expression instanceof LambdaExpression);
+                checkParamType(params[0], wrapTypeIfNecessary(inf), false, lambda);
+            } else if (params == null || params.length > 1) {
+                int paramCount = (params != null ? params.length : 0);
+                addError("Incorrect number of parameters. Expected 1 but found " + paramCount, expression);
+            }
+        }
         super.visitCaseStatement(statement);
         restoreTypeBeforeConditional();
     }
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index 975e1c8602..1f6bd95af2 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -1458,6 +1458,32 @@ class ClosureParamTypeInferenceSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    void testGroovy9854() {
+        assertScript '''
+            def result = switch (42) {
+                case { i -> i > 0 } -> 'positive'
+                case { it < 0 } -> 'negative'
+                default -> 'zero'
+            }
+            assert result == 'positive'
+        '''
+
+        shouldFailWithMessages '''
+            switch (42) { case { -> }: break; }
+        ''',
+        'Incorrect number of parameters. Expected 1 but found 0'
+
+        shouldFailWithMessages '''
+            switch (42) { case { i, j -> }: break; }
+        ''',
+        'Incorrect number of parameters. Expected 1 but found 2'
+
+        shouldFailWithMessages '''
+            switch (42) { case { String s -> }: break; }
+        ''',
+        'Expected type java.lang.Integer for closure parameter: s'
+    }
+
     void testGroovy9968() {
         assertScript '''
             import groovy.transform.*