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 	public TypeParameter[] typeParameters;
27 
28 	/**
29 	 * MethodDeclaration constructor comment.
30 	 */
MethodDeclaration(CompilationResult compilationResult)31 	public MethodDeclaration(CompilationResult compilationResult) {
32 		super(compilationResult);
33 	}
34 
analyseCode( ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo flowInfo)35 	public void analyseCode(
36 		ClassScope classScope,
37 		InitializationFlowContext initializationContext,
38 		FlowInfo flowInfo) {
39 
40 		// starting of the code analysis for methods
41 		if (ignoreFurtherInvestigation)
42 			return;
43 		try {
44 			if (binding == null)
45 				return;
46 
47 			if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
48 				if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
49 					scope.problemReporter().unusedPrivateMethod(this);
50 				}
51 			}
52 
53 			// may be in a non necessary <clinit> for innerclass with static final constant fields
54 			if (binding.isAbstract() || binding.isNative())
55 				return;
56 
57 			ExceptionHandlingFlowContext methodContext =
58 				new ExceptionHandlingFlowContext(
59 					initializationContext,
60 					this,
61 					binding.thrownExceptions,
62 					scope,
63 					FlowInfo.DEAD_END);
64 
65 			// propagate to statements
66 			if (statements != null) {
67 				boolean didAlreadyComplain = false;
68 				for (int i = 0, count = statements.length; i < count; i++) {
69 					Statement stat = statements[i];
70 					if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
71 						flowInfo = stat.analyseCode(scope, methodContext, flowInfo);
72 					} else {
73 						didAlreadyComplain = true;
74 					}
75 				}
76 			}
77 			// check for missing returning path
78 			TypeBinding returnTypeBinding = binding.returnType;
79 			if ((returnTypeBinding == VoidBinding) || isAbstract()) {
80 				this.needFreeReturn = flowInfo.isReachable();
81 			} else {
82 				if (flowInfo != FlowInfo.DEAD_END) {
83 					scope.problemReporter().shouldReturn(returnTypeBinding, this);
84 				}
85 			}
86 			// check unreachable catch blocks
87 			methodContext.complainIfUnusedExceptionHandlers(this);
88 		} catch (AbortMethod e) {
89 			this.ignoreFurtherInvestigation = true;
90 		}
91 	}
92 
isMethod()93 	public boolean isMethod() {
94 
95 		return true;
96 	}
97 
parseStatements(Parser parser, CompilationUnitDeclaration unit)98 	public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
99 
100 		//fill up the method body with statement
101 		if (ignoreFurtherInvestigation)
102 			return;
103 		parser.parse(this, unit);
104 	}
105 
printReturnType(int indent, StringBuffer output)106 	public StringBuffer printReturnType(int indent, StringBuffer output) {
107 
108 		if (returnType == null) return output;
109 		return returnType.printExpression(0, output).append(' ');
110 	}
111 
resolveStatements()112 	public void resolveStatements() {
113 
114 		// ========= abort on fatal error =============
115 		if (this.returnType != null && this.binding != null) {
116 			this.returnType.resolvedType = this.binding.returnType;
117 			// record the return type binding
118 		}
119 		// check if method with constructor name
120 		if (CharOperation.equals(scope.enclosingSourceType().sourceName, selector)) {
121 			scope.problemReporter().methodWithConstructorName(this);
122 		}
123 
124 		// by grammatical construction, interface methods are always abstract
125 		if (!scope.enclosingSourceType().isInterface()){
126 
127 			// if a method has an semicolon body and is not declared as abstract==>error
128 			// native methods may have a semicolon body
129 			if ((modifiers & AccSemicolonBody) != 0) {
130 				if ((modifiers & AccNative) == 0)
131 					if ((modifiers & AccAbstract) == 0)
132 						scope.problemReporter().methodNeedBody(this);
133 			} else {
134 				// the method HAS a body --> abstract native modifiers are forbiden
135 				if (((modifiers & AccNative) != 0) || ((modifiers & AccAbstract) != 0))
136 					scope.problemReporter().methodNeedingNoBody(this);
137 			}
138 		}
139 		super.resolveStatements();
140 	}
141 
traverse( ASTVisitor visitor, ClassScope classScope)142 	public void traverse(
143 		ASTVisitor visitor,
144 		ClassScope classScope) {
145 
146 		if (visitor.visit(this, classScope)) {
147 			if (this.annotations != null) {
148 				int annotationsLength = this.annotations.length;
149 				for (int i = 0; i < annotationsLength; i++)
150 					this.annotations[i].traverse(visitor, scope);
151 			}
152 			if (this.typeParameters != null) {
153 				int typeParametersLength = this.typeParameters.length;
154 				for (int i = 0; i < typeParametersLength; i++) {
155 					this.typeParameters[i].traverse(visitor, scope);
156 				}
157 			}
158 			if (returnType != null)
159 				returnType.traverse(visitor, scope);
160 			if (arguments != null) {
161 				int argumentLength = arguments.length;
162 				for (int i = 0; i < argumentLength; i++)
163 					arguments[i].traverse(visitor, scope);
164 			}
165 			if (thrownExceptions != null) {
166 				int thrownExceptionsLength = thrownExceptions.length;
167 				for (int i = 0; i < thrownExceptionsLength; i++)
168 					thrownExceptions[i].traverse(visitor, scope);
169 			}
170 			if (statements != null) {
171 				int statementsLength = statements.length;
172 				for (int i = 0; i < statementsLength; i++)
173 					statements[i].traverse(visitor, scope);
174 			}
175 		}
176 		visitor.endVisit(this, classScope);
177 	}
typeParameters()178 	public TypeParameter[] typeParameters() {
179 	    return this.typeParameters;
180 	}
181 }
182