KickJava   Java API By Example, From Geeks To Geeks.

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


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.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ASTVisitor;
15 import org.eclipse.jdt.internal.compiler.CompilationResult;
16 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
17 import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
18 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
19 import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
20 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
21 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
22 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
23 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
24 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
25 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
26 import org.eclipse.jdt.internal.compiler.parser.Parser;
27 import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
28 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
29
30 public class MethodDeclaration extends AbstractMethodDeclaration {
31     
32     public TypeReference returnType;
33     public TypeParameter[] typeParameters;
34     
35     /**
36      * MethodDeclaration constructor comment.
37      */

38     public MethodDeclaration(CompilationResult compilationResult) {
39         super(compilationResult);
40     }
41
42     public void analyseCode(
43         ClassScope classScope,
44         InitializationFlowContext initializationContext,
45         FlowInfo flowInfo) {
46
47         // starting of the code analysis for methods
48
if (ignoreFurtherInvestigation)
49             return;
50         try {
51             if (binding == null)
52                 return;
53                 
54             if (!this.binding.isUsed() &&
55                     (this.binding.isPrivate()
56                         || (((this.binding.modifiers & (ExtraCompilerModifiers.AccOverriding|ExtraCompilerModifiers.AccImplementing)) == 0) && this.binding.declaringClass.isLocalType()))) {
57                 if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
58                     scope.problemReporter().unusedPrivateMethod(this);
59                 }
60             }
61                 
62             // skip enum implicit methods
63
if (binding.declaringClass.isEnum() && (this.selector == TypeConstants.VALUES || this.selector == TypeConstants.VALUEOF))
64                 return;
65
66             // may be in a non necessary <clinit> for innerclass with static final constant fields
67
if (binding.isAbstract() || binding.isNative())
68                 return;
69             
70             ExceptionHandlingFlowContext methodContext =
71                 new ExceptionHandlingFlowContext(
72                     initializationContext,
73                     this,
74                     binding.thrownExceptions,
75                     scope,
76                     FlowInfo.DEAD_END);
77
78             // tag parameters as being set
79
if (this.arguments != null) {
80                 for (int i = 0, count = this.arguments.length; i < count; i++) {
81                     flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
82                 }
83             }
84             // propagate to statements
85
if (statements != null) {
86                 boolean didAlreadyComplain = false;
87                 for (int i = 0, count = statements.length; i < count; i++) {
88                     Statement stat = statements[i];
89                     if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
90                         flowInfo = stat.analyseCode(scope, methodContext, flowInfo);
91                     } else {
92                         didAlreadyComplain = true;
93                     }
94                 }
95             }
96             // check for missing returning path
97
TypeBinding returnTypeBinding = binding.returnType;
98             if ((returnTypeBinding == TypeBinding.VOID) || isAbstract()) {
99                 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
100                     this.bits |= ASTNode.NeedFreeReturn;
101                 }
102             } else {
103                 if (flowInfo != FlowInfo.DEAD_END) {
104                     scope.problemReporter().shouldReturn(returnTypeBinding, this);
105                 }
106             }
107             // check unreachable catch blocks
108
methodContext.complainIfUnusedExceptionHandlers(this);
109         } catch (AbortMethod e) {
110             this.ignoreFurtherInvestigation = true;
111         }
112     }
113
114     public boolean isMethod() {
115
116         return true;
117     }
118
119     public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
120
121         //fill up the method body with statement
122
if (ignoreFurtherInvestigation)
123             return;
124         parser.parse(this, unit);
125     }
126
127     public StringBuffer JavaDoc printReturnType(int indent, StringBuffer JavaDoc output) {
128
129         if (returnType == null) return output;
130         return returnType.printExpression(0, output).append(' ');
131     }
132
133     public void resolveStatements() {
134
135         // ========= abort on fatal error =============
136
if (this.returnType != null && this.binding != null) {
137             this.returnType.resolvedType = this.binding.returnType;
138             // record the return type binding
139
}
140         // check if method with constructor name
141
if (CharOperation.equals(this.scope.enclosingSourceType().sourceName, selector)) {
142             this.scope.problemReporter().methodWithConstructorName(this);
143         }
144         
145         if (this.typeParameters != null) {
146             for (int i = 0, length = this.typeParameters.length; i < length; i++) {
147                 this.typeParameters[i].resolve(this.scope);
148             }
149         }
150         
151         // check @Override annotation
152
final CompilerOptions compilerOptions = this.scope.compilerOptions();
153         checkOverride: {
154             if (this.binding == null) break checkOverride;
155             long sourceLevel = compilerOptions.sourceLevel;
156             if (sourceLevel < ClassFileConstants.JDK1_5) break checkOverride;
157             int bindingModifiers = this.binding.modifiers;
158             boolean hasOverrideAnnotation = (this.binding.tagBits & TagBits.AnnotationOverride) != 0;
159             boolean isInterfaceMethod = this.binding.declaringClass.isInterface();
160             if (hasOverrideAnnotation) {
161                 // no static method is considered overriding
162
if (!isInterfaceMethod && (bindingModifiers & (ClassFileConstants.AccStatic|ExtraCompilerModifiers.AccOverriding)) == ExtraCompilerModifiers.AccOverriding)
163                     break checkOverride;
164                 // in 1.5, strictly for overriding superclass method
165
// in 1.6 and above, also tolerate implementing interface method
166
if (sourceLevel >= ClassFileConstants.JDK1_6
167                         && ((bindingModifiers & (ClassFileConstants.AccStatic|ExtraCompilerModifiers.AccImplementing)) == ExtraCompilerModifiers.AccImplementing))
168                     break checkOverride;
169                 // claims to override, and doesn't actually do so
170
this.scope.problemReporter().methodMustOverride(this);
171             } else if (!isInterfaceMethod
172                         && (bindingModifiers & (ClassFileConstants.AccStatic|ExtraCompilerModifiers.AccOverriding)) == ExtraCompilerModifiers.AccOverriding) {
173                 // actually overrides, but did not claim to do so
174
this.scope.problemReporter().missingOverrideAnnotation(this);
175             }
176         }
177                 
178         // by grammatical construction, interface methods are always abstract
179
switch (TypeDeclaration.kind(this.scope.referenceType().modifiers)) {
180             case TypeDeclaration.ENUM_DECL :
181                 if (this.selector == TypeConstants.VALUES) break;
182                 if (this.selector == TypeConstants.VALUEOF) break;
183             case TypeDeclaration.CLASS_DECL :
184                 // if a method has an semicolon body and is not declared as abstract==>error
185
// native methods may have a semicolon body
186
if ((this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) {
187                     if ((this.modifiers & ClassFileConstants.AccNative) == 0)
188                         if ((this.modifiers & ClassFileConstants.AccAbstract) == 0)
189                             this.scope.problemReporter().methodNeedBody(this);
190                 } else {
191                     // the method HAS a body --> abstract native modifiers are forbiden
192
if (((this.modifiers & ClassFileConstants.AccNative) != 0) || ((this.modifiers & ClassFileConstants.AccAbstract) != 0))
193                         this.scope.problemReporter().methodNeedingNoBody(this);
194                 }
195         }
196         super.resolveStatements();
197         
198         // TagBits.OverridingMethodWithSupercall is set during the resolveStatements() call
199
if (compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) {
200             if (this.binding != null) {
201                 int bindingModifiers = this.binding.modifiers;
202                 if ((bindingModifiers & (ExtraCompilerModifiers.AccOverriding|ExtraCompilerModifiers.AccImplementing)) == ExtraCompilerModifiers.AccOverriding
203                         && (this.bits & ASTNode.OverridingMethodWithSupercall) == 0) {
204                     this.scope.problemReporter().overridesMethodWithoutSuperInvocation(this.binding);
205                 }
206             }
207         }
208     }
209
210     public void traverse(
211         ASTVisitor visitor,
212         ClassScope classScope) {
213
214         if (visitor.visit(this, classScope)) {
215             if (this.javadoc != null) {
216                 this.javadoc.traverse(visitor, scope);
217             }
218             if (this.annotations != null) {
219                 int annotationsLength = this.annotations.length;
220                 for (int i = 0; i < annotationsLength; i++)
221                     this.annotations[i].traverse(visitor, scope);
222             }
223             if (this.typeParameters != null) {
224                 int typeParametersLength = this.typeParameters.length;
225                 for (int i = 0; i < typeParametersLength; i++) {
226                     this.typeParameters[i].traverse(visitor, scope);
227                 }
228             }
229             if (returnType != null)
230                 returnType.traverse(visitor, scope);
231             if (arguments != null) {
232                 int argumentLength = arguments.length;
233                 for (int i = 0; i < argumentLength; i++)
234                     arguments[i].traverse(visitor, scope);
235             }
236             if (thrownExceptions != null) {
237                 int thrownExceptionsLength = thrownExceptions.length;
238                 for (int i = 0; i < thrownExceptionsLength; i++)
239                     thrownExceptions[i].traverse(visitor, scope);
240             }
241             if (statements != null) {
242                 int statementsLength = statements.length;
243                 for (int i = 0; i < statementsLength; i++)
244                     statements[i].traverse(visitor, scope);
245             }
246         }
247         visitor.endVisit(this, classScope);
248     }
249     public TypeParameter[] typeParameters() {
250         return this.typeParameters;
251     }
252 }
253
Popular Tags