001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.lookup;
011:
012: import org.eclipse.jdt.core.compiler.CharOperation;
013: import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
014: import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
015:
016: public class PackageBinding extends Binding implements TypeConstants {
017: public long tagBits = 0; // See values in the interface TagBits below
018:
019: public char[][] compoundName;
020: PackageBinding parent;
021: public LookupEnvironment environment;
022: HashtableOfType knownTypes;
023: HashtableOfPackage knownPackages;
024:
025: protected PackageBinding() {
026: // for creating problem package
027: }
028:
029: public PackageBinding(char[][] compoundName, PackageBinding parent,
030: LookupEnvironment environment) {
031: this .compoundName = compoundName;
032: this .parent = parent;
033: this .environment = environment;
034: this .knownTypes = null; // initialized if used... class counts can be very large 300-600
035: this .knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
036: }
037:
038: public PackageBinding(char[] topLevelPackageName,
039: LookupEnvironment environment) {
040: this (new char[][] { topLevelPackageName }, null, environment);
041: }
042:
043: /* Create the default package.
044: */
045:
046: public PackageBinding(LookupEnvironment environment) {
047: this (CharOperation.NO_CHAR_CHAR, null, environment);
048: }
049:
050: private void addNotFoundPackage(char[] simpleName) {
051: knownPackages.put(simpleName,
052: LookupEnvironment.TheNotFoundPackage);
053: }
054:
055: private void addNotFoundType(char[] simpleName) {
056: if (knownTypes == null)
057: knownTypes = new HashtableOfType(25);
058: knownTypes.put(simpleName, LookupEnvironment.TheNotFoundType);
059: }
060:
061: void addPackage(PackageBinding element) {
062: knownPackages.put(
063: element.compoundName[element.compoundName.length - 1],
064: element);
065: }
066:
067: void addType(ReferenceBinding element) {
068: if (knownTypes == null)
069: knownTypes = new HashtableOfType(25);
070: knownTypes.put(
071: element.compoundName[element.compoundName.length - 1],
072: element);
073: }
074:
075: /* API
076: * Answer the receiver's binding type from Binding.BindingID.
077: */
078:
079: public final int kind() {
080: return Binding.PACKAGE;
081: }
082:
083: /*
084: * slash separated name
085: * org.eclipse.jdt.core --> org/eclipse/jdt/core
086: */
087: public char[] computeUniqueKey(boolean isLeaf) {
088: return CharOperation.concatWith(compoundName, '/');
089: }
090:
091: private PackageBinding findPackage(char[] name) {
092: if (!environment.isPackage(this .compoundName, name))
093: return null;
094:
095: char[][] subPkgCompoundName = CharOperation.arrayConcat(
096: this .compoundName, name);
097: PackageBinding subPackageBinding = new PackageBinding(
098: subPkgCompoundName, this , environment);
099: addPackage(subPackageBinding);
100: return subPackageBinding;
101: }
102:
103: /* Answer the subpackage named name; ask the oracle for the package if its not in the cache.
104: * Answer null if it could not be resolved.
105: *
106: * NOTE: This should only be used when we know there is NOT a type with the same name.
107: */
108:
109: PackageBinding getPackage(char[] name) {
110: PackageBinding binding = getPackage0(name);
111: if (binding != null) {
112: if (binding == LookupEnvironment.TheNotFoundPackage)
113: return null;
114: else
115: return binding;
116: }
117: if ((binding = findPackage(name)) != null)
118: return binding;
119:
120: // not found so remember a problem package binding in the cache for future lookups
121: addNotFoundPackage(name);
122: return null;
123: }
124:
125: /* Answer the subpackage named name if it exists in the cache.
126: * Answer theNotFoundPackage if it could not be resolved the first time
127: * it was looked up, otherwise answer null.
128: *
129: * NOTE: Senders must convert theNotFoundPackage into a real problem
130: * package if its to returned.
131: */
132:
133: PackageBinding getPackage0(char[] name) {
134: return knownPackages.get(name);
135: }
136:
137: /* Answer the type named name; ask the oracle for the type if its not in the cache.
138: * Answer a NotVisible problem type if the type is not visible from the invocationPackage.
139: * Answer null if it could not be resolved.
140: *
141: * NOTE: This should only be used by source types/scopes which know there is NOT a
142: * package with the same name.
143: */
144:
145: ReferenceBinding getType(char[] name) {
146: ReferenceBinding typeBinding = getType0(name);
147: if (typeBinding == null) {
148: if ((typeBinding = environment.askForType(this , name)) == null) {
149: // not found so remember a problem type binding in the cache for future lookups
150: addNotFoundType(name);
151: return null;
152: }
153: }
154:
155: if (typeBinding == LookupEnvironment.TheNotFoundType)
156: return null;
157:
158: typeBinding = BinaryTypeBinding.resolveType(typeBinding,
159: environment, false); // no raw conversion for now
160: if (typeBinding.isNestedType())
161: return new ProblemReferenceBinding(name, typeBinding,
162: ProblemReasons.InternalNameProvided);
163: return typeBinding;
164: }
165:
166: /* Answer the type named name if it exists in the cache.
167: * Answer theNotFoundType if it could not be resolved the first time
168: * it was looked up, otherwise answer null.
169: *
170: * NOTE: Senders must convert theNotFoundType into a real problem
171: * reference type if its to returned.
172: */
173:
174: ReferenceBinding getType0(char[] name) {
175: if (knownTypes == null)
176: return null;
177: return knownTypes.get(name);
178: }
179:
180: /* Answer the package or type named name; ask the oracle if it is not in the cache.
181: * Answer null if it could not be resolved.
182: *
183: * When collisions exist between a type name & a package name, answer the type.
184: * Treat the package as if it does not exist... a problem was already reported when the type was defined.
185: *
186: * NOTE: no visibility checks are performed.
187: * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
188: */
189:
190: public Binding getTypeOrPackage(char[] name) {
191: ReferenceBinding typeBinding = getType0(name);
192: if (typeBinding != null
193: && typeBinding != LookupEnvironment.TheNotFoundType) {
194: typeBinding = BinaryTypeBinding.resolveType(typeBinding,
195: environment, false); // no raw conversion for now
196: if (typeBinding.isNestedType())
197: return new ProblemReferenceBinding(name, typeBinding,
198: ProblemReasons.InternalNameProvided);
199: return typeBinding;
200: }
201:
202: PackageBinding packageBinding = getPackage0(name);
203: if (packageBinding != null
204: && packageBinding != LookupEnvironment.TheNotFoundPackage)
205: return packageBinding;
206:
207: if (typeBinding == null) { // have not looked for it before
208: if ((typeBinding = environment.askForType(this , name)) != null) {
209: if (typeBinding.isNestedType())
210: return new ProblemReferenceBinding(name,
211: typeBinding,
212: ProblemReasons.InternalNameProvided);
213: return typeBinding;
214: }
215:
216: // Since name could not be found, add a problem binding
217: // to the collections so it will be reported as an error next time.
218: addNotFoundType(name);
219: }
220:
221: if (packageBinding == null) { // have not looked for it before
222: if ((packageBinding = findPackage(name)) != null)
223: return packageBinding;
224: addNotFoundPackage(name);
225: }
226:
227: return null;
228: }
229:
230: public char[] readableName() /*java.lang*/{
231: return CharOperation.concatWith(compoundName, '.');
232: }
233:
234: public String toString() {
235: if (compoundName == CharOperation.NO_CHAR_CHAR)
236: return "The Default Package"; //$NON-NLS-1$
237: else
238: return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
239: }
240: }
|