Search in sources :

Example 16 with MethodNode

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

the class StaticTypeCheckingVisitor method addListAssignmentConstructorErrors.

private void addListAssignmentConstructorErrors(ClassNode leftRedirect, ClassNode leftExpressionType, ClassNode inferredRightExpressionType, Expression rightExpression, Expression assignmentExpression) {
    // In that case, more checks can be performed
    if (rightExpression instanceof ListExpression && !implementsInterfaceOrIsSubclassOf(LIST_TYPE, leftRedirect)) {
        ArgumentListExpression argList = new ArgumentListExpression(((ListExpression) rightExpression).getExpressions());
        ClassNode[] args = getArgumentTypes(argList);
        MethodNode methodNode = checkGroovyStyleConstructor(leftRedirect, args, assignmentExpression);
        if (methodNode != null) {
            rightExpression.putNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET, methodNode);
        }
    } else if (!implementsInterfaceOrIsSubclassOf(inferredRightExpressionType, leftRedirect) && implementsInterfaceOrIsSubclassOf(inferredRightExpressionType, LIST_TYPE) && !isWildcardLeftHandSide(leftExpressionType)) {
        if (!extension.handleIncompatibleAssignment(leftExpressionType, inferredRightExpressionType, assignmentExpression)) {
            addAssignmentError(leftExpressionType, inferredRightExpressionType, assignmentExpression);
        }
    }
}
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)

Example 17 with MethodNode

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

the class StaticTypeCheckingVisitor method visitClass.

@Override
public void visitClass(final ClassNode node) {
    if (shouldSkipClassNode(node))
        return;
    if (extension.beforeVisitClass(node)) {
        extension.afterVisitClass(node);
        return;
    }
    Object type = node.getNodeMetaData(StaticTypesMarker.INFERRED_TYPE);
    if (type != null) {
        // transformation has already been run on this class node
        // so we'll use a silent collector in order not to duplicate errors
        typeCheckingContext.pushErrorCollector();
    }
    typeCheckingContext.pushEnclosingClassNode(node);
    Set<MethodNode> oldVisitedMethod = typeCheckingContext.alreadyVisitedMethods;
    typeCheckingContext.alreadyVisitedMethods = new LinkedHashSet<MethodNode>();
    super.visitClass(node);
    Iterator<InnerClassNode> innerClasses = node.getInnerClasses();
    while (innerClasses.hasNext()) {
        InnerClassNode innerClassNode = innerClasses.next();
        visitClass(innerClassNode);
    }
    typeCheckingContext.alreadyVisitedMethods = oldVisitedMethod;
    node.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, node);
    // works in a two pass sequence and we don't want to skip the second pass
    for (MethodNode methodNode : node.getMethods()) {
        methodNode.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
    }
    for (ConstructorNode constructorNode : node.getDeclaredConstructors()) {
        constructorNode.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
    }
    extension.afterVisitClass(node);
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 18 with MethodNode

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

the class StaticTypeCheckingVisitor method addGeneratedMethods.

private List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<MethodNode> methods) {
    // using a comparator of parameters
    List<MethodNode> result = new LinkedList<MethodNode>();
    for (MethodNode method : methods) {
        result.add(method);
        Parameter[] parameters = method.getParameters();
        int counter = 0;
        int size = parameters.length;
        for (int i = size - 1; i >= 0; i--) {
            Parameter parameter = parameters[i];
            if (parameter != null && parameter.hasInitialExpression()) {
                counter++;
            }
        }
        for (int j = 1; j <= counter; j++) {
            Parameter[] newParams = new Parameter[parameters.length - j];
            int index = 0;
            int k = 1;
            for (int i = 0; i < parameters.length; i++) {
                if (k > counter - j && parameters[i] != null && parameters[i].hasInitialExpression()) {
                    k++;
                } else if (parameters[i] != null && parameters[i].hasInitialExpression()) {
                    newParams[index++] = parameters[i];
                    k++;
                } else {
                    newParams[index++] = parameters[i];
                }
            }
            MethodNode stubbed;
            if ("<init>".equals(method.getName())) {
                stubbed = new ConstructorNode(method.getModifiers(), newParams, method.getExceptions(), GENERATED_EMPTY_STATEMENT);
            } else {
                stubbed = new MethodNode(method.getName(), method.getModifiers(), method.getReturnType(), newParams, method.getExceptions(), GENERATED_EMPTY_STATEMENT);
                stubbed.setGenericsTypes(method.getGenericsTypes());
            }
            stubbed.setDeclaringClass(receiver);
            result.add(stubbed);
        }
    }
    return result;
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter) LinkedList(java.util.LinkedList) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

