public void visit()

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);
                    }
                }
            }
        }
    }