in src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java [105:214]
public void visit(final ASTNode[] nodes, final SourceUnit source) {
init(nodes, source);
AnnotatedNode parent = (AnnotatedNode) nodes[1];
AnnotationNode node = (AnnotationNode) nodes[0];
DelegateDescription delegate = null;
if (parent instanceof FieldNode) {
FieldNode fieldNode = (FieldNode) parent;
delegate = new DelegateDescription();
delegate.delegate = fieldNode;
delegate.annotation = node;
delegate.name = fieldNode.getName();
delegate.type = fieldNode.getType();
delegate.owner = fieldNode.getOwner();
delegate.getOp = varX(fieldNode);
delegate.origin = "field";
} else if (parent instanceof MethodNode) {
MethodNode methodNode = (MethodNode) parent;
delegate = new DelegateDescription();
delegate.delegate = methodNode;
delegate.annotation = node;
delegate.name = methodNode.getName();
delegate.type = methodNode.getReturnType();
delegate.owner = methodNode.getDeclaringClass();
delegate.getOp = callThisX(delegate.name);
delegate.origin = "method";
if (methodNode.getParameters().length > 0) {
addError("You can only delegate to methods that take no parameters, but " +
delegate.name + " takes " + methodNode.getParameters().length +
" parameters.", parent);
return;
}
}
if (delegate != null) {
if (isObjectType(delegate.type) || isGroovyObjectType(delegate.type)) {
addError(MY_TYPE_NAME + " " + delegate.origin + " '" + delegate.name + "' has an inappropriate type: " + delegate.type.getName() +
". Please add an explicit type but not java.lang.Object or groovy.lang.GroovyObject.", parent);
return;
}
if (delegate.type.equals(delegate.owner)) {
addError(MY_TYPE_NAME + " " + delegate.origin + " '" + delegate.name + "' has an inappropriate type: " + delegate.type.getName() +
". Delegation to own type not supported. Please use a different type.", parent);
return;
}
final boolean skipInterfaces = memberHasValue(node, MEMBER_INTERFACES, Boolean.FALSE);
final boolean includeDeprecated = memberHasValue(node, MEMBER_DEPRECATED, Boolean.TRUE) || (delegate.type.isInterface() && !skipInterfaces);
final boolean allNames = memberHasValue(node, MEMBER_ALL_NAMES, Boolean.TRUE);
delegate.excludes = getMemberStringList(node, MEMBER_EXCLUDES);
delegate.includes = getMemberStringList(node, MEMBER_INCLUDES);
delegate.excludeTypes = getMemberClassList(node, MEMBER_EXCLUDE_TYPES);
delegate.includeTypes = getMemberClassList(node, MEMBER_INCLUDE_TYPES);
checkIncludeExcludeUndefinedAware(node, delegate.excludes, delegate.includes,
delegate.excludeTypes, delegate.includeTypes, MY_TYPE_NAME);
if (!checkPropertyOrMethodList(delegate.type, delegate.excludes, "excludes", node, MY_TYPE_NAME)) return;
if (!checkPropertyOrMethodList(delegate.type, delegate.includes, "includes", node, MY_TYPE_NAME)) return;
final Iterable<MethodNode> ownerMethods = getAllMethods(delegate.owner);
final Iterable<MethodNode> delegateMethods = filterMethods(collectMethods(delegate.type), delegate, allNames, includeDeprecated);
for (MethodNode mn : delegateMethods) {
addDelegateMethod(mn, delegate, ownerMethods);
}
for (PropertyNode prop : getAllProperties(delegate.type)) {
if (prop.isStatic() || !prop.isPublic())
continue;
String name = prop.getName();
addGetterIfNeeded(delegate, prop, name, allNames);
addSetterIfNeeded(delegate, prop, name, allNames);
}
if (delegate.type.isArray()) {
boolean skipLength = delegate.excludes != null && (delegate.excludes.contains("length") || delegate.excludes.contains("getLength"));
if (!skipLength) {
addGeneratedMethod(
delegate.owner,
"getLength",
ACC_PUBLIC,
ClassHelper.int_TYPE,
Parameter.EMPTY_ARRAY,
null,
returnS(propX(delegate.getOp, "length"))
);
}
}
if (skipInterfaces) return;
Set<ClassNode> addedInterfaces = getInterfacesAndSuperInterfaces(delegate.type);
addedInterfaces.removeIf(i -> (i.getModifiers() & (ACC_PUBLIC | ACC_SYNTHETIC)) != ACC_PUBLIC || i.isSealed()); // GROOVY-7288 and JDK16+
if (!addedInterfaces.isEmpty()) {
Set<ClassNode> ownerInterfaces = getInterfacesAndSuperInterfaces(delegate.owner);
for (ClassNode i : addedInterfaces) {
if (!ownerInterfaces.contains(i)) {
ClassNode[] faces = delegate.owner.getInterfaces();
faces = copyOf(faces, faces.length + 1);
faces[faces.length - 1] = i;
delegate.owner.setInterfaces(faces);
}
}
}
}
}