Example 19 with MethodNode

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

the class StaticTypeCheckingVisitor method findMethod.

protected List<MethodNode> findMethod(ClassNode receiver, String name, ClassNode... args) {
    if (isPrimitiveType(receiver))
        receiver = getWrapper(receiver);
    List<MethodNode> methods;
    if (!receiver.isInterface() && "<init>".equals(name)) {
        methods = addGeneratedMethods(receiver, new ArrayList<MethodNode>(receiver.getDeclaredConstructors()));
        if (methods.isEmpty()) {
            MethodNode node = new ConstructorNode(Opcodes.ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
            node.setDeclaringClass(receiver);
            return Collections.singletonList(node);
        }
    } else {
        methods = findMethodsWithGenerated(receiver, name);
        if (receiver.isInterface()) {
            collectAllInterfaceMethodsByName(receiver, name, methods);
            methods.addAll(OBJECT_TYPE.getMethods(name));
        }
        if (typeCheckingContext.getEnclosingClosure() == null) {
            // not in a closure
            ClassNode parent = receiver;
            while (parent instanceof InnerClassNode && !parent.isStaticClass()) {
                parent = parent.getOuterClass();
                methods.addAll(findMethodsWithGenerated(parent, name));
            }
        }
        if (methods.isEmpty()) {
            addArrayMethods(methods, receiver, name, args);
        }
        if (methods.isEmpty() && (args == null || args.length == 0)) {
            // check if it's a property
            String pname = extractPropertyNameFromMethodName("get", name);
            if (pname == null) {
                pname = extractPropertyNameFromMethodName("is", name);
            }
            if (pname != null) {
                // we don't use property exists there because findMethod is called on super clases recursively
                PropertyNode property = null;
                ClassNode curNode = receiver;
                while (property == null && curNode != null) {
                    property = curNode.getProperty(pname);
                    ClassNode svCur = curNode;
                    while (property == null && svCur instanceof InnerClassNode && !svCur.isStaticClass()) {
                        svCur = svCur.getOuterClass();
                        property = svCur.getProperty(pname);
                        if (property != null) {
                            receiver = svCur;
                            break;
                        }
                    }
                    curNode = curNode.getSuperClass();
                }
                if (property != null) {
                    MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
                    if (property.isStatic()) {
                        node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
                    }
                    node.setDeclaringClass(receiver);
                    return Collections.singletonList(node);
                }
            }
        } else if (methods.isEmpty() && args != null && args.length == 1) {
            // maybe we are looking for a setter ?
            String pname = extractPropertyNameFromMethodName("set", name);
            if (pname != null) {
                ClassNode curNode = receiver;
                PropertyNode property = null;
                while (property == null && curNode != null) {
                    property = curNode.getProperty(pname);
                    curNode = curNode.getSuperClass();
                }
                if (property != null) {
                    ClassNode type = property.getOriginType();
                    if (implementsInterfaceOrIsSubclassOf(wrapTypeIfNecessary(args[0]), wrapTypeIfNecessary(type))) {
                        MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, VOID_TYPE, new Parameter[] { new Parameter(type, "arg") }, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
                        if (property.isStatic()) {
                            node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
                        }
                        node.setDeclaringClass(receiver);
                        return Collections.singletonList(node);
                    }
                }
            }
        }
    }
    if (methods.isEmpty()) {
        // look at the interfaces, there's a chance that a method is not implemented and we should not hide the
        // error from the compiler
        collectAllInterfaceMethodsByName(receiver, name, methods);
    }
    // lookup in DGM methods too
    findDGMMethodsByNameAndArguments(getTransformLoader(), receiver, name, args, methods);
    List<MethodNode> chosen = chooseBestMethod(receiver, methods, args);
    if (!chosen.isEmpty())
        return chosen;
    // GROOVY-5566
    if (receiver instanceof InnerClassNode && ((InnerClassNode) receiver).isAnonymous() && methods.size() == 1 && args != null && "<init>".equals(name)) {
        MethodNode constructor = methods.get(0);
        if (constructor.getParameters().length == args.length) {
            return methods;
        }
    }
    if (receiver.equals(CLASS_Type) && receiver.getGenericsTypes() != null) {
        List<MethodNode> result = findMethod(receiver.getGenericsTypes()[0].getType(), name, args);
        if (!result.isEmpty())
            return result;
    }
    if (ClassHelper.GSTRING_TYPE.equals(receiver))
        return findMethod(ClassHelper.STRING_TYPE, name, args);
    if (isBeingCompiled(receiver)) {
        chosen = findMethod(GROOVY_OBJECT_TYPE, name, args);
        if (!chosen.isEmpty())
            return chosen;
    }
    return EMPTY_METHODNODE_LIST;
}
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) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) Parameter(org.codehaus.groovy.ast.Parameter) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 20 with MethodNode

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

