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