/******************************************************************************* | |
* Copyright (c) 2000, 2004 IBM Corporation and others. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Common Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/cpl-v10.html | |
* | |
* Contributors: | |
* IBM Corporation - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.wst.jsdt.internal.compiler.lookup; | |
import org.eclipse.wst.jsdt.core.compiler.CharOperation; | |
import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfPackage; | |
import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfType; | |
public class PackageBinding extends Binding implements TypeConstants { | |
public char[][] compoundName; | |
PackageBinding parent; | |
public LookupEnvironment environment; | |
HashtableOfType knownTypes; | |
HashtableOfPackage knownPackages; | |
protected PackageBinding() { | |
// for creating problem package | |
} | |
public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) { | |
this.compoundName = compoundName; | |
this.parent = parent; | |
this.environment = environment; | |
this.knownTypes = null; // initialized if used... class counts can be very large 300-600 | |
this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3 | |
} | |
public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) { | |
this(new char[][] {topLevelPackageName}, null, environment); | |
} | |
/* Create the default package. | |
*/ | |
public PackageBinding(LookupEnvironment environment) { | |
this(CharOperation.NO_CHAR_CHAR, null, environment); | |
} | |
private void addNotFoundPackage(char[] simpleName) { | |
knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage); | |
} | |
private void addNotFoundType(char[] simpleName) { | |
if (knownTypes == null) | |
knownTypes = new HashtableOfType(25); | |
knownTypes.put(simpleName, LookupEnvironment.TheNotFoundType); | |
} | |
void addPackage(PackageBinding element) { | |
knownPackages.put(element.compoundName[element.compoundName.length - 1], element); | |
} | |
void addType(ReferenceBinding element) { | |
if (knownTypes == null) | |
knownTypes = new HashtableOfType(25); | |
knownTypes.put(element.compoundName[element.compoundName.length - 1], element); | |
} | |
/* API | |
* Answer the receiver's binding type from Binding.BindingID. | |
*/ | |
public final int bindingType() { | |
return PACKAGE; | |
} | |
private PackageBinding findPackage(char[] name) { | |
if (!environment.isPackage(this.compoundName, name)) | |
return null; | |
char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name); | |
PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, environment); | |
addPackage(subPackageBinding); | |
return subPackageBinding; | |
} | |
/* Answer the subpackage named name; ask the oracle for the package if its not in the cache. | |
* Answer null if it could not be resolved. | |
* | |
* NOTE: This should only be used when we know there is NOT a type with the same name. | |
*/ | |
PackageBinding getPackage(char[] name) { | |
PackageBinding binding = getPackage0(name); | |
if (binding != null) { | |
if (binding == LookupEnvironment.TheNotFoundPackage) | |
return null; | |
else | |
return binding; | |
} | |
if ((binding = findPackage(name)) != null) | |
return binding; | |
// not found so remember a problem package binding in the cache for future lookups | |
addNotFoundPackage(name); | |
return null; | |
} | |
/* Answer the subpackage named name if it exists in the cache. | |
* Answer theNotFoundPackage if it could not be resolved the first time | |
* it was looked up, otherwise answer null. | |
* | |
* NOTE: Senders must convert theNotFoundPackage into a real problem | |
* package if its to returned. | |
*/ | |
PackageBinding getPackage0(char[] name) { | |
return knownPackages.get(name); | |
} | |
/* Answer the type named name; ask the oracle for the type if its not in the cache. | |
* Answer a NotVisible problem type if the type is not visible from the invocationPackage. | |
* Answer null if it could not be resolved. | |
* | |
* NOTE: This should only be used by source types/scopes which know there is NOT a | |
* package with the same name. | |
*/ | |
ReferenceBinding getType(char[] name) { | |
ReferenceBinding typeBinding = getType0(name); | |
if (typeBinding == null) { | |
if ((typeBinding = environment.askForType(this, name)) == null) { | |
// not found so remember a problem type binding in the cache for future lookups | |
addNotFoundType(name); | |
return null; | |
} | |
} | |
if (typeBinding == LookupEnvironment.TheNotFoundType) | |
return null; | |
typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now | |
if (typeBinding.isNestedType()) | |
return new ProblemReferenceBinding(name, InternalNameProvided); | |
return typeBinding; | |
} | |
/* Answer the type named name if it exists in the cache. | |
* Answer theNotFoundType if it could not be resolved the first time | |
* it was looked up, otherwise answer null. | |
* | |
* NOTE: Senders must convert theNotFoundType into a real problem | |
* reference type if its to returned. | |
*/ | |
ReferenceBinding getType0(char[] name) { | |
if (knownTypes == null) | |
return null; | |
return knownTypes.get(name); | |
} | |
/* Answer the package or type named name; ask the oracle if it is not in the cache. | |
* Answer null if it could not be resolved. | |
* | |
* When collisions exist between a type name & a package name, answer the type. | |
* Treat the package as if it does not exist... a problem was already reported when the type was defined. | |
* | |
* NOTE: no visibility checks are performed. | |
* THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES. | |
*/ | |
public Binding getTypeOrPackage(char[] name) { | |
ReferenceBinding typeBinding = getType0(name); | |
if (typeBinding != null && typeBinding != LookupEnvironment.TheNotFoundType) { | |
typeBinding = BinaryTypeBinding.resolveType(typeBinding, environment, false); // no raw conversion for now | |
if (typeBinding.isNestedType()) | |
return new ProblemReferenceBinding(name, InternalNameProvided); | |
return typeBinding; | |
} | |
PackageBinding packageBinding = getPackage0(name); | |
if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage) | |
return packageBinding; | |
if (typeBinding == null) { // have not looked for it before | |
if ((typeBinding = environment.askForType(this, name)) != null) { | |
if (typeBinding.isNestedType()) | |
return new ProblemReferenceBinding(name, InternalNameProvided); | |
return typeBinding; | |
} | |
// Since name could not be found, add a problem binding | |
// to the collections so it will be reported as an error next time. | |
addNotFoundType(name); | |
} | |
if (packageBinding == null) { // have not looked for it before | |
if ((packageBinding = findPackage(name)) != null) | |
return packageBinding; | |
addNotFoundPackage(name); | |
} | |
return null; | |
} | |
public char[] readableName() /*java.lang*/ { | |
return CharOperation.concatWith(compoundName, '.'); | |
} | |
public String toString() { | |
if (compoundName == CharOperation.NO_CHAR_CHAR) | |
return "The Default Package"; //$NON-NLS-1$ | |
else | |
return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$ | |
} | |
} |