You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/03/24 14:43:36 UTC

[groovy] 02/02: GROOVY-9997: infer closure/lambda params + return types from cast/coerce

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

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

commit 9a63e8cc7bd9bdb1efd97046907549199260e715
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Mar 22 21:54:30 2021 -0500

    GROOVY-9997: infer closure/lambda params + return types from cast/coerce
---
 .../transform/stc/StaticTypeCheckingVisitor.java    | 21 ++++++++++++---------
 src/test/groovy/transform/stc/LambdaTest.groovy     | 15 +++++++++++++++
 .../groovy/console/ui/ButtonOrTextEditor.groovy     |  4 ++--
 3 files changed, 29 insertions(+), 11 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 e611cee..888a1c5 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4092,16 +4092,19 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitCastExpression(final CastExpression expression) {
-        super.visitCastExpression(expression);
-        if (!expression.isCoerce()) {
-            ClassNode targetType = expression.getType();
-            Expression source = expression.getExpression();
-            ClassNode expressionType = getType(source);
-            if (!checkCast(targetType, source) && !isDelegateOrOwnerInClosure(source)) {
-                addStaticTypeError("Inconvertible types: cannot cast " + prettyPrintType(expressionType) + " to " + prettyPrintType(targetType), expression);
-            }
+        ClassNode type = expression.getType();
+        Expression source = expression.getExpression();
+        if (isFunctionalInterface(type)) { // GROOVY-9997
+            processFunctionalInterfaceAssignment(type, source);
+        } else if (isClosureWithType(type) && source instanceof ClosureExpression) {
+            storeInferredReturnType(source, getCombinedBoundType(type.getGenericsTypes()[0]));
+        }
+
+        source.visit(this);
+
+        if (!expression.isCoerce() && !checkCast(type, source) && !isDelegateOrOwnerInClosure(source)) {
+            addStaticTypeError("Inconvertible types: cannot cast " + prettyPrintType(getType(source)) + " to " + prettyPrintType(type), expression);
         }
-        storeType(expression, expression.getType());
     }
 
     private boolean isDelegateOrOwnerInClosure(final Expression exp) {
diff --git a/src/test/groovy/transform/stc/LambdaTest.groovy b/src/test/groovy/transform/stc/LambdaTest.groovy
index 618f18f..be0e437 100644
--- a/src/test/groovy/transform/stc/LambdaTest.groovy
+++ b/src/test/groovy/transform/stc/LambdaTest.groovy
@@ -330,6 +330,21 @@ final class LambdaTest {
         '''
     }
 
+    @Test // GROOVY-9997
+    void testComparator3() {
+        assertScript '''
+            @groovy.transform.TypeChecked
+            void test() {
+                def cast = (Comparator<Integer>) (a, b) -> Integer.compare(a, b)
+                assert cast.compare(0,0) == 0
+
+                def coerce = ((a, b) -> Integer.compare(a, b)) as Comparator<Integer>
+                assert coerce.compare(0,0) == 0
+            }
+            test()
+        '''
+    }
+
     @Test
     void testFunctionWithLocalVariables() {
         assertScript '''
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy
index ddb97ce..38992ce 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy
@@ -44,12 +44,12 @@ class ButtonOrTextEditor extends AbstractCellEditor implements TableCellEditor {
     Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
         if (value instanceof JButton) {
             editorComponent = value
-            ((JButton) editorComponent).addActionListener({ fireEditingStopped() } as ActionListener)
+            ((JButton) editorComponent).addActionListener({ e -> fireEditingStopped() } as ActionListener)
         } else if (value instanceof JTextArea) {
             editorComponent = value
         } else if (value) {
             editorComponent = new JTextArea(value.toString())
-            editorComponent.addFocusListener({ fireEditingCanceled() } as FocusListener)
+            editorComponent.addFocusListener({ e -> fireEditingCanceled() } as FocusListener)
         } else {
             editorComponent = null
         }