Search in sources :

Example 6 with ExtensionMethodNode

use of org.codehaus.groovy.transform.stc.ExtensionMethodNode in project groovy by apache.

the class StaticTypesMethodReferenceExpressionWriter method writeMethodReferenceExpression.

@Override
public void writeMethodReferenceExpression(final MethodReferenceExpression methodReferenceExpression) {
    ClassNode functionalInterfaceType = getFunctionalInterfaceType(methodReferenceExpression);
    if (!ClassHelper.isFunctionalInterface(functionalInterfaceType)) {
        // generate the default bytecode; most likely a method closure
        super.writeMethodReferenceExpression(methodReferenceExpression);
        return;
    }
    ClassNode redirect = functionalInterfaceType.redirect();
    MethodNode abstractMethod = ClassHelper.findSAM(redirect);
    String abstractMethodDesc = createMethodDescriptor(abstractMethod);
    ClassNode classNode = controller.getClassNode();
    Expression typeOrTargetRef = methodReferenceExpression.getExpression();
    boolean isClassExpression = (typeOrTargetRef instanceof ClassExpression);
    ClassNode typeOrTargetRefType = isClassExpression ? typeOrTargetRef.getType() : controller.getTypeChooser().resolveType(typeOrTargetRef, classNode);
    ClassNode[] methodReferenceParamTypes = methodReferenceExpression.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
    Parameter[] parametersWithExactType = createParametersWithExactType(abstractMethod, methodReferenceParamTypes);
    String methodRefName = methodReferenceExpression.getMethodName().getText();
    boolean isConstructorReference = isConstructorReference(methodRefName);
    MethodNode methodRefMethod;
    if (isConstructorReference) {
        methodRefName = controller.getContext().getNextConstructorReferenceSyntheticMethodName(controller.getMethodNode());
        methodRefMethod = addSyntheticMethodForConstructorReference(methodRefName, typeOrTargetRefType, parametersWithExactType);
    } else {
        // TODO: move the findMethodRefMethod and checking to StaticTypeCheckingVisitor
        methodRefMethod = findMethodRefMethod(methodRefName, parametersWithExactType, typeOrTargetRef, typeOrTargetRefType);
    }
    validate(methodReferenceExpression, typeOrTargetRef, typeOrTargetRefType, methodRefName, parametersWithExactType, methodRefMethod);
    if (isExtensionMethod(methodRefMethod)) {
        ExtensionMethodNode extensionMethodNode = (ExtensionMethodNode) methodRefMethod;
        methodRefMethod = extensionMethodNode.getExtensionMethodNode();
        if (extensionMethodNode.isStaticExtension()) {
            methodRefMethod = addSyntheticMethodForDGSM(methodRefMethod);
        }
        typeOrTargetRefType = methodRefMethod.getDeclaringClass();
        Expression classExpression = classX(typeOrTargetRefType);
        classExpression.setSourcePosition(typeOrTargetRef);
        typeOrTargetRef = classExpression;
    }
    methodRefMethod.putNodeMetaData(ORIGINAL_PARAMETERS_WITH_EXACT_TYPE, parametersWithExactType);
    if (!isClassExpression) {
        if (isConstructorReference) {
            // TODO: move the checking code to the parser
            addFatalError("Constructor reference must be className::new", methodReferenceExpression);
        } else if (methodRefMethod.isStatic()) {
            ClassExpression classExpression = classX(typeOrTargetRefType);
            classExpression.setSourcePosition(typeOrTargetRef);
            typeOrTargetRef = classExpression;
            isClassExpression = true;
        } else {
            typeOrTargetRef.visit(controller.getAcg());
        }
    }
    controller.getMethodVisitor().visitInvokeDynamicInsn(abstractMethod.getName(), createAbstractMethodDesc(functionalInterfaceType, typeOrTargetRef), createBootstrapMethod(classNode.isInterface(), false), createBootstrapMethodArguments(abstractMethodDesc, methodRefMethod.isStatic() || isConstructorReference ? Opcodes.H_INVOKESTATIC : Opcodes.H_INVOKEVIRTUAL, isConstructorReference ? controller.getClassNode() : typeOrTargetRefType, methodRefMethod, false));
    if (isClassExpression) {
        controller.getOperandStack().push(redirect);
    } else {
        controller.getOperandStack().replace(redirect, 1);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) StaticTypeCheckingSupport.findDGMMethodsForClassNode(org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsForClassNode) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ArrayExpression(org.codehaus.groovy.ast.expr.ArrayExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) MethodReferenceExpression(org.codehaus.groovy.ast.expr.MethodReferenceExpression) Parameter(org.codehaus.groovy.ast.Parameter) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode)

Aggregations

MethodNode (org.codehaus.groovy.ast.MethodNode)6 ExtensionMethodNode (org.codehaus.groovy.transform.stc.ExtensionMethodNode)6 ClassNode (org.codehaus.groovy.ast.ClassNode)5 Expression (org.codehaus.groovy.ast.expr.Expression)5 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)5 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)4 TupleExpression (org.codehaus.groovy.ast.expr.TupleExpression)4 Parameter (org.codehaus.groovy.ast.Parameter)3 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)3 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)3 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)2 ArrayExpression (org.codehaus.groovy.ast.expr.ArrayExpression)2 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)2 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)2 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)2 SyntaxException (org.codehaus.groovy.syntax.SyntaxException)2 MethodVisitor (org.objectweb.asm.MethodVisitor)2 ArrayList (java.util.ArrayList)1 LinkedList (java.util.LinkedList)1 ExpressionUtils.isSuperExpression (org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression)1