1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 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
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
12 
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
15 import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
16 
17 public class PackageBinding extends Binding implements TypeConstants {
18 	public char[][] compoundName;
19 	PackageBinding parent;
20 	public LookupEnvironment environment;
21 	HashtableOfType knownTypes;
22 	HashtableOfPackage knownPackages;
PackageBinding()23 protected PackageBinding() {
24 	// for creating problem package
25 }
PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment)26 public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) {
27 	this.compoundName = compoundName;
28 	this.parent = parent;
29 	this.environment = environment;
30 	this.knownTypes = null; // initialized if used... class counts can be very large 300-600
31 	this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
32 }
PackageBinding(char[] topLevelPackageName, LookupEnvironment environment)33 public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) {
34 	this(new char[][] {topLevelPackageName}, null, environment);
35 }
36 /* Create the default package.
37 */
38 
PackageBinding(LookupEnvironment environment)39 public PackageBinding(LookupEnvironment environment) {
40 	this(CharOperation.NO_CHAR_CHAR, null, environment);
41 }
addNotFoundPackage(char[] simpleName)42 private void addNotFoundPackage(char[] simpleName) {
43 	knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage);
44 }
addNotFoundType(char[] simpleName)45 private void addNotFoundType(char[] simpleName) {
46 	if (knownTypes == null)
47 		knownTypes = new HashtableOfType(25);
48 	knownTypes.put(simpleName, LookupEnvironment.TheNotFoundType);
49 }
addPackage(PackageBinding element)50 void addPackage(PackageBinding element) {
51 	knownPackages.put(element.compoundName[element.compoundName.length - 1], element);
52 }
addType(ReferenceBinding element)53 void addType(ReferenceBinding element) {
54 	if (knownTypes == null)
55 		knownTypes = new HashtableOfType(25);
56 	knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
57 }
58 /* API
59 * Answer the receiver's binding type from Binding.BindingID.
60 */
61 
bindingType()62 public final int bindingType() {
63 	return PACKAGE;
64 }
findPackage(char[] name)65 private PackageBinding findPackage(char[] name) {
66 	if (!environment.isPackage(this.compoundName, name))
67 		return null;
68 
69 	char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name);
70 	PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, environment);
71 	addPackage(subPackageBinding);
72 	return subPackageBinding;
73 }
74 /* Answer the subpackage named name; ask the oracle for the package if its not in the cache.
75 * Answer null if it could not be resolved.
76 *
77 * NOTE: This should only be used when we know there is NOT a type with the same name.
78 */
79 
getPackage(char[] name)80 PackageBinding getPackage(char[] name) {
81 	PackageBinding binding = getPackage0(name);
82 	if (binding != null) {
83 		if (binding == LookupEnvironment.TheNotFoundPackage)
84 			return null;
85 		else
86 			return binding;
87 	}
88 	if ((binding = findPackage(name)) != null)
89 		return binding;
90 
91 	// not found so remember a problem package binding in the cache for future lookups
92 	addNotFoundPackage(name);
93 	return null;
94 }
95 /* Answer the subpackage named name if it exists in the cache.
96 * Answer theNotFoundPackage if it could not be resolved the first time
97 * it was looked up, otherwise answer null.
98 *
99 * NOTE: Senders must convert theNotFoundPackage into a real problem
100 * package if its to returned.
101 */
102 
getPackage0(char[] name)103 PackageBinding getPackage0(char[] name) {
104 	return knownPackages.get(name);
105 }
106 /* Answer the type named name; ask the oracle for the type if its not in the cache.
107 * Answer a NotVisible problem type if the type is not visible from the invocationPackage.
108 * Answer null if it could not be resolved.
109 *
110 * NOTE: This should only be used by source types/scopes which know there is NOT a
111 * package with the same name.
112 */
113 
getType(char[] name)114 ReferenceBinding getType(char[] name) {
115 	ReferenceBinding typeBinding = getType0(name);
116 	if (typeBinding == null) {
117 		if ((typeBinding = environment.askForType(this, name)) == null) {
118 			// not found so remember a problem type binding in the cache for future lookups
119 			addNotFoundType(name);
120 			return null;
121 		}
122 	}
123 
124 	if (typeBinding == LookupEnvironment.TheNotFoundType)
125 		return null;
126 
127 	typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
128 	if (typeBinding.isNestedType())
129 		return new ProblemReferenceBinding(name, InternalNameProvided);
130 	return typeBinding;
131 }
132 /* Answer the type named name if it exists in the cache.
133 * Answer theNotFoundType if it could not be resolved the first time
134 * it was looked up, otherwise answer null.
135 *
136 * NOTE: Senders must convert theNotFoundType into a real problem
137 * reference type if its to returned.
138 */
139 
getType0(char[] name)140 ReferenceBinding getType0(char[] name) {
141 	if (knownTypes == null)
142 		return null;
143 	return knownTypes.get(name);
144 }
145 /* Answer the package or type named name; ask the oracle if it is not in the cache.
146 * Answer null if it could not be resolved.
147 *
148 * When collisions exist between a type name & a package name, answer the type.
149 * Treat the package as if it does not exist... a problem was already reported when the type was defined.
150 *
151 * NOTE: no visibility checks are performed.
152 * THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
153 */
154 
getTypeOrPackage(char[] name)155 public Binding getTypeOrPackage(char[] name) {
156 	ReferenceBinding typeBinding = getType0(name);
157 	if (typeBinding != null && typeBinding != LookupEnvironment.TheNotFoundType) {
158 		typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now
159 		if (typeBinding.isNestedType())
160 			return new ProblemReferenceBinding(name, InternalNameProvided);
161 		return typeBinding;
162 	}
163 
164 	PackageBinding packageBinding = getPackage0(name);
165 	if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage)
166 		return packageBinding;
167 
168 	if (typeBinding == null) { // have not looked for it before
169 		if ((typeBinding = environment.askForType(this, name)) != null) {
170 			if (typeBinding.isNestedType())
171 				return new ProblemReferenceBinding(name, InternalNameProvided);
172 			return typeBinding;
173 		}
174 
175 		// Since name could not be found, add a problem binding
176 		// to the collections so it will be reported as an error next time.
177 		addNotFoundType(name);
178 	}
179 
180 	if (packageBinding == null) { // have not looked for it before
181 		if ((packageBinding = findPackage(name)) != null)
182 			return packageBinding;
183 		addNotFoundPackage(name);
184 	}
185 
186 	return null;
187 }
readableName()188 public char[] readableName() /*java.lang*/ {
189 	return CharOperation.concatWith(compoundName, '.');
190 }
toString()191 public String toString() {
192 	if (compoundName == CharOperation.NO_CHAR_CHAR)
193 		return "The Default Package"; //$NON-NLS-1$
194 	else
195 		return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
196 }
197 }
198