Search in sources :

Example 31 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method getType.

protected ClassNode getType(ASTNode exp) {
    ClassNode cn = exp.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
    if (cn != null)
        return cn;
    if (exp instanceof ClassExpression) {
        ClassNode node = CLASS_Type.getPlainNodeReference();
        node.setGenericsTypes(new GenericsType[] { new GenericsType(((ClassExpression) exp).getType()) });
        return node;
    } else if (exp instanceof VariableExpression) {
        VariableExpression vexp = (VariableExpression) exp;
        if (vexp == VariableExpression.THIS_EXPRESSION)
            return makeThis();
        if (vexp == VariableExpression.SUPER_EXPRESSION)
            return makeSuper();
        ClassNode selfTrait = isTraitSelf(vexp);
        if (selfTrait != null)
            return makeSelf(selfTrait);
        final Variable variable = vexp.getAccessedVariable();
        if (variable instanceof FieldNode) {
            checkOrMarkPrivateAccess(vexp, (FieldNode) variable);
            return getType((FieldNode) variable);
        }
        if (variable != null && variable != vexp && variable instanceof VariableExpression) {
            return getType((Expression) variable);
        }
        if (variable instanceof Parameter) {
            Parameter parameter = (Parameter) variable;
            ClassNode type = typeCheckingContext.controlStructureVariables.get(parameter);
            TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
            ClassNode[] closureParamTypes = (ClassNode[]) (enclosingClosure != null ? enclosingClosure.getClosureExpression().getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS) : null);
            if (type == null && enclosingClosure != null && "it".equals(variable.getName()) && closureParamTypes != null) {
                final Parameter[] parameters = enclosingClosure.getClosureExpression().getParameters();
                if (parameters.length == 0 && getTemporaryTypesForExpression(vexp) == null) {
                    type = closureParamTypes[0];
                }
            }
            if (type != null) {
                storeType((VariableExpression) exp, type);
                return type;
            }
        }
    }
    if (exp instanceof ListExpression) {
        return inferListExpressionType((ListExpression) exp);
    } else if (exp instanceof MapExpression) {
        return inferMapExpressionType((MapExpression) exp);
    }
    if (exp instanceof ConstructorCallExpression) {
        return ((ConstructorCallExpression) exp).getType();
    }
    if (exp instanceof MethodNode) {
        if ((exp == GET_DELEGATE || exp == GET_OWNER || exp == GET_THISOBJECT) && typeCheckingContext.getEnclosingClosure() != null) {
            return typeCheckingContext.getEnclosingClassNode();
        }
        ClassNode ret = getInferredReturnType(exp);
        return ret != null ? ret : ((MethodNode) exp).getReturnType();
    }
    if (exp instanceof ClosureExpression) {
        ClassNode irt = getInferredReturnType(exp);
        if (irt != null) {
            irt = wrapTypeIfNecessary(irt);
            ClassNode result = CLOSURE_TYPE.getPlainNodeReference();
            result.setGenericsTypes(new GenericsType[] { new GenericsType(irt) });
            return result;
        }
    }
    if (exp instanceof RangeExpression) {
        ClassNode plain = ClassHelper.RANGE_TYPE.getPlainNodeReference();
        RangeExpression re = (RangeExpression) exp;
        ClassNode fromType = getType(re.getFrom());
        ClassNode toType = getType(re.getTo());
        if (fromType.equals(toType)) {
            plain.setGenericsTypes(new GenericsType[] { new GenericsType(wrapTypeIfNecessary(fromType)) });
        } else {
            plain.setGenericsTypes(new GenericsType[] { new GenericsType(wrapTypeIfNecessary(lowestUpperBound(fromType, toType))) });
        }
        return plain;
    }
    if (exp instanceof UnaryPlusExpression) {
        return getType(((UnaryPlusExpression) exp).getExpression());
    }
    if (exp instanceof UnaryMinusExpression) {
        return getType(((UnaryMinusExpression) exp).getExpression());
    }
    if (exp instanceof BitwiseNegationExpression) {
        return getType(((BitwiseNegationExpression) exp).getExpression());
    }
    if (exp instanceof MethodCall) {
        MethodNode target = (MethodNode) exp.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
        if (target != null) {
            return getType(target);
        }
    }
    if (exp instanceof Parameter) {
        return ((Parameter) exp).getOriginType();
    }
    if (exp instanceof FieldNode) {
        FieldNode fn = (FieldNode) exp;
        return getGenericsResolvedTypeOfFieldOrProperty(fn, fn.getOriginType());
    }
    if (exp instanceof PropertyNode) {
        PropertyNode pn = (PropertyNode) exp;
        return getGenericsResolvedTypeOfFieldOrProperty(pn, pn.getOriginType());
    }
    return exp instanceof VariableExpression ? ((VariableExpression) exp).getOriginType() : ((Expression) exp).getType();
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Variable(org.codehaus.groovy.ast.Variable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) FieldNode(org.codehaus.groovy.ast.FieldNode) MethodNode(org.codehaus.groovy.ast.MethodNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) GenericsType(org.codehaus.groovy.ast.GenericsType) Parameter(org.codehaus.groovy.ast.Parameter)

