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:34 UTC
[groovy] branch master updated (8eaae55 -> 9a63e8c)
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git.
from 8eaae55 GROOVY-8104: fix this$0 for closure with anon. inner class of inner type
new 39422ed GROOVY-9995: infer ctor call diamond type from closure target type
new 9a63e8c GROOVY-9997: infer closure/lambda params + return types from cast/coerce
The 2 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/stc/StaticTypeCheckingVisitor.java | 46 +++++++++++++++-------
.../groovy/transform/stc/GenericsSTCTest.groovy | 20 ++++++++++
src/test/groovy/transform/stc/LambdaTest.groovy | 15 +++++++
.../groovy/console/ui/ButtonOrTextEditor.groovy | 4 +-
4 files changed, 69 insertions(+), 16 deletions(-)
[groovy] 02/02: GROOVY-9997: infer closure/lambda params + return
types from cast/coerce
Posted by su...@apache.org.
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
}
[groovy] 01/02: GROOVY-9995: infer ctor call diamond type from
closure target type
Posted by su...@apache.org.
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 39422ed19bb739603d56ec5aa7e07bd2f89cc649
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Mar 22 12:27:23 2021 -0500
GROOVY-9995: infer ctor call diamond type from closure target type
---
.../transform/stc/StaticTypeCheckingVisitor.java | 25 +++++++++++++++++-----
.../groovy/transform/stc/GenericsSTCTest.groovy | 20 +++++++++++++++++
2 files changed, 40 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 ed54498..e611cee 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -749,8 +749,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
lType = getType(leftExpression);
} else {
lType = getType(leftExpression);
- if (op == ASSIGN && isFunctionalInterface(lType)) {
- processFunctionalInterfaceAssignment(lType, rightExpression);
+ if (op == ASSIGN) {
+ if (isFunctionalInterface(lType)) {
+ processFunctionalInterfaceAssignment(lType, rightExpression);
+ } else if (isClosureWithType(lType) && rightExpression instanceof ClosureExpression) {
+ storeInferredReturnType(rightExpression, getCombinedBoundType(lType.getGenericsTypes()[0]));
+ }
}
rightExpression.visit(this);
}
@@ -994,6 +998,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
}
+ private static boolean isClosureWithType(final ClassNode type) {
+ return type.equals(CLOSURE_TYPE) && Optional.ofNullable(type.getGenericsTypes()).filter(gts -> gts != null && gts.length == 1).isPresent();
+ }
+
private boolean isCompoundAssignment(final Expression exp) {
if (!(exp instanceof BinaryExpression)) return false;
int type = ((BinaryExpression) exp).getOperation().getType();
@@ -1275,7 +1283,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
ClassNode rTypeInferred, rTypeWrapped; // check for instanceof and spreading
if (rightExpression instanceof VariableExpression && hasInferredReturnType(rightExpression) && assignmentExpression.getOperation().getType() == ASSIGN) {
- rTypeInferred = rightExpression.getNodeMetaData(INFERRED_RETURN_TYPE);
+ rTypeInferred = getInferredReturnType(rightExpression);
} else {
rTypeInferred = rightExpressionType;
}
@@ -1847,6 +1855,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
ClassNode lType = getType(node);
if (isFunctionalInterface(lType)) { // GROOVY-9977
processFunctionalInterfaceAssignment(lType, init);
+ } else if (isClosureWithType(lType) && init instanceof ClosureExpression) {
+ storeInferredReturnType(init, getCombinedBoundType(lType.getGenericsTypes()[0]));
}
init.visit(this);
ClassNode rType = getType(init);
@@ -2147,11 +2157,16 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
Expression expression = statement.getExpression();
ClassNode type;
if (expression instanceof VariableExpression && hasInferredReturnType(expression)) {
- type = expression.getNodeMetaData(INFERRED_RETURN_TYPE);
+ type = getInferredReturnType(expression);
} else {
type = getType(expression);
}
if (typeCheckingContext.getEnclosingClosure() != null) {
+ // GROOVY-9995: return ctor call with diamond operator
+ if (expression instanceof ConstructorCallExpression) {
+ ClassNode inferredClosureReturnType = getInferredReturnType(typeCheckingContext.getEnclosingClosure().getClosureExpression());
+ if (inferredClosureReturnType != null) inferDiamondType((ConstructorCallExpression) expression, inferredClosureReturnType);
+ }
return type;
}
MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
@@ -4159,7 +4174,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
* @param type the inferred type of {@code expr}
*/
private ClassNode checkForTargetType(final Expression expr, final ClassNode type) {
- ClassNode sourceType = (hasInferredReturnType(expr) ? expr.getNodeMetaData(INFERRED_RETURN_TYPE) : type);
+ ClassNode sourceType = (hasInferredReturnType(expr) ? getInferredReturnType(expr) : type);
ClassNode targetType = null;
MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index dc1a4ae..7c74674 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -475,6 +475,26 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-9995
+ void testDiamondInferrenceFromConstructor12() {
+ [
+ ['Closure<A<Long>>', 'java.util.concurrent.Callable<A<Long>>'],
+ ['new A<>(42L)', 'return new A<>(42L)']
+ ].combinations { functionalType, returnStmt ->
+ assertScript """
+ @groovy.transform.TupleConstructor(defaults=false)
+ class A<T extends Number> {
+ T p
+ }
+ $functionalType callable = { ->
+ $returnStmt
+ }
+ Long n = callable.call().p
+ assert n == 42L
+ """
+ }
+ }
+
void testLinkedListWithListArgument() {
assertScript '''
List<String> list = new LinkedList<String>(['1','2','3'])