/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.codehaus.groovy.ast;

import org.apache.groovy.ast.tools.ClassNodeUtils;
import org.apache.groovy.lang.annotation.Incubating;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.expr.BinaryExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.FieldExpression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.ast.tools.ParameterUtils;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.transform.ASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;
import org.codehaus.groovy.vmplugin.VMPluginFactory;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;
import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
import static org.codehaus.groovy.ast.ClassHelper.SEALED_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.isObjectType;
import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveBoolean;
import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
import static org.codehaus.groovy.transform.RecordTypeASTTransformation.recordNative;
import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
import static org.objectweb.asm.Opcodes.ACC_ANNOTATION;
import static org.objectweb.asm.Opcodes.ACC_ENUM;
import static org.objectweb.asm.Opcodes.ACC_INTERFACE;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;

/**
 * Represents a class in the AST.
 * <p>
 * A ClassNode should be created using the methods in ClassHelper.
 * This ClassNode may be used to represent a class declaration or
 * any other type. This class uses a proxy mechanism allowing to
 * create a class for a plain name at AST creation time. In another
 * phase of the compiler the real ClassNode for the plain name may be
 * found. To avoid the need of exchanging this ClassNode with an
 * instance of the correct ClassNode the correct ClassNode is set as
 * redirect. Most method calls are then redirected to that ClassNode.
 * <p>
 * There are three types of ClassNodes:
 * <ol>
 * <li> Primary ClassNodes:<br>
 * A primary ClassNode is one where we have a source representation
 * which is to be compiled by Groovy and which we have an AST for.
 * The groovy compiler will output one class for each such ClassNode
 * that passes through AsmBytecodeGenerator... not more, not less.
 * That means for example Closures become such ClassNodes too at
 * some point.
 * <li> ClassNodes create through different sources (typically created
 * from a java.lang.reflect.Class object):<br>
 * The compiler will not output classes from these, the methods
 * usually do not contain bodies. These kind of ClassNodes will be
 * used in different checks, but not checks that work on the method
 * bodies. For example if such a ClassNode is a super class to a primary
 * ClassNode, then the abstract method test and others will be done
 * with data based on these. Theoretically it is also possible to mix both
 * (1 and 2) kind of classes in a hierarchy, but this probably works only
 *  in the newest Groovy versions. Such ClassNodes normally have to
 *  isResolved() returning true without having a redirect.In the Groovy
 *  compiler the only version of this, that exists, is a ClassNode created
 *  through a Class instance
 * <li> Labels:<br>
 * ClassNodes created through ClassHelper.makeWithoutCaching. They
 * are placeholders, its redirect points to the real structure, which can
 * be a label too, but following all redirects it should end with a ClassNode
 * from one of the other two categories. If ResolveVisitor finds such a
 * node, it tries to set the redirects. Any such label created after
 * ResolveVisitor has done its work needs to have a redirect pointing to
 * case 1 or 2. If not the compiler may react strange... this can be considered
 * as a kind of dangling pointer.
 * </ol>
 * <b>Note:</b> the redirect mechanism is only allowed for classes
 * that are not primary ClassNodes. Typically this is done for classes
 * created by name only.  The redirect itself can be any type of ClassNode.
 * <p>
 * To describe generic type signature see {@link #getGenericsTypes()} and
 * {@link #setGenericsTypes(GenericsType[])}. These methods are not proxied,
 * they describe the type signature used at the point of declaration or the
 * type signatures provided by the class. If the type signatures provided
 * by the class are needed, then a call to {@link #redirect()} will help.
 *
 * @see org.codehaus.groovy.ast.ClassHelper
 */
public class ClassNode extends AnnotatedNode {

    private static class MapOfLists {
        Map<Object, List<MethodNode>> map;

        List<MethodNode> get(Object key) {
            return Optional.ofNullable(map)
                .map(m -> m.get(key)).orElseGet(Collections::emptyList);
        }

        void put(Object key, MethodNode value) {
            if (map == null) map = new LinkedHashMap<>();
            map.computeIfAbsent(key, k -> new ArrayList<>(2)).add(value);
        }

        void remove(Object key, MethodNode value) {
            get(key).remove(value);
        }
    }

    public static final ClassNode[] EMPTY_ARRAY = new ClassNode[0];
    public static final ClassNode THIS = new ClassNode(Object.class);
    public static final ClassNode SUPER = new ClassNode(Object.class);

    private String name;
    private int modifiers;
    private boolean syntheticPublic;
    private ClassNode[] interfaces;
    private MixinNode[] mixins;
    private List<Statement> objectInitializers;
    private List<ConstructorNode> constructors;
    // TODO: initialize for primary nodes only!
    private final MapOfLists methods = new MapOfLists();
    private List<MethodNode> methodsList = Collections.emptyList();
    private List<FieldNode> fields;
    private List<PropertyNode> properties;
    private Map<String, FieldNode> fieldIndex;
    private ModuleNode module;
    private CompileUnit compileUnit;
    private boolean staticClass;
    private boolean scriptBody;
    private boolean script;
    private ClassNode superClass;
    protected boolean isPrimaryNode;
    protected List<InnerClassNode> innerClasses;
    // TODO: initialize for primary nodes only!!
    private List<ClassNode> permittedSubclasses = new ArrayList<>();
    private List<AnnotationNode> typeAnnotations = Collections.emptyList();
    private List<RecordComponentNode> recordComponents = Collections.emptyList();

    /**
     * The AST Transformations to be applied during compilation.
     */
    private Map<CompilePhase, Map<Class<? extends ASTTransformation>, Set<ASTNode>>> transformInstances;

    // use this to synchronize access for the lazy init
    protected final Object lazyInitLock = new Object();
    // only false when this classNode is constructed from a class
    private volatile boolean lazyInitDone = true;

    // clazz!=null when resolved
    protected Class<?> clazz;
    // not null if the ClassNode is an array
    private ClassNode componentType;
    // if not null this instance is handled as proxy
    // for the redirect
    private ClassNode redirect;
    // flag if the classes or its members are annotated
    private boolean annotated;

    // type spec for generics
    private GenericsType[] genericsTypes;
    private boolean usesGenerics;

