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

emilles pushed a commit to branch GROOVY-11669
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit cd150946b1e0155e0e86ddc34b050de771223f58
Author: Eric Milles <[email protected]>
AuthorDate: Sat May 17 23:42:14 2025 -0500

    GROOVY-11669: SC: support `ClassLiteral::javaLangClassMethod`
---
 ...StaticTypesMethodReferenceExpressionWriter.java | 24 ++++++++++++-
 .../transform/stc/MethodReferenceTest.groovy       | 41 ++++++++++++++++++++--
 2 files changed, 62 insertions(+), 3 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
index fa7c4d8263..c526caa7b4 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesMethodReferenceExpressionWriter.java
@@ -59,6 +59,7 @@ import static 
org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.extractPlaceholders;
+import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafe0;
 import static org.codehaus.groovy.ast.tools.ParameterUtils.isVargs;
 import static 
org.codehaus.groovy.ast.tools.ParameterUtils.parametersCompatible;
 import static org.codehaus.groovy.runtime.ArrayGroovyMethods.last;
@@ -116,10 +117,16 @@ public class StaticTypesMethodReferenceExpressionWriter 
extends MethodReferenceE
                 Map<MethodNode,MethodNode> bridgeMethods = 
typeOrTargetRefType.redirect().getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS);
                 if (bridgeMethods != null) methodRefMethod = 
bridgeMethods.getOrDefault(methodRefMethod, methodRefMethod); // bridge may not 
have been generated
             }
+            if (methodRefMethod == null && isClassExpression) {
+                var classValue = varX("_class_", typeOrTargetRefType);
+                var classClass = makeClassSafe0(ClassHelper.CLASS_Type, new 
GenericsType(typeOrTargetRefType));
+                methodRefMethod = findMethodRefMethod(methodRefName, 
parametersWithExactType, classValue, classClass);
+                if (methodRefMethod != null) methodRefMethod = 
addSyntheticMethodForClassReference(methodRefMethod, typeOrTargetRefType);
+            }
         }
 
         validate(methodReferenceExpression, typeOrTargetRefType, 
methodRefName, methodRefMethod, parametersWithExactType,
-                resolveClassNodeGenerics(extractPlaceholders(functionalType), 
null, abstractMethod.getReturnType()));
+                    
resolveClassNodeGenerics(extractPlaceholders(functionalType), null, 
abstractMethod.getReturnType()));
 
         if (isBridgeMethod(methodRefMethod)) {
             targetIsArgument = true; // GROOVY-11301, GROOVY-11365
@@ -242,6 +249,21 @@ public class StaticTypesMethodReferenceExpressionWriter 
extends MethodReferenceE
         return delegateMethod;
     }
 
+    private MethodNode addSyntheticMethodForClassReference(final MethodNode 
mn, final ClassNode classType) {
+        MethodCallExpression methodCall = callX(classX(classType), 
mn.getName(), new ArgumentListExpression(mn.getParameters()));
+        methodCall.setImplicitThis(false);
+        methodCall.setMethodTarget(mn);
+        
methodCall.putNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, mn);
+
+        String methodName = "class$" + classType.getNameWithoutPackage() + "$" 
+ mn.getName() + "$" + System.nanoTime();
+
+        ClassNode returnType = resolveClassNodeGenerics(Map.of(new 
GenericsType.GenericsTypeName("T"), new GenericsType(classType)), null, 
mn.getReturnType());
+
+        MethodNode delegateMethod = addSyntheticMethod(methodName, returnType, 
methodCall, mn.getParameters(), mn.getExceptions());
+        
delegateMethod.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE,
 Boolean.TRUE);
+        return delegateMethod;
+    }
+
     private MethodNode addSyntheticMethodForVariadicReference(final MethodNode 
mn, final int samParameters, final boolean isStaticTarget) {
         Parameter[] parameters = new Parameter[samParameters];
         Expression arguments, receiver;
diff --git a/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy 
b/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy
index 74288f1eb4..2446bd8093 100644
--- a/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy
@@ -918,6 +918,33 @@ final class MethodReferenceTest {
         '''
     }
 
+    // GROOVY-11669
+    @Test // class::classMethod
+    void testFunctionCC1() {
+        assertScript shell, '''
+            @CompileStatic
+            void test() {
+                [1,2,3].stream().map(Number::cast).collect(Collectors.toList())
+            }
+
+            test()
+        '''
+    }
+
+    // GROOVY-11669
+    @Test // class::classMethod
+    void testFunctionCC2() {
+        def err = shouldFail shell, '''
+            @CompileStatic
+            void test() {
+                [1,2,3].stream().map(String::cast).collect(Collectors.toList())
+            }
+
+            test()
+        '''
+        assert err =~ /ClassCastException: Cannot cast java.lang.Integer to 
java.lang.String/
+    }
+
     @Test // class::new
     void testFunctionCN1() {
         assertScript shell, '''
@@ -1422,13 +1449,23 @@ final class MethodReferenceTest {
 
             test()
         '''
+        assertScript shell, '''
+            @CompileStatic
+            void test() {
+                Supplier<String> s = Object::toString
+                def result = s.get()
+                assert result == 'class java.lang.Object'
+            }
+
+            test()
+        '''
         def err = shouldFail shell, '''
             @CompileStatic
             void test() {
-                Supplier<String> s = Object::toString // all options require 
an object
+                BinaryOperator<String> s = Object::toString
             }
         '''
-        assert err.message.contains("Failed to find class method 'toString()' 
for the type: java.lang.Object")
+        assert err.message.contains("Failed to find class method 
'toString(java.lang.String,java.lang.String)' or instance method 
'toString(java.lang.String)' for the type: java.lang.Object")
     }
 
     // GROOVY-10859

Reply via email to