Search in sources :

Example 86 with AnnotationNode

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

the class ArtefactTypeAstTransformation method visit.

public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
    AnnotatedNode parent = (AnnotatedNode) astNodes[1];
    AnnotationNode node = (AnnotationNode) astNodes[0];
    if (!(node instanceof AnnotationNode) || !(parent instanceof AnnotatedNode)) {
        throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
    }
    if (!isArtefactAnnotationNode(node) || !(parent instanceof ClassNode)) {
        return;
    }
    ClassNode cNode = (ClassNode) parent;
    if (cNode.isInterface()) {
        throw new RuntimeException("Error processing interface '" + cNode.getName() + "'. @" + getAnnotationType().getNameWithoutPackage() + " not allowed for interfaces.");
    }
    if (isApplied(cNode)) {
        return;
    }
    String artefactType = resolveArtefactType(sourceUnit, node, cNode);
    if (artefactType != null) {
        AbstractGrailsArtefactTransformer.addToTransformedClasses(cNode.getName());
    }
    performInjectionOnArtefactType(sourceUnit, cNode, artefactType);
    performTraitInjectionOnArtefactType(sourceUnit, cNode, artefactType);
    postProcess(sourceUnit, node, cNode, artefactType);
    markApplied(cNode);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) AnnotatedNode(org.codehaus.groovy.ast.AnnotatedNode)

Example 87 with AnnotationNode

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

the class TraitASTTransformation method processMethod.

private MethodNode processMethod(ClassNode traitClass, MethodNode methodNode, ClassNode fieldHelper, Collection<String> knownFields) {
    Parameter[] initialParams = methodNode.getParameters();
    Parameter[] newParams = new Parameter[initialParams.length + 1];
    newParams[0] = createSelfParameter(traitClass, methodNode.isStatic());
    System.arraycopy(initialParams, 0, newParams, 1, initialParams.length);
    final int mod = methodNode.isPrivate() ? ACC_PRIVATE : ACC_PUBLIC;
    MethodNode mNode = new MethodNode(methodNode.getName(), mod | ACC_STATIC, methodNode.getReturnType(), newParams, methodNode.getExceptions(), processBody(new VariableExpression(newParams[0]), methodNode, methodNode.getCode(), traitClass, fieldHelper, knownFields));
    mNode.setSourcePosition(methodNode);
    mNode.addAnnotations(filterAnnotations(methodNode.getAnnotations()));
    mNode.setGenericsTypes(methodNode.getGenericsTypes());
    if (methodNode.isAbstract()) {
        mNode.setModifiers(ACC_PUBLIC | ACC_ABSTRACT);
    } else {
        methodNode.addAnnotation(new AnnotationNode(Traits.IMPLEMENTED_CLASSNODE));
    }
    methodNode.setCode(null);
    if (!methodNode.isPrivate() && !methodNode.isStatic()) {
        methodNode.setModifiers(ACC_PUBLIC | ACC_ABSTRACT);
    }
    return mNode;
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) Parameter(org.codehaus.groovy.ast.Parameter) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression)

Example 88 with AnnotationNode

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

the class TraitASTTransformation method processField.

