Makefile fixup
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ast / MethodDeclaration.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-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.CompilationResult;
15 import org.eclipse.jdt.internal.compiler.ASTVisitor;
16 import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
17 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
18 import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
19 import org.eclipse.jdt.internal.compiler.lookup.*;
20 import org.eclipse.jdt.internal.compiler.parser.*;
21 import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
22
23 public class MethodDeclaration extends AbstractMethodDeclaration {
24         
25         public TypeReference returnType;
26
27         /**
28          * MethodDeclaration constructor comment.
29          */
30         public MethodDeclaration(CompilationResult compilationResult) {
31                 super(compilationResult);
32         }
33
34         public void analyseCode(
35                 ClassScope classScope,
36                 InitializationFlowContext initializationContext,
37                 FlowInfo flowInfo) {
38
39                 // starting of the code analysis for methods
40                 if (ignoreFurtherInvestigation)
41                         return;
42                 try {
43                         if (binding == null)
44                                 return;
45                                 
46                         if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
47                                 if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
48                                         scope.problemReporter().unusedPrivateMethod(this);
49                                 }
50                         }
51                                 
52                         // may be in a non necessary <clinit> for innerclass with static final constant fields
53                         if (binding.isAbstract() || binding.isNative())
54                                 return;
55
56                         ExceptionHandlingFlowContext methodContext =
57                                 new ExceptionHandlingFlowContext(
58                                         initializationContext,
59                                         this,
60                                         binding.thrownExceptions,
61                                         scope,
62                                         FlowInfo.DEAD_END);
63
64                         // propagate to statements
65                         if (statements != null) {
66                                 boolean didAlreadyComplain = false;
67                                 for (int i = 0, count = statements.length; i < count; i++) {
68                                         Statement stat = statements[i];
69                                         if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
70                                                 flowInfo = stat.analyseCode(scope, methodContext, flowInfo);
71                                         } else {
72                                                 didAlreadyComplain = true;
73                                         }
74                                 }
75                         }
76                         // check for missing returning path
77                         TypeBinding returnTypeBinding = binding.returnType;
78                         if ((returnTypeBinding == VoidBinding) || isAbstract()) {
79                                 this.needFreeReturn = flowInfo.isReachable();
80                         } else {
81                                 if (flowInfo != FlowInfo.DEAD_END) { 
82                                         scope.problemReporter().shouldReturn(returnTypeBinding, this);
83                                 }
84                         }
85                         // check unreachable catch blocks
86                         methodContext.complainIfUnusedExceptionHandlers(this);
87                 } catch (AbortMethod e) {
88                         this.ignoreFurtherInvestigation = true;
89                 }
90         }
91
92         public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
93
94                 //fill up the method body with statement
95                 if (ignoreFurtherInvestigation)
96                         return;
97                 parser.parse(this, unit);
98         }
99
100         public StringBuffer printReturnType(int indent, StringBuffer output) {
101
102                 if (returnType == null) return output;
103                 return returnType.printExpression(0, output).append(' ');
104         }
105
106         public void resolveStatements() {
107
108                 // ========= abort on fatal error =============
109                 if (this.returnType != null && this.binding != null) {
110                         this.returnType.resolvedType = this.binding.returnType;
111                         // record the return type binding
112                 }
113                 // look if the name of the method is correct
114                 if (binding != null && isTypeUseDeprecated(binding.returnType, scope))
115                         scope.problemReporter().deprecatedType(binding.returnType, returnType);
116
117                 // check if method with constructor name
118                 if (CharOperation.equals(scope.enclosingSourceType().sourceName, selector)) {
119                         scope.problemReporter().methodWithConstructorName(this);
120                 }
121                 
122                 // by grammatical construction, interface methods are always abstract
123                 if (!scope.enclosingSourceType().isInterface()){
124
125                         // if a method has an semicolon body and is not declared as abstract==>error
126                         // native methods may have a semicolon body 
127                         if ((modifiers & AccSemicolonBody) != 0) {
128                                 if ((modifiers & AccNative) == 0)
129                                         if ((modifiers & AccAbstract) == 0)
130                                                 scope.problemReporter().methodNeedBody(this);
131                         } else {
132                                 // the method HAS a body --> abstract native modifiers are forbiden
133                                 if (((modifiers & AccNative) != 0) || ((modifiers & AccAbstract) != 0))
134                                         scope.problemReporter().methodNeedingNoBody(this);
135                         }
136                 }
137                 super.resolveStatements(); 
138         }
139
140         public void traverse(
141                 ASTVisitor visitor,
142                 ClassScope classScope) {
143
144                 if (visitor.visit(this, classScope)) {
145                         if (returnType != null)
146                                 returnType.traverse(visitor, scope);
147                         if (arguments != null) {
148                                 int argumentLength = arguments.length;
149                                 for (int i = 0; i < argumentLength; i++)
150                                         arguments[i].traverse(visitor, scope);
151                         }
152                         if (thrownExceptions != null) {
153                                 int thrownExceptionsLength = thrownExceptions.length;
154                                 for (int i = 0; i < thrownExceptionsLength; i++)
155                                         thrownExceptions[i].traverse(visitor, scope);
156                         }
157                         if (statements != null) {
158                                 int statementsLength = statements.length;
159                                 for (int i = 0; i < statementsLength; i++)
160                                         statements[i].traverse(visitor, scope);
161                         }
162                 }
163                 visitor.endVisit(this, classScope);
164         }
165 }