use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class BindableASTTransformation method visit.
/**
* Handles the bulk of the processing, mostly delegating to other methods.
*
* @param nodes the ast nodes
* @param source the source unit for the nodes
*/
public void visit(ASTNode[] nodes, SourceUnit source) {
if (!(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
throw new RuntimeException("Internal error: wrong types: $node.class / $parent.class");
}
AnnotationNode node = (AnnotationNode) nodes[0];
AnnotatedNode parent = (AnnotatedNode) nodes[1];
if (VetoableASTTransformation.hasVetoableAnnotation(parent)) {
// VetoableASTTransformation will handle both @Bindable and @Vetoable
return;
}
ClassNode declaringClass = parent.getDeclaringClass();
if (parent instanceof FieldNode) {
if ((((FieldNode) parent).getModifiers() & Opcodes.ACC_FINAL) != 0) {
source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException("@groovy.beans.Bindable cannot annotate a final property.", node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()), source));
}
if (VetoableASTTransformation.hasVetoableAnnotation(parent.getDeclaringClass())) {
// VetoableASTTransformation will handle both @Bindable and @Vetoable
return;
}
addListenerToProperty(source, node, declaringClass, (FieldNode) parent);
} else if (parent instanceof ClassNode) {
addListenerToClass(source, (ClassNode) parent);
}
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class VetoableASTTransformation method needsVetoableChangeSupport.
/**
* Snoops through the declaring class and all parents looking for a field
* of type VetoableChangeSupport. Remembers the field and returns false
* if found otherwise returns true to indicate that such support should
* be added.
*
* @param declaringClass the class to search
* @return true if vetoable change support should be added
*/
protected boolean needsVetoableChangeSupport(ClassNode declaringClass, SourceUnit sourceUnit) {
boolean foundAdd = false, foundRemove = false, foundFire = false;
ClassNode consideredClass = declaringClass;
while (consideredClass != null) {
for (MethodNode method : consideredClass.getMethods()) {
// just check length, MOP will match it up
foundAdd = foundAdd || method.getName().equals("addVetoableChangeListener") && method.getParameters().length == 1;
foundRemove = foundRemove || method.getName().equals("removeVetoableChangeListener") && method.getParameters().length == 1;
foundFire = foundFire || method.getName().equals("fireVetoableChange") && method.getParameters().length == 3;
if (foundAdd && foundRemove && foundFire) {
return false;
}
}
consideredClass = consideredClass.getSuperClass();
}
// check if a super class has @Vetoable annotations
consideredClass = declaringClass.getSuperClass();
while (consideredClass != null) {
if (hasVetoableAnnotation(consideredClass))
return false;
for (FieldNode field : consideredClass.getFields()) {
if (hasVetoableAnnotation(field))
return false;
}
consideredClass = consideredClass.getSuperClass();
}
if (foundAdd || foundRemove || foundFire) {
sourceUnit.getErrorCollector().addErrorAndContinue(new SimpleMessage("@Vetoable cannot be processed on " + declaringClass.getName() + " because some but not all of addVetoableChangeListener, removeVetoableChange, and fireVetoableChange were declared in the current or super classes.", sourceUnit));
return false;
}
return true;
}
use of org.codehaus.groovy.ast.ClassNode in project groovy-core by groovy.
the class VetoableASTTransformation method addListenerToProperty.
private void addListenerToProperty(SourceUnit source, AnnotationNode node, AnnotatedNode parent) {
ClassNode declaringClass = parent.getDeclaringClass();
FieldNode field = ((FieldNode) parent);
String fieldName = field.getName();
for (PropertyNode propertyNode : declaringClass.getProperties()) {
boolean bindable = BindableASTTransformation.hasBindableAnnotation(parent) || BindableASTTransformation.hasBindableAnnotation(parent.getDeclaringClass());
if (propertyNode.getName().equals(fieldName)) {
if (field.isStatic()) {
//noinspection ThrowableInstanceNeverThrown
source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException("@groovy.beans.Vetoable cannot annotate a static property.", node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()), source));
} else {
createListenerSetter(source, bindable, declaringClass, propertyNode);
}
return;
}
}
//noinspection ThrowableInstanceNeverThrown
source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException("@groovy.beans.Vetoable must be on a property, not a field. Try removing the private, protected, or public modifier.", node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()), source));
}
use of org.codehaus.groovy.ast.ClassNode in project grails-core by grails.
the class TestMixinTransformation method weaveMixinIntoClass.
protected void weaveMixinIntoClass(final ClassNode classNode, final ClassNode mixinClassNode, final Junit3TestFixtureMethodHandler junit3MethodHandler, ClassNode applicationClassNode) {
if (mixinClassNode.getName().equals(IntegrationTestMixin.class.getName())) {
new IntegrationTestMixinTransformation().weaveIntegrationTestMixin(classNode, applicationClassNode);
return;
}
final String fieldName = '$' + GrailsNameUtils.getPropertyName(mixinClassNode.getName());
boolean implementsTestRuntimeAwareMixin = GrailsASTUtils.findInterface(mixinClassNode, ClassHelper.make(TestRuntimeAwareMixin.class)) != null;
FieldNode mixinFieldNode;
if (!implementsTestRuntimeAwareMixin) {
mixinFieldNode = addLegacyMixinFieldIfNonExistent(classNode, mixinClassNode, fieldName);
} else {
mixinFieldNode = addTestRuntimeAwareMixinFieldIfNonExistent(classNode, mixinClassNode, fieldName);
}
// already woven
if (mixinFieldNode == null)
return;
FieldExpression fieldReference = new FieldExpression(mixinFieldNode);
ClassNode currentMixinClassNode = mixinClassNode;
while (!currentMixinClassNode.getName().equals(GrailsASTUtils.OBJECT_CLASS)) {
final List<MethodNode> mixinMethods = currentMixinClassNode.getMethods();
for (MethodNode mixinMethod : mixinMethods) {
if (!isCandidateMethod(mixinMethod) || hasDeclaredMethod(classNode, mixinMethod)) {
continue;
}
MethodNode methodNode;
if (mixinMethod.isStatic()) {
methodNode = GrailsASTUtils.addDelegateStaticMethod(classNode, mixinMethod);
} else {
methodNode = GrailsASTUtils.addDelegateInstanceMethod(classNode, fieldReference, mixinMethod, false);
}
if (methodNode != null) {
methodNode.addAnnotation(MIXIN_METHOD_ANNOTATION);
GrailsASTUtils.addCompileStaticAnnotation(methodNode);
}
if (junit3MethodHandler != null) {
junit3MethodHandler.handle(mixinMethod, methodNode);
}
}
currentMixinClassNode = currentMixinClassNode.getSuperClass();
if (junit3MethodHandler != null) {
junit3MethodHandler.mixinSuperClassChanged();
}
}
}
use of org.codehaus.groovy.ast.ClassNode in project grails-core by grails.
the class DefaultASTValidateableHelper method getPropertiesToEnsureConstraintsFor.
/**
* Retrieves a Map describing all of the properties which need to be constrained for the class
* represented by classNode. The keys in the Map will be property names and the values are the
* type of the corresponding property.
*
* @param classNode the class to inspect
* @return a Map describing all of the properties which need to be constrained
*/
protected Map<String, ClassNode> getPropertiesToEnsureConstraintsFor(final ClassNode classNode) {
final Map<String, ClassNode> fieldsToConstrain = new HashMap<String, ClassNode>();
final List<FieldNode> allFields = classNode.getFields();
for (final FieldNode field : allFields) {
if (!field.isStatic()) {
final PropertyNode property = classNode.getProperty(field.getName());
if (property != null) {
fieldsToConstrain.put(field.getName(), field.getType());
}
}
}
final Map<String, MethodNode> declaredMethodsMap = classNode.getDeclaredMethodsMap();
for (Entry<String, MethodNode> methodEntry : declaredMethodsMap.entrySet()) {
final MethodNode value = methodEntry.getValue();
if (!value.isStatic() && value.isPublic() && classNode.equals(value.getDeclaringClass()) && value.getLineNumber() > 0) {
Parameter[] parameters = value.getParameters();
if (parameters == null || parameters.length == 0) {
final String methodName = value.getName();
if (methodName.startsWith("get")) {
final ClassNode returnType = value.getReturnType();
final String restOfMethodName = methodName.substring(3);
final String propertyName = GrailsNameUtils.getPropertyName(restOfMethodName);
fieldsToConstrain.put(propertyName, returnType);
}
}
}
}
final ClassNode superClass = classNode.getSuperClass();
if (!superClass.equals(new ClassNode(Object.class))) {
fieldsToConstrain.putAll(getPropertiesToEnsureConstraintsFor(superClass));
}
return fieldsToConstrain;
}
Aggregations