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