X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AllocationExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AllocationExpression.java index ca948ca..c164bcb 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AllocationExpression.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/ast/AllocationExpression.java @@ -1,120 +1,153 @@ /******************************************************************************* - * 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.internal.compiler.IAbstractSyntaxTreeVisitor; -import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream; +import net.sourceforge.phpdt.internal.compiler.ASTVisitor; import net.sourceforge.phpdt.internal.compiler.flow.FlowContext; import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo; import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; import net.sourceforge.phpdt.internal.compiler.lookup.InvocationSite; import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding; import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.NestedTypeBinding; import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding; import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding; +import net.sourceforge.phpdt.internal.compiler.lookup.SyntheticArgumentBinding; import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; -public class AllocationExpression - extends Expression - implements InvocationSite { - +public class AllocationExpression extends Expression implements InvocationSite { + public TypeReference type; + public Expression[] arguments; + public MethodBinding binding; MethodBinding syntheticAccessor; public AllocationExpression() { - super(); } - public FlowInfo analyseCode( - BlockScope currentScope, - FlowContext flowContext, - FlowInfo flowInfo) { + public FlowInfo analyseCode(BlockScope currentScope, + FlowContext flowContext, FlowInfo flowInfo) { - // must verify that exceptions potentially thrown by this expression are caught in the method + // check captured variables are initialized in current context (26134) + checkCapturedLocalInitializationIfNecessary( + this.binding.declaringClass, currentScope, flowInfo); // process arguments if (arguments != null) { for (int i = 0, count = arguments.length; i < count; i++) { - flowInfo = - arguments[i] - .analyseCode(currentScope, flowContext, flowInfo) - .unconditionalInits(); + flowInfo = arguments[i].analyseCode(currentScope, flowContext, + flowInfo).unconditionalInits(); } } // record some dependency information for exception types ReferenceBinding[] thrownExceptions; - if (((thrownExceptions = binding.thrownExceptions).length) != 0) { + if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) { // check exception handling - flowContext.checkExceptionHandlers( - thrownExceptions, - this, - flowInfo, - currentScope); + flowContext.checkExceptionHandlers(thrownExceptions, this, + flowInfo, currentScope); } manageEnclosingInstanceAccessIfNecessary(currentScope); manageSyntheticAccessIfNecessary(currentScope); + return flowInfo; } + public void checkCapturedLocalInitializationIfNecessary( + ReferenceBinding checkedType, BlockScope currentScope, + FlowInfo flowInfo) { + + if (checkedType.isLocalType() && !checkedType.isAnonymousType() + && !currentScope.isDefinedInType(checkedType)) { // only + // check + // external + // allocations + NestedTypeBinding nestedType = (NestedTypeBinding) checkedType; + SyntheticArgumentBinding[] syntheticArguments = nestedType + .syntheticOuterLocalVariables(); + if (syntheticArguments != null) + for (int i = 0, count = syntheticArguments.length; i < count; i++) { + SyntheticArgumentBinding syntheticArgument = syntheticArguments[i]; + LocalVariableBinding targetLocal; + if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null) + continue; + // if (targetLocal.declaration != null && + // !flowInfo.isDefinitelyAssigned(targetLocal)){ + // currentScope.problemReporter().uninitializedLocalVariable(targetLocal, + // this); + // } + } + + } + } + public Expression enclosingInstance() { return null; } - public void generateCode( - BlockScope currentScope, - CodeStream codeStream, - boolean valueRequired) { - - int pc = codeStream.position; - ReferenceBinding allocatedType = binding.declaringClass; - - codeStream.new_(allocatedType); - if (valueRequired) { - codeStream.dup(); - } - // better highlight for allocation: display the type individually - codeStream.recordPositionsFrom(pc, type.sourceStart); - - // handling innerclass instance allocation - if (allocatedType.isNestedType()) { - codeStream.generateSyntheticArgumentValues( - currentScope, - allocatedType, - enclosingInstance(), - this); - } - // generate the arguments for constructor - if (arguments != null) { - for (int i = 0, count = arguments.length; i < count; i++) { - arguments[i].generateCode(currentScope, codeStream, true); - } - } - // invoke constructor - if (syntheticAccessor == null) { - codeStream.invokespecial(binding); - } else { - // synthetic accessor got some extra arguments appended to its signature, which need values - for (int i = 0, - max = syntheticAccessor.parameters.length - binding.parameters.length; - i < max; - i++) { - codeStream.aconst_null(); - } - codeStream.invokespecial(syntheticAccessor); - } - codeStream.recordPositionsFrom(pc, this.sourceStart); - } + // public void generateCode( + // BlockScope currentScope, + // CodeStream codeStream, + // boolean valueRequired) { + // + // int pc = codeStream.position; + // ReferenceBinding allocatedType = binding.declaringClass; + // + // codeStream.new_(allocatedType); + // if (valueRequired) { + // codeStream.dup(); + // } + // // better highlight for allocation: display the type individually + // codeStream.recordPositionsFrom(pc, type.sourceStart); + // + // // handling innerclass instance allocation - enclosing instance arguments + // if (allocatedType.isNestedType()) { + // codeStream.generateSyntheticEnclosingInstanceValues( + // currentScope, + // allocatedType, + // enclosingInstance(), + // this); + // } + // // generate the arguments for constructor + // if (arguments != null) { + // for (int i = 0, count = arguments.length; i < count; i++) { + // arguments[i].generateCode(currentScope, codeStream, true); + // } + // } + // // handling innerclass instance allocation - outer local arguments + // if (allocatedType.isNestedType()) { + // codeStream.generateSyntheticOuterArgumentValues( + // currentScope, + // allocatedType, + // this); + // } + // // invoke constructor + // if (syntheticAccessor == null) { + // codeStream.invokespecial(binding); + // } else { + // // synthetic accessor got some extra arguments appended to its signature, + // which need values + // for (int i = 0, + // max = syntheticAccessor.parameters.length - binding.parameters.length; + // i < max; + // i++) { + // codeStream.aconst_null(); + // } + // codeStream.invokespecial(syntheticAccessor); + // } + // codeStream.recordPositionsFrom(pc, this.sourceStart); + // } public boolean isSuperAccess() { @@ -126,30 +159,30 @@ public class AllocationExpression return true; } - /* Inner emulation consists in either recording a dependency - * link only, or performing one level of propagation. - * - * Dependency mechanism is used whenever dealing with source target - * types, since by the time we reach them, we might not yet know their - * exact need. + /* + * Inner emulation consists in either recording a dependency link only, or + * performing one level of propagation. + * + * Dependency mechanism is used whenever dealing with source target types, + * since by the time we reach them, we might not yet know their exact need. */ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) { ReferenceBinding allocatedType; - // perform some emulation work in case there is some and we are inside a local type only + // perform some emulation work in case there is some and we are inside a + // local type only if ((allocatedType = binding.declaringClass).isNestedType() - && currentScope.enclosingSourceType().isLocalType()) { + && currentScope.enclosingSourceType().isLocalType()) { if (allocatedType.isLocalType()) { ((LocalTypeBinding) allocatedType).addInnerEmulationDependent( - currentScope, - false, - false); + currentScope, false); // request cascade of accesses } else { - // locally propagate, since we already now the desired shape for sure - currentScope.propagateInnerEmulation(allocatedType, false, false); + // locally propagate, since we already now the desired shape for + // sure + currentScope.propagateInnerEmulation(allocatedType, false); // request cascade of accesses } } @@ -158,27 +191,45 @@ public class AllocationExpression public void manageSyntheticAccessIfNecessary(BlockScope currentScope) { if (binding.isPrivate() - && (currentScope.enclosingSourceType() != binding.declaringClass)) { - - if (currentScope - .environment() - .options - .isPrivateConstructorAccessChangingVisibility) { - binding.tagForClearingPrivateModifier(); - // constructor will not be dumped as private, no emulation required thus - } else { - syntheticAccessor = - ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding); - currentScope.problemReporter().needToEmulateMethodAccess(binding, this); + && (currentScope.enclosingSourceType() != binding.declaringClass)) { + + // if (currentScope + // .environment() + // .options + // .isPrivateConstructorAccessChangingVisibility) { + // binding.tagForClearingPrivateModifier(); + // // constructor will not be dumped as private, no emulation + // required thus + // } else { + syntheticAccessor = ((SourceTypeBinding) binding.declaringClass) + .addSyntheticMethod(binding, isSuperAccess()); + currentScope.problemReporter().needToEmulateMethodAccess(binding, + this); + // } + } + } + + public StringBuffer printExpression(int indent, StringBuffer output) { + + output.append("new "); //$NON-NLS-1$ + type.printExpression(0, output); + output.append('('); + if (arguments != null) { + for (int i = 0; i < arguments.length; i++) { + if (i > 0) + output.append(", "); //$NON-NLS-1$ + arguments[i].printExpression(0, output); } } + return output.append(')'); } public TypeBinding resolveType(BlockScope scope) { - // Propagate the type checking to the arguments, and check if the constructor is defined. + // Propagate the type checking to the arguments, and check if the + // constructor is defined. constant = NotAConstant; - TypeBinding typeBinding = type.resolveType(scope); + this.resolvedType = type.resolveType(scope); // will check for null after args are resolved // buffering the arguments' types @@ -191,29 +242,31 @@ public class AllocationExpression if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null) argHasError = true; if (argHasError) - return typeBinding; + return this.resolvedType; } - if (typeBinding == null) + if (this.resolvedType == null) return null; - if (!typeBinding.canBeInstantiated()) { - scope.problemReporter().cannotInstantiate(type, typeBinding); - return typeBinding; + if (!this.resolvedType.canBeInstantiated()) { + scope.problemReporter().cannotInstantiate(type, this.resolvedType); + return this.resolvedType; } - ReferenceBinding allocatedType = (ReferenceBinding) typeBinding; - if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this)) - .isValidBinding()) { + ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType; + if (!(binding = scope + .getConstructor(allocatedType, argumentTypes, this)) + .isValidBinding()) { if (binding.declaringClass == null) binding.declaringClass = allocatedType; scope.problemReporter().invalidConstructor(this, binding); - return typeBinding; + return this.resolvedType; } if (isMethodUseDeprecated(binding, scope)) scope.problemReporter().deprecatedMethod(binding, this); if (arguments != null) for (int i = 0; i < arguments.length; i++) - arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]); + arguments[i].implicitWidening(binding.parameters[i], + argumentTypes[i]); return allocatedType; } @@ -247,7 +300,7 @@ public class AllocationExpression return s; } - public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) { + public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { int argumentsLength; @@ -260,4 +313,4 @@ public class AllocationExpression } visitor.endVisit(this, scope); } -} \ No newline at end of file +}