Search in sources :

Example 6 with InnerClassNode

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

the class StaticInvocationWriter method tryBridgeMethod.

/**
     * Attempts to make a direct method call on a bridge method, if it exists.
     */
protected boolean tryBridgeMethod(MethodNode target, Expression receiver, boolean implicitThis, TupleExpression args) {
    ClassNode lookupClassNode;
    if (target.isProtected()) {
        lookupClassNode = controller.getClassNode();
        if (controller.isInClosure()) {
            lookupClassNode = lookupClassNode.getOuterClass();
        }
    } else {
        lookupClassNode = target.getDeclaringClass().redirect();
    }
    Map<MethodNode, MethodNode> bridges = lookupClassNode.getNodeMetaData(PRIVATE_BRIDGE_METHODS);
    MethodNode bridge = bridges == null ? null : bridges.get(target);
    if (bridge != null) {
        Expression fixedReceiver = receiver;
        ClassNode classNode = implicitThis ? controller.getClassNode() : null;
        ClassNode declaringClass = bridge.getDeclaringClass();
        if (implicitThis && !controller.isInClosure() && !classNode.isDerivedFrom(declaringClass) && !classNode.implementsInterface(declaringClass) && classNode instanceof InnerClassNode) {
            fixedReceiver = new PropertyExpression(new ClassExpression(classNode.getOuterClass()), "this");
        }
        ArgumentListExpression newArgs = new ArgumentListExpression(target.isStatic() ? new ConstantExpression(null) : fixedReceiver);
        for (Expression expression : args.getExpressions()) {
            newArgs.addExpression(expression);
        }
        return writeDirectMethodCall(bridge, implicitThis, fixedReceiver, newArgs);
    }
    return false;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ExtensionMethodNode(org.codehaus.groovy.transform.stc.ExtensionMethodNode) MethodNode(org.codehaus.groovy.ast.MethodNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 7 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode 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 8 with InnerClassNode

use of org.codehaus.groovy.ast.InnerClassNode 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 9 with InnerClassNode

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

the class Traits method findHelpers.

static TraitHelpersTuple findHelpers(final ClassNode trait) {
    ClassNode helperClassNode = null;
    ClassNode fieldHelperClassNode = null;
    Iterator<InnerClassNode> innerClasses = trait.redirect().getInnerClasses();
    if (innerClasses != null && innerClasses.hasNext()) {
        // trait defined in same source unit
        while (innerClasses.hasNext()) {
            ClassNode icn = innerClasses.next();
            if (icn.getName().endsWith(Traits.FIELD_HELPER)) {
                fieldHelperClassNode = icn;
            } else if (icn.getName().endsWith(Traits.TRAIT_HELPER)) {
                helperClassNode = icn;
            }
        }
    } else {
        // precompiled trait
        try {
            final ClassLoader classLoader = trait.getTypeClass().getClassLoader();
            String helperClassName = Traits.helperClassName(trait);
            helperClassNode = ClassHelper.make(classLoader.loadClass(helperClassName));
            try {
                fieldHelperClassNode = ClassHelper.make(classLoader.loadClass(Traits.fieldHelperClassName(trait)));
            } catch (ClassNotFoundException e) {
            // not a problem, the field helper may be absent
            }
        } catch (ClassNotFoundException e) {
            throw new GroovyBugError("Couldn't find trait helper classes on compile classpath!", e);
        }
    }
    return new TraitHelpersTuple(helperClassNode, fieldHelperClassNode);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) GroovyBugError(org.codehaus.groovy.GroovyBugError) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Example 10 with InnerClassNode

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

the class InitializerStrategy method createInnerHelperClass.

private ClassNode createInnerHelperClass(ClassNode buildee, String builderClassName, int fieldsSize) {
    final String fullName = buildee.getName() + "$" + builderClassName;
    ClassNode builder = new InnerClassNode(buildee, fullName, PUBLIC_STATIC, OBJECT_TYPE);
    GenericsType[] gtypes = new GenericsType[fieldsSize];
    for (int i = 0; i < gtypes.length; i++) {
        gtypes[i] = makePlaceholder(i);
    }
    builder.setGenericsTypes(gtypes);
    return builder;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) GenericsType(org.codehaus.groovy.ast.GenericsType) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode)

Aggregations

InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)60 ClassNode (org.codehaus.groovy.ast.ClassNode)52 MethodNode (org.codehaus.groovy.ast.MethodNode)26 FieldNode (org.codehaus.groovy.ast.FieldNode)17 Parameter (org.codehaus.groovy.ast.Parameter)12 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)12 ArrayList (java.util.ArrayList)11 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)9 LinkedList (java.util.LinkedList)8 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)8 InterfaceHelperClassNode (org.codehaus.groovy.ast.InterfaceHelperClassNode)8 Expression (org.codehaus.groovy.ast.expr.Expression)8 GenericsType (org.codehaus.groovy.ast.GenericsType)7 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)7 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)7 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)7 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)7 MethodVisitor (org.objectweb.asm.MethodVisitor)7 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)6 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)6