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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.ast;
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;
23 public class MethodDeclaration extends AbstractMethodDeclaration {
25 public TypeReference returnType;
28 * MethodDeclaration constructor comment.
30 public MethodDeclaration(CompilationResult compilationResult) {
31 super(compilationResult);
34 public void analyseCode(
35 ClassScope classScope,
36 InitializationFlowContext initializationContext,
39 // starting of the code analysis for methods
40 if (ignoreFurtherInvestigation)
46 if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
47 if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
48 scope.problemReporter().unusedPrivateMethod(this);
52 // may be in a non necessary <clinit> for innerclass with static final constant fields
53 if (binding.isAbstract() || binding.isNative())
56 ExceptionHandlingFlowContext methodContext =
57 new ExceptionHandlingFlowContext(
58 initializationContext,
60 binding.thrownExceptions,
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);
72 didAlreadyComplain = true;
76 // check for missing returning path
77 TypeBinding returnTypeBinding = binding.returnType;
78 if ((returnTypeBinding == VoidBinding) || isAbstract()) {
79 this.needFreeReturn = flowInfo.isReachable();
81 if (flowInfo != FlowInfo.DEAD_END) {
82 scope.problemReporter().shouldReturn(returnTypeBinding, this);
85 // check unreachable catch blocks
86 methodContext.complainIfUnusedExceptionHandlers(this);
87 } catch (AbortMethod e) {
88 this.ignoreFurtherInvestigation = true;
92 public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
94 //fill up the method body with statement
95 if (ignoreFurtherInvestigation)
97 parser.parse(this, unit);
100 public StringBuffer printReturnType(int indent, StringBuffer output) {
102 if (returnType == null) return output;
103 return returnType.printExpression(0, output).append(' ');
106 public void resolveStatements() {
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
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);
117 // check if method with constructor name
118 if (CharOperation.equals(scope.enclosingSourceType().sourceName, selector)) {
119 scope.problemReporter().methodWithConstructorName(this);
122 // by grammatical construction, interface methods are always abstract
123 if (!scope.enclosingSourceType().isInterface()){
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);
132 // the method HAS a body --> abstract native modifiers are forbiden
133 if (((modifiers & AccNative) != 0) || ((modifiers & AccAbstract) != 0))
134 scope.problemReporter().methodNeedingNoBody(this);
137 super.resolveStatements();
140 public void traverse(
142 ClassScope classScope) {
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);
152 if (thrownExceptions != null) {
153 int thrownExceptionsLength = thrownExceptions.length;
154 for (int i = 0; i < thrownExceptionsLength; i++)
155 thrownExceptions[i].traverse(visitor, scope);
157 if (statements != null) {
158 int statementsLength = statements.length;
159 for (int i = 0; i < statementsLength; i++)
160 statements[i].traverse(visitor, scope);
163 visitor.endVisit(this, classScope);