Example 32 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method inferSAMType.

private void inferSAMType(Parameter param, ClassNode receiver, MethodNode methodWithSAMParameter, ArgumentListExpression originalMethodCallArguments, ClosureExpression openBlock) {
    // In a method call with SAM coercion the inference is to be
    // understood as a two phase process. We have the normal method call
    // to the target method with the closure argument and we have the 
    // SAM method that will be called inside the normal target method. 
    // To infer correctly we have to "simulate" this process. We know the
    // call to the closure will be done through the SAM type, so the SAM
    // type generics deliver information about the Closure. At the same
    // time the SAM class is used in the target method parameter, 
    // providing a connection from the SAM type and the target method
    // declaration class.
    // First we try to get as much information about the declaration
    // class through the receiver
    Map<String, GenericsType> targetMethodDeclarationClassConnections = new HashMap<String, GenericsType>();
    extractGenericsConnections(targetMethodDeclarationClassConnections, receiver, receiver.redirect());
    // then we use the method with the SAM parameter to get more information about the declaration
    Parameter[] parametersOfMethodContainingSAM = methodWithSAMParameter.getParameters();
    for (int i = 0; i < parametersOfMethodContainingSAM.length; i++) {
        Expression callArg = originalMethodCallArguments.getExpression(i);
        // we look at the closure later in detail, so skip it here
        if (callArg == openBlock)
            continue;
        ClassNode parameterType = parametersOfMethodContainingSAM[i].getType();
        extractGenericsConnections(targetMethodDeclarationClassConnections, getType(callArg), parameterType);
    }
    // To make a connection to the SAM class we use that new information
    // to replace the generics in the SAM type parameter of the target
    // method and than that to make the connections to the SAM type generics
    ClassNode paramTypeWithReceiverInformation = applyGenericsContext(targetMethodDeclarationClassConnections, param.getOriginType());
    Map<String, GenericsType> SAMTypeConnections = new HashMap<String, GenericsType>();
    ClassNode classForSAM = paramTypeWithReceiverInformation.redirect();
    extractGenericsConnections(SAMTypeConnections, paramTypeWithReceiverInformation, classForSAM);
    // should the open block provide final information we apply that
    // to the corresponding parameters of the SAM type method
    MethodNode methodForSAM = findSAM(classForSAM);
    ClassNode[] parameterTypesForSAM = extractTypesFromParameters(methodForSAM.getParameters());
    ClassNode[] blockParameterTypes = (ClassNode[]) openBlock.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
    if (blockParameterTypes == null) {
        Parameter[] p = openBlock.getParameters();
        if (p.length == 0 && parameterTypesForSAM.length != 0) {
            // implicit it
            blockParameterTypes = parameterTypesForSAM;
        } else {
            blockParameterTypes = extractTypesFromParameters(p);
        }
    }
    for (int i = 0; i < blockParameterTypes.length; i++) {
        //TODO: equal length guaranteed?
        extractGenericsConnections(SAMTypeConnections, blockParameterTypes[i], parameterTypesForSAM[i]);
    }
    // store the type of parameter and block type as meta information
    for (int i = 0; i < blockParameterTypes.length; i++) {
        //TODO: equal length guaranteed?
        ClassNode resolvedParameter = applyGenericsContext(SAMTypeConnections, parameterTypesForSAM[i]);
        blockParameterTypes[i] = resolvedParameter;
    }
    openBlock.putNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS, blockParameterTypes);
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) LinkedHashMap(java.util.LinkedHashMap) ListHashMap(org.codehaus.groovy.util.ListHashMap) HashMap(java.util.HashMap) GenericsType(org.codehaus.groovy.ast.GenericsType) Parameter(org.codehaus.groovy.ast.Parameter) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

