1 /*******************************************************************************
 
   2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
 
   3  * All rights reserved. This program and the accompanying materials 
 
   4  * are made available under the terms of the Common Public License v0.5 
 
   5  * which accompanies this distribution, and is available at
 
   6  * http://www.eclipse.org/legal/cpl-v05.html
 
   9  *     IBM Corporation - initial API and implementation
 
  10  ******************************************************************************/
 
  11 package net.sourceforge.phpdt.internal.compiler.lookup;
 
  13 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
 
  14 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfPackage;
 
  15 import net.sourceforge.phpdt.internal.compiler.util.HashtableOfType;
 
  17 public class PackageBinding extends Binding implements TypeConstants {
 
  18         public char[][] compoundName;
 
  19         PackageBinding parent;
 
  20         LookupEnvironment environment;
 
  21         HashtableOfType knownTypes;
 
  22         HashtableOfPackage knownPackages;
 
  23 protected PackageBinding() {
 
  25 public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) {
 
  26         this.compoundName = compoundName;
 
  28         this.environment = environment;
 
  29         this.knownTypes = null; // initialized if used... class counts can be very large 300-600
 
  30         this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
 
  32 public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) {
 
  33         this(new char[][] {topLevelPackageName}, null, environment);
 
  35 /* Create the default package.
 
  38 public PackageBinding(LookupEnvironment environment) {
 
  39         this(NoCharChar, null, environment);
 
  41 private void addNotFoundPackage(char[] simpleName) {
 
  42         knownPackages.put(simpleName, LookupEnvironment.theNotFoundPackage);
 
  44 private void addNotFoundType(char[] simpleName) {
 
  45         if (knownTypes == null)
 
  46                 knownTypes = new HashtableOfType(25);
 
  47         knownTypes.put(simpleName, LookupEnvironment.theNotFoundType);
 
  49 void addPackage(PackageBinding element) {
 
  50         knownPackages.put(element.compoundName[element.compoundName.length - 1], element);
 
  52 void addType(ReferenceBinding element) {
 
  53         if (knownTypes == null)
 
  54                 knownTypes = new HashtableOfType(25);
 
  55         knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
 
  58 * Answer the receiver's binding type from Binding.BindingID.
 
  61 public final int bindingType() {
 
  64 private PackageBinding findPackage(char[] name) {
 
  65         if (!environment.isPackage(this.compoundName, name))
 
  68         char[][] compoundName = CharOperation.arrayConcat(this.compoundName, name);
 
  69         PackageBinding newPackageBinding = new PackageBinding(compoundName, this, environment);
 
  70         addPackage(newPackageBinding);
 
  71         return newPackageBinding;
 
  73 /* Answer the subpackage named name; ask the oracle for the package if its not in the cache.
 
  74 * Answer null if it could not be resolved.
 
  76 * NOTE: This should only be used when we know there is NOT a type with the same name.
 
  79 PackageBinding getPackage(char[] name) {
 
  80         PackageBinding binding = getPackage0(name);
 
  81         if (binding != null) {
 
  82                 if (binding == LookupEnvironment.theNotFoundPackage)
 
  87         if ((binding = findPackage(name)) != null)
 
  90         // not found so remember a problem package binding in the cache for future lookups
 
  91         addNotFoundPackage(name);
 
  94 /* Answer the subpackage named name if it exists in the cache.
 
  95 * Answer theNotFoundPackage if it could not be resolved the first time
 
  96 * it was looked up, otherwise answer null.
 
  98 * NOTE: Senders must convert theNotFoundPackage into a real problem
 
  99 * package if its to returned.
 
 102 PackageBinding getPackage0(char[] name) {
 
 103         return knownPackages.get(name);
 
 105 /* Answer the type named name; ask the oracle for the type if its not in the cache.
 
 106 * Answer a NotVisible problem type if the type is not visible from the invocationPackage.
 
 107 * Answer null if it could not be resolved.
 
 109 * NOTE: This should only be used by source types/scopes which know there is NOT a
 
 110 * package with the same name.
 
 113 ReferenceBinding getType(char[] name) {
 
 114         ReferenceBinding binding = getType0(name);
 
 115         if (binding == null) {
 
 116                 if ((binding = environment.askForType(this, name)) == null) {
 
 117                         // not found so remember a problem type binding in the cache for future lookups
 
 118                         addNotFoundType(name);
 
 123         if (binding == LookupEnvironment.theNotFoundType)
 
 125         if (binding instanceof UnresolvedReferenceBinding)
 
 126                 binding = ((UnresolvedReferenceBinding) binding).resolve(environment);
 
 127         if (binding.isNestedType())
 
 128                 return new ProblemReferenceBinding(name, InternalNameProvided);
 
 131 /* Answer the type named name if it exists in the cache.
 
 132 * Answer theNotFoundType if it could not be resolved the first time
 
 133 * it was looked up, otherwise answer null.
 
 135 * NOTE: Senders must convert theNotFoundType into a real problem
 
 136 * reference type if its to returned.
 
 139 ReferenceBinding getType0(char[] name) {
 
 140         if (knownTypes == null)
 
 142         return knownTypes.get(name);
 
 144 /* Answer the package or type named name; ask the oracle if it is not in the cache.
 
 145 * Answer null if it could not be resolved.
 
 147 * When collisions exist between a type name & a package name, answer the package.
 
 148 * Treat the type as if it does not exist... a problem was already reported when the type was defined.
 
 150 * NOTE: no visibility checks are performed.
 
 151 * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
 
 154 public Binding getTypeOrPackage(char[] name) {
 
 155         PackageBinding packageBinding = getPackage0(name);
 
 156         if (packageBinding != null && packageBinding != LookupEnvironment.theNotFoundPackage)
 
 157                 return packageBinding;
 
 159         ReferenceBinding typeBinding = getType0(name);
 
 160         if (typeBinding != null && typeBinding != LookupEnvironment.theNotFoundType) {
 
 161                 if (typeBinding instanceof UnresolvedReferenceBinding)
 
 162                         typeBinding = ((UnresolvedReferenceBinding) typeBinding).resolve(environment);
 
 163                 if (typeBinding.isNestedType())
 
 164                         return new ProblemReferenceBinding(name, InternalNameProvided);
 
 168         if (typeBinding == null && packageBinding == null) {
 
 170                 if ((packageBinding = findPackage(name)) != null)
 
 171                         return packageBinding;
 
 173                 // if no package was found, find the type named name relative to the receiver
 
 174                 if ((typeBinding = environment.askForType(this, name)) != null) {
 
 175                         if (typeBinding.isNestedType())
 
 176                                 return new ProblemReferenceBinding(name, InternalNameProvided);
 
 180                 // Since name could not be found, add problem bindings
 
 181                 // to the collections so it will be reported as an error next time.
 
 182                 addNotFoundPackage(name);
 
 183                 addNotFoundType(name);
 
 185                 if (packageBinding == LookupEnvironment.theNotFoundPackage)
 
 186                         packageBinding = null;
 
 187                 if (typeBinding == LookupEnvironment.theNotFoundType)
 
 191         if (packageBinding != null)
 
 192                 return packageBinding;
 
 196 public char[] readableName() /*java.lang*/ {
 
 197         return CharOperation.concatWith(compoundName, '.');
 
 199 public String toString() {
 
 200         if (compoundName == NoCharChar)
 
 201                 return "The Default Package"; //$NON-NLS-1$
 
 203                 return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$