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.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(CharOperation.NO_CHAR_CHAR, 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 // always look for the name as a sub-package if its not a known type
169 if (packageBinding == null && (packageBinding = findPackage(name)) != null)
170 return packageBinding;
171 if (typeBinding == null) {
172 // if no package was found, find the type named name relative to the receiver
173 if ((typeBinding = environment.askForType(this, name)) != null) {
174 if (typeBinding.isNestedType())
175 return new ProblemReferenceBinding(name, InternalNameProvided);
179 // Since name could not be found, add problem bindings
180 // to the collections so it will be reported as an error next time.
181 addNotFoundPackage(name);
182 addNotFoundType(name);
184 if (packageBinding == LookupEnvironment.TheNotFoundPackage)
185 packageBinding = null;
186 if (typeBinding == LookupEnvironment.TheNotFoundType)
190 if (packageBinding != null)
191 return packageBinding;
195 public char[] readableName() /*java.lang*/ {
196 return CharOperation.concatWith(compoundName, '.');
198 public String toString() {
199 if (compoundName == CharOperation.NO_CHAR_CHAR)
200 return "The Default Package"; //$NON-NLS-1$
202 return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$