Example 33 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method convertClosureTypeToSAMType.

/**
     * This method will convert a closure type to the appropriate SAM type, which will be used
     * to infer return type generics.
     *
     * @param closureType the inferred type of a closure (Closure&lt;ClosureReturnType&gt;)
     * @param samType the type into which the closure is coerced into
     * @return same SAM type, but completed with information from the closure node
     */
private static ClassNode convertClosureTypeToSAMType(final Expression expression, final ClassNode closureType, final ClassNode samType, final Map<String, GenericsType> placeholders) {
    if (!samType.isUsingGenerics())
        return samType;
    // use the generics information from the Closure to further specify the type
    MethodNode sam = findSAM(samType);
    if (closureType.isUsingGenerics() && sam != null) {
        //correct SAM type for generics
        //sam = applyGenericsContext(placeholders, sam);
        // the return type of the SAM method exactly corresponds to the inferred return type
        ClassNode samReturnType = sam.getReturnType();
        ClassNode closureReturnType = expression.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
        if (closureReturnType != null && closureReturnType.isUsingGenerics()) {
            ClassNode unwrapped = closureReturnType.getGenericsTypes()[0].getType();
            extractGenericsConnections(placeholders, unwrapped, samReturnType);
        } else if (samReturnType.isGenericsPlaceHolder()) {
            placeholders.put(samReturnType.getGenericsTypes()[0].getName(), closureType.getGenericsTypes()[0]);
        }
        // now repeat the same for each parameter given in the ClosureExpression
        if (expression instanceof ClosureExpression) {
            List<ClassNode[]> genericsToConnect = new LinkedList<ClassNode[]>();
            Parameter[] closureParams = ((ClosureExpression) expression).getParameters();
            ClassNode[] closureParamTypes = extractTypesFromParameters(closureParams);
            if (expression.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS) != null) {
                closureParamTypes = expression.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
            }
            final Parameter[] parameters = sam.getParameters();
            for (int i = 0; i < parameters.length; i++) {
                final Parameter parameter = parameters[i];
                if (parameter.getOriginType().isUsingGenerics() && closureParamTypes.length > i) {
                    genericsToConnect.add(new ClassNode[] { closureParamTypes[i], parameter.getOriginType() });
                }
            }
            for (ClassNode[] classNodes : genericsToConnect) {
                ClassNode found = classNodes[0];
                ClassNode expected = classNodes[1];
                if (!isAssignableTo(found, expected)) {
                    // probably facing a type mismatch
                    continue;
                }
                ClassNode generifiedType = GenericsUtils.parameterizeType(found, expected);
                while (expected.isArray()) {
                    expected = expected.getComponentType();
                    generifiedType = generifiedType.getComponentType();
                }
                if (expected.isGenericsPlaceHolder()) {
                    placeholders.put(expected.getGenericsTypes()[0].getName(), new GenericsType(generifiedType));
                } else {
                    GenericsType[] expectedGenericsTypes = expected.getGenericsTypes();
                    GenericsType[] foundGenericsTypes = generifiedType.getGenericsTypes();
                    for (int i = 0; i < expectedGenericsTypes.length; i++) {
                        final GenericsType type = expectedGenericsTypes[i];
                        if (type.isPlaceholder()) {
                            String name = type.getName();
                            placeholders.put(name, foundGenericsTypes[i]);
                        }
                    }
                }
            }
        }
    }
    ClassNode result = applyGenericsContext(placeholders, samType.redirect());
    return result;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) GenericsType(org.codehaus.groovy.ast.GenericsType) Parameter(org.codehaus.groovy.ast.Parameter) LinkedList(java.util.LinkedList) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

Example 34 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method doInferClosureParameterTypes.

