1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.codehaus.groovy.ast;
47
48 import org.codehaus.groovy.ast.stmt.Statement;
49 import org.codehaus.groovy.classgen.VariableScopeCodeVisitor;
50 import org.objectweb.asm.Opcodes;
51
52 /***
53 * Represents a method declaration
54 *
55 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
56 * @version $Revision: 1.20 $
57 */
58 public class MethodNode extends AnnotatedNode implements Opcodes {
59
60 private String name;
61 private int modifiers;
62 private ClassNode returnType;
63 private Parameter[] parameters;
64 private boolean hasDefaultValue = false;
65 private Statement code;
66 private boolean dynamicReturnType;
67 private VariableScope variableScope;
68
69 public MethodNode(String name, int modifiers, ClassNode returnType, Parameter[] parameters, Statement code) {
70 this.name = name;
71 this.modifiers = modifiers;
72 this.parameters = parameters;
73 this.code = code;
74 this.returnType = returnType;
75 if (returnType==null) this.returnType = ClassHelper.OBJECT_TYPE;
76
77 if (parameters != null && parameters.length > 0) {
78 for (int i = 0; i < parameters.length; i++) {
79 if (parameters[i].hasInitialExpression()) {
80 this.hasDefaultValue = true;
81 }
82 parameters[i].setInStaticContext(isStatic());
83 }
84 }
85 }
86
87 /***
88 * The type descriptor for a method node is a string containing the name of the method, its return type,
89 * and its parameter types in a canonical form. For simplicity, I'm using the format of a Java declaration
90 * without parameter names, and with $dynamic as the type for any dynamically typed values.
91 *
92 * @return
93 */
94
95 public String getTypeDescriptor() {
96 StringBuffer buf = new StringBuffer();
97
98
99 buf.append(returnType.getName());
100
101 buf.append(' ');
102 buf.append(name);
103 buf.append('(');
104 for (int i = 0; i < parameters.length; i++) {
105 if (i > 0) {
106 buf.append(',');
107 }
108 Parameter param = parameters[i];
109 buf.append(param.getType().getName());
110 }
111 buf.append(')');
112 return buf.toString();
113 }
114
115 public boolean isVoidMethod() {
116 return returnType==ClassHelper.VOID_TYPE;
117 }
118
119 public Statement getCode() {
120 return code;
121 }
122
123 public void setCode(Statement code) {
124 this.code = code;
125 }
126
127 public int getModifiers() {
128 return modifiers;
129 }
130
131 public void setModifiers(int modifiers) {
132 this.modifiers = modifiers;
133 }
134
135 public String getName() {
136 return name;
137 }
138
139 public Parameter[] getParameters() {
140 return parameters;
141 }
142
143 public ClassNode getReturnType() {
144 return returnType;
145 }
146
147 public VariableScope getVariableScope() {
148 if (variableScope == null) {
149 variableScope = createVariableScope();
150 }
151 return variableScope;
152 }
153
154 public void setVariableScope(VariableScope variableScope) {
155 this.variableScope = variableScope;
156 }
157
158 public boolean isDynamicReturnType() {
159 return dynamicReturnType;
160 }
161
162 public boolean isAbstract() {
163 return (modifiers & ACC_ABSTRACT) != 0;
164 }
165
166 public boolean isStatic() {
167 return (modifiers & ACC_STATIC) != 0;
168 }
169
170 public boolean hasDefaultValue() {
171 return this.hasDefaultValue;
172 }
173
174 public String toString() {
175 return super.toString() + "[name: " + name + "]";
176 }
177
178 public void setReturnType(ClassNode returnType) {
179 this.returnType = returnType;
180 }
181
182
183 protected VariableScope createVariableScope() {
184 VariableScope variableScope = new VariableScope();
185 VariableScopeCodeVisitor visitor = new VariableScopeCodeVisitor(variableScope);
186 visitor.setParameters(getParameters());
187 Statement code = getCode();
188 if (code != null) {
189 code.visit(visitor);
190 }
191 addFieldsToVisitor(variableScope);
192 return variableScope;
193 }
194 }