    // if set to true the name getGenericsTypes consists
    // of 1 element describing the name of the placeholder
    private boolean placeholder;

    //--------------------------------------------------------------------------

    /**
     * @param name       the fully-qualified name of the class
     * @param modifiers  the modifiers; see {@link java.lang.reflect.Modifier Modifier} or {@link org.objectweb.asm.Opcodes Opcodes}
     * @param superClass the base class; use "java.lang.Object" if no direct base class
     * @param interfaces the interfaces
     * @param mixins     the mixins
     */
    public ClassNode(final String name, final int modifiers, final ClassNode superClass, final ClassNode[] interfaces, final MixinNode[] mixins) {
        this.name = name;
        this.modifiers = modifiers;

        this.isPrimaryNode = true;
        setSuperClass(superClass);
        setInterfaces(interfaces);
        setMixins(mixins);
    }

    /**
     * @param name       the fully-qualified name of the class
     * @param modifiers  the modifiers; see {@link java.lang.reflect.Modifier Modifier} or {@link org.objectweb.asm.Opcodes Opcodes}
     * @param superClass the base class; use "java.lang.Object" if no direct base class
     */
    public ClassNode(final String name, final int modifiers, final ClassNode superClass) {
        this(name, modifiers, superClass, ClassNode.EMPTY_ARRAY, MixinNode.EMPTY_ARRAY);
    }

    /**
     * Creates a non-primary {@code ClassNode} from a real class.
     */
    public ClassNode(final Class<?> c) {
        this(c.getName(), c.getModifiers(), null, null, MixinNode.EMPTY_ARRAY);
        this.clazz = c;
        this.lazyInitDone = false;
        this.isPrimaryNode = false;
    }

    /**
     * Constructor used by {@code makeArray()} if a real class is available.
     */
    private ClassNode(final Class<?> c, final ClassNode componentType) {
        this(c);
        this.componentType = componentType;
    }

