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.phpdt.internal.compiler.lookup;
 
  13 import net.sourceforge.phpdt.core.compiler.CharOperation;
 
  14 import net.sourceforge.phpdt.internal.compiler.util.Util;
 
  15 import net.sourceforge.phpeclipse.internal.compiler.ast.AnonymousLocalTypeDeclaration;
 
  17 public final class LocalTypeBinding extends NestedTypeBinding {
 
  18         final static char[] LocalTypePrefix = { '$', 'L', 'o', 'c', 'a', 'l', '$' };
 
  20         private InnerEmulationDependency[] dependents;
 
  21         ArrayBinding[] localArrayBindings; // used to cache array bindings of various dimensions for this local type
 
  23 public LocalTypeBinding(ClassScope scope, SourceTypeBinding enclosingType) {
 
  25                 new char[][] {CharOperation.concat(LocalTypePrefix, scope.referenceContext.name)},
 
  29         if (this.sourceName == AnonymousLocalTypeDeclaration.ANONYMOUS_EMPTY_NAME)
 
  30                 this.tagBits |= AnonymousTypeMask;
 
  32                 this.tagBits |= LocalTypeMask;
 
  34 /* Record a dependency onto a source target type which may be altered
 
  35 * by the end of the innerclass emulation. Later on, we will revisit
 
  36 * all its dependents so as to update them (see updateInnerEmulationDependents()).
 
  39 public void addInnerEmulationDependent(BlockScope scope, boolean wasEnclosingInstanceSupplied) {
 
  41         if (dependents == null) {
 
  43                 dependents = new InnerEmulationDependency[1];
 
  45                 index = dependents.length;
 
  46                 for (int i = 0; i < index; i++)
 
  47                         if (dependents[i].scope == scope)
 
  48                                 return; // already stored
 
  49                 System.arraycopy(dependents, 0, (dependents = new InnerEmulationDependency[index + 1]), 0, index);
 
  51         dependents[index] = new InnerEmulationDependency(scope, wasEnclosingInstanceSupplied);
 
  52         //  System.out.println("Adding dependency: "+ new String(scope.enclosingType().readableName()) + " --> " + new String(this.readableName()));
 
  54 /* Answer the receiver's constant pool name.
 
  56 * NOTE: This method should only be used during/after code gen.
 
  59 public char[] constantPoolName() /* java/lang/Object */ {
 
  60         return constantPoolName;
 
  63 ArrayBinding createArrayType(int dimensionCount) {
 
  64         if (localArrayBindings == null) {
 
  65                 localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount)};
 
  66                 return localArrayBindings[0];
 
  69         // find the cached array binding for this dimensionCount (if any)
 
  70         int length = localArrayBindings.length;
 
  71         for (int i = 0; i < length; i++)
 
  72                 if (localArrayBindings[i].dimensions == dimensionCount)
 
  73                         return localArrayBindings[i];
 
  76         System.arraycopy(localArrayBindings, 0, localArrayBindings = new ArrayBinding[length + 1], 0, length); 
 
  77         return localArrayBindings[length] = new ArrayBinding(this, dimensionCount);
 
  80 public char[] readableName() {
 
  81         if (isAnonymousType()) {
 
  82                 if (superInterfaces == NoSuperInterfaces)
 
  83                         return ("<"+Util.bind("binding.subclass",new String(superclass.readableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
 
  85                         return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].readableName())) + ">").toCharArray();                      //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
 
  86         } else if (isMemberType()) {
 
  87                 return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
 
  93 public char[] shortReadableName() {
 
  94         if (isAnonymousType()) {
 
  95                 if (superInterfaces == NoSuperInterfaces)
 
  96                         return ("<"+Util.bind("binding.subclass",new String(superclass.shortReadableName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
 
  98                         return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].shortReadableName())) + ">").toCharArray();                         //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
 
  99         } else if (isMemberType()) {
 
 100                 return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
 
 106 // Record that the type is a local member type
 
 107 public void setAsMemberType() {
 
 108         tagBits |= MemberTypeMask;
 
 111 public void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Object */ {
 
 112         this.constantPoolName = computedConstantPoolName;
 
 115 public char[] sourceName() {
 
 116         if (isAnonymousType()) {
 
 117                 //return readableName();
 
 118                 if (superInterfaces == NoSuperInterfaces)
 
 119                         return ("<"+Util.bind("binding.subclass",new String(superclass.sourceName())) + ">").toCharArray(); //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
 
 121                         return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].sourceName())) + ">").toCharArray();                        //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
 
 126 public String toString() {
 
 127         if (isAnonymousType())
 
 128                 return "Anonymous type : " + super.toString(); //$NON-NLS-1$
 
 130                 return "Local member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
 
 131         return "Local type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
 
 133 /* Trigger the dependency mechanism forcing the innerclass emulation
 
 134 * to be propagated to all dependent source types.
 
 137 public void updateInnerEmulationDependents() {
 
 138         if (dependents != null) {
 
 139                 for (int i = 0; i < dependents.length; i++) {
 
 140                         InnerEmulationDependency dependency = dependents[i];
 
 141                         // System.out.println("Updating " + new String(this.readableName()) + " --> " + new String(dependency.scope.enclosingType().readableName()));
 
 142                         dependency.scope.propagateInnerEmulation(this, dependency.wasEnclosingInstanceSupplied);