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