X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ConstructorDeclaration.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ConstructorDeclaration.java index 0bf4ad0..e43ddcb 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ConstructorDeclaration.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/ConstructorDeclaration.java @@ -24,66 +24,66 @@ import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; import net.sourceforge.phpdt.internal.compiler.parser.UnitParser; import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod; - public class ConstructorDeclaration extends AbstractMethodDeclaration { public ExplicitConstructorCall constructorCall; + public final static char[] ConstantPoolName = "".toCharArray(); //$NON-NLS-1$ + public boolean isDefaultConstructor = false; - public ConstructorDeclaration(CompilationResult compilationResult){ + public ConstructorDeclaration(CompilationResult compilationResult) { super(compilationResult); } - - public void analyseCode( - ClassScope classScope, - InitializationFlowContext initializerFlowContext, - FlowInfo flowInfo) { + + public void analyseCode(ClassScope classScope, + InitializationFlowContext initializerFlowContext, FlowInfo flowInfo) { if (ignoreFurtherInvestigation) return; - if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) { - if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) { + if (this.binding != null && this.binding.isPrivate() + && !this.binding.isPrivateUsed()) { + if (!classScope.referenceCompilationUnit().compilationResult + .hasSyntaxError()) { scope.problemReporter().unusedPrivateConstructor(this); } } - + // check constructor recursion, once all constructor got resolved - if (isRecursive(null /*lazy initialized visited list*/)) { - this.scope.problemReporter().recursiveConstructorInvocation(this.constructorCall); + if (isRecursive(null /* lazy initialized visited list */)) { + this.scope.problemReporter().recursiveConstructorInvocation( + this.constructorCall); } - + try { - ExceptionHandlingFlowContext constructorContext = - new ExceptionHandlingFlowContext( - initializerFlowContext.parent, - this, - binding.thrownExceptions, - scope, - FlowInfo.DEAD_END); - initializerFlowContext.checkInitializerExceptions( - scope, - constructorContext, - flowInfo); - - // anonymous constructor can gain extra thrown exceptions from unhandled ones + ExceptionHandlingFlowContext constructorContext = new ExceptionHandlingFlowContext( + initializerFlowContext.parent, this, + binding.thrownExceptions, scope, FlowInfo.DEAD_END); + initializerFlowContext.checkInitializerExceptions(scope, + constructorContext, flowInfo); + + // anonymous constructor can gain extra thrown exceptions from + // unhandled ones if (binding.declaringClass.isAnonymousType()) { ArrayList computedExceptions = constructorContext.extendedExceptions; - if (computedExceptions != null){ + if (computedExceptions != null) { int size; - if ((size = computedExceptions.size()) > 0){ + if ((size = computedExceptions.size()) > 0) { ReferenceBinding[] actuallyThrownExceptions; - computedExceptions.toArray(actuallyThrownExceptions = new ReferenceBinding[size]); + computedExceptions + .toArray(actuallyThrownExceptions = new ReferenceBinding[size]); binding.thrownExceptions = actuallyThrownExceptions; } } } - + // propagate to constructor call if (constructorCall != null) { - // if calling 'this(...)', then flag all non-static fields as definitely - // set since they are supposed to be set inside other local constructor + // if calling 'this(...)', then flag all non-static fields as + // definitely + // set since they are supposed to be set inside other local + // constructor if (constructorCall.accessMode == ExplicitConstructorCall.This) { FieldBinding[] fields = binding.declaringClass.fields(); for (int i = 0, count = fields.length; i < count; i++) { @@ -93,15 +93,18 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration { } } } - flowInfo = constructorCall.analyseCode(scope, constructorContext, flowInfo); + flowInfo = constructorCall.analyseCode(scope, + constructorContext, flowInfo); } // propagate to statements if (statements != null) { boolean didAlreadyComplain = false; for (int i = 0, count = statements.length; i < count; i++) { Statement stat; - if (!flowInfo.complainIfUnreachable(stat = statements[i], scope, didAlreadyComplain)) { - flowInfo = stat.analyseCode(scope, constructorContext, flowInfo); + if (!flowInfo.complainIfUnreachable(stat = statements[i], + scope, didAlreadyComplain)) { + flowInfo = stat.analyseCode(scope, constructorContext, + flowInfo); } else { didAlreadyComplain = true; } @@ -112,17 +115,18 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration { // check missing blank final field initializations if ((constructorCall != null) - && (constructorCall.accessMode != ExplicitConstructorCall.This)) { - flowInfo = flowInfo.mergedWith(constructorContext.initsOnReturn); + && (constructorCall.accessMode != ExplicitConstructorCall.This)) { + flowInfo = flowInfo + .mergedWith(constructorContext.initsOnReturn); FieldBinding[] fields = binding.declaringClass.fields(); for (int i = 0, count = fields.length; i < count; i++) { FieldBinding field; - if ((!(field = fields[i]).isStatic()) - && field.isFinal() - && (!flowInfo.isDefinitelyAssigned(fields[i]))) { + if ((!(field = fields[i]).isStatic()) && field.isFinal() + && (!flowInfo.isDefinitelyAssigned(fields[i]))) { scope.problemReporter().uninitializedBlankFinalField( - field, - isDefaultConstructor ? (ASTNode) scope.referenceType() : this); + field, + isDefaultConstructor ? (ASTNode) scope + .referenceType() : this); } } } @@ -133,185 +137,205 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration { /** * Bytecode generation for a constructor - * - * @param classScope net.sourceforge.phpdt.internal.compiler.lookup.ClassScope - * @param classFile net.sourceforge.phpdt.internal.compiler.codegen.ClassFile + * + * @param classScope + * net.sourceforge.phpdt.internal.compiler.lookup.ClassScope + * @param classFile + * net.sourceforge.phpdt.internal.compiler.codegen.ClassFile */ -// public void generateCode(ClassScope classScope, ClassFile classFile) { -// -// int problemResetPC = 0; -// if (ignoreFurtherInvestigation) { -// 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.addProblemConstructor(this, binding, problemsCopy); -// return; -// } -// try { -// problemResetPC = classFile.contentsOffset; -// this.internalGenerateCode(classScope, classFile); -// } catch (AbortMethod e) { -// if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { -// // a branch target required a goto_w, restart code gen in wide mode. -// try { -// if (statements != null) { -// for (int i = 0, max = statements.length; i < max; i++) -// statements[i].resetStateForCodeGeneration(); -// } -// classFile.contentsOffset = problemResetPC; -// classFile.methodCount--; -// classFile.codeStream.wideMode = true; // request wide mode -// this.internalGenerateCode(classScope, 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.addProblemConstructor(this, binding, problemsCopy, problemResetPC); -// } -// } else { -// int problemsLength; -// IProblem[] problems = -// scope.referenceCompilationUnit().compilationResult.getAllProblems(); -// IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; -// System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); -// classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC); -// } -// } -// } -// -// public void generateSyntheticFieldInitializationsIfNecessary( -// MethodScope scope, -// CodeStream codeStream, -// ReferenceBinding declaringClass) { -// -// if (!declaringClass.isNestedType()) return; -// -// NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass; -// -// SyntheticArgumentBinding[] syntheticArgs = nestedType.syntheticEnclosingInstances(); -// for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) { -// SyntheticArgumentBinding syntheticArg; -// if ((syntheticArg = syntheticArgs[i]).matchingField != null) { -// codeStream.aload_0(); -// codeStream.load(syntheticArg); -// codeStream.putfield(syntheticArg.matchingField); -// } -// } -// syntheticArgs = nestedType.syntheticOuterLocalVariables(); -// for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) { -// SyntheticArgumentBinding syntheticArg; -// if ((syntheticArg = syntheticArgs[i]).matchingField != null) { -// codeStream.aload_0(); -// codeStream.load(syntheticArg); -// codeStream.putfield(syntheticArg.matchingField); -// } -// } -// } -// -// private void internalGenerateCode(ClassScope classScope, ClassFile classFile) { -// -// classFile.generateMethodInfoHeader(binding); -// int methodAttributeOffset = classFile.contentsOffset; -// int attributeNumber = classFile.generateMethodInfoAttribute(binding); -// if ((!binding.isNative()) && (!binding.isAbstract())) { -// -// TypeDeclaration declaringType = classScope.referenceContext; -// int codeAttributeOffset = classFile.contentsOffset; -// classFile.generateCodeAttributeHeader(); -// CodeStream codeStream = classFile.codeStream; -// codeStream.reset(this, classFile); -// -// // initialize local positions - including initializer scope. -// ReferenceBinding declaringClass = binding.declaringClass; -// -// int argSlotSize = 1; // this==aload0 -// -// if (declaringClass.isNestedType()){ -// NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass; -// this.scope.extraSyntheticArguments = nestedType.syntheticOuterLocalVariables(); -// scope.computeLocalVariablePositions(// consider synthetic arguments if any -// nestedType.enclosingInstancesSlotSize + 1, -// codeStream); -// argSlotSize += nestedType.enclosingInstancesSlotSize; -// argSlotSize += nestedType.outerLocalVariablesSlotSize; -// } else { -// scope.computeLocalVariablePositions(1, codeStream); -// } -// -// if (arguments != null) { -// for (int i = 0, max = arguments.length; i < max; i++) { -// // arguments initialization for local variable debug attributes -// LocalVariableBinding argBinding; -// codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding); -// argBinding.recordInitializationStartPC(0); -// TypeBinding argType; -// if ((argType = argBinding.type) == LongBinding || (argType == DoubleBinding)) { -// argSlotSize += 2; -// } else { -// argSlotSize++; -// } -// } -// } -// -// MethodScope initializerScope = declaringType.initializerScope; -// initializerScope.computeLocalVariablePositions(argSlotSize, codeStream); // offset by the argument size (since not linked to method scope) -// -// boolean needFieldInitializations = constructorCall == null || constructorCall.accessMode != ExplicitConstructorCall.This; -// -// // post 1.4 source level, synthetic initializations occur prior to explicit constructor call -// boolean preInitSyntheticFields = scope.environment().options.targetJDK >= CompilerOptions.JDK1_4; -// -// if (needFieldInitializations && preInitSyntheticFields){ -// generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass); -// } -// // generate constructor call -// if (constructorCall != null) { -// constructorCall.generateCode(scope, codeStream); -// } -// // generate field initialization - only if not invoking another constructor call of the same class -// if (needFieldInitializations) { -// if (!preInitSyntheticFields){ -// generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass); -// } -// // generate user field initialization -// if (declaringType.fields != null) { -// for (int i = 0, max = declaringType.fields.length; i < max; i++) { -// FieldDeclaration fieldDecl; -// if (!(fieldDecl = declaringType.fields[i]).isStatic()) { -// fieldDecl.generateCode(initializerScope, codeStream); -// } -// } -// } -// } -// // generate statements -// 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.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; + // if (ignoreFurtherInvestigation) { + // 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.addProblemConstructor(this, binding, problemsCopy); + // return; + // } + // try { + // problemResetPC = classFile.contentsOffset; + // this.internalGenerateCode(classScope, classFile); + // } catch (AbortMethod e) { + // if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { + // // a branch target required a goto_w, restart code gen in wide mode. + // try { + // if (statements != null) { + // for (int i = 0, max = statements.length; i < max; i++) + // statements[i].resetStateForCodeGeneration(); + // } + // classFile.contentsOffset = problemResetPC; + // classFile.methodCount--; + // classFile.codeStream.wideMode = true; // request wide mode + // this.internalGenerateCode(classScope, 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.addProblemConstructor(this, binding, problemsCopy, + // problemResetPC); + // } + // } else { + // int problemsLength; + // IProblem[] problems = + // scope.referenceCompilationUnit().compilationResult.getAllProblems(); + // IProblem[] problemsCopy = new IProblem[problemsLength = problems.length]; + // System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); + // classFile.addProblemConstructor(this, binding, problemsCopy, + // problemResetPC); + // } + // } + // } + // + // public void generateSyntheticFieldInitializationsIfNecessary( + // MethodScope scope, + // CodeStream codeStream, + // ReferenceBinding declaringClass) { + // + // if (!declaringClass.isNestedType()) return; + // + // NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass; + // + // SyntheticArgumentBinding[] syntheticArgs = + // nestedType.syntheticEnclosingInstances(); + // for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i + // < max; i++) { + // SyntheticArgumentBinding syntheticArg; + // if ((syntheticArg = syntheticArgs[i]).matchingField != null) { + // codeStream.aload_0(); + // codeStream.load(syntheticArg); + // codeStream.putfield(syntheticArg.matchingField); + // } + // } + // syntheticArgs = nestedType.syntheticOuterLocalVariables(); + // for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i + // < max; i++) { + // SyntheticArgumentBinding syntheticArg; + // if ((syntheticArg = syntheticArgs[i]).matchingField != null) { + // codeStream.aload_0(); + // codeStream.load(syntheticArg); + // codeStream.putfield(syntheticArg.matchingField); + // } + // } + // } + // + // private void internalGenerateCode(ClassScope classScope, ClassFile + // classFile) { + // + // classFile.generateMethodInfoHeader(binding); + // int methodAttributeOffset = classFile.contentsOffset; + // int attributeNumber = classFile.generateMethodInfoAttribute(binding); + // if ((!binding.isNative()) && (!binding.isAbstract())) { + // + // TypeDeclaration declaringType = classScope.referenceContext; + // int codeAttributeOffset = classFile.contentsOffset; + // classFile.generateCodeAttributeHeader(); + // CodeStream codeStream = classFile.codeStream; + // codeStream.reset(this, classFile); + // + // // initialize local positions - including initializer scope. + // ReferenceBinding declaringClass = binding.declaringClass; + // + // int argSlotSize = 1; // this==aload0 + // + // if (declaringClass.isNestedType()){ + // NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass; + // this.scope.extraSyntheticArguments = + // nestedType.syntheticOuterLocalVariables(); + // scope.computeLocalVariablePositions(// consider synthetic arguments if + // any + // nestedType.enclosingInstancesSlotSize + 1, + // codeStream); + // argSlotSize += nestedType.enclosingInstancesSlotSize; + // argSlotSize += nestedType.outerLocalVariablesSlotSize; + // } else { + // scope.computeLocalVariablePositions(1, codeStream); + // } + // + // if (arguments != null) { + // for (int i = 0, max = arguments.length; i < max; i++) { + // // arguments initialization for local variable debug attributes + // LocalVariableBinding argBinding; + // codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding); + // argBinding.recordInitializationStartPC(0); + // TypeBinding argType; + // if ((argType = argBinding.type) == LongBinding || (argType == + // DoubleBinding)) { + // argSlotSize += 2; + // } else { + // argSlotSize++; + // } + // } + // } + // + // MethodScope initializerScope = declaringType.initializerScope; + // initializerScope.computeLocalVariablePositions(argSlotSize, codeStream); + // // offset by the argument size (since not linked to method scope) + // + // boolean needFieldInitializations = constructorCall == null || + // constructorCall.accessMode != ExplicitConstructorCall.This; + // + // // post 1.4 source level, synthetic initializations occur prior to + // explicit constructor call + // boolean preInitSyntheticFields = scope.environment().options.targetJDK >= + // CompilerOptions.JDK1_4; + // + // if (needFieldInitializations && preInitSyntheticFields){ + // generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, + // declaringClass); + // } + // // generate constructor call + // if (constructorCall != null) { + // constructorCall.generateCode(scope, codeStream); + // } + // // generate field initialization - only if not invoking another + // constructor call of the same class + // if (needFieldInitializations) { + // if (!preInitSyntheticFields){ + // generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, + // declaringClass); + // } + // // generate user field initialization + // if (declaringType.fields != null) { + // for (int i = 0, max = declaringType.fields.length; i < max; i++) { + // FieldDeclaration fieldDecl; + // if (!(fieldDecl = declaringType.fields[i]).isStatic()) { + // fieldDecl.generateCode(initializerScope, codeStream); + // } + // } + // } + // } + // // generate statements + // 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.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 boolean isConstructor() { return true; @@ -328,44 +352,45 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration { } /** - * Returns true if the constructor is directly involved in a cycle. - * Given most constructors aren't, we only allocate the visited list - * lazily. + * Returns true if the constructor is directly involved in a cycle. Given + * most constructors aren't, we only allocate the visited list lazily. */ public boolean isRecursive(ArrayList visited) { - if (this.binding == null - || this.constructorCall == null + if (this.binding == null || this.constructorCall == null || this.constructorCall.binding == null || this.constructorCall.isSuperAccess() || !this.constructorCall.binding.isValidBinding()) { return false; } - - ConstructorDeclaration targetConstructor = - ((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding)); - if (this == targetConstructor) return true; // direct case + + ConstructorDeclaration targetConstructor = ((ConstructorDeclaration) this.scope + .referenceType().declarationOf(constructorCall.binding)); + if (this == targetConstructor) + return true; // direct case if (visited == null) { // lazy allocation visited = new ArrayList(1); } else { int index = visited.indexOf(this); - if (index >= 0) return index == 0; // only blame if directly part of the cycle + if (index >= 0) + return index == 0; // only blame if directly part of the cycle } visited.add(this); return targetConstructor.isRecursive(visited); } - - public void parseStatements(UnitParser parser, CompilationUnitDeclaration unit) { - //fill up the constructor body with its statements + public void parseStatements(UnitParser parser, + CompilationUnitDeclaration unit) { + + // fill up the constructor body with its statements if (ignoreFurtherInvestigation) return; - if (isDefaultConstructor){ + if (isDefaultConstructor) { constructorCall = SuperReference.implicitSuperConstructorCall(); constructorCall.sourceStart = sourceStart; - constructorCall.sourceEnd = sourceEnd; + constructorCall.sourceEnd = sourceEnd; return; } parser.parse(this, unit); @@ -373,12 +398,13 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration { } /* - * Type checking for constructor, just another method, except for special check - * for recursive constructor invocations. + * Type checking for constructor, just another method, except for special + * check for recursive constructor invocations. */ public void resolveStatements() { - if (!CharOperation.equals(scope.enclosingSourceType().sourceName, selector)){ + if (!CharOperation.equals(scope.enclosingSourceType().sourceName, + selector)) { scope.problemReporter().missingReturnType(this); } @@ -386,17 +412,18 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration { if (this.constructorCall != null) { // e.g. using super() in java.lang.Object if (this.binding != null - && this.binding.declaringClass.id == T_Object - && this.constructorCall.accessMode != ExplicitConstructorCall.This) { - if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) { - scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall); - } - this.constructorCall = null; + && this.binding.declaringClass.id == T_Object + && this.constructorCall.accessMode != ExplicitConstructorCall.This) { + if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) { + scope.problemReporter().cannotUseSuperInJavaLangObject( + this.constructorCall); + } + this.constructorCall = null; } else { this.constructorCall.resolve(this.scope); } } - + super.resolveStatements(); } @@ -419,9 +446,7 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration { return s; } - public void traverse( - ASTVisitor visitor, - ClassScope classScope) { + public void traverse(ASTVisitor visitor, ClassScope classScope) { if (visitor.visit(this, classScope)) { if (arguments != null) {