private void processField(final FieldNode field, final MethodNode initializer, final MethodNode staticInitializer, final ClassNode fieldHelper, final ClassNode trait, final Set<String> knownFields) {
    Expression initialExpression = field.getInitialExpression();
    MethodNode selectedMethod = field.isStatic() ? staticInitializer : initializer;
    if (initialExpression != null) {
        VariableExpression thisObject = new VariableExpression(selectedMethod.getParameters()[0]);
        ExpressionStatement initCode = new ExpressionStatement(initialExpression);
        processBody(thisObject, selectedMethod, initCode, trait, fieldHelper, knownFields);
        BlockStatement code = (BlockStatement) selectedMethod.getCode();
        MethodCallExpression mce;
        if (field.isStatic()) {
            mce = new MethodCallExpression(new ClassExpression(INVOKERHELPER_CLASSNODE), "invokeStaticMethod", new ArgumentListExpression(thisObject, new ConstantExpression(Traits.helperSetterName(field)), initCode.getExpression()));
        } else {
            mce = new MethodCallExpression(new CastExpression(createReceiverType(field.isStatic(), fieldHelper), thisObject), Traits.helperSetterName(field), new CastExpression(field.getOriginType(), initCode.getExpression()));
        }
        mce.setImplicitThis(false);
        mce.setSourcePosition(initialExpression);
        code.addStatement(new ExpressionStatement(mce));
    }
    // define setter/getter helper methods
    fieldHelper.addMethod(Traits.helperSetterName(field), ACC_PUBLIC | ACC_ABSTRACT, field.getOriginType(), new Parameter[] { new Parameter(field.getOriginType(), "val") }, ClassNode.EMPTY_ARRAY, null);
    fieldHelper.addMethod(Traits.helperGetterName(field), ACC_PUBLIC | ACC_ABSTRACT, field.getOriginType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, null);
    // dummy fields are only used to carry annotations if instance field
    // and to differentiate from static fields otherwise
    String dummyFieldName = (field.isStatic() ? Traits.STATIC_FIELD_PREFIX : Traits.FIELD_PREFIX) + (field.isPublic() ? Traits.PUBLIC_FIELD_PREFIX : Traits.PRIVATE_FIELD_PREFIX) + Traits.remappedFieldName(field.getOwner(), field.getName());
    FieldNode dummyField = new FieldNode(dummyFieldName, ACC_STATIC | ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC, field.getOriginType(), fieldHelper, null);
    // copy annotations from field to dummy field
    List<AnnotationNode> copied = new LinkedList<AnnotationNode>();
    List<AnnotationNode> notCopied = new LinkedList<AnnotationNode>();
    GeneralUtils.copyAnnotatedNodeAnnotations(field, copied, notCopied);
    dummyField.addAnnotations(copied);
    fieldHelper.addField(dummyField);
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) LinkedList(java.util.LinkedList) MethodNode(org.codehaus.groovy.ast.MethodNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) FieldExpression(org.codehaus.groovy.ast.expr.FieldExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) CastExpression(org.codehaus.groovy.ast.expr.CastExpression)

Example 89 with AnnotationNode

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

the class StaticTypeCheckingVisitor method checkClosureWithDelegatesTo.

