This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY_4_0_X in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push: new fd952456e3 GROOVY-11201: STC: support method pointer to SAM-type assignment fd952456e3 is described below commit fd952456e33aa3cdd90393af8eebe57815fa6575 Author: Eric Milles <eric.mil...@thomsonreuters.com> AuthorDate: Sun Oct 22 12:49:25 2023 -0500 GROOVY-11201: STC: support method pointer to SAM-type assignment --- .../transform/stc/StaticTypeCheckingVisitor.java | 33 +++++++++---- src/test/groovy/transform/stc/BugsSTCTest.groovy | 55 ++++++++++++---------- 2 files changed, 55 insertions(+), 33 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 a1cf015808..1b8b69fb73 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -4437,15 +4437,30 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { if (op == EQUAL || op == ELVIS_EQUAL) { if (rightRedirect.isDerivedFrom(CLOSURE_TYPE)) { - ClosureExpression closureExpression = null; - if (rightExpression instanceof ClosureExpression) { - closureExpression = (ClosureExpression) rightExpression; - } else if (rightExpression instanceof MethodReferenceExpression) { - closureExpression = rightExpression.getNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION); - } - if (closureExpression != null) { - MethodNode abstractMethod = findSAM(left); - if (abstractMethod != null) { + MethodNode abstractMethod = findSAM(left); + if (abstractMethod != null) { + ClosureExpression closureExpression = null; + if (rightExpression instanceof ClosureExpression) { + closureExpression = (ClosureExpression) rightExpression; + } else if (rightExpression instanceof MethodPointerExpression) { + closureExpression = rightExpression.getNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION); + if (closureExpression == null) { // GROOVY-11201 + ClassNode[] paramTypes; + List<MethodNode> methods = rightExpression.getNodeMetaData(MethodNode.class); + if (methods == null || methods.isEmpty()) { int nParameters = abstractMethod.getParameters().length; + paramTypes = IntStream.range(0, nParameters).mapToObj(i -> dynamicType()).toArray(ClassNode[]::new); + } else { + paramTypes = collateMethodReferenceParameterTypes((MethodPointerExpression) rightExpression, methods.get(0)); + } + Parameter[] parameters = new Parameter[paramTypes.length]; + for (int i = 0; i < paramTypes.length; i += 1) { + parameters[i] = new Parameter(paramTypes[i], "p" + i); + } + closureExpression = new ClosureExpression(parameters, GENERATED_EMPTY_STATEMENT); + closureExpression.putNodeMetaData(INFERRED_TYPE, rightExpression.getNodeMetaData(INFERRED_TYPE)); + } + } + if (closureExpression != null) { return inferSAMTypeGenericsInAssignment(left, abstractMethod, right, closureExpression); } } diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy b/src/test/groovy/transform/stc/BugsSTCTest.groovy index a50dfde53a..91d339ca84 100644 --- a/src/test/groovy/transform/stc/BugsSTCTest.groovy +++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy @@ -655,29 +655,24 @@ assert o.bar() == 2*o.x // GROOVY-6965 void testShouldNotFailWithClassCastExceptionDuringCompilation() { assertScript ''' -interface Job { - Runnable getRunnable() -} - - -class Printer implements Job{ - - protected void execute() { - println "Printing" - } - - public void acceptsRunnable(Runnable r){ - r.run() - } - - public Runnable getRunnable(){ - acceptsRunnable(this.&execute) // OK - return this.&execute // compile error - } -} + interface Job { + Runnable getRunnable() + } + class Printer implements Job { + protected void execute() { + println "Printing" + } + void acceptsRunnable(Runnable r) { + r.run() + } + Runnable getRunnable() { + acceptsRunnable(this.&execute) // works + return this.&execute // fails + } + } -Printer -''' + new Printer().runnable.run() + ''' } // GROOVY-6970 @@ -968,14 +963,26 @@ Printer shouldFailWithMessages ''' class C { final foo } def set = C.&setFoo - ''', 'Cannot find matching method C#setFoo' + ''', + 'Cannot find matching method C#setFoo' } // GROOVY-9463 void testMethodPointerUnknownReference() { shouldFailWithMessages ''' def ptr = String.&toLowerCaseX - ''', 'Cannot find matching method java.lang.String#toLowerCaseX.' + ''', + 'Cannot find matching method java.lang.String#toLowerCaseX' + } + + // GROOVY-11201 + void testMethodPointerClosureCoercion() { + for (op in ['.&', '::']) { + assertScript """import java.util.function.Consumer + void setX(String string) { } + Consumer<String> c = this${op}setX + """ + } } // GROOVY-9938