use of org.codehaus.groovy.ast.FieldNode in project groovy by apache.
the class AutoCloneASTTransformation method addSimpleCloneHelperMethod.
private static void addSimpleCloneHelperMethod(ClassNode cNode, List<FieldNode> fieldNodes, List<String> excludes) {
Parameter methodParam = new Parameter(GenericsUtils.nonGeneric(cNode), "other");
final Expression other = varX(methodParam);
boolean hasParent = cNode.getSuperClass() != ClassHelper.OBJECT_TYPE;
BlockStatement methodBody = new BlockStatement();
if (hasParent) {
methodBody.addStatement(stmt(callSuperX("cloneOrCopyMembers", args(other))));
}
for (FieldNode fieldNode : fieldNodes) {
String name = fieldNode.getName();
if (excludes != null && excludes.contains(name))
continue;
ClassNode fieldType = fieldNode.getType();
Expression direct = propX(varX("this"), name);
Expression to = propX(other, name);
Statement assignDirect = assignS(to, direct);
Statement assignCloned = assignS(to, castX(fieldType, callCloneDirectX(direct)));
Statement assignClonedDynamic = assignS(to, castX(fieldType, callCloneDynamicX(direct)));
if (isCloneableType(fieldType)) {
methodBody.addStatement(assignCloned);
} else if (!possiblyCloneable(fieldType)) {
methodBody.addStatement(assignDirect);
} else {
methodBody.addStatement(ifElseS(isInstanceOfX(direct, CLONEABLE_TYPE), assignClonedDynamic, assignDirect));
}
}
ClassNode[] exceptions = { make(CloneNotSupportedException.class) };
cNode.addMethod("cloneOrCopyMembers", ACC_PROTECTED, ClassHelper.VOID_TYPE, params(methodParam), exceptions, methodBody);
}
use of org.codehaus.groovy.ast.FieldNode in project groovy by apache.
the class CategoryASTTransformation method ensureNoInstanceFieldOrProperty.
private static 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.FieldNode in project groovy by apache.
the class EqualsAndHashCodeASTTransformation method createHashCode.
public static void createHashCode(ClassNode cNode, boolean cacheResult, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes, boolean allNames) {
// make a public method if none exists otherwise try a private method with leading underscore
boolean hasExistingHashCode = hasDeclaredMethod(cNode, "hashCode", 0);
if (hasExistingHashCode && hasDeclaredMethod(cNode, "_hashCode", 0))
return;
final BlockStatement body = new BlockStatement();
// TODO use pList and fList
if (cacheResult) {
final FieldNode hashField = cNode.addField("$hash$code", ACC_PRIVATE | ACC_SYNTHETIC, ClassHelper.int_TYPE, null);
final Expression hash = varX(hashField);
body.addStatement(ifS(isZeroX(hash), calculateHashStatements(cNode, hash, includeFields, callSuper, excludes, includes, allNames)));
body.addStatement(returnS(hash));
} else {
body.addStatement(calculateHashStatements(cNode, null, includeFields, callSuper, excludes, includes, allNames));
}
cNode.addMethod(new MethodNode(hasExistingHashCode ? "_hashCode" : "hashCode", hasExistingHashCode ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.int_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body));
}
use of org.codehaus.groovy.ast.FieldNode in project groovy by apache.
the class EqualsAndHashCodeASTTransformation method createEquals.
public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes, boolean allNames) {
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, allNames))
continue;
boolean canBeSelf = StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(pNode.getOriginType(), cNode);
if (!canBeSelf) {
body.addStatement(ifS(notX(hasEqualPropertyX(otherTyped.getOriginType(), 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(otherTyped.getOriginType(), 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, allNames))
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.FieldNode in project groovy by apache.
the class AntlrParserPlugin method fieldDef.
protected void fieldDef(AST fieldDef) {
List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
AST node = fieldDef.getFirstChild();
int modifiers = 0;
if (isType(MODIFIERS, node)) {
modifiers = modifiers(node, annotations, modifiers);
node = node.getNextSibling();
}
if (classNode.isInterface()) {
modifiers |= Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
if ((modifiers & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) == 0) {
modifiers |= Opcodes.ACC_PUBLIC;
}
}
ClassNode type = null;
if (isType(TYPE, node)) {
type = makeTypeWithArguments(node);
node = node.getNextSibling();
}
String name = identifier(node);
node = node.getNextSibling();
Expression initialValue = null;
if (node != null) {
assertNodeType(ASSIGN, node);
initialValue = expression(node.getFirstChild());
}
if (classNode.isInterface() && initialValue == null && type != null) {
initialValue = getDefaultValueForPrimitive(type);
}
FieldNode fieldNode = new FieldNode(name, modifiers, type, classNode, initialValue);
fieldNode.addAnnotations(annotations);
configureAST(fieldNode, fieldDef);
if (!hasVisibility(modifiers)) {
// let's set the modifiers on the field
int fieldModifiers = 0;
int flags = Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT | Opcodes.ACC_VOLATILE | Opcodes.ACC_FINAL;
if (!hasVisibility(modifiers)) {
modifiers |= Opcodes.ACC_PUBLIC;
fieldModifiers |= Opcodes.ACC_PRIVATE;
}
// let's pass along any other modifiers we need
fieldModifiers |= (modifiers & flags);
fieldNode.setModifiers(fieldModifiers);
fieldNode.setSynthetic(true);
// in the case that there is already a field, we would
// like to use that field, instead of the default field
// for the property
FieldNode storedNode = classNode.getDeclaredField(fieldNode.getName());
if (storedNode != null && !classNode.hasProperty(name)) {
fieldNode = storedNode;
// we remove it here, because addProperty will add it
// again and we want to avoid it showing up multiple
// times in the fields list.
classNode.getFields().remove(storedNode);
}
PropertyNode propertyNode = new PropertyNode(fieldNode, modifiers, null, null);
configureAST(propertyNode, fieldDef);
classNode.addProperty(propertyNode);
} else {
fieldNode.setModifiers(modifiers);
// if there is a property of that name, then a field of that
// name already exists, which means this new field here should
// be used instead of the field the property originally has.
PropertyNode pn = classNode.getProperty(name);
if (pn != null && pn.getField().isSynthetic()) {
classNode.getFields().remove(pn.getField());
pn.setField(fieldNode);
}
classNode.addField(fieldNode);
}
}
Aggregations