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);
}
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;
}
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);
}
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);
}
}
}
}
}
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);
}
}
Aggregations