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.17 $
57 */
58 public class MethodNode extends AnnotatedNode implements Opcodes {
59
60 private String name;
61 private int modifiers;
62 private String 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, String returnType, Parameter[] parameters, Statement code) {
70 this.name = name;
71 this.modifiers = modifiers;
72 this.parameters = parameters;
73 this.code = code;
74
75 if (parameters != null && parameters.length > 0) {
76 for (int i = 0; i < parameters.length; i++) {
77 if (parameters[i].hasDefaultValue()) {
78 this.hasDefaultValue = true;
79 break;
80 }
81 }
82 }
83
84 if (returnType == null || returnType.length() == 0) {
85 this.returnType = "java.lang.Object";
86 this.dynamicReturnType = true;
87 }
88 else {
89 this.returnType = ensureJavaTypeNameSyntax(returnType);
90 }
91 }
92
93 /***
94 * The type descriptor for a method node is a string containing the name of the method, its return type,
95 * and its parameter types in a canonical form. For simplicity, I'm using the format of a Java declaration
96 * without parameter names, and with $dynamic as the type for any dynamically typed values.
97 *
98 * @return
99 */
100
101 public String getTypeDescriptor() {
102 StringBuffer buf = new StringBuffer();
103
104
105 buf.append(ensureJavaTypeNameSyntax(returnType));
106
107 buf.append(' ');
108 buf.append(name);
109 buf.append('(');
110 for (int i = 0; i < parameters.length; i++) {
111 if (i > 0) {
112 buf.append(',');
113 }
114 Parameter param = parameters[i];
115 buf.append(ensureJavaTypeNameSyntax(param.getType()));
116 }
117 buf.append(')');
118 return buf.toString();
119 }
120
121 public static String ensureJavaTypeNameSyntax(String typename) {
122
123
124 if (typename.charAt(0) == '[') {
125 return ensureJavaTypeNameSyntax(typename.substring(1)) + "[]";
126 }
127 if (typename.length() == 1) {
128 switch (typename.charAt(0)) {
129 case 'B':
130 return "byte";
131 case 'C':
132 return "char";
133 case 'D':
134 return "double";
135 case 'F':
136 return "float";
137 case 'J':
138 return "long";
139 case 'I':
140 return "int";
141 case 'S':
142 return "short";
143 case 'V':
144 return "void";
145 case 'Z':
146 return "boolean";
147 }
148 }
149 if (typename.endsWith(";")) {
150
151 return typename.substring(1, typename.length() - 1);
152 }
153 return typename;
154
155 }
156
157 public boolean isVoidMethod() {
158 return "void".equals(returnType);
159 }
160
161 public Statement getCode() {
162 return code;
163 }
164
165 public void setCode(Statement code) {
166 this.code = code;
167 }
168
169 public int getModifiers() {
170 return modifiers;
171 }
172
173 public void setModifiers(int modifiers) {
174 this.modifiers = modifiers;
175 }
176
177 public String getName() {
178 return name;
179 }
180
181 public Parameter[] getParameters() {
182 return parameters;
183 }
184
185 public String getReturnType() {
186 return returnType;
187 }
188
189 public VariableScope getVariableScope() {
190 if (variableScope == null) {
191 variableScope = createVariableScope();
192 }
193 return variableScope;
194 }
195
196 public void setVariableScope(VariableScope variableScope) {
197 this.variableScope = variableScope;
198 }
199
200 public boolean isDynamicReturnType() {
201 return dynamicReturnType;
202 }
203
204 public boolean isAbstract() {
205 return (modifiers & ACC_ABSTRACT) != 0;
206 }
207
208 public boolean isStatic() {
209 return (modifiers & ACC_STATIC) != 0;
210 }
211
212 public boolean hasDefaultValue() {
213 return this.hasDefaultValue;
214 }
215
216 public String toString() {
217 return super.toString() + "[name: " + name + "]";
218 }
219
220 public void setReturnType(String returnType) {
221 this.returnType = returnType;
222 }
223
224
225 protected VariableScope createVariableScope() {
226 VariableScope variableScope = new VariableScope();
227 VariableScopeCodeVisitor visitor = new VariableScopeCodeVisitor(variableScope);
228 visitor.setParameters(getParameters());
229 Statement code = getCode();
230 if (code != null) {
231 code.visit(visitor);
232 }
233 addFieldsToVisitor(variableScope);
234 return variableScope;
235 }
236 }