001: /*
002: $Id: MethodNode.java 4032 2006-08-30 07:18:49Z mguillem $
003:
004: Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005:
006: Redistribution and use of this software and associated documentation
007: ("Software"), with or without modification, are permitted provided
008: that the following conditions are met:
009:
010: 1. Redistributions of source code must retain copyright
011: statements and notices. Redistributions must also contain a
012: copy of this document.
013:
014: 2. Redistributions in binary form must reproduce the
015: above copyright notice, this list of conditions and the
016: following disclaimer in the documentation and/or other
017: materials provided with the distribution.
018:
019: 3. The name "groovy" must not be used to endorse or promote
020: products derived from this Software without prior written
021: permission of The Codehaus. For written permission,
022: please contact info@codehaus.org.
023:
024: 4. Products derived from this Software may not be called "groovy"
025: nor may "groovy" appear in their names without prior written
026: permission of The Codehaus. "groovy" is a registered
027: trademark of The Codehaus.
028:
029: 5. Due credit should be given to The Codehaus -
030: http://groovy.codehaus.org/
031:
032: THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033: ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034: NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
036: THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043: OF THE POSSIBILITY OF SUCH DAMAGE.
044:
045: */
046: package org.codehaus.groovy.ast;
047:
048: import java.util.List;
049:
050: import org.codehaus.groovy.ast.stmt.BlockStatement;
051: import org.codehaus.groovy.ast.stmt.Statement;
052: import org.objectweb.asm.Opcodes;
053:
054: /**
055: * Represents a method declaration
056: *
057: * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
058: * @version $Revision: 4032 $
059: */
060: public class MethodNode extends AnnotatedNode implements Opcodes {
061:
062: private String name;
063: private int modifiers;
064: private ClassNode returnType;
065: private Parameter[] parameters;
066: private boolean hasDefaultValue = false;
067: private Statement code;
068: private boolean dynamicReturnType;
069: private VariableScope variableScope;
070: private ClassNode[] exceptions;
071:
072: public MethodNode(String name, int modifiers, ClassNode returnType,
073: Parameter[] parameters, ClassNode[] exceptions,
074: Statement code) {
075: this .name = name;
076: this .modifiers = modifiers;
077: this .parameters = parameters;
078: this .code = code;
079: this .returnType = returnType;
080: if (returnType == null)
081: this .returnType = ClassHelper.OBJECT_TYPE;
082:
083: variableScope = new VariableScope();
084: if (parameters != null && parameters.length > 0) {
085: for (int i = 0; i < parameters.length; i++) {
086: Parameter para = parameters[i];
087: if (para.hasInitialExpression()) {
088: this .hasDefaultValue = true;
089: }
090: para.setInStaticContext(isStatic());
091: variableScope.getDeclaredVariables().put(
092: para.getName(), para);
093: }
094: }
095: variableScope.setInStaticContext(isStatic());
096:
097: this .exceptions = exceptions;
098: }
099:
100: /**
101: * The type descriptor for a method node is a string containing the name of the method, its return type,
102: * and its parameter types in a canonical form. For simplicity, I'm using the format of a Java declaration
103: * without parameter names, and with $dynamic as the type for any dynamically typed values.
104: */
105: // TODO: add test case for type descriptor
106: public String getTypeDescriptor() {
107: StringBuffer buf = new StringBuffer();
108: // buf.append(dynamicReturnType ? "$dynamic" : cleanupTypeName(returnType));
109: //
110: buf.append(returnType.getName()); // br to replace the above. Dynamic type returns Object.
111: //
112: buf.append(' ');
113: buf.append(name);
114: buf.append('(');
115: for (int i = 0; i < parameters.length; i++) {
116: if (i > 0) {
117: buf.append(',');
118: }
119: Parameter param = parameters[i];
120: buf.append(param.getType().getName());
121: }
122: buf.append(')');
123: return buf.toString();
124: }
125:
126: public boolean isVoidMethod() {
127: return returnType == ClassHelper.VOID_TYPE;
128: }
129:
130: public Statement getCode() {
131: return code;
132: }
133:
134: public void setCode(Statement code) {
135: this .code = code;
136: }
137:
138: public int getModifiers() {
139: return modifiers;
140: }
141:
142: public void setModifiers(int modifiers) {
143: this .modifiers = modifiers;
144: }
145:
146: public String getName() {
147: return name;
148: }
149:
150: public Parameter[] getParameters() {
151: return parameters;
152: }
153:
154: public ClassNode getReturnType() {
155: return returnType;
156: }
157:
158: public VariableScope getVariableScope() {
159: return variableScope;
160: }
161:
162: public void setVariableScope(VariableScope variableScope) {
163: this .variableScope = variableScope;
164: }
165:
166: public boolean isDynamicReturnType() {
167: return dynamicReturnType;
168: }
169:
170: public boolean isAbstract() {
171: return (modifiers & ACC_ABSTRACT) != 0;
172: }
173:
174: public boolean isStatic() {
175: return (modifiers & ACC_STATIC) != 0;
176: }
177:
178: public boolean hasDefaultValue() {
179: return this .hasDefaultValue;
180: }
181:
182: public String toString() {
183: return super .toString() + "[name: " + name + "]";
184: }
185:
186: public void setReturnType(ClassNode returnType) {
187: this .returnType = returnType;
188: }
189:
190: public ClassNode[] getExceptions() {
191: return exceptions;
192: }
193:
194: public Statement getFirstStatement() {
195: if (code == null)
196: return null;
197: if (code instanceof BlockStatement) {
198: List list = ((BlockStatement) code).getStatements();
199: if (list.size() > 0)
200: return (Statement) list.get(0);
201: return null;
202: }
203: return code;
204: }
205: }
|