Search in sources :

Example 66 with MethodNode

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

the class AbstractASTTransformation method shouldSkipOnDescriptor.

public static boolean shouldSkipOnDescriptor(boolean checkReturn, Map genericsSpec, MethodNode mNode, List<ClassNode> excludeTypes, List<ClassNode> includeTypes) {
    String descriptor = mNode.getTypeDescriptor();
    String descriptorNoReturn = GeneralUtils.makeDescriptorWithoutReturnType(mNode);
    for (ClassNode cn : excludeTypes) {
        List<ClassNode> remaining = new LinkedList<ClassNode>();
        remaining.add(cn);
        Map updatedGenericsSpec = new HashMap(genericsSpec);
        while (!remaining.isEmpty()) {
            ClassNode next = remaining.remove(0);
            if (!next.equals(ClassHelper.OBJECT_TYPE)) {
                updatedGenericsSpec = GenericsUtils.createGenericsSpec(next, updatedGenericsSpec);
                for (MethodNode mn : next.getMethods()) {
                    MethodNode correctedMethodNode = GenericsUtils.correctToGenericsSpec(updatedGenericsSpec, mn);
                    if (checkReturn) {
                        String md = correctedMethodNode.getTypeDescriptor();
                        if (md.equals(descriptor))
                            return true;
                    } else {
                        String md = GeneralUtils.makeDescriptorWithoutReturnType(correctedMethodNode);
                        if (md.equals(descriptorNoReturn))
                            return true;
                    }
                }
                remaining.addAll(Arrays.asList(next.getInterfaces()));
            }
        }
    }
    if (includeTypes.isEmpty())
        return false;
    for (ClassNode cn : includeTypes) {
        List<ClassNode> remaining = new LinkedList<ClassNode>();
        remaining.add(cn);
        Map updatedGenericsSpec = new HashMap(genericsSpec);
        while (!remaining.isEmpty()) {
            ClassNode next = remaining.remove(0);
            if (!next.equals(ClassHelper.OBJECT_TYPE)) {
                updatedGenericsSpec = GenericsUtils.createGenericsSpec(next, updatedGenericsSpec);
                for (MethodNode mn : next.getMethods()) {
                    MethodNode correctedMethodNode = GenericsUtils.correctToGenericsSpec(updatedGenericsSpec, mn);
                    if (checkReturn) {
                        String md = correctedMethodNode.getTypeDescriptor();
                        if (md.equals(descriptor))
                            return false;
                    } else {
                        String md = GeneralUtils.makeDescriptorWithoutReturnType(correctedMethodNode);
                        if (md.equals(descriptorNoReturn))
                            return false;
                    }
                }
                remaining.addAll(Arrays.asList(next.getInterfaces()));
            }
        }
    }
    return true;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) HashMap(java.util.HashMap) HashMap(java.util.HashMap) Map(java.util.Map) LinkedList(java.util.LinkedList)

Example 67 with MethodNode

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

the class EqualsAndHashCodeASTTransformation method createHashCode.

public static void createHashCode(ClassNode cNode, boolean cacheResult, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes) {
    // make a public method if none exists otherwise try a private method with leading underscore
    boolean hasExistingHashCode = hasDeclaredMethod(cNode, "hashCode", 0);
    if (hasExistingHashCode && hasDeclaredMethod(cNode, "_hashCode", 0))
        return;
    final BlockStatement body = new BlockStatement();
    // TODO use pList and fList
    if (cacheResult) {
        final FieldNode hashField = cNode.addField("$hash$code", ACC_PRIVATE | ACC_SYNTHETIC, ClassHelper.int_TYPE, null);
        final Expression hash = varX(hashField);
        body.addStatement(ifS(isZeroX(hash), calculateHashStatements(cNode, hash, includeFields, callSuper, excludes, includes)));
        body.addStatement(returnS(hash));
    } else {
        body.addStatement(calculateHashStatements(cNode, null, includeFields, callSuper, excludes, includes));
    }
    cNode.addMethod(new MethodNode(hasExistingHashCode ? "_hashCode" : "hashCode", hasExistingHashCode ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.int_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body));
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) MethodNode(org.codehaus.groovy.ast.MethodNode) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 68 with MethodNode

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

the class MemoizedASTTransformation method visit.

public void visit(ASTNode[] nodes, final SourceUnit source) {
    init(nodes, source);
    AnnotationNode annotationNode = (AnnotationNode) nodes[0];
    AnnotatedNode annotatedNode = (AnnotatedNode) nodes[1];
    if (MY_TYPE.equals(annotationNode.getClassNode()) && annotatedNode instanceof MethodNode) {
        MethodNode methodNode = (MethodNode) annotatedNode;
        if (methodNode.isAbstract()) {
            addError("Annotation " + MY_TYPE_NAME + " cannot be used for abstract methods.", methodNode);
            return;
        }
        if (methodNode.isVoidMethod()) {
            addError("Annotation " + MY_TYPE_NAME + " cannot be used for void methods.", methodNode);
            return;
        }
        ClassNode ownerClassNode = methodNode.getDeclaringClass();
        MethodNode delegatingMethod = buildDelegatingMethod(methodNode, ownerClassNode);
        ownerClassNode.addMethod(delegatingMethod);
        int modifiers = FieldNode.ACC_PRIVATE | FieldNode.ACC_FINAL;
        if (methodNode.isStatic()) {
            modifiers = modifiers | FieldNode.ACC_STATIC;
        }
        int protectedCacheSize = getMemberIntValue(annotationNode, PROTECTED_CACHE_SIZE_NAME);
        int maxCacheSize = getMemberIntValue(annotationNode, MAX_CACHE_SIZE_NAME);
        MethodCallExpression memoizeClosureCallExpression = buildMemoizeClosureCallExpression(delegatingMethod, protectedCacheSize, maxCacheSize);
        String memoizedClosureFieldName = buildUniqueName(ownerClassNode, CLOSURE_LABEL, methodNode);
        FieldNode memoizedClosureField = new FieldNode(memoizedClosureFieldName, modifiers, newClass(ClassHelper.CLOSURE_TYPE), null, memoizeClosureCallExpression);
        ownerClassNode.addField(memoizedClosureField);
        BlockStatement newCode = new BlockStatement();
        MethodCallExpression closureCallExpression = callX(fieldX(memoizedClosureField), CLOSURE_CALL_METHOD_NAME, args(methodNode.getParameters()));
        closureCallExpression.setImplicitThis(false);
        newCode.addStatement(returnS(closureCallExpression));
        methodNode.setCode(newCode);
        VariableScopeVisitor visitor = new VariableScopeVisitor(source);
        visitor.visitClass(ownerClassNode);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) AnnotatedNode(org.codehaus.groovy.ast.AnnotatedNode) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableScopeVisitor(org.codehaus.groovy.classgen.VariableScopeVisitor)

Example 69 with MethodNode

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

the class DelegateASTTransformation method visit.

public void visit(ASTNode[] nodes, SourceUnit source) {
    init(nodes, source);
    AnnotatedNode parent = (AnnotatedNode) nodes[1];
    AnnotationNode node = (AnnotationNode) nodes[0];
    if (parent instanceof FieldNode) {
        FieldNode fieldNode = (FieldNode) parent;
        final ClassNode type = fieldNode.getType();
        final ClassNode owner = fieldNode.getOwner();
        if (type.equals(ClassHelper.OBJECT_TYPE) || type.equals(GROOVYOBJECT_TYPE)) {
            addError(MY_TYPE_NAME + " field '" + fieldNode.getName() + "' has an inappropriate type: " + type.getName() + ". Please add an explicit type but not java.lang.Object or groovy.lang.GroovyObject.", parent);
            return;
        }
        if (type.equals(owner)) {
            addError(MY_TYPE_NAME + " field '" + fieldNode.getName() + "' has an inappropriate type: " + type.getName() + ". Delegation to own type not supported. Please use a different type.", parent);
            return;
        }
        final List<MethodNode> fieldMethods = getAllMethods(type);
        for (ClassNode next : type.getAllInterfaces()) {
            fieldMethods.addAll(getAllMethods(next));
        }
        final boolean skipInterfaces = memberHasValue(node, MEMBER_INTERFACES, false);
        final boolean includeDeprecated = memberHasValue(node, MEMBER_DEPRECATED, true) || (type.isInterface() && !skipInterfaces);
        List<String> excludes = getMemberList(node, MEMBER_EXCLUDES);
        List<String> includes = getMemberList(node, MEMBER_INCLUDES);
        List<ClassNode> excludeTypes = getClassList(node, MEMBER_EXCLUDE_TYPES);
        List<ClassNode> includeTypes = getClassList(node, MEMBER_INCLUDE_TYPES);
        checkIncludeExclude(node, excludes, includes, excludeTypes, includeTypes, MY_TYPE_NAME);
        final List<MethodNode> ownerMethods = getAllMethods(owner);
        for (MethodNode mn : fieldMethods) {
            addDelegateMethod(node, fieldNode, owner, ownerMethods, mn, includeDeprecated, includes, excludes, includeTypes, excludeTypes);
        }
        for (PropertyNode prop : getAllProperties(type)) {
            if (prop.isStatic() || !prop.isPublic())
                continue;
            String name = prop.getName();
            addGetterIfNeeded(fieldNode, owner, prop, name, includes, excludes);
            addSetterIfNeeded(fieldNode, owner, prop, name, includes, excludes);
        }
        if (skipInterfaces)
            return;
        final Set<ClassNode> allInterfaces = getInterfacesAndSuperInterfaces(type);
        final Set<ClassNode> ownerIfaces = owner.getAllInterfaces();
        Map<String, ClassNode> genericsSpec = createGenericsSpec(fieldNode.getDeclaringClass());
        genericsSpec = createGenericsSpec(fieldNode.getType(), genericsSpec);
        for (ClassNode iface : allInterfaces) {
            if (Modifier.isPublic(iface.getModifiers()) && !ownerIfaces.contains(iface)) {
                final ClassNode[] ifaces = owner.getInterfaces();
                final ClassNode[] newIfaces = new ClassNode[ifaces.length + 1];
                for (int i = 0; i < ifaces.length; i++) {
                    newIfaces[i] = correctToGenericsSpecRecurse(genericsSpec, ifaces[i]);
                }
                newIfaces[ifaces.length] = correctToGenericsSpecRecurse(genericsSpec, iface);
                owner.setInterfaces(newIfaces);
            }
        }
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotatedNode(org.codehaus.groovy.ast.AnnotatedNode) MethodNode(org.codehaus.groovy.ast.MethodNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode)

Example 70 with MethodNode

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

the class PackageScopeASTTransformation method visitClassNode.

private void visitClassNode(ClassNode cNode, List<PackageScopeTarget> value) {
    String cName = cNode.getName();
    if (cNode.isInterface() && value.size() != 1 && value.get(0) != PackageScopeTarget.CLASS) {
        addError("Error processing interface '" + cName + "'. " + MY_TYPE_NAME + " not allowed for interfaces except when targeting Class level.", cNode);
    }
    if (value.contains(groovy.transform.PackageScopeTarget.CLASS)) {
        if (cNode.isSyntheticPublic())
            revertVisibility(cNode);
        else
            addError("Can't use " + MY_TYPE_NAME + " for class '" + cNode.getName() + "' which has explicit visibility.", cNode);
    }
    if (value.contains(groovy.transform.PackageScopeTarget.METHODS)) {
        final List<MethodNode> mList = cNode.getMethods();
        for (MethodNode mNode : mList) {
            if (mNode.isSyntheticPublic())
                revertVisibility(mNode);
        }
    }
    if (value.contains(groovy.transform.PackageScopeTarget.CONSTRUCTORS)) {
        final List<ConstructorNode> cList = cNode.getDeclaredConstructors();
        for (MethodNode mNode : cList) {
            if (mNode.isSyntheticPublic())
                revertVisibility(mNode);
        }
    }
    if (value.contains(PackageScopeTarget.FIELDS)) {
        final List<PropertyNode> pList = cNode.getProperties();
        List<PropertyNode> foundProps = new ArrayList<PropertyNode>();
        List<String> foundNames = new ArrayList<String>();
        for (PropertyNode pNode : pList) {
            foundProps.add(pNode);
            foundNames.add(pNode.getName());
        }
        for (PropertyNode pNode : foundProps) {
            pList.remove(pNode);
        }
        final List<FieldNode> fList = cNode.getFields();
        for (FieldNode fNode : fList) {
            if (foundNames.contains(fNode.getName())) {
                revertVisibility(fNode);
            }
        }
    }
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList)

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