KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > AbstractMethodDeclaration


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.core.compiler.*;
14 import org.eclipse.jdt.internal.compiler.*;
15 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
16 import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
17 import org.eclipse.jdt.internal.compiler.impl.*;
18 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
19 import org.eclipse.jdt.internal.compiler.codegen.*;
20 import org.eclipse.jdt.internal.compiler.lookup.*;
21 import org.eclipse.jdt.internal.compiler.problem.*;
22 import org.eclipse.jdt.internal.compiler.parser.*;
23
24 public abstract class AbstractMethodDeclaration
25     extends ASTNode
26     implements ProblemSeverities, ReferenceContext {
27         
28     public MethodScope scope;
29     //it is not relevent for constructor but it helps to have the name of the constructor here
30
//which is always the name of the class.....parsing do extra work to fill it up while it do not have to....
31
public char[] selector;
32     public int declarationSourceStart;
33     public int declarationSourceEnd;
34     public int modifiers;
35     public int modifiersSourceStart;
36     public Annotation[] annotations;
37     public Argument[] arguments;
38     public TypeReference[] thrownExceptions;
39     public Statement[] statements;
40     public int explicitDeclarations;
41     public MethodBinding binding;
42     public boolean ignoreFurtherInvestigation = false;
43     
44     public Javadoc javadoc;
45     
46     public int bodyStart;
47     public int bodyEnd = -1;
48     public CompilationResult compilationResult;
49     
50     AbstractMethodDeclaration(CompilationResult compilationResult){
51         this.compilationResult = compilationResult;
52     }
53     
54     /*
55      * We cause the compilation task to abort to a given extent.
56      */

57     public void abort(int abortLevel, CategorizedProblem problem) {
58
59         switch (abortLevel) {
60             case AbortCompilation :
61                 throw new AbortCompilation(this.compilationResult, problem);
62             case AbortCompilationUnit :
63                 throw new AbortCompilationUnit(this.compilationResult, problem);
64             case AbortType :
65                 throw new AbortType(this.compilationResult, problem);
66             default :
67                 throw new AbortMethod(this.compilationResult, problem);
68         }
69     }
70
71     public abstract void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo info);
72
73     /**
74      * Bind and add argument's binding into the scope of the method
75      */

76     public void bindArguments() {
77
78         if (this.arguments != null) {
79             // by default arguments in abstract/native methods are considered to be used (no complaint is expected)
80
if (this.binding == null) {
81                 for (int i = 0, length = this.arguments.length; i < length; i++) {
82                     this.arguments[i].bind(this.scope, null, true);
83                 }
84                 return;
85             }
86             boolean used = this.binding.isAbstract() || this.binding.isNative();
87             AnnotationBinding[][] paramAnnotations = null;
88             for (int i = 0, length = this.arguments.length; i < length; i++) {
89                 Argument argument = this.arguments[i];
90                 argument.bind(this.scope, this.binding.parameters[i], used);
91                 if (argument.annotations != null) {
92                     this.binding.tagBits |= TagBits.HasParameterAnnotations;
93                     if (paramAnnotations == null)
94                         paramAnnotations = new AnnotationBinding[length][];
95                     paramAnnotations[i] = argument.binding.getAnnotations();
96                 }
97             }
98             if (paramAnnotations != null)
99                 this.binding.setParameterAnnotations(paramAnnotations);
100         }
101     }
102
103     /**
104      * Record the thrown exception type bindings in the corresponding type references.
105      */

106     public void bindThrownExceptions() {
107
108         if (this.thrownExceptions != null
109             && this.binding != null
110             && this.binding.thrownExceptions != null) {
111             int thrownExceptionLength = this.thrownExceptions.length;
112             int length = this.binding.thrownExceptions.length;
113             if (length == thrownExceptionLength) {
114                 for (int i = 0; i < length; i++) {
115                     this.thrownExceptions[i].resolvedType = this.binding.thrownExceptions[i];
116                 }
117             } else {
118                 int bindingIndex = 0;
119                 for (int i = 0; i < thrownExceptionLength && bindingIndex < length; i++) {
120                     TypeReference thrownException = this.thrownExceptions[i];
121                     ReferenceBinding thrownExceptionBinding = this.binding.thrownExceptions[bindingIndex];
122                     char[][] bindingCompoundName = thrownExceptionBinding.compoundName;
123                     if (bindingCompoundName == null) continue; // skip problem case
124
if (thrownException instanceof SingleTypeReference) {
125                         // single type reference
126
int lengthName = bindingCompoundName.length;
127                         char[] thrownExceptionTypeName = thrownException.getTypeName()[0];
128                         if (CharOperation.equals(thrownExceptionTypeName, bindingCompoundName[lengthName - 1])) {
129                             thrownException.resolvedType = thrownExceptionBinding;
130                             bindingIndex++;
131                         }
132                     } else {
133                         // qualified type reference
134
if (CharOperation.equals(thrownException.getTypeName(), bindingCompoundName)) {
135                             thrownException.resolvedType = thrownExceptionBinding;
136                             bindingIndex++;
137                         }
138                     }
139                 }
140             }
141         }
142     }
143
144     public CompilationResult compilationResult() {
145         
146         return this.compilationResult;
147     }
148     
149     /**
150      * Bytecode generation for a method
151      * @param classScope
152      * @param classFile
153      */