private void doInferClosureParameterTypes(final ClassNode receiver, final Expression arguments, final ClosureExpression expression, final MethodNode selectedMethod, final Expression hintClass, final Expression options) {
    List<ClassNode[]> closureSignatures = getSignaturesFromHint(expression, selectedMethod, hintClass, options);
    List<ClassNode[]> candidates = new LinkedList<ClassNode[]>();
    for (ClassNode[] signature : closureSignatures) {
        // in order to compute the inferred types of the closure parameters, we're using the following trick:
        // 1. create a dummy MethodNode for which the return type is a class node for which the generic types are the types returned by the hint
        // 2. call inferReturnTypeGenerics
        // 3. fetch inferred types from the result of inferReturnTypeGenerics
        // In practice, it could be done differently but it has the main advantage of reusing
        // existing code, hence reducing the amount of code to debug in case of failure.
        ClassNode[] inferred = resolveGenericsFromTypeHint(receiver, arguments, selectedMethod, signature);
        Parameter[] closureParams = expression.getParameters();
        if (// same number of arguments
        signature.length == closureParams.length || // implicit it
        (signature.length == 1 && closureParams.length == 0) || (closureParams.length > signature.length && inferred[inferred.length - 1].isArray())) {
            // vargs
            candidates.add(inferred);
        }
    }
    Parameter[] closureParams = expression.getParameters();
    if (candidates.size() > 1) {
        Iterator<ClassNode[]> candIt = candidates.iterator();
        while (candIt.hasNext()) {
            ClassNode[] inferred = candIt.next();
            final int length = closureParams.length;
            for (int i = 0; i < length; i++) {
                Parameter closureParam = closureParams[i];
                final ClassNode originType = closureParam.getOriginType();
                ClassNode inferredType;
                if (i < inferred.length - 1 || inferred.length == closureParams.length) {
                    inferredType = inferred[i];
                } else {
                    // vargs?
                    ClassNode lastArgInferred = inferred[inferred.length - 1];
                    if (lastArgInferred.isArray()) {
                        inferredType = lastArgInferred.getComponentType();
                    } else {
                        candIt.remove();
                        continue;
                    }
                }
                if (!typeCheckMethodArgumentWithGenerics(originType, inferredType, i == length - 1)) {
                    candIt.remove();
                }
            }
        }
        if (candidates.size() > 1) {
            addError("Ambiguous prototypes for closure. More than one target method matches. Please use explicit argument types.", expression);
        }
    }
    if (candidates.size() == 1) {
        ClassNode[] inferred = candidates.get(0);
        if (closureParams.length == 0 && inferred.length == 1) {
            expression.putNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS, inferred);
        } else {
            final int length = closureParams.length;
            for (int i = 0; i < length; i++) {
                Parameter closureParam = closureParams[i];
                final ClassNode originType = closureParam.getOriginType();
                ClassNode inferredType = OBJECT_TYPE;
                if (i < inferred.length - 1 || inferred.length == closureParams.length) {
                    inferredType = inferred[i];
                } else {
                    // vargs?
                    ClassNode lastArgInferred = inferred[inferred.length - 1];
                    if (lastArgInferred.isArray()) {
                        inferredType = lastArgInferred.getComponentType();
                    } else {
                        addError("Incorrect number of parameters. Expected " + inferred.length + " but found " + closureParams.length, expression);
                    }
                }
                boolean lastArg = i == length - 1;
                if (lastArg && inferredType.isArray()) {
                    if (inferredType.getComponentType().equals(originType)) {
                        inferredType = originType;
                    }
                } else if (!typeCheckMethodArgumentWithGenerics(originType, inferredType, lastArg)) {
                    addError("Expected parameter of type " + inferredType.toString(false) + " but got " + originType.toString(false), closureParam.getType());
                }
                typeCheckingContext.controlStructureVariables.put(closureParam, inferredType);
            }
        }
    }
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Parameter(org.codehaus.groovy.ast.Parameter) LinkedList(java.util.LinkedList) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

Example 35 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method visitClosureExpression.

