1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2003 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
 
   9  *     IBM Corporation - initial API and implementation
 
  10  *******************************************************************************/
 
  11 package net.sourceforge.phpeclipse.internal.compiler.ast;
 
  13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
 
  14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
 
  15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
 
  16 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
 
  17 import net.sourceforge.phpdt.internal.compiler.lookup.InvocationSite;
 
  18 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
 
  19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
 
  20 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
 
  21 import net.sourceforge.phpdt.internal.compiler.lookup.NestedTypeBinding;
 
  22 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
 
  23 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
 
  24 import net.sourceforge.phpdt.internal.compiler.lookup.SyntheticArgumentBinding;
 
  25 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
 
  27 public class AllocationExpression
 
  29         implements InvocationSite {
 
  31         public TypeReference type;
 
  32         public Expression[] arguments;
 
  33         public MethodBinding binding;
 
  35         MethodBinding syntheticAccessor;
 
  37         public AllocationExpression() {
 
  40         public FlowInfo analyseCode(
 
  41                 BlockScope currentScope,
 
  42                 FlowContext flowContext,
 
  45                 // check captured variables are initialized in current context (26134)
 
  46                 checkCapturedLocalInitializationIfNecessary(this.binding.declaringClass, currentScope, flowInfo);
 
  49                 if (arguments != null) {
 
  50                         for (int i = 0, count = arguments.length; i < count; i++) {
 
  53                                                 .analyseCode(currentScope, flowContext, flowInfo)
 
  54                                                 .unconditionalInits();
 
  57                 // record some dependency information for exception types
 
  58                 ReferenceBinding[] thrownExceptions;
 
  59                 if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
 
  60                         // check exception handling
 
  61                         flowContext.checkExceptionHandlers(
 
  67                 manageEnclosingInstanceAccessIfNecessary(currentScope);
 
  68                 manageSyntheticAccessIfNecessary(currentScope);
 
  73         public void checkCapturedLocalInitializationIfNecessary(ReferenceBinding checkedType, BlockScope currentScope, FlowInfo flowInfo) {
 
  75                 if (checkedType.isLocalType() 
 
  76                                 && !checkedType.isAnonymousType()
 
  77                                 && !currentScope.isDefinedInType(checkedType)) { // only check external allocations
 
  78                         NestedTypeBinding nestedType = (NestedTypeBinding) checkedType;
 
  79                         SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
 
  80                         if (syntheticArguments != null) 
 
  81                                 for (int i = 0, count = syntheticArguments.length; i < count; i++){
 
  82                                         SyntheticArgumentBinding syntheticArgument = syntheticArguments[i];
 
  83                                         LocalVariableBinding targetLocal;
 
  84                                         if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null) continue;
 
  85                                         if (targetLocal.declaration != null && !flowInfo.isDefinitelyAssigned(targetLocal)){
 
  86                                                 currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this);
 
  93         public Expression enclosingInstance() {
 
  97 //      public void generateCode(
 
  98 //              BlockScope currentScope,
 
  99 //              CodeStream codeStream,
 
 100 //              boolean valueRequired) {
 
 102 //              int pc = codeStream.position;
 
 103 //              ReferenceBinding allocatedType = binding.declaringClass;
 
 105 //              codeStream.new_(allocatedType);
 
 106 //              if (valueRequired) {
 
 109 //              // better highlight for allocation: display the type individually
 
 110 //              codeStream.recordPositionsFrom(pc, type.sourceStart);
 
 112 //              // handling innerclass instance allocation - enclosing instance arguments
 
 113 //              if (allocatedType.isNestedType()) {
 
 114 //                      codeStream.generateSyntheticEnclosingInstanceValues(
 
 117 //                              enclosingInstance(),
 
 120 //              // generate the arguments for constructor
 
 121 //              if (arguments != null) {
 
 122 //                      for (int i = 0, count = arguments.length; i < count; i++) {
 
 123 //                              arguments[i].generateCode(currentScope, codeStream, true);
 
 126 //              // handling innerclass instance allocation - outer local arguments
 
 127 //              if (allocatedType.isNestedType()) {
 
 128 //                      codeStream.generateSyntheticOuterArgumentValues(
 
 133 //              // invoke constructor
 
 134 //              if (syntheticAccessor == null) {
 
 135 //                      codeStream.invokespecial(binding);
 
 137 //                      // synthetic accessor got some extra arguments appended to its signature, which need values
 
 139 //                              max = syntheticAccessor.parameters.length - binding.parameters.length;
 
 142 //                              codeStream.aconst_null();
 
 144 //                      codeStream.invokespecial(syntheticAccessor);
 
 146 //              codeStream.recordPositionsFrom(pc, this.sourceStart);
 
 149         public boolean isSuperAccess() {
 
 154         public boolean isTypeAccess() {
 
 159         /* Inner emulation consists in either recording a dependency 
 
 160          * link only, or performing one level of propagation.
 
 162          * Dependency mechanism is used whenever dealing with source target
 
 163          * types, since by the time we reach them, we might not yet know their
 
 166         public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
 
 168                 ReferenceBinding allocatedType;
 
 170                 // perform some emulation work in case there is some and we are inside a local type only
 
 171                 if ((allocatedType = binding.declaringClass).isNestedType()
 
 172                         && currentScope.enclosingSourceType().isLocalType()) {
 
 174                         if (allocatedType.isLocalType()) {
 
 175                                 ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, false);
 
 176                                 // request cascade of accesses
 
 178                                 // locally propagate, since we already now the desired shape for sure
 
 179                                 currentScope.propagateInnerEmulation(allocatedType, false);
 
 180                                 // request cascade of accesses
 
 185         public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
 
 187                 if (binding.isPrivate()
 
 188                         && (currentScope.enclosingSourceType() != binding.declaringClass)) {
 
 193 //                              .isPrivateConstructorAccessChangingVisibility) {
 
 194 //                              binding.tagForClearingPrivateModifier();
 
 195 //                              // constructor will not be dumped as private, no emulation required thus
 
 198                                         ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
 
 199                                 currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
 
 203         public StringBuffer printExpression(int indent, StringBuffer output) {
 
 205                 output.append("new "); //$NON-NLS-1$
 
 206                 type.printExpression(0, output); 
 
 208                 if (arguments != null) {
 
 209                         for (int i = 0; i < arguments.length; i++) {
 
 210                                 if (i > 0) output.append(", "); //$NON-NLS-1$
 
 211                                 arguments[i].printExpression(0, output);
 
 214                 return output.append(')');
 
 216         public TypeBinding resolveType(BlockScope scope) {
 
 218                 // Propagate the type checking to the arguments, and check if the constructor is defined.
 
 219                 constant = NotAConstant;
 
 220                 this.resolvedType = type.resolveType(scope);
 
 221                 // will check for null after args are resolved
 
 223                 // buffering the arguments' types
 
 224                 TypeBinding[] argumentTypes = NoParameters;
 
 225                 if (arguments != null) {
 
 226                         boolean argHasError = false;
 
 227                         int length = arguments.length;
 
 228                         argumentTypes = new TypeBinding[length];
 
 229                         for (int i = 0; i < length; i++)
 
 230                                 if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
 
 233                                 return this.resolvedType;
 
 235                 if (this.resolvedType == null)
 
 238                 if (!this.resolvedType.canBeInstantiated()) {
 
 239                         scope.problemReporter().cannotInstantiate(type, this.resolvedType);
 
 240                         return this.resolvedType;
 
 242                 ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType;
 
 243                 if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this))
 
 245                         if (binding.declaringClass == null)
 
 246                                 binding.declaringClass = allocatedType;
 
 247                         scope.problemReporter().invalidConstructor(this, binding);
 
 248                         return this.resolvedType;
 
 250                 if (isMethodUseDeprecated(binding, scope))
 
 251                         scope.problemReporter().deprecatedMethod(binding, this);
 
 253                 if (arguments != null)
 
 254                         for (int i = 0; i < arguments.length; i++)
 
 255                                 arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
 
 256                 return allocatedType;
 
 259         public void setActualReceiverType(ReferenceBinding receiverType) {
 
 263         public void setDepth(int i) {
 
 267         public void setFieldIndex(int i) {
 
 271         public String toStringExpression() {
 
 273                 String s = "new " + type.toString(0); //$NON-NLS-1$
 
 274                 if (arguments == null)
 
 275                         s = s + "()"; //$NON-NLS-1$
 
 277                         s = s + "("; //$NON-NLS-1$
 
 278                         for (int i = 0; i < arguments.length; i++) {
 
 279                                 s = s + arguments[i].toStringExpression();
 
 280                                 if (i == (arguments.length - 1))
 
 281                                         s = s + ")"; //$NON-NLS-1$
 
 283                                         s = s + ", "; //$NON-NLS-1$
 
 289         public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 291                 if (visitor.visit(this, scope)) {
 
 293                         type.traverse(visitor, scope);
 
 294                         if (arguments != null) {
 
 295                                 argumentsLength = arguments.length;
 
 296                                 for (int i = 0; i < argumentsLength; i++)
 
 297                                         arguments[i].traverse(visitor, scope);
 
 300                 visitor.endVisit(this, scope);