154     public void generateCode(ClassScope classScope, ClassFile classFile) {
155         
156         int problemResetPC = 0;
157         classFile.codeStream.wideMode = false; // reset wideMode to false
158
if (this.ignoreFurtherInvestigation) {
159             // method is known to have errors, dump a problem method
160
if (this.binding == null)
161                 return; // handle methods with invalid signature or duplicates
162
int problemsLength;
163             CategorizedProblem[] problems =
164                 this.scope.referenceCompilationUnit().compilationResult.getProblems();
165             CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
166             System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
167             classFile.addProblemMethod(this, this.binding, problemsCopy);
168             return;
169         }
170         // regular code generation
171
try {
172             problemResetPC = classFile.contentsOffset;
173             this.generateCode(classFile);
174         } catch (AbortMethod e) {
175             // a fatal error was detected during code generation, need to restart code gen if possible
176
if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
177                 // a branch target required a goto_w, restart code gen in wide mode.
178
try {
179                     classFile.contentsOffset = problemResetPC;
180                     classFile.methodCount--;
181                     classFile.codeStream.wideMode = true; // request wide mode
182
this.generateCode(classFile); // restart method generation
183
} catch (AbortMethod e2) {
184                     int problemsLength;
185                     CategorizedProblem[] problems =
186                         this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
187                     CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
188                     System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
189                     classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
190                 }
191             } else {
192                 // produce a problem method accounting for this fatal error
193
int problemsLength;
194                 CategorizedProblem[] problems =
195                     this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
196                 CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
197                 System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
198                 classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
199             }
200         }
201     }
202
203     public void generateCode(ClassFile classFile) {
204
205         classFile.generateMethodInfoHeader(this.binding);
206         int methodAttributeOffset = classFile.contentsOffset;
207         int attributeNumber = classFile.generateMethodInfoAttribute(this.binding);
208         if ((!this.binding.isNative()) && (!this.binding.isAbstract())) {
209             int codeAttributeOffset = classFile.contentsOffset;
210             classFile.generateCodeAttributeHeader();
211             CodeStream codeStream = classFile.codeStream;
212             codeStream.reset(this, classFile);
213             // initialize local positions
214
this.scope.computeLocalVariablePositions(this.binding.isStatic() ? 0 : 1, codeStream);
215
216             // arguments initialization for local variable debug attributes
217
if (this.arguments != null) {
218                 for (int i = 0, max = this.arguments.length; i < max; i++) {
219                     LocalVariableBinding argBinding;
220                     codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
221                     argBinding.recordInitializationStartPC(0);
222                 }
223             }
224             if (this.statements != null) {
225                 for (int i = 0, max = this.statements.length; i < max; i++)
226                     this.statements[i].generateCode(this.scope, codeStream);
227             }
228             if ((this.bits & ASTNode.NeedFreeReturn) != 0) {
229                 codeStream.return_();
230             }
231             // local variable attributes
232
codeStream.exitUserScope(this.scope);
233             codeStream.recordPositionsFrom(0, this.declarationSourceEnd);
234             classFile.completeCodeAttribute(codeAttributeOffset);
235             attributeNumber++;
236         } else {
237             checkArgumentsSize();
238         }
239         classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
240
241         // if a problem got reported during code gen, then trigger problem method creation
242
if (this.ignoreFurtherInvestigation) {
243             throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
244         }
245     }
246
247     private void checkArgumentsSize() {
248         TypeBinding[] parameters = this.binding.parameters;
249         int size = 1; // an abstact method or a native method cannot be static
250
for (int i = 0, max = parameters.length; i < max; i++) {
251             TypeBinding parameter = parameters[i];
252             if (parameter == TypeBinding.LONG || parameter == TypeBinding.DOUBLE) {
253                 size += 2;
254             } else {
255                 size++;
256             }
257             if (size > 0xFF) {
258                 this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration);
259             }
260         }
261     }
262     
263     public boolean hasErrors() {
264         return this.ignoreFurtherInvestigation;
265     }
266
267     public boolean isAbstract() {
268
269         if (this.binding != null)
270             return this.binding.isAbstract();
271         return (this.modifiers & ClassFileConstants.AccAbstract) != 0;
272     }
273
274     public boolean isAnnotationMethod() {
275
276         return false;
277     }
278     
279     public boolean isClinit() {
280
281         return false;
282     }
283
284     public boolean isConstructor() {
285
286         return false;
287     }
288
289     public boolean isDefaultConstructor() {
290
291         return false;
292     }
293
294     public boolean isInitializationMethod() {
295
296         return false;
297     }
298
299     public boolean isMethod() {
300
301         return false;
302     }
303
304     public boolean isNative() {
305
306         if (this.binding != null)
307             return this.binding.isNative();
308         return (this.modifiers & ClassFileConstants.AccNative) != 0;
309     }
310
311     public boolean isStatic() {
312
313         if (this.binding != null)
314             return this.binding.isStatic();
315         return (this.modifiers & ClassFileConstants.AccStatic) != 0;
316     }
317
318     /**
319      * Fill up the method body with statement
320      * @param parser
321      * @param unit
322      */