    /**
     * Constructor used by {@code makeArray()} if no real class is available.
     */
    private ClassNode(final ClassNode componentType) {
        this(componentType.getName() + "[]", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
        this.componentType = componentType.redirect();
        this.isPrimaryNode = false;
    }

    //--------------------------------------------------------------------------

    /**
     * Returns the {@code ClassNode} this node is a proxy for or the node itself.
     */
    public ClassNode redirect() {
        return (redirect == null ? this : redirect.redirect());
    }

    public boolean isRedirectNode() {
        return (redirect != null);
    }

    /**
     * Sets this instance as proxy for the given {@code ClassNode}.
     *
     * @param node the class to redirect to; if {@code null} the redirect is removed
     */
    public void setRedirect(ClassNode node) {
        if (isPrimaryNode) throw new GroovyBugError("tried to set a redirect for a primary ClassNode (" + getName() + "->" + node.getName() + ").");
        if (node != null && !isGenericsPlaceHolder()) node = node.redirect();
        if (node == this) return;
        redirect = node;
    }

    /**
     * Returns a {@code ClassNode} representing an array of the type represented
     * by this.
     */
    public ClassNode makeArray() {
        ClassNode node;
        if (redirect != null) {
            node = redirect.makeArray();
            node.componentType = this;
        } else if (clazz != null) {
            Class<?> type = Array.newInstance(clazz, 0).getClass();
            // don't use the ClassHelper here!
            node = new ClassNode(type, this);
        } else {
            node = new ClassNode(this);
        }
        return node;
    }

    /**
     * @return {@code true} if this instance is a primary {@code ClassNode}
     */
    public boolean isPrimaryClassNode() {
        return redirect().isPrimaryNode || (componentType != null && componentType.isPrimaryClassNode());
    }

    /**
     * The complete class structure will be initialized only when really needed
     * to avoid having too many objects during compilation.
     */
    private void lazyClassInit() {
        if (lazyInitDone) return;
        synchronized (lazyInitLock) {
            if (redirect != null) {
                throw new GroovyBugError("lazyClassInit called on a proxy ClassNode, that must not happen. " +
                                         "A redirect() call is missing somewhere!");
            }
            if (lazyInitDone) return;
            VMPluginFactory.getPlugin().configureClassNode(compileUnit, this);
            lazyInitDone = true;
        }
    }

    /**
     * Tracks the enclosing method for local inner classes.
     */
    private MethodNode enclosingMethod;

    public MethodNode getEnclosingMethod() {
        return redirect().enclosingMethod;
    }

    public void setEnclosingMethod(MethodNode enclosingMethod) {
        redirect().enclosingMethod = enclosingMethod;
    }

    /**
     * Indicates that this class has been "promoted" to public by Groovy when in
     * fact there was no public modifier explicitly in the source code. That is,
     * it remembers that it has applied Groovy's "public classes by default" rule.
     * This property is typically only of interest to AST transform writers.
     *
     * @return {@code true} if node is public but had no explicit public modifier
     */
    public boolean isSyntheticPublic() {
        return syntheticPublic;
    }

    public void setSyntheticPublic(boolean syntheticPublic) {
        this.syntheticPublic = syntheticPublic;
    }

    public void setSuperClass(final ClassNode superClass) {
        if (redirect != null) {
            redirect.setSuperClass(superClass);
        } else {
            this.superClass = superClass;
            // GROOVY-10763: update generics indicator
            if (superClass != null && !usesGenerics && isPrimaryNode) {
                usesGenerics = superClass.isUsingGenerics();
            }
        }
    }

    /**
     * @return the fields associated with this {@code ClassNode}
     */
    public List<FieldNode> getFields() {
        if (redirect != null)
            return redirect.getFields();
        lazyClassInit();
        if (fields == null)
            fields = new ArrayList<>();
        return fields;
    }

    /**
     * @return the interfaces implemented by this {@code ClassNode}
     */
    public ClassNode[] getInterfaces() {
        if (redirect != null)
            return redirect.getInterfaces();
        lazyClassInit();
        return interfaces;
    }

    public void setInterfaces(final ClassNode[] interfaces) {
        if (redirect != null) {
            redirect.setInterfaces(interfaces);
        } else {
            this.interfaces = interfaces;
            // GROOVY-10763: update generics indicator
            if (interfaces != null && !usesGenerics && isPrimaryNode) {
                for (int i = 0, n = interfaces.length; i < n; i += 1) {
                    usesGenerics |= interfaces[i].isUsingGenerics();
                }
            }
        }
    }

    /**
     * @return permitted subclasses of sealed type, may initially be empty in early compiler phases
     */
    @Incubating
    public List<ClassNode> getPermittedSubclasses() {
        if (redirect != null)
            return redirect.getPermittedSubclasses();
        lazyClassInit();
        return permittedSubclasses;
    }

    @Incubating
    public void setPermittedSubclasses(List<ClassNode> permittedSubclasses) {
        if (redirect != null) {
            redirect.setPermittedSubclasses(permittedSubclasses);
        } else {
            this.permittedSubclasses = permittedSubclasses;
        }
    }

    /**
     * @return the mixins associated with this {@code ClassNode}
     */
    public MixinNode[] getMixins() {
        return redirect().mixins;
    }

    public void setMixins(final MixinNode[] mixins) {
        if (redirect != null) {
            redirect.setMixins(mixins);
        } else {
            this.mixins = mixins;
        }
    }

    /**
     * @return the methods associated with this {@code ClassNode}
     */
    public List<MethodNode> getMethods() {
        if (redirect != null)
            return redirect.getMethods();
        lazyClassInit();
        return methodsList;
    }

    /**
     * @return the abstract methods associated with this {@code ClassNode}
     */
    public List<MethodNode> getAbstractMethods() {
        return getDeclaredMethodsMap().values().stream()
            .filter(MethodNode::isAbstract).collect(toList());
    }

    public List<MethodNode> getAllDeclaredMethods() {
        return new ArrayList<>(getDeclaredMethodsMap().values());
    }

    public Set<ClassNode> getAllInterfaces() {
        Set<ClassNode> result = new LinkedHashSet<>();
        if (isInterface()) result.add(this);
        getAllInterfaces(result);
        return result;
    }

    private void getAllInterfaces(Set<ClassNode> set) {
        for (ClassNode face : getInterfaces()) {
            if (set.add(face)) // GROOVY-11036
                face.getAllInterfaces(set);
        }
    }

    public Map<String, MethodNode> getDeclaredMethodsMap() {
        Map<String, MethodNode> result = ClassNodeUtils.getDeclaredMethodsFromSuper(this);
        ClassNodeUtils.addDeclaredMethodsFromInterfaces(this, result);
        // add in the methods implemented in this class
        for (MethodNode method : getMethods()) {
            result.put(method.getTypeDescriptor(), method);
        }
        return result;
    }

    public String getName() {
        return redirect().name;
    }

    public String getUnresolvedName() {
        return name;
    }

    public String setName(String name) {
        return redirect().name = name;
    }

    public int getModifiers() {
        return redirect().modifiers;
    }

    public void setModifiers(int modifiers) {
        redirect().modifiers = modifiers;
    }

    public List<PropertyNode> getProperties() {
        if (redirect != null)
            return redirect.getProperties();
        if (properties == null)
            properties = new ArrayList<>();
        return properties;
    }

    public List<ConstructorNode> getDeclaredConstructors() {
        if (redirect != null)
            return redirect.getDeclaredConstructors();
        lazyClassInit();
        if (constructors == null)
            constructors = new ArrayList<>();
        return constructors;
    }

    /**
     * @return the constructor matching the given parameters or {@code null}
     */
    public ConstructorNode getDeclaredConstructor(Parameter[] parameters) {
        for (ConstructorNode constructor : getDeclaredConstructors()) {
            if (parametersEqual(constructor.getParameters(), parameters)) {
                return constructor;
            }
        }
        return null;
    }

    public void removeConstructor(ConstructorNode node) {
        getDeclaredConstructors().remove(node);
    }

    public ModuleNode getModule() {
        return redirect().module;
    }

    public PackageNode getPackage() {
        return Optional.ofNullable(getModule()).map(ModuleNode::getPackage).orElse(null);
    }

    public void setModule(ModuleNode module) {
        redirect().module = module;
        if (module != null) {
            redirect().compileUnit = module.getUnit();
        }
    }

    public void addField(FieldNode node) {
        addField(node, false);
    }

    public void addFieldFirst(FieldNode node) {
        addField(node, true);
    }

    private void addField(FieldNode node, boolean isFirst) {
        ClassNode r = redirect();
        node.setDeclaringClass(r);
        node.setOwner(r);
        if (r.fields == null)
            r.fields = new ArrayList<>();
        if (r.fieldIndex == null)
            r.fieldIndex = new LinkedHashMap<>();

        if (isFirst) {
            r.fields.add(0, node);
        } else {
            r.fields.add(node);
        }
        r.fieldIndex.put(node.getName(), node);
    }

    public Map<String, FieldNode> getFieldIndex() {
        return fieldIndex;
    }

    public void addProperty(PropertyNode node) {
        node.setDeclaringClass(redirect());
        addField(node.getField());
        getProperties().add(node);
    }

    public PropertyNode addProperty(String name,
                                    int modifiers,
                                    ClassNode type,
                                    Expression initialValueExpression,
                                    Statement getterBlock,
                                    Statement setterBlock) {
        for (PropertyNode pn : getProperties()) {
            if (pn.getName().equals(name)) {
                if (pn.getInitialExpression() == null && initialValueExpression != null)
                    pn.getField().setInitialValueExpression(initialValueExpression);

                if (pn.getGetterBlock() == null && getterBlock != null)
                    pn.setGetterBlock(getterBlock);

                if (pn.getSetterBlock() == null && setterBlock != null)
                    pn.setSetterBlock(setterBlock);

                return pn;
            }
        }
        PropertyNode node =
                new PropertyNode(name, modifiers, type, redirect(), initialValueExpression, getterBlock, setterBlock);
        addProperty(node);
        return node;
    }

    public boolean hasProperty(String name) {
        return getProperties().stream().map(PropertyNode::getName).anyMatch(name::equals);
    }

    public PropertyNode getProperty(String name) {
        return getProperties().stream().filter(pn -> pn.getName().equals(name)).findFirst().orElse(null);
    }

    public void addConstructor(ConstructorNode node) {
        ClassNode r = redirect();
        node.setDeclaringClass(r);
        if (r.constructors == null)
            r.constructors = new ArrayList<>();
        r.constructors.add(node);
    }

    public ConstructorNode addConstructor(int modifiers, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
        ConstructorNode node = new ConstructorNode(modifiers, parameters, exceptions, code);
        addConstructor(node);
        return node;
    }

    public void addMethod(MethodNode node) {
        ClassNode r = redirect();
        node.setDeclaringClass(r);
        if (r.methodsList.isEmpty()) {
            r.methodsList = new ArrayList<>();
        }
        r.methodsList.add(node);
        r.methods.put(node.getName(), node);
    }

    public void removeMethod(MethodNode node) {
        ClassNode r = redirect();
        if (!r.methodsList.isEmpty()) {
            r.methodsList.remove(node);
        }
        r.methods.remove(node.getName(), node);
    }

    /**
     * If a method with the given name and parameters is already defined then it is returned
     * otherwise the given method is added to this node. This method is useful for
     * default method adding like getProperty() or invokeMethod() where there may already
     * be a method defined in a class and so the default implementations should not be added
     * if already present.
     */
    public MethodNode addMethod(String name,
                                int modifiers,
                                ClassNode returnType,
                                Parameter[] parameters,
                                ClassNode[] exceptions,
                                Statement code) {
        MethodNode other = getDeclaredMethod(name, parameters);
        // don't add duplicate methods
        if (other != null) {
            return other;
        }
        MethodNode node = new MethodNode(name, modifiers, returnType, parameters, exceptions, code);
        addMethod(node);
        return node;
    }

    /**
     * @see #getDeclaredMethod(String, Parameter[])
     */
    public boolean hasDeclaredMethod(String name, Parameter[] parameters) {
        return (getDeclaredMethod(name, parameters) != null);
    }

    /**
     * @see #getMethod(String, Parameter[])
     */
    public boolean hasMethod(String name, Parameter[] parameters) {
        return (getMethod(name, parameters) != null);
    }

    /**
     * Adds a synthetic method as part of the compilation process.
     */
    public MethodNode addSyntheticMethod(String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
        MethodNode node = addMethod(name, modifiers | ACC_SYNTHETIC, returnType, parameters, exceptions, code);
        node.setSynthetic(true);
        return node;
    }

    public FieldNode addField(String name, int modifiers, ClassNode type, Expression initialValue) {
        FieldNode node = new FieldNode(name, modifiers, type, redirect(), initialValue);
        addField(node);
        return node;
    }

    public FieldNode addFieldFirst(String name, int modifiers, ClassNode type, Expression initialValue) {
        FieldNode node = new FieldNode(name, modifiers, type, redirect(), initialValue);
        addFieldFirst(node);
        return node;
    }

    public void addInterface(final ClassNode type) {
        ClassNode[] interfaces = getInterfaces();
        for (ClassNode face : interfaces) {
            if (face.equals(type)) return;
        }
        final int n = interfaces.length;

        System.arraycopy(interfaces, 0, interfaces = new ClassNode[n + 1], 0, n);
        interfaces[n] = type; // append interface
        setInterfaces(interfaces);
    }

    @Override
    public boolean equals(Object that) {
        if (that == this) return true;
        if (!(that instanceof ClassNode)) return false;
        if (redirect != null) return redirect.equals(that);
        if (componentType != null) return componentType.equals(((ClassNode) that).componentType);
        return ((ClassNode) that).getText().equals(getText()); // arrays could be "T[]" or "[LT;"
    }

    @Override
    public int hashCode() {
        return (redirect != null ? redirect.hashCode() : getText().hashCode());
    }

    public void addMixin(MixinNode mixin) {
        // let's check if it already uses a mixin
        MixinNode[] mixins = getMixins();
        boolean skip = false;
        for (MixinNode existing : mixins) {
            if (mixin.equals(existing)) {
                skip = true;
                break;
            }
        }
        if (!skip) {
            MixinNode[] newMixins = new MixinNode[mixins.length + 1];
            System.arraycopy(mixins, 0, newMixins, 0, mixins.length);
            newMixins[mixins.length] = mixin;
            redirect().mixins = newMixins;
        }
    }

    /**
     * Finds a field matching the given name in this class.
     *
     * @param name the name of the field of interest
     * @return the method matching the given name and parameters or null
     */
    public FieldNode getDeclaredField(String name) {
        if (redirect != null)
            return redirect.getDeclaredField(name);
        lazyClassInit();
        return fieldIndex == null ? null : fieldIndex.get(name);
    }

    /**
     * Finds a field matching the given name in this class or a parent class.
     *
     * @param name the name of the field of interest
     * @return the method matching the given name and parameters or null
     */
    public FieldNode getField(String name) {
        ClassNode node = this;
        while (node != null) {
            FieldNode fn = node.getDeclaredField(name);
            if (fn != null) return fn;
            node = node.getSuperClass();
        }
        return null;
    }

    /**
     * @return the field on the outer class or {@code null} if this is not an inner class
     */
    public FieldNode getOuterField(String name) {
        if (redirect != null) {
            return redirect.getOuterField(name);
        }
        return null;
    }

    public ClassNode getOuterClass() {
        if (redirect != null) {
            return redirect.getOuterClass();
        }
        return null;
    }

    public List<ClassNode> getOuterClasses() {
        ClassNode outer = getOuterClass();
        if (outer == null) {
            return Collections.emptyList();
        }
        List<ClassNode> result = new LinkedList<>();
        do {
            result.add(outer);
        } while ((outer = outer.getOuterClass()) != null);

        return result;
    }

    /**
     * Adds a statement to the object initializer.
     *
     * @param statements the statement to be added
     */
    public void addObjectInitializerStatements(Statement statements) {
        getObjectInitializerStatements().add(statements);
    }

    public List<Statement> getObjectInitializerStatements() {
        if (objectInitializers == null)
            objectInitializers = new LinkedList<>();
        return objectInitializers;
    }

    private MethodNode getOrAddStaticConstructorNode() {
        MethodNode method;
        final String classInitializer = "<clinit>";
        List<MethodNode> declaredMethods = getDeclaredMethods(classInitializer);
        if (declaredMethods.isEmpty()) {
            method = addMethod(classInitializer, ACC_STATIC, ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BlockStatement());
            method.setSynthetic(true);
        } else {
            method = declaredMethods.get(0);
        }
        return method;
    }

    public void addStaticInitializerStatements(List<Statement> staticStatements, boolean fieldInit) {
        MethodNode method = getOrAddStaticConstructorNode();
        BlockStatement block = getCodeAsBlock(method);

        // while anything inside a static initializer block is appended
        // we don't want to append in the case we have an initialization
        // expression of a static field. In that case we want to add
        // before the other statements
        if (!fieldInit) {
            block.addStatements(staticStatements);
        } else {
            List<Statement> blockStatements = block.getStatements();
            staticStatements.addAll(blockStatements);
            blockStatements.clear();
            blockStatements.addAll(staticStatements);
        }
    }

    public void positionStmtsAfterEnumInitStmts(List<Statement> staticFieldStatements) {
        MethodNode constructor = getOrAddStaticConstructorNode();
        Statement statement = constructor.getCode();
        if (statement instanceof BlockStatement) {
            BlockStatement block = (BlockStatement) statement;
            // add given statements for explicitly declared static fields just after enum-special fields
            // are found - the $VALUES binary expression marks the end of such fields.
            List<Statement> blockStatements = block.getStatements();
            ListIterator<Statement> litr = blockStatements.listIterator();
            while (litr.hasNext()) {
                Statement stmt = litr.next();
                if (stmt instanceof ExpressionStatement &&
                        ((ExpressionStatement) stmt).getExpression() instanceof BinaryExpression) {
                    BinaryExpression bExp = (BinaryExpression) ((ExpressionStatement) stmt).getExpression();
                    if (bExp.getLeftExpression() instanceof FieldExpression) {
                        FieldExpression fExp = (FieldExpression) bExp.getLeftExpression();
                        if (fExp.getFieldName().equals("$VALUES")) {
                            for (Statement tmpStmt : staticFieldStatements) {
                                litr.add(tmpStmt);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * This method returns a list of all methods of the given name
     * defined in the current class
     * @return the method list
     * @see #getMethods(String)
     */
    public List<MethodNode> getDeclaredMethods(String name) {
        if (redirect != null)
            return redirect.getDeclaredMethods(name);
        lazyClassInit();
        return methods.get(name);
    }

    /**
     * This method creates a list of all methods with this name of the
     * current class and of all super classes
     * @return the methods list
     * @see #getDeclaredMethods(String)
     */
    public List<MethodNode> getMethods(String name) {
        List<MethodNode> result = new ArrayList<>();
        ClassNode node = this;
        while (node != null) {
            result.addAll(node.getDeclaredMethods(name));
            node = node.getSuperClass();
        }
        return result;
    }

    /**
     * Finds a method matching the given name and parameters in this class.
     *
     * @return the method matching the given name and parameters or null
     */
    public MethodNode getDeclaredMethod(String name, Parameter[] parameters) {
        for (MethodNode method : getDeclaredMethods(name)) {
            if (parametersEqual(method.getParameters(), parameters)) {
                return method;
            }
        }
        return null;
    }

    /**
     * Finds a method matching the given name and parameters in this class
     * or any parent class.
     *
     * @return the method matching the given name and parameters or null
     */
    public MethodNode getMethod(String name, Parameter[] parameters) {
        for (MethodNode method : getMethods(name)) {
            if (parametersEqual(method.getParameters(), parameters)) {
                return method;
            }
        }
        return null;
    }

    /**
     * @param type the ClassNode of interest
     * @return true if this node is derived from the given ClassNode
     */
    public boolean isDerivedFrom(ClassNode type) {
        if (isPrimitiveVoid(this)) {
            return isPrimitiveVoid(type);
        }
        if (isObjectType(type)) {
            return true;
        }
        ClassNode node = this;
        while (node != null) {
            if (type.equals(node)) {
                return true;
            }
            node = node.getSuperClass();
        }
        return false;
    }

    /**
     * @return {@code true} if this type implements {@code GroovyObject}
     */
    public boolean isDerivedFromGroovyObject() {
        return implementsInterface(ClassHelper.GROOVY_OBJECT_TYPE);
    }

    /**
     * @param classNodes the class nodes for the interfaces
     * @return {@code true} if this type implements any of the given interfaces
     */
    public boolean implementsAnyInterfaces(ClassNode... classNodes) {
        for (ClassNode classNode : classNodes) {
            if (implementsInterface(classNode)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param classNode the class node for the interface
     * @return {@code true} if this type implements the given interface
     */
    public boolean implementsInterface(ClassNode classNode) {
        ClassNode node = redirect();
        do {
            if (node.declaresInterface(classNode)) {
                return true;
            }
            node = node.getSuperClass();
        }
        while (node != null);

        return false;
    }

    /**
     *
     * @param classNodes the class nodes for the interfaces
     * @return {@code true} if this type declares that it implements any of the
     * given interfaces or if one of its interfaces extends directly/indirectly
     * any of the given interfaces
     */
    public boolean declaresAnyInterfaces(ClassNode... classNodes) {
        for (ClassNode classNode : classNodes) {
            if (declaresInterface(classNode)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param classNode the class node for the interface
     * @return {@code true} if this class declares that it implements the given
     * interface or if one of its interfaces extends directly/indirectly the interface
     *
     * NOTE: Doesn't consider an interface to implement itself.
     * I think this is intended to be called on ClassNodes representing
     * classes, not interfaces.
     *
     * @see org.codehaus.groovy.ast.tools.GeneralUtils#isOrImplements
     */
    public boolean declaresInterface(ClassNode classNode) {
        ClassNode[] interfaces = getInterfaces();
        for (ClassNode face : interfaces) {
            if (face.equals(classNode)) {
                return true;
            }
        }
        for (ClassNode face : interfaces) {
            if (face.declaresInterface(classNode)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return the {@code ClassNode} of the super class of this type
     */
    public ClassNode getSuperClass() {
        if (!lazyInitDone && !isResolved()) {
            throw new GroovyBugError("ClassNode#getSuperClass for " + getName() + " called before class resolving");
        }
        ClassNode sn = redirect().getUnresolvedSuperClass();
        if (sn != null) sn = sn.redirect();
        return sn;
    }

    public ClassNode getUnresolvedSuperClass() {
        return getUnresolvedSuperClass(true);
    }

    public ClassNode getUnresolvedSuperClass(boolean useRedirect) {
        if (!useRedirect)
            return superClass;
        if (redirect != null)
            return redirect.getUnresolvedSuperClass(true);
        lazyClassInit();
        return superClass;
    }

    public void setUnresolvedSuperClass(ClassNode superClass) {
        this.superClass = superClass;
    }

    public ClassNode[] getUnresolvedInterfaces() {
        return getUnresolvedInterfaces(true);
    }

    public ClassNode[] getUnresolvedInterfaces(boolean useRedirect) {
        if (!useRedirect)
            return interfaces;
        if (redirect != null)
            return redirect.getUnresolvedInterfaces(true);
        lazyClassInit();
        return interfaces;
    }

    public CompileUnit getCompileUnit() {
        if (redirect != null)
            return redirect.getCompileUnit();
        if (compileUnit == null && module != null) {
            compileUnit = module.getUnit();
        }
        return compileUnit;
    }

    protected void setCompileUnit(CompileUnit cu) {
        if (redirect != null)
            redirect.setCompileUnit(cu);
        if (compileUnit != null) compileUnit = cu;
    }

    @Deprecated(forRemoval = true, since = "4.0.0")
    protected boolean parametersEqual(Parameter[] a, Parameter[] b) {
        return ParameterUtils.parametersEqual(a, b);
    }

    public String getPackageName() {
        int idx = getName().lastIndexOf('.');
        if (idx > 0) {
            return getName().substring(0, idx);
        }
        return null;
    }

    public String getNameWithoutPackage() {
        int idx = getName().lastIndexOf('.');
        if (idx > 0) {
            return getName().substring(idx + 1);
        }
        return getName();
    }

    public void visitContents(GroovyClassVisitor visitor) {
        // now let's visit the contents of the class
        for (PropertyNode pn : getProperties()) {
            visitor.visitProperty(pn);
        }

        for (FieldNode fn : getFields()) {
            visitor.visitField(fn);
        }

        for (ConstructorNode cn : getDeclaredConstructors()) {
            visitor.visitConstructor(cn);
        }

        visitMethods(visitor);
    }

    private void visitMethods(GroovyClassVisitor visitor) {
        // create snapshot of the method list to avoid ConcurrentModificationException
        List<MethodNode> methodList = new ArrayList<>(getMethods());
        for (MethodNode mn : methodList) {
            visitor.visitMethod(mn);
        }

        // visit the method nodes added while iterating,
        // e.g. synthetic method for constructor reference
        final List<MethodNode> newMethodList = getMethods();
        if (newMethodList.size() > methodList.size()) { // if the newly added method nodes found, visit them
            List<MethodNode> changedMethodList = new ArrayList<>(newMethodList);
            boolean changed = changedMethodList.removeAll(methodList);
            if (changed) {
                for (MethodNode mn : changedMethodList) {
                    visitor.visitMethod(mn);
                }
            }
        }
    }

    public MethodNode getGetterMethod(String getterName) {
        return getGetterMethod(getterName, true);
    }

    public MethodNode getGetterMethod(String getterName, boolean searchSuperClasses) {
        MethodNode getterMethod = null;
        boolean booleanReturnOnly = getterName.startsWith("is");
        for (MethodNode method : getDeclaredMethods(getterName)) {
            if (method.getName().equals(getterName) && method.getParameters().length == 0
                    && (booleanReturnOnly ? isPrimitiveBoolean(method.getReturnType()) : !method.isVoidMethod())) {
                // GROOVY-7363: There can be multiple matches for a getter returning a generic parameter type, due to
                // the generation of a bridge method. The real getter is really the non-bridge, non-synthetic one as it
                // has the most specific and exact return type of the two. Picking the bridge method results in loss of
                // type information, as it down-casts the return type to the lower bound of the generic parameter.
                if (getterMethod == null || getterMethod.isSynthetic()) {
                    getterMethod = method;
                }
            }
        }
        if (getterMethod != null) {
            return getterMethod;
        }
        if (searchSuperClasses) {
            ClassNode parent = getSuperClass();
            if (parent != null) {
                return parent.getGetterMethod(getterName);
            }
        }
        return null;
    }

    public MethodNode getSetterMethod(String setterName) {
        return getSetterMethod(setterName, true);
    }

    public MethodNode getSetterMethod(String setterName, boolean voidOnly) {
        for (MethodNode method : getDeclaredMethods(setterName)) {
            if (setterName.equals(method.getName())
                    && method.getParameters().length == 1
                    && (!voidOnly || method.isVoidMethod())) {
                return method;
            }
        }
        ClassNode parent = getSuperClass();
        if (parent != null) {
            return parent.getSetterMethod(setterName, voidOnly);
        }
        return null;
    }

    /**
     * Is this class declared in a static method (such as a closure / inner class declared in a static method)
     */
    public boolean isStaticClass() {
        return redirect().staticClass;
    }

    public void setStaticClass(boolean staticClass) {
        redirect().staticClass = staticClass;
    }

    /**
     * @return {@code true} if this inner class or closure was declared inside a script body
     */
    public boolean isScriptBody() {
        return redirect().scriptBody;
    }

    public void setScriptBody(boolean scriptBody) {
        redirect().scriptBody = scriptBody;
    }

    public boolean isScript() {
        return redirect().script || isDerivedFrom(ClassHelper.SCRIPT_TYPE);
    }

    public void setScript(boolean script) {
        redirect().script = script;
    }

    @Override
    public String toString() {
        return toString(true);
    }

    public String toString(final boolean showRedirect) {
        if (isArray()) {
            return getComponentType().toString(showRedirect) + "[]";
        }
        boolean placeholder = isGenericsPlaceHolder();
        StringBuilder ret = new StringBuilder(!placeholder ? getName() : getUnresolvedName());
        GenericsType[] genericsTypes = getGenericsTypes();
        if (!placeholder && genericsTypes != null) {
            ret.append('<');
            for (int i = 0, n = genericsTypes.length; i < n; i += 1) {
                if (i != 0) ret.append(", ");
                ret.append(genericsTypes[i]);
            }
            ret.append('>');
        }
        if (showRedirect && redirect != null) {
            ret.append(" -> ").append(redirect);
        }
        return ret.toString();
    }

    /**
     * Determines if the type has a possibly-matching instance method with the given name and arguments.
     *
     * @param name      the name of the method of interest
     * @param arguments the arguments to match against
     * @return true if a matching method was found
     */
    public boolean hasPossibleMethod(final String name, final Expression arguments) {
        int count;
        if (arguments instanceof TupleExpression) {
            // TODO: this won't strictly be true when using list expansion in argument calls
            count = ((TupleExpression) arguments).getExpressions().size();
        } else {
            count = 0;
        }

        for (ClassNode cn = this; cn != null; cn = cn.getSuperClass()) {
            for (MethodNode mn : cn.getDeclaredMethods(name)) {
                if (!mn.isStatic() && hasCompatibleNumberOfArgs(mn, count)) {
                    return true;
                }
            }
            for (ClassNode in : cn.getAllInterfaces()) {
                for (MethodNode mn : in.getDeclaredMethods(name)) {
                    if (mn.isDefault() && hasCompatibleNumberOfArgs(mn, count)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    public MethodNode tryFindPossibleMethod(final String name, final Expression arguments) {
        if (!(arguments instanceof TupleExpression)) {
            return null;
        }

        // TODO: this won't strictly be true when using list expansion in argument calls
        TupleExpression args = (TupleExpression) arguments;
        int nArgs = args.getExpressions().size();
        MethodNode method = null;

        for (ClassNode cn = this; cn != null; cn = cn.getSuperClass()) {
            for (MethodNode mn : cn.getDeclaredMethods(name)) {
                if (hasCompatibleNumberOfArgs(mn, nArgs)) {
                    boolean match = true;
                    for (int i = 0; i < nArgs; i += 1) {
                        if (!hasCompatibleType(args, mn, i)) {
                            match = false;
                            break;
                        }
                    }
                    if (match) {
                        if (method == null) {
                            method = mn;
                        } else if (cn.equals(this)
                                || method.getParameters().length != nArgs) {
                            return null;
                        } else {
                            for (int i = 0; i < nArgs; i += 1) {
                                // prefer super method if it matches better
                                if (!hasExactMatchingCompatibleType(method, mn, i)) {
                                    return null;
                                }
                            }
                        }
                    }
                }
            }
        }

        return method;
    }

    private static boolean hasExactMatchingCompatibleType(final MethodNode match, final MethodNode maybe, final int i) {
        int lastParamIndex = maybe.getParameters().length - 1;
        return (i <= lastParamIndex && match.getParameters()[i].getType().equals(maybe.getParameters()[i].getType()))
                || (i >= lastParamIndex && isPotentialVarArg(maybe, lastParamIndex) && match.getParameters()[i].getType().equals(maybe.getParameters()[lastParamIndex].getType().getComponentType()));
    }

    private static boolean hasCompatibleType(final TupleExpression args, final MethodNode method, final int i) {
        int lastParamIndex = method.getParameters().length - 1;
        return (i <= lastParamIndex && args.getExpression(i).getType().isDerivedFrom(method.getParameters()[i].getType()))
                || (i >= lastParamIndex && isPotentialVarArg(method, lastParamIndex) && args.getExpression(i).getType().isDerivedFrom(method.getParameters()[lastParamIndex].getType().getComponentType()));
    }

    private static boolean hasCompatibleNumberOfArgs(final MethodNode method, final int nArgs) {
        int lastParamIndex = method.getParameters().length - 1;
        return nArgs == method.getParameters().length || (nArgs >= lastParamIndex && isPotentialVarArg(method, lastParamIndex));
    }

    private static boolean isPotentialVarArg(final MethodNode method, final int lastParamIndex) {
        return lastParamIndex >= 0 && method.getParameters()[lastParamIndex].getType().isArray();
    }

    /**
     * Checks if the given method has a possibly matching static method with the
     * given name and arguments.
     *
     * @param name      the name of the method of interest
     * @param arguments the arguments to match against
     * @return {@code true} if a matching method was found
     */
    public boolean hasPossibleStaticMethod(final String name, final Expression arguments) {
        return ClassNodeUtils.hasPossibleStaticMethod(this, name, arguments, false);
    }

    public boolean isInterface() {
        return (getModifiers() & ACC_INTERFACE) != 0;
    }

    /**
     * Checks if the {@link ClassNode} instance represents a native {@code record}.
     * Check instead for the {@code RecordBase} annotation if looking for records and
     * record-like classes currently being compiled.
     *
     * @return {@code true} if the instance represents a native {@code record}
     * @since 4.0.0
     */
    @Incubating
    public boolean isRecord() {
        return recordNative(this);
    }

    /**
     * Gets the record components of record type.
     *
     * @return {@code RecordComponentNode} instances
     * @since 4.0.0
     */
    @Incubating
    public List<RecordComponentNode> getRecordComponents() {
        if (redirect != null)
            return redirect.getRecordComponents();
        lazyClassInit();
        return recordComponents;
    }

    /**
     * Sets the record components for record type.
     *
     * @since 4.0.0
     */
    @Incubating
    public void setRecordComponents(List<RecordComponentNode> recordComponents) {
        if (redirect != null) {
            redirect.setRecordComponents(recordComponents);
        } else {
            this.recordComponents = recordComponents;
        }
    }

    public boolean isAbstract() {
        return (getModifiers() & ACC_ABSTRACT) != 0;
    }

    /**
     * @return {@code true} for native and emulated (annotation based) sealed classes
     * @since 4.0.0
     */
    @Incubating
    public boolean isSealed() {
        if (redirect != null) return redirect.isSealed();
        lazyClassInit();
        return !getAnnotations(SEALED_TYPE).isEmpty() || !getPermittedSubclasses().isEmpty();
    }

    public boolean isResolved() {
        if (clazz != null) return true;
        if (redirect != null) return redirect.isResolved();
        return (componentType != null && componentType.isResolved());
    }

    public boolean isArray() {
        return (componentType != null);
    }

    public ClassNode getComponentType() {
        return componentType;
    }

    /**
     * Returns the concrete class this classnode relates to. However, this method
     * is inherently unsafe as it may return null depending on the compile phase you are
     * using. AST transformations should never use this method directly, but rather obtain
     * a new class node using {@link #getPlainNodeReference()}.
     * @return the class this classnode relates to. May return null.
     */
    public Class getTypeClass() {
        if (clazz != null) return clazz;
        if (redirect != null) return redirect.getTypeClass();

        ClassNode component = redirect().componentType;
        if (component != null && component.isResolved()) {
            return Array.newInstance(component.getTypeClass(), 0).getClass();
        }
        throw new GroovyBugError("ClassNode#getTypeClass for " + getName() + " called before the type class is set");
    }

    public boolean hasPackageName() {
        return (redirect().name.indexOf('.') > 0);
    }

    /**
     * Marks if the current class uses annotations or not.
     */
    public void setAnnotated(boolean annotated) {
        this.annotated = annotated;
    }

    public boolean isAnnotated() {
        return this.annotated;
    }

    public GenericsType asGenericsType() {
        if (!isGenericsPlaceHolder()) {
            return new GenericsType(this);
        } else if (genericsTypes != null
                && genericsTypes[0].getUpperBounds() != null) {
            return genericsTypes[0];
        } else {
            ClassNode upper = (redirect != null ? redirect : this);
            return new GenericsType(this, new ClassNode[]{upper}, null);
        }
    }

    public GenericsType[] getGenericsTypes() {
        return genericsTypes;
    }

    public void setGenericsTypes(GenericsType[] genericsTypes) {
        usesGenerics = usesGenerics || genericsTypes != null;
        this.genericsTypes = genericsTypes;
    }

    public void setGenericsPlaceHolder(boolean placeholder) {
        usesGenerics = usesGenerics || placeholder;
        this.placeholder = placeholder;
    }

    public boolean isGenericsPlaceHolder() {
        return placeholder;
    }

    public boolean isUsingGenerics() {
        return usesGenerics;
    }

    public void setUsingGenerics(boolean usesGenerics) {
        this.usesGenerics = usesGenerics;
    }

    public ClassNode getPlainNodeReference(boolean skipPrimitives) {
        if (skipPrimitives && ClassHelper.isPrimitiveType(this)) return this;
        ClassNode n = new ClassNode(name, modifiers, superClass, null, null);
        n.isPrimaryNode = false;
        n.setRedirect(redirect());
        if (isArray()) {
            n.componentType = redirect().getComponentType();
        }
        return n;
    }

    public ClassNode getPlainNodeReference() {
        return getPlainNodeReference(true);
    }

    public boolean isAnnotationDefinition() {
        return isInterface() && (getModifiers() & ACC_ANNOTATION) != 0;
    }

    @Override
    public List<AnnotationNode> getAnnotations() {
        if (redirect != null)
            return redirect.getAnnotations();
        lazyClassInit();
        return super.getAnnotations();
    }

    @Override
    public List<AnnotationNode> getAnnotations(ClassNode type) {
        if (redirect != null)
            return redirect.getAnnotations(type);
        lazyClassInit();
        return super.getAnnotations(type);
    }

    public void addTransform(Class<? extends ASTTransformation> transform, ASTNode node) {
        GroovyASTTransformation annotation = transform.getAnnotation(GroovyASTTransformation.class);
        if (annotation != null) {
            Map<Class<? extends ASTTransformation>, Set<ASTNode>> transforms = getTransforms(annotation.phase());
            Set<ASTNode> nodes = transforms.computeIfAbsent(transform, k -> new LinkedHashSet<>());
            nodes.add(node);
        }
    }

    public Map<Class <? extends ASTTransformation>, Set<ASTNode>> getTransforms(CompilePhase phase) {
        return getTransformInstances().get(phase);
    }

    public void renameField(String oldName, String newName) {
        ClassNode r = redirect();
        if (r.fieldIndex == null)
            r.fieldIndex = new LinkedHashMap<>();
        Map<String, FieldNode> index = r.fieldIndex;
        index.put(newName, index.remove(oldName));
    }

    public void removeField(String oldName) {
        ClassNode r = redirect();
        if (r.fieldIndex == null)
            r.fieldIndex = new LinkedHashMap<>();
        Map<String, FieldNode> index = r.fieldIndex;
        r.fields.remove(index.get(oldName));
        index.remove(oldName);
    }

    public boolean isEnum() {
        return (getModifiers() & ACC_ENUM) != 0;
    }

    /**
     * @return iterator of inner classes defined inside this one
     */
    public Iterator<InnerClassNode> getInnerClasses() {
        return (innerClasses == null ? Collections.<InnerClassNode>emptyList() : innerClasses).iterator();
    }

    private Map<CompilePhase, Map<Class<? extends ASTTransformation>, Set<ASTNode>>> getTransformInstances() {
        if (transformInstances == null) {
            transformInstances = new EnumMap<>(CompilePhase.class);
            for (CompilePhase phase : CompilePhase.values()) {
                transformInstances.put(phase, new LinkedHashMap<>());
            }
        }
        return transformInstances;
    }

    @Override
    public String getText() {
        return getName();
    }

    public List<AnnotationNode> getTypeAnnotations() {
        return new ArrayList<>(typeAnnotations);
    }

    public List<AnnotationNode> getTypeAnnotations(final ClassNode type) {
        List<AnnotationNode> annotations = new ArrayList<>();
        for (AnnotationNode node : typeAnnotations) {
            if (type.equals(node.getClassNode())) {
                annotations.add(node);
            }
        }
        return annotations;
    }

    public void addTypeAnnotation(final AnnotationNode annotation) {
        if (!isPrimaryClassNode() && !isRedirectNode() && isResolved()) {
            throw new GroovyBugError("Adding type annotation @" + annotation.getClassNode().getNameWithoutPackage() + " to non-primary, non-redirect node: " + getName());
        }
        if (typeAnnotations == Collections.EMPTY_LIST) {
            typeAnnotations = new ArrayList<>(3);
        }
        typeAnnotations.add(requireNonNull(annotation));
        setAnnotated(true);
    }

    public void addTypeAnnotations(final List<AnnotationNode> annotations) {
        for (AnnotationNode annotation : annotations) {
            addTypeAnnotation(annotation);
        }
    }
}