the class TraitTypeCheckingExtension method handleMissingMethod.

@Override
public List<MethodNode> handleMissingMethod(final ClassNode receiver, final String name, final ArgumentListExpression argumentList, final ClassNode[] argumentTypes, final MethodCall call) {
    String[] decomposed = Traits.decomposeSuperCallName(name);
    if (decomposed != null) {
        return convertToDynamicCall(call, receiver, decomposed, argumentTypes);
    }
    if (call instanceof MethodCallExpression) {
        MethodCallExpression mce = (MethodCallExpression) call;
        if (mce.getReceiver() instanceof VariableExpression) {
            VariableExpression var = (VariableExpression) mce.getReceiver();
            // GROOVY-7322
            // static method call in trait?
            ClassNode type = null;
            if (isStaticTraitReceiver(receiver, var)) {
                type = receiver.getGenericsTypes()[0].getType();
            } else if (isThisTraitReceiver(var)) {
                type = receiver;
            }
            if (type != null && Traits.isTrait(type)) {
                ClassNode helper = Traits.findHelper(type);
                Parameter[] params = new Parameter[argumentTypes.length + 1];
                params[0] = new Parameter(ClassHelper.CLASS_Type.getPlainNodeReference(), "staticSelf");
                for (int i = 1; i < params.length; i++) {
                    params[i] = new Parameter(argumentTypes[i - 1], "p" + i);
                }
                MethodNode method = helper.getDeclaredMethod(name, params);
                if (method != null) {
                    return Collections.singletonList(makeDynamic(call, method.getReturnType()));
                }
            }
        }
        ClassNode dynamic = mce.getNodeMetaData(TraitASTTransformation.DO_DYNAMIC);
        if (dynamic != null) {
            return Collections.singletonList(makeDynamic(call, dynamic));
        }
    }
    return NOTFOUND;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) Parameter(org.codehaus.groovy.ast.Parameter) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Aggregations

MethodNode (org.codehaus.groovy.ast.MethodNode)294 ClassNode (org.codehaus.groovy.ast.ClassNode)193 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)94 Parameter (org.codehaus.groovy.ast.Parameter)79 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)65 FieldNode (org.codehaus.groovy.ast.FieldNode)57 LinkedList (java.util.LinkedList)50 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)50 Expression (org.codehaus.groovy.ast.expr.Expression)49 LowestUpperBoundClassNode (org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode)47 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)43 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)39 ArrayList (java.util.ArrayList)36 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)36 Statement (org.codehaus.groovy.ast.stmt.Statement)34 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)33 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)30 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)29 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)27 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)27