use of org.codehaus.groovy.ast.PropertyNode in project groovy by apache.
the class SortableASTTransformation method createSortable.
private void createSortable(AnnotationNode anno, ClassNode classNode) {
List<String> includes = getMemberStringList(anno, "includes");
List<String> excludes = getMemberStringList(anno, "excludes");
boolean reversed = memberHasValue(anno, "reversed", true);
boolean includeSuperProperties = memberHasValue(anno, "includeSuperProperties", true);
boolean allNames = memberHasValue(anno, "allNames", true);
boolean allProperties = !memberHasValue(anno, "allProperties", false);
if (!checkIncludeExcludeUndefinedAware(anno, excludes, includes, MY_TYPE_NAME))
return;
if (!checkPropertyList(classNode, includes, "includes", anno, MY_TYPE_NAME, false, includeSuperProperties, allProperties))
return;
if (!checkPropertyList(classNode, excludes, "excludes", anno, MY_TYPE_NAME, false, includeSuperProperties, allProperties))
return;
if (classNode.isInterface()) {
addError(MY_TYPE_NAME + " cannot be applied to interface " + classNode.getName(), anno);
}
List<PropertyNode> properties = findProperties(anno, classNode, includes, excludes, allProperties, includeSuperProperties, allNames);
implementComparable(classNode);
addGeneratedMethod(classNode, "compareTo", ACC_PUBLIC, ClassHelper.int_TYPE, params(param(newClass(classNode), OTHER)), ClassNode.EMPTY_ARRAY, createCompareToMethodBody(properties, reversed));
for (PropertyNode property : properties) {
createComparatorFor(classNode, property, reversed);
}
new VariableScopeVisitor(sourceUnit, true).visitClass(classNode);
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy by apache.
the class SortableASTTransformation method createCompareToMethodBody.
private static Statement createCompareToMethodBody(List<PropertyNode> properties, boolean reversed) {
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(localVarX(THIS_HASH, ClassHelper.Integer_TYPE), callX(varX("this"), "hashCode")));
statements.add(declS(localVarX(OTHER_HASH, ClassHelper.Integer_TYPE), callX(varX(OTHER), "hashCode")));
statements.add(returnS(compareExpr(varX(THIS_HASH), varX(OTHER_HASH), reversed)));
} else {
// int value = 0;
statements.add(declS(localVarX(VALUE, ClassHelper.int_TYPE), constX(0)));
for (PropertyNode property : properties) {
String propName = property.getName();
// value = this.prop <=> other.prop;
statements.add(assignS(varX(VALUE), compareExpr(propX(varX("this"), propName), propX(varX(OTHER), propName), reversed)));
// 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 by apache.
the class ToStringASTTransformation method calculateToStringStatements.
private static Expression calculateToStringStatements(ClassNode cNode, boolean includeSuper, boolean includeFields, boolean includeSuperFields, List<String> excludes, final List<String> includes, boolean includeNames, boolean ignoreNulls, boolean includePackage, boolean includeSuperProperties, boolean allProperties, BlockStatement body, boolean allNames, boolean pojo, String[] delims) {
// def _result = new StringBuilder()
final Expression result = localVarX("_result");
body.addStatement(declS(result, ctorX(STRINGBUILDER_TYPE)));
List<ToStringElement> elements = new ArrayList<>();
// def $toStringFirst = true
final VariableExpression first = localVarX("$toStringFirst");
body.addStatement(declS(first, constX(Boolean.TRUE)));
// <class_name>(
String className = (includePackage) ? cNode.getName() : cNode.getNameWithoutPackage();
body.addStatement(appendS(result, constX(className + delims[0])));
Set<String> names = new HashSet<>();
List<PropertyNode> superList;
if (includeSuperProperties || includeSuperFields) {
superList = getAllProperties(names, cNode, cNode.getSuperClass(), includeSuperProperties, includeSuperFields, allProperties, false, true, true, true, allNames, false);
} else {
superList = new ArrayList<PropertyNode>();
}
List<PropertyNode> list = getAllProperties(names, cNode, cNode, true, includeFields, allProperties, false, false, true, false, allNames, false);
list.addAll(superList);
for (PropertyNode pNode : list) {
String name = pNode.getName();
if (shouldSkipUndefinedAware(name, excludes, includes, allNames))
continue;
FieldNode fNode = pNode.getField();
if (!cNode.hasProperty(name) && fNode.getDeclaringClass() != null) {
// it's really just a field
elements.add(new ToStringElement(varX(fNode), name, canBeSelf(cNode, fNode.getType())));
} else {
Expression getter = getterThisX(cNode, pNode);
elements.add(new ToStringElement(getter, name, canBeSelf(cNode, pNode.getType())));
}
}
// append super if needed
if (includeSuper) {
// not through MOP to avoid infinite recursion
elements.add(new ToStringElement(callSuperX(TO_STRING), "super", false));
}
if (includes != null) {
Comparator<ToStringElement> includeComparator = Comparator.comparingInt(tse -> includes.indexOf(tse.name));
elements.sort(includeComparator);
}
for (ToStringElement el : elements) {
appendValue(body, result, first, el.value, el.name, includeNames, ignoreNulls, el.canBeSelf, pojo, delims);
}
// wrap up
body.addStatement(appendS(result, constX(delims[1])));
return toStringX(result);
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy by apache.
the class AstBuilder method declareProperty.
private PropertyNode declareProperty(final GroovyParserRuleContext ctx, final ModifierManager modifierManager, final ClassNode variableType, final ClassNode classNode, final int i, final ASTNode startNode, final String fieldName, final int modifiers, final Expression initialValue) {
PropertyNode propertyNode;
FieldNode fieldNode = classNode.getDeclaredField(fieldName);
if (fieldNode != null && !classNode.hasProperty(fieldName)) {
if (fieldNode.hasInitialExpression() && initialValue != null) {
throw createParsingFailedException("The split property definition named '" + fieldName + "' must not have an initial value for both the field and the property", ctx);
}
if (!fieldNode.getType().equals(variableType)) {
throw createParsingFailedException("The split property definition named '" + fieldName + "' must not have different types for the field and the property", ctx);
}
classNode.getFields().remove(fieldNode);
propertyNode = new PropertyNode(fieldNode, modifiers | Opcodes.ACC_PUBLIC, null, null);
classNode.addProperty(propertyNode);
if (initialValue != null) {
fieldNode.setInitialValueExpression(initialValue);
}
modifierManager.attachAnnotations(propertyNode);
propertyNode.addAnnotation(new AnnotationNode(ClassHelper.make(CompileStatic.class)));
// expand properties early so AST transforms will be handled correctly
PropertyExpander expander = new PropertyExpander(classNode);
expander.visitProperty(propertyNode);
} else {
propertyNode = new PropertyNode(fieldName, modifiers | Opcodes.ACC_PUBLIC, variableType, classNode, initialValue, null, null);
classNode.addProperty(propertyNode);
fieldNode = propertyNode.getField();
fieldNode.setModifiers(modifiers & ~Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE);
fieldNode.setSynthetic(!classNode.isInterface());
modifierManager.attachAnnotations(fieldNode);
modifierManager.attachAnnotations(propertyNode);
if (i == 0) {
configureAST(fieldNode, ctx, initialValue);
} else {
configureAST(fieldNode, startNode, initialValue);
}
}
groovydocManager.handle(fieldNode, ctx);
groovydocManager.handle(propertyNode, ctx);
if (i == 0) {
configureAST(propertyNode, ctx, initialValue);
} else {
configureAST(propertyNode, startNode, initialValue);
}
return propertyNode;
}
use of org.codehaus.groovy.ast.PropertyNode in project groovy by apache.
the class AutoImplementASTTransformation method getAllCorrectedMethodsMap.
/**
* Returns all methods including abstract super/interface methods but only
* if not overridden by a concrete declared/inherited method.
*/
private static Map<String, MethodNode> getAllCorrectedMethodsMap(final ClassNode cNode) {
Map<String, MethodNode> result = new HashMap<>();
for (MethodNode mn : cNode.getMethods()) {
result.put(methodDescriptorWithoutReturnType(mn), mn);
}
ClassNode next = cNode;
while (true) {
Map<String, ClassNode> genericsSpec = createGenericsSpec(next);
if (next != cNode) {
for (MethodNode mn : next.getMethods()) {
MethodNode correctedMethod = correctToGenericsSpec(genericsSpec, mn);
ClassNode correctedClass = correctToGenericsSpecRecurse(genericsSpec, next);
MethodNode found = getDeclaredMethodCorrected(genericsSpec, correctedMethod, correctedClass);
if (found != null) {
String td = methodDescriptorWithoutReturnType(found);
if (result.containsKey(td) && isWeakerCandidate(result.get(td), found))
continue;
result.put(td, found);
}
}
}
List<ClassNode> interfaces = new ArrayList<>();
Collections.addAll(interfaces, next.getInterfaces());
Map<String, ClassNode> updatedGenericsSpec = new HashMap<>(genericsSpec);
while (!interfaces.isEmpty()) {
ClassNode origInterface = interfaces.remove(0);
// ignore java.lang.Object; also methods added by Verifier for GroovyObject are already good enough
if (!isObjectType(origInterface) && !isGroovyObjectType(origInterface)) {
updatedGenericsSpec = createGenericsSpec(origInterface, updatedGenericsSpec);
ClassNode correctedInterface = correctToGenericsSpecRecurse(updatedGenericsSpec, origInterface);
for (MethodNode nextMethod : correctedInterface.getMethods()) {
MethodNode correctedMethod = correctToGenericsSpec(updatedGenericsSpec, nextMethod);
MethodNode found = getDeclaredMethodCorrected(updatedGenericsSpec, correctedMethod, correctedInterface);
if (found != null) {
String td = methodDescriptorWithoutReturnType(found);
if (result.containsKey(td) && isWeakerCandidate(result.get(td), found))
continue;
result.put(td, found);
}
}
Collections.addAll(interfaces, correctedInterface.getInterfaces());
}
}
ClassNode superClass = next.getUnresolvedSuperClass();
if (superClass == null) {
break;
}
next = correctToGenericsSpecRecurse(updatedGenericsSpec, superClass);
}
// GROOVY-9816: remove entries for to-be-generated property access and mutate methods
for (ClassNode cn = cNode; cn != null && !isObjectType(cn); cn = cn.getSuperClass()) {
for (PropertyNode pn : cn.getProperties()) {
if (!pn.getField().isFinal()) {
result.remove(pn.getSetterNameOrDefault() + ":" + pn.getType().getText() + ",");
}
if (!isPrimitiveBoolean(pn.getType())) {
result.remove(pn.getGetterNameOrDefault() + ":");
} else if (pn.getGetterName() != null) {
result.remove(pn.getGetterName() + ":");
} else {
// getter generated only if no explicit isser and vice versa
String isserName = "is" + capitalize(pn.getName());
String getterName = getGetterName(pn.getName());
if (!cNode.hasMethod(isserName, Parameter.EMPTY_ARRAY)) {
result.remove(getterName + ":");
}
if (!cNode.hasMethod(getterName, Parameter.EMPTY_ARRAY)) {
result.remove(isserName + ":");
}
}
}
}
return result;
}
Aggregations