323     public abstract void parseStatements(
324         Parser parser,
325         CompilationUnitDeclaration unit);
326
327     public StringBuffer JavaDoc print(int tab, StringBuffer JavaDoc output) {
328
329         if (this.javadoc != null) {
330             this.javadoc.print(tab, output);
331         }
332         printIndent(tab, output);
333         printModifiers(this.modifiers, output);
334         if (this.annotations != null) printAnnotations(this.annotations, output);
335         
336         TypeParameter[] typeParams = typeParameters();
337         if (typeParams != null) {
338             output.append('<');
339             int max = typeParams.length - 1;
340             for (int j = 0; j < max; j++) {
341                 typeParams[j].print(0, output);
342                 output.append(", ");//$NON-NLS-1$
343
}
344             typeParams[max].print(0, output);
345             output.append('>');
346         }
347         
348         printReturnType(0, output).append(this.selector).append('(');
349         if (this.arguments != null) {
350             for (int i = 0; i < this.arguments.length; i++) {
351                 if (i > 0) output.append(", "); //$NON-NLS-1$
352
this.arguments[i].print(0, output);
353             }
354         }
355         output.append(')');
356         if (this.thrownExceptions != null) {
357             output.append(" throws "); //$NON-NLS-1$
358
for (int i = 0; i < this.thrownExceptions.length; i++) {
359                 if (i > 0) output.append(", "); //$NON-NLS-1$
360
this.thrownExceptions[i].print(0, output);
361             }
362         }
363         printBody(tab + 1, output);
364         return output;
365     }
366
367     public StringBuffer JavaDoc printBody(int indent, StringBuffer JavaDoc output) {
368
369         if (isAbstract() || (this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
370             return output.append(';');
371
372         output.append(" {"); //$NON-NLS-1$
373
if (this.statements != null) {
374             for (int i = 0; i < this.statements.length; i++) {
375                 output.append('\n');
376                 this.statements[i].printStatement(indent, output);
377             }
378         }
379         output.append('\n');
380         printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
381         return output;
382     }
383
384     public StringBuffer JavaDoc printReturnType(int indent, StringBuffer JavaDoc output) {
385         
386         return output;
387     }
388
389     public void resolve(ClassScope upperScope) {
390
391         if (this.binding == null) {
392             this.ignoreFurtherInvestigation = true;
393         }
394
395         try {
396             bindArguments();
397             bindThrownExceptions();
398             resolveJavadoc();
399             resolveAnnotations(scope, this.annotations, this.binding);
400             resolveStatements();
401             // check @Deprecated annotation presence
402
if (this.binding != null
403                     && (this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
404                     && (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
405                     && this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
406                 this.scope.problemReporter().missingDeprecatedAnnotationForMethod(this);
407             }
408         } catch (AbortMethod e) { // ========= abort on fatal error =============
409
this.ignoreFurtherInvestigation = true;
410         }
411     }
412
413     public void resolveJavadoc() {
414         
415         if (this.binding == null) return;
416         if (this.javadoc != null) {
417             this.javadoc.resolve(this.scope);
418             return;
419         }
420         if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
421             this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
422         }
423     }
424
425     public void resolveStatements() {
426
427         if (this.statements != null) {
428             for (int i = 0, length = this.statements.length; i < length; i++) {
429                 this.statements[i].resolve(this.scope);
430             }
431         } else if ((this.bits & UndocumentedEmptyBlock) != 0) {
432             this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd+1);
433         }
434     }
435
436     public void tagAsHavingErrors() {
437
438         this.ignoreFurtherInvestigation = true;
439     }
440
441     public void traverse(
442         ASTVisitor visitor,
443         ClassScope classScope) {
444         // default implementation: subclass will define it
445
}
446     
447     public TypeParameter[] typeParameters() {
448         return null;
449     }
450 }
451
Popular Tags