Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright 2003-2007 the original author or authors.
    *
    * Licensed 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.objectweb.asm.Opcodes;
  
  import java.util.*;
  
Represents a class in the AST.
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.
There are three types of ClassNodes:
  1. Primary ClassNodes:
    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.
  2. ClassNodes create through different sources (typically created from a java.lang.reflect.Class object):
    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
  3. Labels:
    ClassNodes created through ClassHelper.makeWithoutCaching. They are place holders, 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.
    Note: 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.
    To describe generic type signature see getGenericsTypes() and 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 redirect() will help.

    Author(s):
    James Strachan
    Jochen Theodorou
    Version:
    $Revision: 16205 $
    See also:
    org.codehaus.groovy.ast.ClassHelper
  
  public class ClassNode extends AnnotatedNode implements Opcodes {
      private static class MapOfLists {
         private Map map = new HashMap();
         public List get(Object key) {
             return (List.get(key);
         }
         public List getNotNull(Object key) {
             List ret = get(key);
             if (ret==nullret = .;
             return ret;
         }
         public void put(Object keyObject value) {
             if (.containsKey(key)) {
                 get(key).add(value);
             } else {
                 ArrayList list = new ArrayList(2);
                 list.add(value);
                 .put(keylist);
             }
         }
     }
 
     public static ClassNode[] EMPTY_ARRAY = new ClassNode[0];
 
     public static ClassNode THIS = new ClassNode(Object.class);
     public static ClassNode SUPER = new ClassNode(Object.class);
 
     private String name;
     private final int modifiers;
     private ClassNode[] interfaces;
     private MixinNode[] mixins;
     private List constructors;
     private List  objectInitializers;
     private MapOfLists methods;
     private List<MethodNodemethodsList;
     private LinkedList<FieldNodefields;
     private List properties;
     private Map fieldIndex;
     private ModuleNode module;
     private CompileUnit compileUnit;
     private boolean staticClass = false;
     private boolean scriptBody = false;
     private boolean script;
     private ClassNode superClass;
     protected boolean isPrimaryNode;

    
The ASTTransformations to be applied to the Class
 
     private Map<CompilePhaseMap<Class<? extends ASTTransformation>, Set<ASTNode>>> transformInstances;
 
 
     // use this to synchronize access for the lazy init
     protected Object lazyInitLock = new Object();
 
     // clazz!=null when resolved
     protected Class clazz;
     // only false when this classNode is constructed from a class
     private boolean lazyInitDone=true;
     // not null if if the ClassNode is an array
     private ClassNode componentType = null;
     // if not null this instance is handled as proxy
     // for the redirect
     private ClassNode redirect=null;
     // flag if the classes or its members are annotated
     private boolean annotated;
 
     // type spec for generics
     private GenericsType[] genericsTypes=null;
     private boolean usesGenerics=false;
 
     // if set to true the name getGenericsTypes consists
     // of 1 element describing the name of the placeholder
     private boolean placeholder;

    
Returns the ClassNode this ClassNode is redirecting to.
 
     public ClassNode redirect(){
         ClassNode res = this;
         while (res.redirect != nullres = res.redirect;
         return res;
     }

    
Sets this instance as proxy for the given ClassNode.

Parameters:
cn the class to redirect to. If set to null the redirect will be removed
 
     public void setRedirect(ClassNode cn) {
         if (throw new GroovyBugError("tried to set a redirect for a primary ClassNode ("+getName()+"->"+cn.getName()+").");
         if (cn!=nullcn = cn.redirect();
         if (cn==thisreturn;
          = cn;
     }

    
Returns a ClassNode representing an array of the class represented by this ClassNode
 
     public ClassNode makeArray() {
         if (!=nullreturn redirect().makeArray();
         ClassNode cn;
         if (!=null) {
             Class ret = Array.newInstance(,0).getClass();
             // don't use the ClassHelper here!
             cn = new ClassNode(ret,this);
         } else {
             cn = new ClassNode(this);
         }
         return cn;
     }

    
Returns if this instance is a primary ClassNode
 
     public boolean isPrimaryClassNode(){
     	return redirect(). || (!= null && .isPrimaryClassNode());
     }

    
Constructor used by makeArray() if no real class is available
 
     private ClassNode(ClassNode componentType) {
         this(componentType.getName()+"[]", ACC_PUBLIC, .);
         this. = componentType.redirect();
         =false;
     }

    
Constructor used by makeArray() if a real class is available
 
     private ClassNode(Class cClassNode componentType) {
         this(c);
         this. = componentType;
         =false;
     }

    
Creates a ClassNode from a real class. The resulting ClassNode will not be a primary ClassNode.
 
     public ClassNode(Class c) {
         this(c.getName(), c.getModifiers(), nullnull ,.);
         =c;
         =false;
         CompileUnit cu = getCompileUnit();
         if (cu!=nullcu.addClass(this);
         =false;
     }

    
The complete class structure will be initialized only when really needed to avoid having too many objects during compilation
 
     private void lazyClassInit() {
         synchronized () {
             if (!=null) {
                 throw new GroovyBugError("lazyClassInit called on a proxy ClassNode, that must not happen."+
                                          "A redirect() call is missing somewhere!");
             }   
             if (return;
             VMPluginFactory.getPlugin().configureClassNode(,this);
              = true;
         }
     }
 
     // added to track the enclosing method for local inner classes
     private MethodNode enclosingMethod = null;
 
     public MethodNode getEnclosingMethod() {
         return redirect().;
     }
 
     public void setEnclosingMethod(MethodNode enclosingMethod) {
         redirect(). = enclosingMethod;
     }


    

Parameters:
name is the full name of the class
modifiers the modifiers,
superClass the base class name - use "java.lang.Object" if no direct base class
See also:
org.objectweb.asm.Opcodes
 
     public ClassNode(String nameint modifiersClassNode superClass) {
         this(namemodifierssuperClass.);
     }

    

Parameters:
name is the full name of the class
modifiers the modifiers,
superClass the base class name - use "java.lang.Object" if no direct base class
See also:
org.objectweb.asm.Opcodes
 
     public ClassNode(String nameint modifiersClassNode superClassClassNode[] interfacesMixinNode[] mixins) {
         this. = name;
         this. = modifiers;
         this. = superClass;
         this. = interfaces;
         this. = mixins;
          = true;
         if (superClass!=null) {
              = superClass.isUsingGenerics();
         }
         if (! && interfaces!=null) {
             for (int i = 0; i < interfaces.lengthi++) {
                  =  || interfaces[i].isUsingGenerics();
             }
         }
 
         if ((modifiers & ACC_INTERFACE) == 0)
           addField("$ownClass", ACC_STATIC|ACC_PUBLIC|ACC_FINAL|ACC_SYNTHETIC, .new ClassExpression(this)).setSynthetic(true);
     }
 
     private void getTransformInstancesLazy() {
          = new EnumMap<CompilePhaseMap<Class <? extends ASTTransformation>, Set<ASTNode>>>(CompilePhase.class);
         for (CompilePhase phase : CompilePhase.values()) {
             .put(phasenew HashMap<Class <? extends ASTTransformation>, Set<ASTNode>>());
         }
     }

    
Sets the superclass of this ClassNode
 
     public void setSuperClass(ClassNode superClass) {
         redirect(). = superClass;
     }

    
Returns a list containing FieldNode objects for each field in the class represented by this ClassNode
 
     public List<FieldNodegetFields() {
         if (!redirect().redirect().lazyClassInit();
         if (!=nullreturn redirect().getFields();
         return getFieldsLazy();
     }
 
     private List<FieldNodegetFieldsLazy() {
         if ( == null) {
              = new LinkedList<FieldNode>();
         }
         return ;
     }

    
Returns an array of ClassNodes representing the interfaces the class implements
 
     public ClassNode[] getInterfaces() {
         if (!redirect().redirect().lazyClassInit();
         if (!=nullreturn redirect().getInterfaces();
         return ;
     }
 
     public void setInterfaces(ClassNode[] interfaces) {
         if (!=null) {
             redirect().setInterfaces(interfaces);
         } else {
             this. = interfaces;
         }
     }
 
     public MixinNode[] getMixins() {
         return redirect().;
     }

    
Returns a list containing MethodNode objects for each method in the class represented by this ClassNode
 
     public List<MethodNodegetMethods() {
         if (!redirect().redirect().lazyClassInit();
         if (!=nullreturn redirect().getMethods();
         return getMethodsListLazy();
     }

    
Returns a list containing MethodNode objects for each abstract method in the class represented by this ClassNode
 
     public List getAbstractMethods() {
         List result = new ArrayList(3);
         Map declaredMethods = getDeclaredMethodsMap();
         for (Iterator it = declaredMethods.values().iterator(); it.hasNext();) {
             MethodNode method = (MethodNodeit.next();
             if (method.isAbstract()) {
                 result.add(method);
             }
         }
         
         if (result.isEmpty()) {
             return null;
         } else {
             return result;
         }
     }
 
     public List getAllDeclaredMethods() {
         return new ArrayList(getDeclaredMethodsMap().values());
     }
 
     public Set getAllInterfaces () {
         Set res = new HashSet ();
         getAllInterfaces(res);
         return res;
     }
 
     private void getAllInterfaces(Set res) {
         if (isInterface())
           res.add(this);
         
         ClassNode[] interfaces = getInterfaces();
         for (int i = 0; i < interfaces.lengthi++) {
             res.add(interfaces[i]);
             interfaces[i].getAllInterfaces(res);
         }
     }
 
     public Map getDeclaredMethodsMap() {
         // Start off with the methods from the superclass.
         ClassNode parent = getSuperClass();
         Map result = null;
         if (parent != null) {
             result = parent.getDeclaredMethodsMap();
         } else {
             result = new HashMap();
         }
 
         // add in unimplemented abstract methods from the interfaces
         ClassNode[] interfaces = getInterfaces();
         for (int i = 0; i < interfaces.lengthi++) {
             ClassNode iface = interfaces[i];
             Map ifaceMethodsMap = iface.getDeclaredMethodsMap();
             for (Object o : ifaceMethodsMap.keySet()) {
                 String methSig = (Stringo;
                 if (!result.containsKey(methSig)) {
                     MethodNode methNode = (MethodNodeifaceMethodsMap.get(methSig);
                     result.put(methSigmethNode);
                 }
             }
         }
 
         // And add in the methods implemented in this class.
         for (Object o : getMethods()) {
             MethodNode method = (MethodNodeo;
             String sig = method.getTypeDescriptor();
             result.put(sigmethod);
         }
         return result;
     }
 
     public String getName() {
         return redirect().;
     }
 
     public String setName(String name) {
         return redirect().=name;
     }
 
     public int getModifiers() {
         return redirect().;
     }
 
     public List getProperties() {
         return redirect().getPropertiesLazy();
     }
 
     private List getPropertiesLazy() {
         if ( == null)
              = new LinkedList ();
         return ;
     }
 
     public List getDeclaredConstructors() {
         if (!redirect().redirect().lazyClassInit();
         return redirect().getDeclaredConstructorsLazy();
     }
 
     private List getDeclaredConstructorsLazy () {
         if ( == null)
              = new LinkedList();
         return ;
     }
 
     public ModuleNode getModule() {
         return redirect().;
     }
 
     public void setModule(ModuleNode module) {
         redirect(). = module;
         if (module != null) {
             redirect(). = module.getUnit();
         }
     }
 
     public void addField(FieldNode node) {
         node.setDeclaringClass(redirect());
         node.setOwner(redirect());
         redirect().getFieldsLazy().add(node);
         redirect().getFieldIndexLazy().put(node.getName(), node);
     }
 
     private Map getFieldIndexLazy() {
         if ( == null)
              = new HashMap();
         return ;
     }
 
     public void addProperty(PropertyNode node) {
         node.setDeclaringClass(redirect());
         FieldNode field = node.getField();
         addField(field);
         redirect().getPropertiesLazy().add(node);
     }
 
     public PropertyNode addProperty(String name,
                                     int modifiers,
                                     ClassNode type,
                                     Expression initialValueExpression,
                                     Statement getterBlock,
                                     Statement setterBlock) {
         for (Object o : getProperties()) {
             PropertyNode pn = (PropertyNodeo;
             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(namemodifierstyperedirect(), initialValueExpressiongetterBlocksetterBlock);
         addProperty(node);
         return node;
     }
 
     public boolean hasProperty(String name) {
     	return getProperty(name)!=null;
     }
     
     public PropertyNode getProperty(String name) {
     	for (Object o : getProperties()) {
             PropertyNode pn = (PropertyNodeo;
             if (pn.getName().equals(name)) return pn;
         }
         return null;   	
     }
 
     public void addConstructor(ConstructorNode node) {
         node.setDeclaringClass(this);
         redirect().getDeclaredConstructorsLazy().add(node);
     }
 
     public ConstructorNode addConstructor(int modifiersParameter[] parametersClassNode[] exceptionsStatement code) {
         ConstructorNode node = new ConstructorNode(modifiersparametersexceptionscode);
         addConstructor(node);
         return node;
     }
 
     public void addMethod(MethodNode node) {
         node.setDeclaringClass(this);
         redirect().getMethodsListLazy().add(node);
         redirect().getMethodsLazy().put(node.getName(), node);
     }
 
     private MapOfLists getMethodsLazy() {
         if ( == null)
              = new MapOfLists();
         return ;
     }
 
     private List<MethodNodegetMethodsListLazy() {
         if ( == null)
              = new LinkedList<MethodNode>();
         return ;
     }

    
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(nameparameters);
         // let's not add duplicate methods
         if (other != null) {
             return other;
         }
         MethodNode node = new MethodNode(namemodifiersreturnTypeparametersexceptionscode);
         addMethod(node);
         return node;
     }

    

See also:
getDeclaredMethod(String, Parameter[])
 
     public boolean hasDeclaredMethod(String nameParameter[] parameters) {
         MethodNode other = getDeclaredMethod(nameparameters);
         return other != null;
     }

    

See also:
getMethod(String, Parameter[])
 
     public boolean hasMethod(String nameParameter[] parameters) {
         MethodNode other = getMethod(nameparameters);
         return other != 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 answer = addMethod(namemodifiers|ACC_SYNTHETIC, returnTypeparametersexceptionscode);
         answer.setSynthetic(true);
         return answer;
     }
 
     public FieldNode addField(String nameint modifiersClassNode typeExpression initialValue) {
         FieldNode node = new FieldNode(namemodifierstyperedirect(), initialValue);
         addField(node);
         return node;
     }
 
     public void addInterface(ClassNode type) {
         // lets check if it already implements an interface
         boolean skip = false;
         ClassNode[] interfaces = redirect().;
         for (int i = 0; i < interfaces.lengthi++) {
             if (type.equals(interfaces[i])) {
                 skip = true;
             }
         }
         if (!skip) {
             ClassNode[] newInterfaces = new ClassNode[interfaces.length + 1];
             System.arraycopy(interfaces, 0, newInterfaces, 0, interfaces.length);
             newInterfaces[interfaces.length] = type;
             redirect(). = newInterfaces;
         }
     }
 
     public boolean equals(Object o) {
         if (!=nullreturn redirect().equals(o);
         ClassNode cn = (ClassNodeo;
         return (cn.getName().equals(getName()));
     }
 
     public int hashCode() {
         if (!=nullreturn redirect().hashCode();
         return getName().hashCode();
     }
 
     public void addMixin(MixinNode mixin) {
         // lets check if it already uses a mixin
         MixinNode[] mixins = redirect().;
         boolean skip = false;
         for (int i = 0; i < mixins.lengthi++) {
             if (mixin.equals(mixins[i])) {
                 skip = true;
             }
         }
         if (!skip) {
             MixinNode[] newMixins = new MixinNode[mixins.length + 1];
             System.arraycopy(mixins, 0, newMixins, 0, mixins.length);
             newMixins[mixins.length] = mixin;
             redirect(). = newMixins;
         }
     }

    
Finds a field matching the given name in this class.

Parameters:
name the name of the field of interest
Returns:
the method matching the given name and parameters or null
 
     public FieldNode getDeclaredField(String name) {
         return (FieldNoderedirect().getFieldIndexLazy().get(name);
     }

    
Finds a field matching the given name in this class or a parent class.

Parameters:
name the name of the field of interest
Returns:
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 != nullreturn fn;
             node = node.getSuperClass();
         }
         return null;
     }

    

Returns:
the field node on the outer class or null if this is not an inner class
 
     public FieldNode getOuterField(String name) {
         return null;
     }

    
Helper method to avoid casting to inner class
 
     public ClassNode getOuterClass() {
         return null;
     }
 
     public void addObjectInitializerStatements(Statement statements) {
         if ( == null)
              = new LinkedList();
         .add(statements);
     }
 
     public List getObjectInitializerStatements() {
         if ( == null)
              = new LinkedList();
         return ;
     }
 
     public void addStaticInitializerStatements(List staticStatementsboolean fieldInit) {
         MethodNode method = null;
         List declaredMethods = getDeclaredMethods("<clinit>");
         if (declaredMethods.isEmpty()) {
             method =
                     addMethod("<clinit>", ACC_STATIC, ...new BlockStatement());
             method.setSynthetic(true);
         }
         else {
             method = (MethodNodedeclaredMethods.get(0);
         }
         BlockStatement block = null;
         Statement statement = method.getCode();
         if (statement == null) {
             block = new BlockStatement();
         }
         else if (statement instanceof BlockStatement) {
             block = (BlockStatementstatement;
         }
         else {
             block = new BlockStatement();
             block.addStatement(statement);
         }
 
         // while anything inside a static initializer block is appended
         // we don't want to append in the case we have a initialization
         // expression of a static field. In that case we want to add
         // before the other statements
         if (!fieldInit) {
             block.addStatements(staticStatements);
         } else {
             List blockStatements = block.getStatements();
             staticStatements.addAll(blockStatements);
             blockStatements.clear();
             blockStatements.addAll(staticStatements);
         }
     }

    
This methods returns a list of all methods of the given name defined in the current class

Returns:
the method list
See also:
getMethods(String)
 
     public List getDeclaredMethods(String name) {
         if (!redirect().redirect().lazyClassInit();
         if (!=nullreturn redirect().getDeclaredMethods(name);
         return getMethodsLazy().getNotNull(name);
     }

    
This methods creates a list of all methods with this name of the current class and of all super classes

Returns:
the methods list
See also:
getDeclaredMethods(String)
 
     public List getMethods(String name) {
         List answer = new ArrayList();
         ClassNode node = this;
         while (node != null) {
             answer.addAll(node.getDeclaredMethods(name));
             node = node.getSuperClass();
         }
         return answer;
     }

    
Finds a method matching the given name and parameters in this class.

Returns:
the method matching the given name and parameters or null
 
     public MethodNode getDeclaredMethod(String nameParameter[] parameters) {
         for (Object o :  getDeclaredMethods(name)) {
             MethodNode method = (MethodNodeo;
             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.

Returns:
the method matching the given name and parameters or null
 
     public MethodNode getMethod(String nameParameter[] parameters) {
         for (Object o : getMethods(name)) {
             MethodNode method = (MethodNodeo;
             if (parametersEqual(method.getParameters(), parameters)) {
                 return method;
             }
         }
         return null;
     }

    

Parameters:
type the ClassNode of interest
Returns:
true if this node is derived from the given ClassNode
 
     public boolean isDerivedFrom(ClassNode type) {
         if (type.equals(.)) return true;
         ClassNode node = this;
         while (node != null) {
             if (type.equals(node)) {
                 return true;
             }
             node = node.getSuperClass();
         }
         return false;
     }

    

Returns:
true if this class is derived from a groovy object i.e. it implements GroovyObject
 
     public boolean isDerivedFromGroovyObject() {
         return implementsInterface(ClassHelper.make(GroovyObject.class));
     }

    

Parameters:
classNode the class node for the interface
Returns:
true if this class or any base class 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;
     }

    

Parameters:
classNode the class node for the interface
Returns:
true if this class declares that it implements the given interface or if one of its interfaces extends directly or indirectly the interface
 
     public boolean declaresInterface(ClassNode classNode) {
         ClassNode[] interfaces = redirect().getInterfaces();
         if (declaresInterfaceDirect(interfacesclassNode)) return true;
         List superInterfaces = Arrays.asList(interfaces);
         while (superInterfaces.size() > 0) {
             List keep = new ArrayList();
             for (int i = 0; i < superInterfaces.size(); i++) {
                 ClassNode cn = (ClassNodesuperInterfaces.get(i);
                 if (cn.declaresInterface(classNode)) return true;
                 keep.addAll(Arrays.asList(cn.getInterfaces()));
             }
             superInterfaces = keep;
         }
         return false;
     }
 
     private boolean declaresInterfaceDirect(ClassNode[] interfacesClassNode classNode) {
         int size = interfaces.length;
         for (int i = 0; i < sizei++) {
             if (interfaces[i].equals(classNode)) {
                 return true;
             }
         }
         return false;
     }

    

Returns:
the ClassNode of the super class of this type
 
     public ClassNode getSuperClass() {
         if (! && !isResolved()) {
             throw new GroovyBugError("ClassNode#getSuperClass for "+getName()+" called before class resolving");
         }
         ClassNode sn = redirect().getUnresolvedSuperClass();
         if (sn!=nullsn=sn.redirect();
         return sn;
     }
 
     public ClassNode getUnresolvedSuperClass() {
         return getUnresolvedSuperClass(true);
     }
 
     public ClassNode getUnresolvedSuperClass(boolean useRedirect) {
         if (!useRedirectreturn ;
         if (!redirect().redirect().lazyClassInit();
         return redirect().;
     }
 
     public void setUnresolvedSuperClass(ClassNode sn) {
          = sn;
     }
 
     public CompileUnit getCompileUnit() {
         if (!=nullreturn redirect().getCompileUnit();
         if ( == null &&  != null) {
              = .getUnit();
         }
         return ;
     }
 
     protected void setCompileUnit(CompileUnit cu) {
         if (!=nullredirect().setCompileUnit(cu);
         if (!= null = cu;
     }

    

Returns:
true if the two arrays are of the same size and have the same contents
 
     protected boolean parametersEqual(Parameter[] aParameter[] b) {
         if (a.length == b.length) {
             boolean answer = true;
             for (int i = 0; i < a.lengthi++) {
                 if (!a[i].getType().equals(b[i].getType())) {
                     answer = false;
                     break;
                 }
             }
             return answer;
         }
         return false;
     }

    

Returns:
the package name of this class
 
     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 (Object o : getProperties()) {
             PropertyNode pn = (PropertyNodeo;
             visitor.visitProperty(pn);
         }
 
         for (Object o : getFields()) {
             FieldNode fn = (FieldNodeo;
             visitor.visitField(fn);
         }
 
         for (Object o : getDeclaredConstructors()) {
             ConstructorNode cn = (ConstructorNodeo;
             visitor.visitConstructor(cn);
        }
        for (Object o : getMethods()) {
            MethodNode mn = (MethodNodeo;
            visitor.visitMethod(mn);
        }
    }
    public MethodNode getGetterMethod(String getterName) {
        for (Object o : getDeclaredMethods(getterName)) {
            MethodNode method = (MethodNodeo;
            if (getterName.equals(method.getName())
                    && .!=method.getReturnType()
                    && method.getParameters().length == 0) {
                return method;
            }
        }
        ClassNode parent = getSuperClass();
        if (parent!=nullreturn parent.getGetterMethod(getterName);
        return null;
    }
    public MethodNode getSetterMethod(String setterName) {
        for (Object o : getDeclaredMethods(setterName)) {
            MethodNode method = (MethodNodeo;
            if (setterName.equals(method.getName())
                    && .==method.getReturnType()
                    && method.getParameters().length == 1) {
                return method;
            }
        }
        ClassNode parent = getSuperClass();
        if (parent!=nullreturn parent.getSetterMethod(setterName);
        return null;
    }

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

    

Returns:
Returns true if this inner class or closure was declared inside a script body
    public boolean isScriptBody() {
        return redirect().;
    }
    public void setScriptBody(boolean scriptBody) {
        redirect(). = scriptBody;
    }
    public boolean isScript() {
        return redirect(). || isDerivedFrom(.);
    }
    public void setScript(boolean script) {
        redirect(). = script;
    }
    public String toString() {
        String ret = getName();
        if ( != null) {
            ret += " <";
            for (int i = 0; i < .i++) {
                if (i != 0) ret += ", ";
                ret += [i];
            }
            ret += ">";
        }
        if ( != null) {
            ret += " -> " + redirect().toString();
        }
        return ret;
    }

    
Returns true if the given method has a possibly matching instance method with the given name and arguments.

Parameters:
name the name of the method of interest
arguments the arguments to match against
Returns:
true if a matching method was found
    public boolean hasPossibleMethod(String nameExpression arguments) {
        int count = 0;
        if (arguments instanceof TupleExpression) {
            TupleExpression tuple = (TupleExpressionarguments;
            // TODO this won't strictly be true when using list expansion in argument calls
            count = tuple.getExpressions().size();
        }
        ClassNode node = this;
        do {
            for (Object o : getMethods(name)) {
                MethodNode method = (MethodNodeo;
                if (method.getParameters().length == count) {
                    return true;
                }
            }
            node = node.getSuperClass();
        }
        while (node != null);
        return false;
    }
    public MethodNode tryFindPossibleMethod(String nameExpression arguments) {
        int count = 0;
        if (arguments instanceof TupleExpression) {
            TupleExpression tuple = (TupleExpressionarguments;
            // TODO this won't strictly be true when using list expansion in argument calls
            count = tuple.getExpressions().size();
        } else
            return null;
        MethodNode res = null;
        ClassNode node = this;
        TupleExpression args = (TupleExpressionarguments;
        do {
            for (Object o : node.getMethods(name)) {
                MethodNode method = (MethodNodeo;
                if (method.getParameters().length == count) {
                    boolean match = true;
                    for (int i = 0; i != count; ++i)
                        if (!args.getType().isDerivedFrom(method.getParameters()[i].getType())) {
                            match = false;
                            break;
                        }
                    if (match) {
                        if (res == null)
                            res = method;
                        else {
                            if (res.getParameters().length != count)
                                return null;
                            if (node.equals(this))
                                return null;
                            match = true;
                            for (int i = 0; i != count; ++i)
                                if (!res.getParameters()[i].getType().equals(method.getParameters()[i].getType())) {
                                    match = false;
                                    break;
                                }
                            if (!match)
                                return null;
                        }
                    }
                }
            }
            node = node.getSuperClass();
        }
        while (node != null);
        return res;
    }

    
Returns true if the given method has a possibly matching static method with the given name and arguments.

Parameters:
name the name of the method of interest
arguments the arguments to match against
Returns:
true if a matching method was found
    public boolean hasPossibleStaticMethod(String nameExpression arguments) {
        int count = 0;
        if (arguments instanceof TupleExpression) {
            TupleExpression tuple = (TupleExpressionarguments;
            // TODO this won't strictly be true when using list expansion in argument calls
            count = tuple.getExpressions().size();
        } else if (arguments instanceof MapExpression) {
        	count = 1;
        }
        
        for (Object o : getMethods(name)) {
            MethodNode method = (MethodNodeo;
            if(method.isStatic()) {
                Parameter[] parameters = method.getParameters(); 
                if (parameters.length == countreturn true;
                // handle varargs case
                if (parameters.length > 0 && parameters[parameters.length - 1].getType().isArray()) {
                    if (count >= parameters.length - 1) return true;
                }
                
                // handle parameters with default values
                int nonDefaultParameters = 0;
                for(int i = 0; i < parameters.lengthi++) {
                	if(parameters[i].hasInitialExpression() == false) {
                		nonDefaultParameters++;
                	}
                }
                
            	if(count < parameters.length && nonDefaultParameters <= count) {
            		return true;
            	}
            }
        }
        return false;
    }
    public boolean isInterface(){
        return (getModifiers() & Opcodes.ACC_INTERFACE) > 0;
    }
    public boolean isResolved(){
        return redirect().!=null || ( != null && .isResolved());
    }
    public boolean isArray(){
        return !=null;
    }
    public ClassNode getComponentType() {
        return ;
    }
    public Class getTypeClass(){
        Class c = redirect().;
        if (c!=nullreturn c;
        ClassNode component = redirect().;
        if (component!=null && component.isResolved()){
            ClassNode cn = component.makeArray();
            setRedirect(cn);