private void checkClosureWithDelegatesTo(final ClassNode receiver, final MethodNode mn, final ArgumentListExpression arguments, final Parameter[] params, final Expression expression, final Parameter param) {
    List<AnnotationNode> annotations = param.getAnnotations(DELEGATES_TO);
    if (annotations != null && !annotations.isEmpty()) {
        for (AnnotationNode annotation : annotations) {
            // in theory, there can only be one annotation of that type
            Expression value = annotation.getMember("value");
            Expression strategy = annotation.getMember("strategy");
            Expression genericTypeIndex = annotation.getMember("genericTypeIndex");
            Expression type = annotation.getMember("type");
            Integer stInt = Closure.OWNER_FIRST;
            if (strategy != null) {
                stInt = (Integer) evaluateExpression(new CastExpression(ClassHelper.Integer_TYPE, strategy), typeCheckingContext.source.getConfiguration());
            }
            if (value instanceof ClassExpression && !value.getType().equals(DELEGATES_TO_TARGET)) {
                if (genericTypeIndex != null) {
                    addStaticTypeError("Cannot use @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") without @DelegatesTo.Target because generic argument types are not available at runtime", value);
                }
                // temporarily store the delegation strategy and the delegate type
                expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(value.getType(), stInt, typeCheckingContext.delegationMetadata));
            } else if (type != null && !"".equals(type.getText()) && type instanceof ConstantExpression) {
                String typeString = type.getText();
                ClassNode[] resolved = GenericsUtils.parseClassNodesFromString(typeString, getSourceUnit(), typeCheckingContext.compilationUnit, mn, type);
                if (resolved != null) {
                    if (resolved.length == 1) {
                        resolved = resolveGenericsFromTypeHint(receiver, arguments, mn, resolved);
                        expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(resolved[0], stInt, typeCheckingContext.delegationMetadata));
                    } else {
                        addStaticTypeError("Incorrect type hint found in method " + (mn), type);
                    }
                }
            } else {
                final List<Expression> expressions = arguments.getExpressions();
                final int expressionsSize = expressions.size();
                Expression parameter = annotation.getMember("target");
                String parameterName = parameter != null && parameter instanceof ConstantExpression ? parameter.getText() : "";
                // todo: handle vargs!
                for (int j = 0, paramsLength = params.length; j < paramsLength; j++) {
                    final Parameter methodParam = params[j];
                    List<AnnotationNode> targets = methodParam.getAnnotations(DELEGATES_TO_TARGET);
                    if (targets != null && targets.size() == 1) {
                        // @DelegatesTo.Target Obj foo
                        AnnotationNode targetAnnotation = targets.get(0);
                        Expression idMember = targetAnnotation.getMember("value");
                        String id = idMember != null && idMember instanceof ConstantExpression ? idMember.getText() : "";
                        if (id.equals(parameterName)) {
                            if (j < expressionsSize) {
                                Expression actualArgument = expressions.get(j);
                                ClassNode actualType = getType(actualArgument);
                                if (genericTypeIndex != null && genericTypeIndex instanceof ConstantExpression) {
                                    int gti = Integer.parseInt(genericTypeIndex.getText());
                                    // type annotated with @DelegatesTo.Target
                                    ClassNode paramType = methodParam.getType();
                                    GenericsType[] genericsTypes = paramType.getGenericsTypes();
                                    if (genericsTypes == null) {
                                        addStaticTypeError("Cannot use @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") with a type that doesn't use generics", methodParam);
                                    } else if (gti < 0 || gti >= genericsTypes.length) {
                                        addStaticTypeError("Index of generic type @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") " + (gti < 0 ? "lower" : "greater") + " than those of the selected type", methodParam);
                                    } else {
                                        ClassNode pType = GenericsUtils.parameterizeType(actualType, paramType);
                                        GenericsType[] pTypeGenerics = pType.getGenericsTypes();
                                        if (pTypeGenerics != null && pTypeGenerics.length > gti) {
                                            actualType = pTypeGenerics[gti].getType();
                                        } else {
                                            addStaticTypeError("Unable to map actual type [" + actualType.toString(false) + "] onto " + paramType.toString(false), methodParam);
                                        }
                                    }
                                }
                                expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(actualType, stInt, typeCheckingContext.delegationMetadata));
                                break;
                            }
                        }
                    }
                }
                if (expression.getNodeMetaData(StaticTypesMarker.DELEGATION_METADATA) == null) {
                    addError("Not enough arguments found for a @DelegatesTo method call. Please check that you either use an explicit class or @DelegatesTo.Target with a correct id", arguments);
                }
            }
        }
    }
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) GenericsType(org.codehaus.groovy.ast.GenericsType) Parameter(org.codehaus.groovy.ast.Parameter) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList)

Example 90 with AnnotationNode

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

the class StaticTypeCheckingVisitor method inferClosureParameterTypes.

/**
     * 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
     */
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");
            if (hintClass instanceof ClassExpression) {
                doInferClosureParameterTypes(receiver, arguments, expression, selectedMethod, hintClass, options);
            }
        }
    } else if (isSAMType(param.getOriginType())) {
        // SAM coercion
        inferSAMType(param, receiver, selectedMethod, InvocationWriter.makeArgumentList(arguments), expression);
    }
}
Also used : AnnotationNode(org.codehaus.groovy.ast.AnnotationNode)

Aggregations

AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)173 ClassNode (org.codehaus.groovy.ast.ClassNode)117 AnnotatedNode (org.codehaus.groovy.ast.AnnotatedNode)67 FieldNode (org.codehaus.groovy.ast.FieldNode)43 MethodNode (org.codehaus.groovy.ast.MethodNode)39 Expression (org.codehaus.groovy.ast.expr.Expression)37 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)36 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)31 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)29 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)29 ArrayList (java.util.ArrayList)26 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)22 Parameter (org.codehaus.groovy.ast.Parameter)18 DeclarationExpression (org.codehaus.groovy.ast.expr.DeclarationExpression)16 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)16 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)16 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)15 AST (antlr.collections.AST)14 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)14 Statement (org.codehaus.groovy.ast.stmt.Statement)14