first scanner /parser copied from the jdt java version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / PackageBinding.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
12
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;
16
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() {
24 }
25 public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) {
26         this.compoundName = compoundName;
27         this.parent = parent;
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
31 }
32 public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) {
33         this(new char[][] {topLevelPackageName}, null, environment);
34 }
35 /* Create the default package.
36 */
37
38 public PackageBinding(LookupEnvironment environment) {
39         this(NoCharChar, null, environment);
40 }
41 private void addNotFoundPackage(char[] simpleName) {
42         knownPackages.put(simpleName, environment.theNotFoundPackage);
43 }
44 private void addNotFoundType(char[] simpleName) {
45         if (knownTypes == null)
46                 knownTypes = new HashtableOfType(25);
47         knownTypes.put(simpleName, environment.theNotFoundType);
48 }
49 void addPackage(PackageBinding element) {
50         knownPackages.put(element.compoundName[element.compoundName.length - 1], element);
51 }
52 void addType(ReferenceBinding element) {
53         if (knownTypes == null)
54                 knownTypes = new HashtableOfType(25);
55         knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
56 }
57 /* API
58 * Answer the receiver's binding type from Binding.BindingID.
59 */
60
61 public final int bindingType() {
62         return PACKAGE;
63 }
64 private PackageBinding findPackage(char[] name) {
65         if (!environment.isPackage(this.compoundName, name))
66                 return null;
67
68         char[][] compoundName = CharOperation.arrayConcat(this.compoundName, name);
69         PackageBinding newPackageBinding = new PackageBinding(compoundName, this, environment);
70         addPackage(newPackageBinding);
71         return newPackageBinding;
72 }
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.
75 *
76 * NOTE: This should only be used when we know there is NOT a type with the same name.
77 */
78
79 PackageBinding getPackage(char[] name) {
80         PackageBinding binding = getPackage0(name);
81         if (binding != null) {
82                 if (binding == environment.theNotFoundPackage)
83                         return null;
84                 else
85                         return binding;
86         }
87         if ((binding = findPackage(name)) != null)
88                 return binding;
89
90         // not found so remember a problem package binding in the cache for future lookups
91         addNotFoundPackage(name);
92         return null;
93 }
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.
97 *
98 * NOTE: Senders must convert theNotFoundPackage into a real problem
99 * package if its to returned.
100 */
101
102 PackageBinding getPackage0(char[] name) {
103         return knownPackages.get(name);
104 }
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.
108 *
109 * NOTE: This should only be used by source types/scopes which know there is NOT a
110 * package with the same name.
111 */
112
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);
119                         return null;
120                 }
121         }
122
123         if (binding == environment.theNotFoundType)
124                 return null;
125         if (binding instanceof UnresolvedReferenceBinding)
126                 binding = ((UnresolvedReferenceBinding) binding).resolve(environment);
127         if (binding.isNestedType())
128                 return new ProblemReferenceBinding(name, InternalNameProvided);
129         return binding;
130 }
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.
134 *
135 * NOTE: Senders must convert theNotFoundType into a real problem
136 * reference type if its to returned.
137 */
138
139 ReferenceBinding getType0(char[] name) {
140         if (knownTypes == null)
141                 return null;
142         return knownTypes.get(name);
143 }
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.
146 *
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.
149 *
150 * NOTE: no visibility checks are performed.
151 * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
152 */
153
154 public Binding getTypeOrPackage(char[] name) {
155         PackageBinding packageBinding = getPackage0(name);
156         if (packageBinding != null && packageBinding != environment.theNotFoundPackage)
157                 return packageBinding;
158
159         ReferenceBinding typeBinding = getType0(name);
160         if (typeBinding != null && typeBinding != environment.theNotFoundType) {
161                 if (typeBinding instanceof UnresolvedReferenceBinding)
162                         typeBinding = ((UnresolvedReferenceBinding) typeBinding).resolve(environment);
163                 if (typeBinding.isNestedType())
164                         return new ProblemReferenceBinding(name, InternalNameProvided);
165                 return typeBinding;
166         }
167
168         if (typeBinding == null && packageBinding == null) {
169                 // find the package
170                 if ((packageBinding = findPackage(name)) != null)
171                         return packageBinding;
172
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);
177                         return typeBinding;
178                 }
179
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);
184         } else {
185                 if (packageBinding == environment.theNotFoundPackage)
186                         packageBinding = null;
187                 if (typeBinding == environment.theNotFoundType)
188                         typeBinding = null;
189         }
190
191         if (packageBinding != null)
192                 return packageBinding;
193         else
194                 return typeBinding;
195 }
196 public char[] readableName() /*java.lang*/ {
197         return CharOperation.concatWith(compoundName, '.');
198 }
199 public String toString() {
200         if (compoundName == NoCharChar)
201                 return "The Default Package"; //$NON-NLS-1$
202         else
203                 return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
204 }
205 }