/*******************************************************************************
- * 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.*;
-import net.sourceforge.phpdt.internal.compiler.flow.*;
-import net.sourceforge.phpdt.internal.compiler.lookup.*;
-
+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.LocalTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * Variation on allocation, where can be specified an enclosing instance and an
+ * anonymous type
+ */
public class QualifiedAllocationExpression extends AllocationExpression {
-
- //qualification may be on both side
+
+ // qualification may be on both side
public Expression enclosingInstance;
+
public AnonymousLocalTypeDeclaration anonymousType;
+ public ReferenceBinding superTypeBinding;
+
public QualifiedAllocationExpression() {
}
- public QualifiedAllocationExpression(AnonymousLocalTypeDeclaration anonymousType) {
+ public QualifiedAllocationExpression(
+ AnonymousLocalTypeDeclaration anonymousType) {
this.anonymousType = anonymousType;
}
- public FlowInfo analyseCode(
- BlockScope currentScope,
- FlowContext flowContext,
- FlowInfo flowInfo) {
-
- // variation on allocation, where can be specified an enclosing instance and an anonymous type
+ public FlowInfo analyseCode(BlockScope currentScope,
+ FlowContext flowContext, FlowInfo flowInfo) {
// analyse the enclosing instance
if (enclosingInstance != null) {
- flowInfo = enclosingInstance.analyseCode(currentScope, flowContext, flowInfo);
+ flowInfo = enclosingInstance.analyseCode(currentScope, flowContext,
+ flowInfo);
}
+
+ // check captured variables are initialized in current context (26134)
+ checkCapturedLocalInitializationIfNecessary(
+ this.superTypeBinding == null ? this.binding.declaringClass
+ : this.superTypeBinding, currentScope, flowInfo);
+
// process arguments
if (arguments != null) {
for (int i = 0, count = arguments.length; i < count; i++) {
- flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo);
+ flowInfo = arguments[i].analyseCode(currentScope, flowContext,
+ flowInfo);
}
}
// analyse the anonymous nested type
if (anonymousType != null) {
- flowInfo = anonymousType.analyseCode(currentScope, flowContext, flowInfo);
+ flowInfo = anonymousType.analyseCode(currentScope, flowContext,
+ flowInfo);
}
// record some dependency information for exception types
ReferenceBinding[] thrownExceptions;
if (((thrownExceptions = binding.thrownExceptions).length) != 0) {
// check exception handling
- flowContext.checkExceptionHandlers(
- thrownExceptions,
- this,
- flowInfo,
- currentScope);
+ flowContext.checkExceptionHandlers(thrownExceptions, this,
+ flowInfo, currentScope);
}
manageEnclosingInstanceAccessIfNecessary(currentScope);
manageSyntheticAccessIfNecessary(currentScope);
return enclosingInstance;
}
- public void generateCode(
- BlockScope currentScope,
- CodeStream codeStream,
- boolean valueRequired) {
-
- int pc = codeStream.position;
- ReferenceBinding allocatedType = binding.declaringClass;
- if (allocatedType.isLocalType()) {
- LocalTypeBinding localType = (LocalTypeBinding) allocatedType;
- localType.constantPoolName(
- codeStream.classFile.outerMostEnclosingClassFile().computeConstantPoolName(
- localType));
- }
- 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()) {
- // make sure its name is computed before arguments, since may be necessary for argument emulation
- 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);
- if (anonymousType != null) {
- anonymousType.generateCode(currentScope, codeStream);
- }
- }
-
+ // 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);
+ //
+ // if (anonymousType != null) {
+ // anonymousType.generateCode(currentScope, codeStream);
+ // }
+ // }
+
public boolean isSuperAccess() {
// necessary to lookup super constructor of anonymous type
return anonymousType != null;
}
-
- /* 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,
- enclosingInstance != null,
- false);
- // request cascade of accesses
+ currentScope, enclosingInstance != null);
} else {
- // locally propagate, since we already now the desired shape for sure
- currentScope.propagateInnerEmulation(
- allocatedType,
- enclosingInstance != null,
- false);
- // request cascade of accesses
+ // locally propagate, since we already now the desired shape for
+ // sure
+ currentScope.propagateInnerEmulation(allocatedType,
+ enclosingInstance != null);
}
}
}
public TypeBinding resolveType(BlockScope scope) {
- if (anonymousType == null && enclosingInstance == null)
+ // added for code assist...cannot occur with 'normal' code
+ if (anonymousType == null && enclosingInstance == null) {
return super.resolveType(scope);
- // added for code assist... is not possible with 'normal' code
-
- // Propagate the type checking to the arguments, and checks if the constructor is defined.
+ }
- // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
- // ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
- // ==> by construction, when there is an enclosing instance the typename may NOT be qualified
- // ==> therefore by construction the type is always a SingleTypeReferenceType instead of being either
+ // Propagate the type checking to the arguments, and checks if the
+ // constructor is defined.
+ // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '('
+ // ArgumentListopt ')' ClassBodyopt
+ // ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '('
+ // ArgumentListopt ')' ClassBodyopt
+ // ==> by construction, when there is an enclosing instance the typename
+ // may NOT be qualified
+ // ==> therefore by construction the type is always a
+ // SingleTypeReferenceType instead of being either
// sometime a SingleTypeReference and sometime a QualifedTypeReference
constant = NotAConstant;
- TypeBinding enclosingInstTb = null;
- TypeBinding recType;
- if (anonymousType == null) {
- //----------------no anonymous class------------------------
- if ((enclosingInstTb = enclosingInstance.resolveType(scope)) == null)
- return null;
- if (enclosingInstTb.isBaseType() | enclosingInstTb.isArrayType()) {
- scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(
- enclosingInstTb,
- enclosingInstance);
- return null;
+ TypeBinding enclosingInstanceType = null;
+ TypeBinding receiverType = null;
+ boolean hasError = false;
+ if (anonymousType == null) { // ----------------no anonymous
+ // class------------------------
+ if ((enclosingInstanceType = enclosingInstance.resolveType(scope)) == null) {
+ hasError = true;
+ } else if (enclosingInstanceType.isBaseType()
+ || enclosingInstanceType.isArrayType()) {
+ scope.problemReporter()
+ .illegalPrimitiveOrArrayTypeForEnclosingInstance(
+ enclosingInstanceType, enclosingInstance);
+ hasError = true;
+ } else if ((this.resolvedType = receiverType = ((SingleTypeReference) type)
+ .resolveTypeEnclosing(scope,
+ (ReferenceBinding) enclosingInstanceType)) == null) {
+ hasError = true;
}
- recType =
- ((SingleTypeReference) type).resolveTypeEnclosing(
- scope,
- (ReferenceBinding) enclosingInstTb);
// will check for null after args are resolved
TypeBinding[] argumentTypes = NoParameters;
if (arguments != null) {
- boolean argHasError = false;
int length = arguments.length;
argumentTypes = new TypeBinding[length];
for (int i = 0; i < length; i++)
- if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
- argHasError = true;
- if (argHasError)
- return recType;
+ if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null) {
+ hasError = true;
+ }
}
- if (recType == null)
- return null;
- if (!recType.canBeInstantiated()) {
- scope.problemReporter().cannotInstantiate(type, recType);
- return recType;
+ // limit of fault-tolerance
+ if (hasError)
+ return receiverType;
+
+ if (!receiverType.canBeInstantiated()) {
+ scope.problemReporter().cannotInstantiate(type, receiverType);
+ return receiverType;
}
- if ((binding =
- scope.getConstructor((ReferenceBinding) recType, argumentTypes, this))
- .isValidBinding()) {
+ if ((this.binding = scope.getConstructor(
+ (ReferenceBinding) receiverType, argumentTypes, this))
+ .isValidBinding()) {
if (isMethodUseDeprecated(binding, scope))
- scope.problemReporter().deprecatedMethod(binding, this);
+ scope.problemReporter()
+ .deprecatedMethod(this.binding, this);
if (arguments != null)
for (int i = 0; i < arguments.length; i++)
- arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+ arguments[i].implicitWidening(
+ this.binding.parameters[i], argumentTypes[i]);
} else {
- if (binding.declaringClass == null)
- binding.declaringClass = (ReferenceBinding) recType;
- scope.problemReporter().invalidConstructor(this, binding);
- return recType;
+ if (this.binding.declaringClass == null)
+ this.binding.declaringClass = (ReferenceBinding) receiverType;
+ scope.problemReporter().invalidConstructor(this, this.binding);
+ return receiverType;
}
- // The enclosing instance must be compatible with the innermost enclosing type
- ReferenceBinding expectedType = binding.declaringClass.enclosingType();
- if (scope.areTypesCompatible(enclosingInstTb, expectedType))
- return recType;
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
- enclosingInstance,
- enclosingInstTb,
- expectedType);
- return recType;
+ // The enclosing instance must be compatible with the innermost
+ // enclosing type
+ ReferenceBinding expectedType = this.binding.declaringClass
+ .enclosingType();
+ if (enclosingInstanceType.isCompatibleWith(expectedType))
+ return receiverType;
+ scope.problemReporter()
+ .typeMismatchErrorActualTypeExpectedType(
+ this.enclosingInstance, enclosingInstanceType,
+ expectedType);
+ return receiverType;
}
- //--------------there is an anonymous type declaration-----------------
- if (enclosingInstance != null) {
- if ((enclosingInstTb = enclosingInstance.resolveType(scope)) == null)
- return null;
- if (enclosingInstTb.isBaseType() | enclosingInstTb.isArrayType()) {
- scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(
- enclosingInstTb,
- enclosingInstance);
- return null;
+ // --------------there is an anonymous type declaration-----------------
+ if (this.enclosingInstance != null) {
+ if ((enclosingInstanceType = this.enclosingInstance
+ .resolveType(scope)) == null) {
+ hasError = true;
+ } else if (enclosingInstanceType.isBaseType()
+ || enclosingInstanceType.isArrayType()) {
+ scope.problemReporter()
+ .illegalPrimitiveOrArrayTypeForEnclosingInstance(
+ enclosingInstanceType, this.enclosingInstance);
+ hasError = true;
+ } else {
+ receiverType = ((SingleTypeReference) type)
+ .resolveTypeEnclosing(scope,
+ (ReferenceBinding) enclosingInstanceType);
}
+ } else {
+ receiverType = type.resolveType(scope);
}
- // due to syntax-construction, recType is a ReferenceBinding
- recType =
- (enclosingInstance == null)
- ? type.resolveType(scope)
- : ((SingleTypeReference) type).resolveTypeEnclosing(
- scope,
- (ReferenceBinding) enclosingInstTb);
- if (recType == null)
- return null;
- if (((ReferenceBinding) recType).isFinal()) {
- scope.problemReporter().anonymousClassCannotExtendFinalClass(type, recType);
- return null;
+ if (receiverType == null) {
+ hasError = true;
+ } else if (((ReferenceBinding) receiverType).isFinal()) {
+ scope.problemReporter().anonymousClassCannotExtendFinalClass(type,
+ receiverType);
+ hasError = true;
}
TypeBinding[] argumentTypes = NoParameters;
if (arguments != null) {
int length = arguments.length;
argumentTypes = new TypeBinding[length];
for (int i = 0; i < length; i++)
- if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
- return null;
+ if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null) {
+ hasError = true;
+ }
+ }
+ // limit of fault-tolerance
+ if (hasError) {
+ return receiverType;
}
- // an anonymous class inherits from java.lang.Object when declared "after" an interface
- ReferenceBinding superBinding =
- recType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) recType;
- MethodBinding inheritedBinding =
- scope.getConstructor(superBinding, argumentTypes, this);
+ // an anonymous class inherits from java.lang.Object when declared
+ // "after" an interface
+ this.superTypeBinding = receiverType.isInterface() ? scope
+ .getJavaLangObject() : (ReferenceBinding) receiverType;
+ MethodBinding inheritedBinding = scope.getConstructor(
+ this.superTypeBinding, argumentTypes, this);
if (!inheritedBinding.isValidBinding()) {
if (inheritedBinding.declaringClass == null)
- inheritedBinding.declaringClass = superBinding;
+ inheritedBinding.declaringClass = this.superTypeBinding;
scope.problemReporter().invalidConstructor(this, inheritedBinding);
return null;
}
if (enclosingInstance != null) {
- if (!scope
- .areTypesCompatible(
- enclosingInstTb,
- inheritedBinding.declaringClass.enclosingType())) {
- scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
- enclosingInstance,
- enclosingInstTb,
- inheritedBinding.declaringClass.enclosingType());
+ if (!enclosingInstanceType
+ .isCompatibleWith(inheritedBinding.declaringClass
+ .enclosingType())) {
+ scope
+ .problemReporter()
+ .typeMismatchErrorActualTypeExpectedType(
+ enclosingInstance, enclosingInstanceType,
+ inheritedBinding.declaringClass.enclosingType());
return null;
}
}
- // this promotion has to be done somewhere: here or inside the constructor of the
- // anonymous class. We do it here while the constructor of the inner is then easier.
+ // this promotion has to be done somewhere: here or inside the
+ // constructor of the
+ // anonymous class. We do it here while the constructor of the inner is
+ // then easier.
if (arguments != null)
for (int i = 0; i < arguments.length; i++)
- arguments[i].implicitWidening(inheritedBinding.parameters[i], argumentTypes[i]);
+ arguments[i].implicitWidening(inheritedBinding.parameters[i],
+ argumentTypes[i]);
- // Update the anonymous inner class : superclass, interface
- scope.addAnonymousType(anonymousType, (ReferenceBinding) recType);
+ // Update the anonymous inner class : superclass, interface
+ scope.addAnonymousType(anonymousType, (ReferenceBinding) receiverType);
anonymousType.resolve(scope);
- binding = anonymousType.createsInternalConstructorWithBinding(inheritedBinding);
+ binding = anonymousType
+ .createsInternalConstructorWithBinding(inheritedBinding);
return anonymousType.binding; // 1.2 change
}
+ public String toStringExpression() {
+ return this.toStringExpression(0);
+ }
+
public String toStringExpression(int tab) {
String s = ""; //$NON-NLS-1$
if (enclosingInstance != null)
s += enclosingInstance.toString() + "."; //$NON-NLS-1$
- s += super.toStringExpression(tab);
+ s += super.toStringExpression();
if (anonymousType != null) {
s += anonymousType.toString(tab);
- } //allows to restart just after the } one line under ....
+ } // allows to restart just after the } one line under ....
return s;
}
- public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
if (visitor.visit(this, scope)) {
if (enclosingInstance != null)
}
visitor.endVisit(this, scope);
}
-}
\ No newline at end of file
+}