protected void inferClosureParameterTypes(final ClassNode receiver, final Expression arguments, final ClosureExpression expression, final Parameter param, final MethodNode selectedMethod) {
        List<AnnotationNode> annotations = param.getAnnotations(CLOSUREPARAMS_CLASSNODE);
        if (annotations != null && !annotations.isEmpty()) {
            for (AnnotationNode annotation : annotations) {
                Expression hintClass = annotation.getMember("value");
                Expression options = annotation.getMember("options");
                Expression resolverClass = annotation.getMember("conflictResolutionStrategy");
                if (hintClass instanceof ClassExpression) {
                    doInferClosureParameterTypes(receiver, arguments, expression, selectedMethod, hintClass, resolverClass, options);
                }
            }
        } else if (isSAMType(param.getOriginType())) {
            // SAM coercion
            inferSAMType(param, receiver, selectedMethod, InvocationWriter.makeArgumentList(arguments), expression);
        }
    }
protected void inferClosureParameterTypes ( final ClassNode receiver , final Expression arguments , final ClosureExpression expression , final Parameter param , final MethodNode selectedMethod ) { List < AnnotationNode > annotations = param . getAnnotations ( CLOSUREPARAMS_CLASSNODE ) ; if ( annotations != null && ! annotations . isEmpty ( ) ) { for ( AnnotationNode annotation : annotations ) { Expression hintClass = annotation . getMember ( "value" ) ; Expression options = annotation . getMember ( "options" ) ; Expression resolverClass = annotation . getMember ( "conflictResolutionStrategy" ) ; if ( hintClass instanceof ClassExpression ) { doInferClosureParameterTypes ( receiver , arguments , expression , selectedMethod , hintClass , resolverClass , options ) ; } } } else if ( isSAMType ( param . getOriginType ( ) ) ) { inferSAMType ( param , receiver , selectedMethod , InvocationWriter . makeArgumentList ( arguments ) , expression ) ; } }
This method is responsible for performing type inference on closure argument types whenever code like this is
found: <code>foo.collect { it.toUpperCase() }</code>.
In this case, the type checker tries to find if the <code>collect</code> method has its {@link Closure} argument
annotated with {@link groovy.transform.stc.ClosureParams}. If yes, then additional type inference can be performed
and the type of <code>it</code> may be inferred.

@param receiver
@param arguments
@param expression     a closure expression for which the argument types should be inferred
@param param          the parameter where to look for a {@link groovy.transform.stc.ClosureParams} annotation.
@param selectedMethod the method accepting a closure