?? classnode.java
字號:
/*
* $Id: ClassNode.java 4216 2006-11-13 16:04:23Z blackdrag $
*
* Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
*
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided that the
* following conditions are met:
* 1. Redistributions of source code must retain copyright statements and
* notices. Redistributions must also contain a copy of this document.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name "groovy" must not be used to endorse or promote products
* derived from this Software without prior written permission of The Codehaus.
* For written permission, please contact info@codehaus.org.
* 4. Products derived from this Software may not be called "groovy" nor may
* "groovy" appear in their names without prior written permission of The
* Codehaus. "groovy" is a registered trademark of The Codehaus.
* 5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
*
* THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
package org.codehaus.groovy.ast;
import groovy.lang.GroovyObject;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.EmptyStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.objectweb.asm.Opcodes;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Represents a class in the AST.<br/>
* 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 meschanism 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. All method calls are then redirected to that ClassNode.
* <br>
* Note: the proxy mechanism is only allowed for classes being marked
* as primary ClassNode which means they represent no actual class.
* The redirect itself can be any type of ClassNode
*
* @see org.codehaus.groovy.ast.ClassHelper
*
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
* @author Jochen Theodorou
* @version $Revision: 4216 $
*/
public class ClassNode extends AnnotatedNode implements Opcodes {
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 int modifiers;
private ClassNode[] interfaces;
private MixinNode[] mixins;
private List constructors = new ArrayList();
private List objectInitializers = new ArrayList();
private List methods = new ArrayList();
private List fields = new ArrayList();
private List properties = new ArrayList();
private Map fieldIndex = new HashMap();
private ModuleNode module;
private CompileUnit compileUnit;
private boolean staticClass = false;
private boolean scriptBody = false;
private boolean script;
private ClassNode superClass;
boolean isPrimaryNode;
// use this to synchronize access for the lazy intit
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;
/**
* Returns the ClassNode this ClassNode is redirecting to.
*/
protected ClassNode redirect(){
if (redirect==null) return this;
return redirect.redirect();
}
/**
* Sets this instance as proxy for the given ClassNode.
* @param cn the class to redirect to. If set to null the redirect will be removed
*/
public void setRedirect(ClassNode cn) {
if (isPrimaryNode) throw new GroovyBugError("tried to set a redirect for a primary ClassNode ("+getName()+"->"+cn.getName()+").");
if (cn!=null) cn = cn.redirect();
redirect = cn;
}
/**
* Returns a ClassNode representing an array of the class
* represented by this ClassNode
*/
public ClassNode makeArray() {
if (redirect!=null) return redirect().makeArray();
ClassNode cn;
if (clazz!=null) {
Class ret = Array.newInstance(clazz,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().isPrimaryNode || (componentType!= null && componentType.isPrimaryClassNode());
}
/**
* Constructor used by makeArray() if no real class is available
*/
private ClassNode(ClassNode componentType) {
this(componentType.getName()+"[]", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
this.componentType = componentType.redirect();
isPrimaryNode=false;
}
/**
* Constructor used by makeArray() if a real class is available
*/
private ClassNode(Class c, ClassNode componentType) {
this(c);
this.componentType = componentType;
isPrimaryNode=false;
}
/**
* Creates a ClassNode from a real class. The resulting
* ClassNode will be no primary ClassNode.
*/
public ClassNode(Class c) {
this(c.getName(), c.getModifiers(), null, null ,MixinNode.EMPTY_ARRAY);
clazz=c;
lazyInitDone=false;
CompileUnit cu = getCompileUnit();
if (cu!=null) cu.addClass(this);
isPrimaryNode=false;
}
/**
* The complete class structure will be initialized only when really
* needed to avoid having too much objects during compilation
*/
private void lazyClassInit() {
synchronized (lazyInitLock) {
if (lazyInitDone) return;
Field[] fields = clazz.getDeclaredFields();
for (int i=0;i<fields.length;i++){
addField(fields[i].getName(),fields[i].getModifiers(),this,null);
}
Method[] methods = clazz.getDeclaredMethods();
for (int i=0;i<methods.length;i++){
Method m = methods[i];
MethodNode mn = new MethodNode(m.getName(), m.getModifiers(), ClassHelper.make(m.getReturnType()), createParameters(m.getParameterTypes()), ClassHelper.make(m.getExceptionTypes()), null);
addMethod(mn);
}
Constructor[] constructors = clazz.getDeclaredConstructors();
for (int i=0;i<constructors.length;i++){
Constructor ctor = constructors[i];
addConstructor(ctor.getModifiers(),createParameters(ctor.getParameterTypes()),ClassHelper.make(ctor.getExceptionTypes()),null);
}
Class sc = clazz.getSuperclass();
if (sc!=null) superClass = ClassHelper.make(sc);
buildInterfaceTypes(clazz);
lazyInitDone=true;
}
}
private void buildInterfaceTypes(Class c) {
Class[] interfaces = c.getInterfaces();
ClassNode[] ret = new ClassNode[interfaces.length];
for (int i=0;i<interfaces.length;i++){
ret[i] = ClassHelper.make(interfaces[i]);
}
this.interfaces = ret;
}
// added to track the enclosing method for local inner classes
private MethodNode enclosingMethod = null;
public MethodNode getEnclosingMethod() {
return redirect().enclosingMethod;
}
public void setEnclosingMethod(MethodNode enclosingMethod) {
redirect().enclosingMethod = enclosingMethod;
}
/**
* @param name is the full name of the class
* @param modifiers the modifiers,
* @param superClass the base class name - use "java.lang.Object" if no direct
* base class
* @see org.objectweb.asm.Opcodes
*/
public ClassNode(String name, int modifiers, ClassNode superClass) {
this(name, modifiers, superClass, ClassHelper.EMPTY_TYPE_ARRAY, MixinNode.EMPTY_ARRAY);
}
/**
* @param name is the full name of the class
* @param modifiers the modifiers,
* @param superClass the base class name - use "java.lang.Object" if no direct
* base class
* @see org.objectweb.asm.Opcodes
*/
public ClassNode(String name, int modifiers, ClassNode superClass, ClassNode[] interfaces, MixinNode[] mixins) {
this.name = name;
this.modifiers = modifiers;
this.superClass = superClass;
this.interfaces = interfaces;
this.mixins = mixins;
isPrimaryNode = true;
}
/**
* Sets the superclass of this ClassNode
*/
public void setSuperClass(ClassNode superClass) {
redirect().superClass = superClass;
}
/**
* Returns a list containing FieldNode objects for
* each field in the class represented by this ClassNode
*/
public List getFields() {
if (!lazyInitDone) {
lazyClassInit();
}
if (redirect!=null) return redirect().getFields();
return fields;
}
/**
* Returns an array of ClassNodes representing the
* interfaces the class implements
*/
public ClassNode[] getInterfaces() {
if (!lazyInitDone) {
lazyClassInit();
}
if (redirect!=null) return redirect().getInterfaces();
return interfaces;
}
public MixinNode[] getMixins() {
return redirect().mixins;
}
/**
* Returns a list containing MethodNode objects for
* each method in the class represented by this ClassNode
*/
public List getMethods() {
if (!lazyInitDone) {
lazyClassInit();
}
if (redirect!=null) return redirect().getMethods();
return methods;
}
/**
* Returns a list containing MethodNode objects for
* each abstract method in the class represented by
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -