X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AbstractMethodDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AbstractMethodDeclaration.java index 214dc4c..9c001cc 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AbstractMethodDeclaration.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AbstractMethodDeclaration.java @@ -1,26 +1,36 @@ /******************************************************************************* - * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others. + * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 + * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html + * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation - ******************************************************************************/ + *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; -import net.sourceforge.phpdt.core.compiler.*; -import net.sourceforge.phpdt.internal.compiler.*; -import net.sourceforge.phpdt.internal.compiler.impl.*; -import net.sourceforge.phpdt.internal.compiler.codegen.*; -import net.sourceforge.phpdt.internal.compiler.flow.*; -import net.sourceforge.phpdt.internal.compiler.lookup.*; -import net.sourceforge.phpdt.internal.compiler.problem.*; -import net.sourceforge.phpdt.internal.compiler.parser.*; +import net.sourceforge.phpdt.core.compiler.CharOperation; +import net.sourceforge.phpdt.internal.compiler.ASTVisitor; +import net.sourceforge.phpdt.internal.compiler.CompilationResult; +import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; +import net.sourceforge.phpdt.internal.compiler.flow.InitializationFlowContext; +import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext; +import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope; +import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope; +import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; +import net.sourceforge.phpdt.internal.compiler.parser.UnitParser; +import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation; +import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilationUnit; +import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod; +import net.sourceforge.phpdt.internal.compiler.problem.AbortType; +import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities; + public abstract class AbstractMethodDeclaration - extends AstNode + extends ASTNode implements ProblemSeverities, ReferenceContext { public MethodScope scope; @@ -38,7 +48,7 @@ public abstract class AbstractMethodDeclaration public MethodBinding binding; public boolean ignoreFurtherInvestigation = false; public boolean needFreeReturn = false; - + public int bodyStart; public int bodyEnd = -1; public CompilationResult compilationResult; @@ -71,68 +81,16 @@ public abstract class AbstractMethodDeclaration } } - public void analyseCode( - ClassScope currentScope, - FlowContext flowContext, - FlowInfo flowInfo) { + public abstract void analyseCode(ClassScope scope, InitializationFlowContext initializationContext, FlowInfo info); - // starting of the code analysis for methods - if (ignoreFurtherInvestigation) - return; - try { - if (binding == null) - return; - // may be in a non necessary for innerclass with static final constant fields - if (binding.isAbstract() || binding.isNative()) - return; - - ExceptionHandlingFlowContext methodContext = - new ExceptionHandlingFlowContext( - flowContext, - this, - binding.thrownExceptions, - scope, - FlowInfo.DeadEnd); - - // propagate to statements - if (statements != null) { - for (int i = 0, count = statements.length; i < count; i++) { - Statement stat; - if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) { - flowInfo = stat.analyseCode(scope, methodContext, flowInfo); - } - } - } - // check for missing returning path - TypeBinding returnType = binding.returnType; - if ((returnType == VoidBinding) || isAbstract()) { - needFreeReturn = - !((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable()); - } else { - if (flowInfo != FlowInfo.DeadEnd) { - // special test for empty methods that should return something - if ((statements == null) && (returnType != VoidBinding)) { - scope.problemReporter().shouldReturn(returnType, this); - } else { - scope.problemReporter().shouldReturn( - returnType, - statements[statements.length - 1]); - } - } - } - } catch (AbortMethod e) { - this.ignoreFurtherInvestigation = true; - } - } - - /** + /** * Bind and add argument's binding into the scope of the method */ public void bindArguments() { if (arguments != null) { // by default arguments in abstract/native methods are considered to be used (no complaint is expected) - boolean used = binding == null || binding.isAbstract() || binding.isNative(); + boolean used = binding == null || binding.isAbstract();// || binding.isNative(); int length = arguments.length; for (int i = 0; i < length; i++) { @@ -150,9 +108,34 @@ public abstract class AbstractMethodDeclaration if (this.thrownExceptions != null && this.binding != null && this.binding.thrownExceptions != null) { + int thrownExceptionLength = this.thrownExceptions.length; int length = this.binding.thrownExceptions.length; - for (int i = 0; i < length; i++) { - this.thrownExceptions[i].binding = this.binding.thrownExceptions[i]; + if (length == thrownExceptionLength) { + for (int i = 0; i < length; i++) { + this.thrownExceptions[i].resolvedType = this.binding.thrownExceptions[i]; + } + } else { + int bindingIndex = 0; + for (int i = 0; i < thrownExceptionLength && bindingIndex < length; i++) { + TypeReference thrownException = this.thrownExceptions[i]; + ReferenceBinding thrownExceptionBinding = this.binding.thrownExceptions[bindingIndex]; + char[][] bindingCompoundName = thrownExceptionBinding.compoundName; + if (thrownException instanceof SingleTypeReference) { + // single type reference + int lengthName = bindingCompoundName.length; + char[] thrownExceptionTypeName = thrownException.getTypeName()[0]; + if (CharOperation.equals(thrownExceptionTypeName, bindingCompoundName[lengthName - 1])) { + thrownException.resolvedType = thrownExceptionBinding; + bindingIndex++; + } + } else { + // qualified type reference + if (CharOperation.equals(thrownException.getTypeName(), bindingCompoundName)) { + thrownException.resolvedType = thrownExceptionBinding; + bindingIndex++; + } + } + } } } } @@ -165,98 +148,116 @@ public abstract class AbstractMethodDeclaration /** * Bytecode generation for a method */ - public void generateCode(ClassScope classScope, ClassFile classFile) { - - int problemResetPC = 0; - classFile.codeStream.wideMode = false; // reset wideMode to false - if (ignoreFurtherInvestigation) { - // method is known to have errors, dump a problem method - if (this.binding == null) - return; // handle methods with invalid signature or duplicates - int problemsLength; - IProblem[] problems = - scope.referenceCompilationUnit().compilationResult.getProblems(); - IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - classFile.addProblemMethod(this, binding, problemsCopy); - return; - } - // regular code generation - try { - problemResetPC = classFile.contentsOffset; - this.generateCode(classFile); - } catch (AbortMethod e) { - // a fatal error was detected during code generation, need to restart code gen if possible - if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { - // a branch target required a goto_w, restart code gen in wide mode. - try { - this.traverse(new ResetStateForCodeGenerationVisitor(), classScope); - classFile.contentsOffset = problemResetPC; - classFile.methodCount--; - classFile.codeStream.wideMode = true; // request wide mode - this.generateCode(classFile); // restart method generation - } catch (AbortMethod e2) { - int problemsLength; - IProblem[] problems = - scope.referenceCompilationUnit().compilationResult.getProblems(); - IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC); - } - } else { - // produce a problem method accounting for this fatal error - int problemsLength; - IProblem[] problems = - scope.referenceCompilationUnit().compilationResult.getProblems(); - IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC); - } - } - } - - private void generateCode(ClassFile classFile) { - - classFile.generateMethodInfoHeader(binding); - int methodAttributeOffset = classFile.contentsOffset; - int attributeNumber = classFile.generateMethodInfoAttribute(binding); - if ((!binding.isNative()) && (!binding.isAbstract())) { - int codeAttributeOffset = classFile.contentsOffset; - classFile.generateCodeAttributeHeader(); - CodeStream codeStream = classFile.codeStream; - codeStream.reset(this, classFile); - // initialize local positions - scope.computeLocalVariablePositions(binding.isStatic() ? 0 : 1, codeStream); - - // arguments initialization for local variable debug attributes - if (arguments != null) { - for (int i = 0, max = arguments.length; i < max; i++) { - LocalVariableBinding argBinding; - codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding); - argBinding.recordInitializationStartPC(0); - } - } - if (statements != null) { - for (int i = 0, max = statements.length; i < max; i++) - statements[i].generateCode(scope, codeStream); - } - if (needFreeReturn) { - codeStream.return_(); - } - // local variable attributes - codeStream.exitUserScope(scope); - codeStream.recordPositionsFrom(0, this.bodyEnd); - classFile.completeCodeAttribute(codeAttributeOffset); - attributeNumber++; - } - classFile.completeMethodInfo(methodAttributeOffset, attributeNumber); - - // if a problem got reported during code gen, then trigger problem method creation - if (ignoreFurtherInvestigation) { - throw new AbortMethod(scope.referenceCompilationUnit().compilationResult); - } - } - +// public void generateCode(ClassScope classScope, ClassFile classFile) { +// +// int problemResetPC = 0; +// classFile.codeStream.wideMode = false; // reset wideMode to false +// if (ignoreFurtherInvestigation) { +// // method is known to have errors, dump a problem method +// if (this.binding == null) +// return; // handle methods with invalid signature or duplicates +// int problemsLength; +// IProblem[] problems = +// scope.referenceCompilationUnit().compilationResult.getProblems(); +// IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; +// System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); +// classFile.addProblemMethod(this, binding, problemsCopy); +// return; +// } +// // regular code generation +// try { +// problemResetPC = classFile.contentsOffset; +// this.generateCode(classFile); +// } catch (AbortMethod e) { +// // a fatal error was detected during code generation, need to restart code gen if possible +// if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { +// // a branch target required a goto_w, restart code gen in wide mode. +// try { +// this.traverse(new ResetStateForCodeGenerationVisitor(), classScope); +// classFile.contentsOffset = problemResetPC; +// classFile.methodCount--; +// classFile.codeStream.wideMode = true; // request wide mode +// this.generateCode(classFile); // restart method generation +// } catch (AbortMethod e2) { +// int problemsLength; +// IProblem[] problems = +// scope.referenceCompilationUnit().compilationResult.getAllProblems(); +// IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; +// System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); +// classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC); +// } +// } else { +// // produce a problem method accounting for this fatal error +// int problemsLength; +// IProblem[] problems = +// scope.referenceCompilationUnit().compilationResult.getAllProblems(); +// IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; +// System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); +// classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC); +// } +// } +// } +// +// private void generateCode(ClassFile classFile) { +// +// classFile.generateMethodInfoHeader(binding); +// int methodAttributeOffset = classFile.contentsOffset; +// int attributeNumber = classFile.generateMethodInfoAttribute(binding); +// if ((!binding.isNative()) && (!binding.isAbstract())) { +// int codeAttributeOffset = classFile.contentsOffset; +// classFile.generateCodeAttributeHeader(); +// CodeStream codeStream = classFile.codeStream; +// codeStream.reset(this, classFile); +// // initialize local positions +// this.scope.computeLocalVariablePositions(binding.isStatic() ? 0 : 1, codeStream); +// +// // arguments initialization for local variable debug attributes +// if (arguments != null) { +// for (int i = 0, max = arguments.length; i < max; i++) { +// LocalVariableBinding argBinding; +// codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding); +// argBinding.recordInitializationStartPC(0); +// } +// } +// if (statements != null) { +// for (int i = 0, max = statements.length; i < max; i++) +// statements[i].generateCode(scope, codeStream); +// } +// if (this.needFreeReturn) { +// codeStream.return_(); +// } +// // local variable attributes +// codeStream.exitUserScope(scope); +// codeStream.recordPositionsFrom(0, this.declarationSourceEnd); +// classFile.completeCodeAttribute(codeAttributeOffset); +// attributeNumber++; +// } else { +// checkArgumentsSize(); +// } +// classFile.completeMethodInfo(methodAttributeOffset, attributeNumber); +// +// // if a problem got reported during code gen, then trigger problem method creation +// if (ignoreFurtherInvestigation) { +// throw new AbortMethod(scope.referenceCompilationUnit().compilationResult); +// } +// } + +// private void checkArgumentsSize() { +// TypeBinding[] parameters = binding.parameters; +// int size = 1; // an abstact method or a native method cannot be static +// for (int i = 0, max = parameters.length; i < max; i++) { +// TypeBinding parameter = parameters[i]; +// if (parameter == LongBinding || parameter == DoubleBinding) { +// size += 2; +// } else { +// size++; +// } +// if (size > 0xFF) { +// scope.problemReporter().noMoreAvailableSpaceForArgument(scope.locals[i], scope.locals[i].declaration); +// } +// } +// } + public boolean hasErrors() { return this.ignoreFurtherInvestigation; } @@ -288,12 +289,12 @@ public abstract class AbstractMethodDeclaration return false; } - public boolean isNative() { - - if (binding != null) - return binding.isNative(); - return (modifiers & AccNative) != 0; - } +// public boolean isNative() { +// +// if (binding != null) +// return binding.isNative(); +// return (modifiers & AccNative) != 0; +// } public boolean isStatic() { @@ -306,9 +307,52 @@ public abstract class AbstractMethodDeclaration * Fill up the method body with statement */ public abstract void parseStatements( - Parser parser, + UnitParser parser, CompilationUnitDeclaration unit); + public StringBuffer print(int tab, StringBuffer output) { + + printIndent(tab, output); + printModifiers(this.modifiers, output); + printReturnType(0, output).append(this.selector).append('('); + if (this.arguments != null) { + for (int i = 0; i < this.arguments.length; i++) { + if (i > 0) output.append(", "); //$NON-NLS-1$ + this.arguments[i].print(0, output); + } + } + output.append(')'); + if (this.thrownExceptions != null) { + output.append(" throws "); //$NON-NLS-1$ + for (int i = 0; i < this.thrownExceptions.length; i++) { + if (i > 0) output.append(", "); //$NON-NLS-1$ + this.thrownExceptions[i].print(0, output); + } + } + printBody(tab + 1, output); + return output; + } + + public StringBuffer printBody(int indent, StringBuffer output) { + if (isAbstract() || (this.modifiers & AccSemicolonBody) != 0) + return output.append(';'); + + output.append(" {"); //$NON-NLS-1$ + if (this.statements != null) { + for (int i = 0; i < this.statements.length; i++) { + output.append('\n'); + this.statements[i].printStatement(indent, output); + } + } + output.append('\n'); //$NON-NLS-1$ + printIndent(indent == 0 ? 0 : indent - 1, output).append('}'); + return output; + } + + public StringBuffer printReturnType(int indent, StringBuffer output) { + + return output; + } public void resolve(ClassScope upperScope) { if (binding == null) { @@ -318,13 +362,13 @@ public abstract class AbstractMethodDeclaration try { bindArguments(); bindThrownExceptions(); - resolveStatements(upperScope); + resolveStatements(); } catch (AbortMethod e) { // ========= abort on fatal error ============= this.ignoreFurtherInvestigation = true; } } - public void resolveStatements(ClassScope upperScope) { + public void resolveStatements() { if (statements != null) { int i = 0, length = statements.length; @@ -392,7 +436,7 @@ public abstract class AbstractMethodDeclaration } public void traverse( - IAbstractSyntaxTreeVisitor visitor, + ASTVisitor visitor, ClassScope classScope) { } -} \ No newline at end of file +}