@Override
public void visitClosureExpression(final ClosureExpression expression) {
    boolean oldStaticContext = typeCheckingContext.isInStaticContext;
    typeCheckingContext.isInStaticContext = false;
    // collect every variable expression used in the loop body
    final Map<VariableExpression, ClassNode> varOrigType = new HashMap<VariableExpression, ClassNode>();
    Statement code = expression.getCode();
    code.visit(new VariableExpressionTypeMemoizer(varOrigType));
    Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking();
    // first, collect closure shared variables and reinitialize types
    SharedVariableCollector collector = new SharedVariableCollector(getSourceUnit());
    collector.visitClosureExpression(expression);
    Set<VariableExpression> closureSharedExpressions = collector.getClosureSharedExpressions();
    Map<VariableExpression, ListHashMap> typesBeforeVisit = null;
    if (!closureSharedExpressions.isEmpty()) {
        typesBeforeVisit = new HashMap<VariableExpression, ListHashMap>();
        saveVariableExpressionMetadata(closureSharedExpressions, typesBeforeVisit);
    }
    // perform visit
    typeCheckingContext.pushEnclosingClosureExpression(expression);
    DelegationMetadata dmd = getDelegationMetadata(expression);
    if (dmd == null) {
        typeCheckingContext.delegationMetadata = new DelegationMetadata(typeCheckingContext.getEnclosingClassNode(), Closure.OWNER_FIRST, typeCheckingContext.delegationMetadata);
    } else {
        typeCheckingContext.delegationMetadata = new DelegationMetadata(dmd.getType(), dmd.getStrategy(), typeCheckingContext.delegationMetadata);
    }
    super.visitClosureExpression(expression);
    typeCheckingContext.delegationMetadata = typeCheckingContext.delegationMetadata.getParent();
    MethodNode node = new MethodNode("dummy", 0, ClassHelper.OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, code);
    returnAdder.visitMethod(node);
    TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
    if (!enclosingClosure.getReturnTypes().isEmpty()) {
        ClassNode returnType = lowestUpperBound(enclosingClosure.getReturnTypes());
        storeInferredReturnType(expression, returnType);
        ClassNode inferredType = wrapClosureType(returnType);
        storeType(enclosingClosure.getClosureExpression(), inferredType);
    }
    typeCheckingContext.popEnclosingClosure();
    boolean typeChanged = isSecondPassNeededForControlStructure(varOrigType, oldTracker);
    if (typeChanged)
        visitClosureExpression(expression);
    // restore original metadata
    restoreVariableExpressionMetadata(typesBeforeVisit);
    typeCheckingContext.isInStaticContext = oldStaticContext;
    Parameter[] parameters = expression.getParameters();
    if (parameters != null) {
        for (Parameter parameter : parameters) {
            typeCheckingContext.controlStructureVariables.remove(parameter);
        }
    }
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedHashMap(java.util.LinkedHashMap) ListHashMap(org.codehaus.groovy.util.ListHashMap) HashMap(java.util.HashMap) CaseStatement(org.codehaus.groovy.ast.stmt.CaseStatement) WhileStatement(org.codehaus.groovy.ast.stmt.WhileStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) ForStatement(org.codehaus.groovy.ast.stmt.ForStatement) CatchStatement(org.codehaus.groovy.ast.stmt.CatchStatement) IfStatement(org.codehaus.groovy.ast.stmt.IfStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) SwitchStatement(org.codehaus.groovy.ast.stmt.SwitchStatement) TryCatchStatement(org.codehaus.groovy.ast.stmt.TryCatchStatement) ListHashMap(org.codehaus.groovy.util.ListHashMap) MethodNode(org.codehaus.groovy.ast.MethodNode) Parameter(org.codehaus.groovy.ast.Parameter) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList)

Aggregations

Parameter (org.codehaus.groovy.ast.Parameter)221 ClassNode (org.codehaus.groovy.ast.ClassNode)135 MethodNode (org.codehaus.groovy.ast.MethodNode)79 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)70 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)67 FieldNode (org.codehaus.groovy.ast.FieldNode)49 Expression (org.codehaus.groovy.ast.expr.Expression)47 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)47 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)44 Statement (org.codehaus.groovy.ast.stmt.Statement)34 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)33 ArrayList (java.util.ArrayList)32 LinkedList (java.util.LinkedList)32 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)30 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)29 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)26 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)26 IfStatement (org.codehaus.groovy.ast.stmt.IfStatement)26 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)25 EmptyStatement (org.codehaus.groovy.ast.stmt.EmptyStatement)25