use of org.codehaus.groovy.ast.PropertyNode in project groovy-core by groovy.
the class SortableASTTransformation method createCompareToMethodBody.
private static Statement createCompareToMethodBody(List<PropertyNode> properties) {
List<Statement> statements = new ArrayList<Statement>();
// if (this.is(other)) return 0;
statements.add(ifS(callThisX("is", args(OTHER)), returnS(constX(0))));
if (properties.isEmpty()) {
// perhaps overkill but let compareTo be based on hashes for commutativity
// return this.hashCode() <=> other.hashCode()
statements.add(declS(varX(THIS_HASH, ClassHelper.Integer_TYPE), callX(varX("this"), "hashCode")));
statements.add(declS(varX(OTHER_HASH, ClassHelper.Integer_TYPE), callX(varX(OTHER), "hashCode")));
statements.add(returnS(cmpX(varX(THIS_HASH), varX(OTHER_HASH))));
} else {
// int value = 0;
statements.add(declS(varX(VALUE, ClassHelper.int_TYPE), constX(0)));
for (PropertyNode property : properties) {
String propName = property.getName();
// value = this.prop <=> other.prop;
statements.add(assignS(varX(VALUE), cmpX(propX(varX("this"), propName), propX(varX(OTHER), propName))));
// if (value != 0) return value;
statements.add(ifS(neX(varX(VALUE), constX(0)), returnS(varX(VALUE))));
}
// objects are equal
statements.add(returnS(constX(0)));
}
final BlockStatement body = new BlockStatement();
body.addStatements(statements);
return body;
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy-core by groovy.
the class ToStringASTTransformation method calculateToStringStatements.
private static Expression calculateToStringStatements(ClassNode cNode, boolean includeSuper, boolean includeFields, List<String> excludes, List<String> includes, boolean includeNames, boolean ignoreNulls, boolean includePackage, boolean includeSuperProperties, BlockStatement body) {
// def _result = new StringBuilder()
final Expression result = varX("_result");
body.addStatement(declS(result, ctorX(STRINGBUILDER_TYPE)));
// def $toStringFirst = true
final VariableExpression first = varX("$toStringFirst");
body.addStatement(declS(first, constX(Boolean.TRUE)));
// <class_name>(
String className = (includePackage) ? cNode.getName() : cNode.getNameWithoutPackage();
body.addStatement(appendS(result, constX(className + "(")));
// append properties
List<PropertyNode> pList;
if (includeSuperProperties) {
pList = getAllProperties(cNode);
Iterator<PropertyNode> pIterator = pList.iterator();
while (pIterator.hasNext()) {
if (pIterator.next().isStatic()) {
pIterator.remove();
}
}
} else {
pList = getInstanceProperties(cNode);
}
for (PropertyNode pNode : pList) {
if (shouldSkip(pNode.getName(), excludes, includes))
continue;
Expression getter = getterX(cNode, pNode);
appendValue(body, result, first, getter, pNode.getName(), includeNames, ignoreNulls);
}
// append fields if needed
if (includeFields) {
List<FieldNode> fList = new ArrayList<FieldNode>();
fList.addAll(getInstanceNonPropertyFields(cNode));
for (FieldNode fNode : fList) {
if (shouldSkip(fNode.getName(), excludes, includes))
continue;
appendValue(body, result, first, varX(fNode), fNode.getName(), includeNames, ignoreNulls);
}
}
// append super if needed
if (includeSuper) {
appendCommaIfNotFirst(body, result, first);
appendPrefix(body, result, "super", includeNames);
// not through MOP to avoid infinite recursion
body.addStatement(appendS(result, callSuperX("toString")));
}
// wrap up
body.addStatement(appendS(result, constX(")")));
MethodCallExpression toString = callX(result, "toString");
toString.setImplicitThis(false);
return toString;
}
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 ImmutableASTTransformation method createConstructorMap.
private void createConstructorMap(ClassNode cNode, List<PropertyNode> list, List<String> knownImmutableClasses, List<String> knownImmutables) {
final BlockStatement body = new BlockStatement();
body.addStatement(ifS(equalsNullX(varX("args")), assignS(varX("args"), new MapExpression())));
for (PropertyNode pNode : list) {
body.addStatement(createConstructorStatement(cNode, pNode, knownImmutableClasses, knownImmutables));
}
// check for missing properties
body.addStatement(stmt(callX(SELF_TYPE, "checkPropNames", args("this", "args"))));
createConstructorMapCommon(cNode, body);
if (list.size() > 0) {
createNoArgConstructor(cNode);
}
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method existsProperty.
/**
* Checks whether a property exists on the receiver, or on any of the possible receiver classes (found in the
* temporary type information table)
*
* @param pexp a property expression
* @param readMode if true, look for property read, else for property set
* @param visitor if not null, when the property node is found, visit it with the provided visitor
* @return true if the property is defined in any of the possible receiver classes
*/
protected boolean existsProperty(final PropertyExpression pexp, final boolean readMode, final ClassCodeVisitorSupport visitor) {
super.visitPropertyExpression(pexp);
String propertyName = pexp.getPropertyAsString();
if (propertyName == null)
return false;
Expression objectExpression = pexp.getObjectExpression();
final ClassNode objectExpressionType = getType(objectExpression);
boolean staticOnlyAccess = isClassClassNodeWrappingConcreteType(objectExpressionType);
if ("this".equals(propertyName) && staticOnlyAccess) {
// Outer.this
ClassNode outerNode = objectExpressionType.getGenericsTypes()[0].getType();
ClassNode current = typeCheckingContext.getEnclosingClassNode();
if (!current.isStaticClass() && current instanceof InnerClassNode) {
InnerClassNode icn = (InnerClassNode) current;
if (outerNode.equals(icn.getOuterClass())) {
storeType(pexp, outerNode);
return true;
}
}
}
if (objectExpressionType.isArray() && "length".equals(pexp.getPropertyAsString())) {
storeType(pexp, int_TYPE);
if (visitor != null) {
PropertyNode node = new PropertyNode("length", Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, int_TYPE, objectExpressionType, null, null, null);
visitor.visitProperty(node);
}
return true;
}
boolean foundGetterOrSetter = false;
List<Receiver<String>> receivers = new LinkedList<Receiver<String>>();
List<Receiver<String>> owners = makeOwnerList(objectExpression);
addReceivers(receivers, owners, pexp.isImplicitThis());
String capName = MetaClassHelper.capitalize(propertyName);
boolean isAttributeExpression = pexp instanceof AttributeExpression;
HashSet<ClassNode> handledNodes = new HashSet<ClassNode>();
for (Receiver<String> receiver : receivers) {
ClassNode testClass = receiver.getType();
LinkedList<ClassNode> queue = new LinkedList<ClassNode>();
queue.add(testClass);
if (isPrimitiveType(testClass)) {
queue.add(getWrapper(testClass));
}
while (!queue.isEmpty()) {
ClassNode current = queue.removeFirst();
if (handledNodes.contains(current))
continue;
handledNodes.add(current);
Set<ClassNode> allInterfaces = current.getAllInterfaces();
for (ClassNode intf : allInterfaces) {
// TODO: apply right generics here!
queue.add(GenericsUtils.parameterizeType(current, intf));
}
// in case of a lookup on Class we look for instance methods on Class
// as well, since in case of a static property access we have the class
// itself in the list of receivers already;
boolean staticOnly;
if (isClassClassNodeWrappingConcreteType(current)) {
staticOnly = false;
} else {
staticOnly = staticOnlyAccess;
}
FieldNode field = current.getDeclaredField(propertyName);
field = allowStaticAccessToMember(field, staticOnly);
if (storeField(field, isAttributeExpression, pexp, current, visitor, receiver.getData()))
return true;
PropertyNode propertyNode = current.getProperty(propertyName);
propertyNode = allowStaticAccessToMember(propertyNode, staticOnly);
if (storeProperty(propertyNode, pexp, current, visitor, receiver.getData()))
return true;
boolean isThisExpression = objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).isThisExpression();
if (storeField(field, isThisExpression, pexp, receiver.getType(), visitor, receiver.getData()))
return true;
MethodNode getter = current.getGetterMethod("get" + capName);
getter = allowStaticAccessToMember(getter, staticOnly);
if (getter == null)
getter = current.getGetterMethod("is" + capName);
getter = allowStaticAccessToMember(getter, staticOnly);
final String setterName = "set" + capName;
List<MethodNode> setters = findSetters(current, setterName, false);
setters = allowStaticAccessToMember(setters, staticOnly);
// need to visit even if we only look for a setters for compatibility
if (visitor != null && getter != null)
visitor.visitMethod(getter);
if (readMode) {
if (getter != null) {
ClassNode cn = inferReturnTypeGenerics(current, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
storeInferredTypeForPropertyExpression(pexp, cn);
pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY);
String delegationData = receiver.getData();
if (delegationData != null)
pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
return true;
}
} else {
if (!setters.isEmpty()) {
if (visitor != null) {
if (field != null) {
visitor.visitField(field);
} else {
for (MethodNode setter : setters) {
ClassNode setterType = setter.getParameters()[0].getOriginType();
FieldNode virtual = new FieldNode(propertyName, 0, setterType, current, EmptyExpression.INSTANCE);
visitor.visitField(virtual);
}
}
}
// TODO: apply generics on parameter[0]?
// storeType(pexp, setter.getParameters()[0].getType());
SetterInfo info = new SetterInfo(current, setterName, setters);
BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
if (enclosingBinaryExpression != null) {
putSetterInfo(enclosingBinaryExpression.getLeftExpression(), info);
}
String delegationData = receiver.getData();
if (delegationData != null) {
pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
}
return true;
} else if (getter != null) {
pexp.putNodeMetaData(StaticTypesMarker.READONLY_PROPERTY, true);
}
}
foundGetterOrSetter = foundGetterOrSetter || !setters.isEmpty() || getter != null;
if (storeField(field, true, pexp, current, visitor, receiver.getData()))
return true;
// we stop now, otherwise we must check the parent class
if (/*!isAttributeExpression && */
current.getSuperClass() != null) {
queue.add(current.getUnresolvedSuperClass());
}
}
// GROOVY-5568, the property may be defined by DGM
List<MethodNode> methods = findDGMMethodsByNameAndArguments(getTransformLoader(), testClass, "get" + capName, ClassNode.EMPTY_ARRAY);
if (!methods.isEmpty()) {
List<MethodNode> methodNodes = chooseBestMethod(testClass, methods, ClassNode.EMPTY_ARRAY);
if (methodNodes.size() == 1) {
MethodNode getter = methodNodes.get(0);
if (visitor != null) {
visitor.visitMethod(getter);
}
ClassNode cn = inferReturnTypeGenerics(testClass, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
storeInferredTypeForPropertyExpression(pexp, cn);
return true;
}
}
}
for (Receiver<String> receiver : receivers) {
ClassNode testClass = receiver.getType();
ClassNode propertyType = getTypeForMapPropertyExpression(testClass, objectExpressionType, pexp);
if (propertyType == null)
propertyType = getTypeForListPropertyExpression(testClass, objectExpressionType, pexp);
if (propertyType == null)
propertyType = getTypeForSpreadExpression(testClass, objectExpressionType, pexp);
if (propertyType == null)
continue;
if (visitor != null) {
// todo : type inference on maps and lists, if possible
PropertyNode node = new PropertyNode(propertyName, Opcodes.ACC_PUBLIC, propertyType, receiver.getType(), null, null, null);
node.setDeclaringClass(receiver.getType());
visitor.visitProperty(node);
}
storeType(pexp, propertyType);
String delegationData = receiver.getData();
if (delegationData != null)
pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
return true;
}
return foundGetterOrSetter;
}
Aggregations