use of org.codehaus.groovy.ast.PropertyNode in project groovy-core by groovy.
the class BindableASTTransformation method addListenerToProperty.
private void addListenerToProperty(SourceUnit source, AnnotationNode node, ClassNode declaringClass, FieldNode field) {
String fieldName = field.getName();
for (PropertyNode propertyNode : declaringClass.getProperties()) {
if (propertyNode.getName().equals(fieldName)) {
if (field.isStatic()) {
//noinspection ThrowableInstanceNeverThrown
source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException("@groovy.beans.Bindable cannot annotate a static property.", node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()), source));
} else {
if (needsPropertyChangeSupport(declaringClass, source)) {
addPropertyChangeSupport(declaringClass);
}
createListenerSetter(declaringClass, propertyNode);
}
return;
}
}
//noinspection ThrowableInstanceNeverThrown
source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException("@groovy.beans.Bindable 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.PropertyNode in project groovy-core by groovy.
the class CategoryASTTransformation method visit.
/**
* Property invocations done on 'this' reference are transformed so that the invocations at runtime are
* done on the additional parameter 'self'
*/
public void visit(ASTNode[] nodes, final SourceUnit source) {
if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof ClassNode)) {
source.getErrorCollector().addError(new SyntaxErrorMessage(new SyntaxException("@Category can only be added to a ClassNode but got: " + (nodes.length == 2 ? nodes[1] : "nothing"), nodes[0].getLineNumber(), nodes[0].getColumnNumber()), source));
}
AnnotationNode annotation = (AnnotationNode) nodes[0];
ClassNode parent = (ClassNode) nodes[1];
ClassNode targetClass = getTargetClass(source, annotation);
thisExpression.setType(targetClass);
final LinkedList<Set<String>> varStack = new LinkedList<Set<String>>();
if (!ensureNoInstanceFieldOrProperty(source, parent))
return;
Set<String> names = new HashSet<String>();
for (FieldNode field : parent.getFields()) {
names.add(field.getName());
}
for (PropertyNode field : parent.getProperties()) {
names.add(field.getName());
}
varStack.add(names);
final Reference parameter = new Reference();
final ClassCodeExpressionTransformer expressionTransformer = new ClassCodeExpressionTransformer() {
protected SourceUnit getSourceUnit() {
return source;
}
private void addVariablesToStack(Parameter[] params) {
Set<String> names = new HashSet<String>();
names.addAll(varStack.getLast());
for (Parameter param : params) {
names.add(param.getName());
}
varStack.add(names);
}
@Override
public void visitCatchStatement(CatchStatement statement) {
varStack.getLast().add(statement.getVariable().getName());
super.visitCatchStatement(statement);
varStack.getLast().remove(statement.getVariable().getName());
}
@Override
public void visitMethod(MethodNode node) {
addVariablesToStack(node.getParameters());
super.visitMethod(node);
varStack.removeLast();
}
@Override
public void visitBlockStatement(BlockStatement block) {
Set<String> names = new HashSet<String>();
names.addAll(varStack.getLast());
varStack.add(names);
super.visitBlockStatement(block);
varStack.remove(names);
}
@Override
public void visitClosureExpression(ClosureExpression ce) {
addVariablesToStack(ce.getParameters());
super.visitClosureExpression(ce);
varStack.removeLast();
}
@Override
public void visitDeclarationExpression(DeclarationExpression expression) {
if (expression.isMultipleAssignmentDeclaration()) {
TupleExpression te = expression.getTupleExpression();
List<Expression> list = te.getExpressions();
for (Expression arg : list) {
VariableExpression ve = (VariableExpression) arg;
varStack.getLast().add(ve.getName());
}
} else {
VariableExpression ve = expression.getVariableExpression();
varStack.getLast().add(ve.getName());
}
super.visitDeclarationExpression(expression);
}
@Override
public void visitForLoop(ForStatement forLoop) {
Expression exp = forLoop.getCollectionExpression();
exp.visit(this);
Parameter loopParam = forLoop.getVariable();
if (loopParam != null) {
varStack.getLast().add(loopParam.getName());
}
super.visitForLoop(forLoop);
}
@Override
public void visitExpressionStatement(ExpressionStatement es) {
// GROOVY-3543: visit the declaration expressions so that declaration variables get added on the varStack
Expression exp = es.getExpression();
if (exp instanceof DeclarationExpression) {
exp.visit(this);
}
super.visitExpressionStatement(es);
}
@Override
public Expression transform(Expression exp) {
if (exp instanceof VariableExpression) {
VariableExpression ve = (VariableExpression) exp;
if (ve.getName().equals("this"))
return thisExpression;
else {
if (!varStack.getLast().contains(ve.getName())) {
return new PropertyExpression(thisExpression, ve.getName());
}
}
} else if (exp instanceof PropertyExpression) {
PropertyExpression pe = (PropertyExpression) exp;
if (pe.getObjectExpression() instanceof VariableExpression) {
VariableExpression vex = (VariableExpression) pe.getObjectExpression();
if (vex.isThisExpression()) {
pe.setObjectExpression(thisExpression);
return pe;
}
}
} else if (exp instanceof ClosureExpression) {
ClosureExpression ce = (ClosureExpression) exp;
ce.getVariableScope().putReferencedLocalVariable((Parameter) parameter.get());
Parameter[] params = ce.getParameters();
if (params == null) {
params = Parameter.EMPTY_ARRAY;
} else if (params.length == 0) {
params = new Parameter[] { new Parameter(ClassHelper.OBJECT_TYPE, "it") };
}
addVariablesToStack(params);
ce.getCode().visit(this);
varStack.removeLast();
}
return super.transform(exp);
}
};
for (MethodNode method : parent.getMethods()) {
if (!method.isStatic()) {
method.setModifiers(method.getModifiers() | Opcodes.ACC_STATIC);
final Parameter[] origParams = method.getParameters();
final Parameter[] newParams = new Parameter[origParams.length + 1];
Parameter p = new Parameter(targetClass, "$this");
p.setClosureSharedVariable(true);
newParams[0] = p;
parameter.set(p);
System.arraycopy(origParams, 0, newParams, 1, origParams.length);
method.setParameters(newParams);
expressionTransformer.visitMethod(method);
}
}
new VariableScopeVisitor(source, true).visitClass(parent);
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy-core by groovy.
the class CategoryASTTransformation method ensureNoInstanceFieldOrProperty.
private boolean ensureNoInstanceFieldOrProperty(final SourceUnit source, final ClassNode parent) {
boolean valid = true;
for (FieldNode fieldNode : parent.getFields()) {
if (!fieldNode.isStatic() && fieldNode.getLineNumber() > 0) {
// if <0, probably an AST transform or internal code (like generated metaclass field, ...)
addUnsupportedError(fieldNode, source);
valid = false;
}
}
for (PropertyNode propertyNode : parent.getProperties()) {
if (!propertyNode.isStatic() && propertyNode.getLineNumber() > 0) {
// if <0, probably an AST transform or internal code (like generated metaclass field, ...)
addUnsupportedError(propertyNode, source);
valid = false;
}
}
return valid;
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy-core by groovy.
the class EqualsAndHashCodeASTTransformation method createEquals.
public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes) {
if (useCanEqual)
createCanEqual(cNode);
// make a public method if none exists otherwise try a private method with leading underscore
boolean hasExistingEquals = hasDeclaredMethod(cNode, "equals", 1);
if (hasExistingEquals && hasDeclaredMethod(cNode, "_equals", 1))
return;
final BlockStatement body = new BlockStatement();
VariableExpression other = varX("other");
// some short circuit cases for efficiency
body.addStatement(ifS(equalsNullX(other), returnS(constX(Boolean.FALSE, true))));
body.addStatement(ifS(sameX(varX("this"), other), returnS(constX(Boolean.TRUE, true))));
if (useCanEqual) {
body.addStatement(ifS(notX(isInstanceOfX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE, true))));
} else {
body.addStatement(ifS(notX(hasClassX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE, true))));
}
VariableExpression otherTyped = varX("otherTyped", GenericsUtils.nonGeneric(cNode));
CastExpression castExpression = new CastExpression(GenericsUtils.nonGeneric(cNode), other);
castExpression.setStrict(true);
body.addStatement(declS(otherTyped, castExpression));
if (useCanEqual) {
body.addStatement(ifS(notX(callX(otherTyped, "canEqual", varX("this"))), returnS(constX(Boolean.FALSE, true))));
}
List<PropertyNode> pList = getInstanceProperties(cNode);
for (PropertyNode pNode : pList) {
if (shouldSkip(pNode.getName(), excludes, includes))
continue;
boolean canBeSelf = StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(pNode.getOriginType(), cNode);
if (!canBeSelf) {
body.addStatement(ifS(notX(hasEqualPropertyX(pNode, otherTyped)), returnS(constX(Boolean.FALSE, true))));
} else {
body.addStatement(ifS(notX(hasSamePropertyX(pNode, otherTyped)), ifElseS(differentSelfRecursivePropertyX(pNode, otherTyped), returnS(constX(Boolean.FALSE, true)), ifS(notX(bothSelfRecursivePropertyX(pNode, otherTyped)), ifS(notX(hasEqualPropertyX(pNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))))));
}
}
List<FieldNode> fList = new ArrayList<FieldNode>();
if (includeFields) {
fList.addAll(getInstanceNonPropertyFields(cNode));
}
for (FieldNode fNode : fList) {
if (shouldSkip(fNode.getName(), excludes, includes))
continue;
body.addStatement(ifS(notX(hasSameFieldX(fNode, otherTyped)), ifElseS(differentSelfRecursiveFieldX(fNode, otherTyped), returnS(constX(Boolean.FALSE, true)), ifS(notX(bothSelfRecursiveFieldX(fNode, otherTyped)), ifS(notX(hasEqualFieldX(fNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))))));
}
if (callSuper) {
body.addStatement(ifS(notX(isTrueX(callSuperX("equals", other))), returnS(constX(Boolean.FALSE, true))));
}
// default
body.addStatement(returnS(constX(Boolean.TRUE, true)));
cNode.addMethod(new MethodNode(hasExistingEquals ? "_equals" : "equals", hasExistingEquals ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.boolean_TYPE, params(param(OBJECT_TYPE, other.getName())), ClassNode.EMPTY_ARRAY, body));
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy-core by groovy.
the class SortableASTTransformation method findProperties.
private List<PropertyNode> findProperties(AnnotationNode annotation, ClassNode classNode, final List<String> includes, final List<String> excludes) {
List<PropertyNode> properties = new ArrayList<PropertyNode>();
for (PropertyNode property : classNode.getProperties()) {
String propertyName = property.getName();
if (property.isStatic() || excludes.contains(propertyName) || !includes.isEmpty() && !includes.contains(propertyName))
continue;
properties.add(property);
}
for (String name : includes) {
checkKnownProperty(annotation, name, properties);
}
for (PropertyNode pNode : properties) {
checkComparable(pNode);
}
if (!includes.isEmpty()) {
Comparator<PropertyNode> includeComparator = new Comparator<PropertyNode>() {
public int compare(PropertyNode o1, PropertyNode o2) {
return new Integer(includes.indexOf(o1.getName())).compareTo(includes.indexOf(o2.getName()));
}
};
Collections.sort(properties, includeComparator);
}
return properties;
}
Aggregations