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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
13 import java.util.HashMap;
16 import org.eclipse.jdt.core.compiler.CharOperation;
17 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
18 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
19 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
20 import org.eclipse.jdt.internal.compiler.env.*;
21 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
22 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
23 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
24 import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
25 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
27 public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants {
28 final static int BUILD_FIELDS_AND_METHODS = 4;
29 final static int BUILD_TYPE_HIERARCHY = 1;
30 final static int CHECK_AND_SET_IMPORTS = 2;
31 final static int CONNECT_TYPE_HIERARCHY = 3;
32 static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
33 static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR, NotFound);
36 * Map from typeBinding -> accessRestriction rule
38 private Map accessRestrictions;
39 ImportBinding[] defaultImports;
41 PackageBinding defaultPackage;
42 HashtableOfPackage knownPackages;
43 private int lastCompletedUnitIndex = -1;
44 private int lastUnitIndex = -1;
46 public INameEnvironment nameEnvironment;
47 public CompilerOptions options;
48 public ProblemReporter problemReporter;
50 // shared byte[]'s used by ClassFile to avoid allocating MBs during a build
51 public boolean sharedArraysUsed = true; // set to false once actual arrays are allocated
52 public byte[] sharedClassFileContents = null;
53 public byte[] sharedClassFileHeader = null;
55 // indicate in which step on the compilation we are.
56 // step 1 : build the reference binding
57 // step 2 : conect the hierarchy (connect bindings)
58 // step 3 : build fields and method bindings.
59 private int stepCompleted;
60 public ITypeRequestor typeRequestor;
61 private ArrayBinding[][] uniqueArrayBindings;
62 private SimpleLookupTable uniqueParameterizedTypeBindings;
63 private SimpleLookupTable uniqueRawTypeBindings;
64 private SimpleLookupTable uniqueWildcardBindings;
66 public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
68 private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
69 private MethodVerifier verifier;
71 public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
72 this.typeRequestor = typeRequestor;
73 this.options = options;
74 this.problemReporter = problemReporter;
75 this.defaultPackage = new PackageBinding(this); // assume the default package always exists
76 this.defaultImports = null;
77 this.nameEnvironment = nameEnvironment;
78 this.knownPackages = new HashtableOfPackage();
79 this.uniqueArrayBindings = new ArrayBinding[5][];
80 this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
81 this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
82 this.uniqueRawTypeBindings = new SimpleLookupTable(3);
83 this.uniqueWildcardBindings = new SimpleLookupTable(3);
84 this.accessRestrictions = new HashMap(3);
88 * Ask the name environment for a type which corresponds to the compoundName.
89 * Answer null if the name cannot be found.
92 public ReferenceBinding askForType(char[][] compoundName) {
93 NameEnvironmentAnswer answer = nameEnvironment.findType(compoundName);
97 if (answer.isBinaryType())
98 // the type was found as a .class file
99 typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName), answer.getAccessRestriction());
100 else if (answer.isCompilationUnit())
101 // the type was found as a .java file, try to build it then search the cache
102 typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
103 else if (answer.isSourceType())
104 // the type was found as a source model
105 typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName), answer.getAccessRestriction());
107 return getCachedType(compoundName);
109 /* Ask the oracle for a type named name in the packageBinding.
110 * Answer null if the name cannot be found.
113 ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
114 if (packageBinding == null) {
115 if (defaultPackage == null)
117 packageBinding = defaultPackage;
119 NameEnvironmentAnswer answer = nameEnvironment.findType(name, packageBinding.compoundName);
123 if (answer.isBinaryType())
124 // the type was found as a .class file
125 typeRequestor.accept(answer.getBinaryType(), packageBinding, answer.getAccessRestriction());
126 else if (answer.isCompilationUnit())
127 // the type was found as a .java file, try to build it then search the cache
128 typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
129 else if (answer.isSourceType())
130 // the type was found as a source model
131 typeRequestor.accept(answer.getSourceTypes(), packageBinding, answer.getAccessRestriction());
133 return packageBinding.getType0(name);
135 /* Create the initial type bindings for the compilation unit.
137 * See completeTypeBindings() for a description of the remaining steps
139 * NOTE: This method can be called multiple times as additional source files are needed
142 public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
143 CompilationUnitScope scope = new CompilationUnitScope(unit, this);
144 scope.buildTypeBindings(accessRestriction);
146 int unitsLength = units.length;
147 if (++lastUnitIndex >= unitsLength)
148 System.arraycopy(units, 0, units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength);
149 units[lastUnitIndex] = unit;
151 /* Cache the binary type since we know it is needed during this compile.
153 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
156 public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, AccessRestriction accessRestriction) {
157 return cacheBinaryType(binaryType, true, accessRestriction);
159 /* Cache the binary type since we know it is needed during this compile.
161 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
164 public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
165 char[][] compoundName = CharOperation.splitOn('/', binaryType.getName());
166 ReferenceBinding existingType = getCachedType(compoundName);
168 if (existingType == null || existingType instanceof UnresolvedReferenceBinding)
169 // only add the binary type if its not already in the cache
170 return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName), needFieldsAndMethods, accessRestriction);
171 return null; // the type already exists & can be retrieved from the cache
174 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
175 * 2. Create the field bindings
176 * 3. Create the method bindings
179 /* We know each known compilationUnit is free of errors at this point...
181 * Each step will create additional bindings unless a problem is detected, in which
182 * case either the faulty import/superinterface/field/method will be skipped or a
183 * suitable replacement will be substituted (such as Object for a missing superclass)
186 public void completeTypeBindings() {
187 stepCompleted = BUILD_TYPE_HIERARCHY;
189 for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
190 (this.unitBeingCompleted = this.units[i]).scope.checkAndSetImports();
192 stepCompleted = CHECK_AND_SET_IMPORTS;
194 for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
195 (this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy();
197 stepCompleted = CONNECT_TYPE_HIERARCHY;
199 for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
200 (this.unitBeingCompleted = this.units[i]).scope.buildFieldsAndMethods();
201 this.units[i] = null; // release unnecessary reference to the parsed unit
203 stepCompleted = BUILD_FIELDS_AND_METHODS;
204 this.lastCompletedUnitIndex = this.lastUnitIndex;
205 this.unitBeingCompleted = null;
208 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
209 * 2. Create the field bindings
210 * 3. Create the method bindings
214 * Each step will create additional bindings unless a problem is detected, in which
215 * case either the faulty import/superinterface/field/method will be skipped or a
216 * suitable replacement will be substituted (such as Object for a missing superclass)
219 public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) {
220 if (stepCompleted == BUILD_FIELDS_AND_METHODS) {
221 // This can only happen because the original set of units are completely built and
222 // are now being processed, so we want to treat all the additional units as a group
223 // until they too are completely processed.
224 completeTypeBindings();
226 if (parsedUnit.scope == null) return; // parsing errors were too severe
228 if (stepCompleted >= CHECK_AND_SET_IMPORTS)
229 (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
231 if (stepCompleted >= CONNECT_TYPE_HIERARCHY)
232 (this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy();
234 this.unitBeingCompleted = null;
238 * Used by other compiler tools which do not start by calling completeTypeBindings().
240 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
241 * 2. Create the field bindings
242 * 3. Create the method bindings
245 public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) {
246 if (parsedUnit.scope == null) return; // parsing errors were too severe
248 (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
249 parsedUnit.scope.connectTypeHierarchy();
250 if (buildFieldsAndMethods)
251 parsedUnit.scope.buildFieldsAndMethods();
252 this.unitBeingCompleted = null;
254 public TypeBinding computeBoxingType(TypeBinding type) {
255 TypeBinding boxedType;
257 case TypeIds.T_JavaLangBoolean :
258 return BooleanBinding;
259 case TypeIds.T_JavaLangByte :
261 case TypeIds.T_JavaLangCharacter :
263 case TypeIds.T_JavaLangShort :
265 case TypeIds.T_JavaLangDouble :
266 return DoubleBinding;
267 case TypeIds.T_JavaLangFloat :
269 case TypeIds.T_JavaLangInteger :
271 case TypeIds.T_JavaLangLong :
273 case TypeIds.T_JavaLangVoid :
277 boxedType = getType(JAVA_LANG_INTEGER);
278 if (boxedType != null) return boxedType;
279 return new ProblemReferenceBinding( JAVA_LANG_INTEGER, NotFound);
280 case TypeIds.T_byte :
281 boxedType = getType(JAVA_LANG_BYTE);
282 if (boxedType != null) return boxedType;
283 return new ProblemReferenceBinding( JAVA_LANG_BYTE, NotFound);
284 case TypeIds.T_short :
285 boxedType = getType(JAVA_LANG_SHORT);
286 if (boxedType != null) return boxedType;
287 return new ProblemReferenceBinding( JAVA_LANG_SHORT, NotFound);
288 case TypeIds.T_char :
289 boxedType = getType(JAVA_LANG_CHARACTER);
290 if (boxedType != null) return boxedType;
291 return new ProblemReferenceBinding( JAVA_LANG_CHARACTER, NotFound);
292 case TypeIds.T_long :
293 boxedType = getType(JAVA_LANG_LONG);
294 if (boxedType != null) return boxedType;
295 return new ProblemReferenceBinding( JAVA_LANG_LONG, NotFound);
296 case TypeIds.T_float :
297 boxedType = getType(JAVA_LANG_FLOAT);
298 if (boxedType != null) return boxedType;
299 return new ProblemReferenceBinding( JAVA_LANG_FLOAT, NotFound);
300 case TypeIds.T_double :
301 boxedType = getType(JAVA_LANG_DOUBLE);
302 if (boxedType != null) return boxedType;
303 return new ProblemReferenceBinding( JAVA_LANG_DOUBLE, NotFound);
304 case TypeIds.T_boolean :
305 boxedType = getType(JAVA_LANG_BOOLEAN);
306 if (boxedType != null) return boxedType;
307 return new ProblemReferenceBinding( JAVA_LANG_BOOLEAN, NotFound);
308 case TypeIds.T_void :
309 boxedType = getType(JAVA_LANG_VOID);
310 if (boxedType != null) return boxedType;
311 return new ProblemReferenceBinding( JAVA_LANG_VOID, NotFound);
315 private PackageBinding computePackageFrom(char[][] constantPoolName) {
316 if (constantPoolName.length == 1)
317 return defaultPackage;
319 PackageBinding packageBinding = getPackage0(constantPoolName[0]);
320 if (packageBinding == null || packageBinding == TheNotFoundPackage) {
321 packageBinding = new PackageBinding(constantPoolName[0], this);
322 knownPackages.put(constantPoolName[0], packageBinding);
325 for (int i = 1, length = constantPoolName.length - 1; i < length; i++) {
326 PackageBinding parent = packageBinding;
327 if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) {
328 packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this);
329 parent.addPackage(packageBinding);
332 return packageBinding;
335 /* Used to guarantee array type identity.
337 public ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
338 if (type instanceof LocalTypeBinding) // cache local type arrays with the local type itself
339 return ((LocalTypeBinding) type).createArrayType(dimensionCount);
341 // find the array binding cache for this dimension
342 int dimIndex = dimensionCount - 1;
343 int length = uniqueArrayBindings.length;
344 ArrayBinding[] arrayBindings;
345 if (dimIndex < length) {
346 if ((arrayBindings = uniqueArrayBindings[dimIndex]) == null)
347 uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
350 uniqueArrayBindings, 0,
351 uniqueArrayBindings = new ArrayBinding[dimensionCount][], 0,
353 uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
356 // find the cached array binding for this leaf component type (if any)
358 length = arrayBindings.length;
359 while (++index < length) {
360 ArrayBinding currentBinding = arrayBindings[index];
361 if (currentBinding == null) // no matching array, but space left
362 return arrayBindings[index] = new ArrayBinding(type, dimensionCount, this);
363 if (currentBinding.leafComponentType == type)
364 return currentBinding;
367 // no matching array, no space left
370 (arrayBindings = new ArrayBinding[length * 2]), 0,
372 uniqueArrayBindings[dimIndex] = arrayBindings;
373 return arrayBindings[length] = new ArrayBinding(type, dimensionCount, this);
375 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
376 return createBinaryTypeFrom(binaryType, packageBinding, true, accessRestriction);
378 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
379 BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this);
381 // resolve any array bindings which reference the unresolvedType
382 ReferenceBinding cachedType = packageBinding.getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]);
383 if (cachedType != null) { // update reference to unresolved binding after having read classfile (knows whether generic for raw conversion)
384 // TODO (kent) suspect the check below is no longer required, since we should not be requesting a binary which is already in the cache
385 if (cachedType.isBinaryBinding()) // sanity check before the cast... at this point the cache should ONLY contain unresolved types
386 return (BinaryTypeBinding) cachedType;
388 ((UnresolvedReferenceBinding) cachedType).setResolvedType(binaryBinding, this);
391 packageBinding.addType(binaryBinding);
392 setAccessRestriction(binaryBinding, accessRestriction);
393 binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
394 return binaryBinding;
396 /* Used to create packages from the package statement.
399 PackageBinding createPackage(char[][] compoundName) {
400 PackageBinding packageBinding = getPackage0(compoundName[0]);
401 if (packageBinding == null || packageBinding == TheNotFoundPackage) {
402 packageBinding = new PackageBinding(compoundName[0], this);
403 knownPackages.put(compoundName[0], packageBinding);
406 for (int i = 1, length = compoundName.length; i < length; i++) {
407 // check to see if it collides with a known type...
408 // this case can only happen if the package does not exist as a directory in the file system
409 // otherwise when the source type was defined, the correct error would have been reported
410 // unless its an unresolved type which is referenced from an inconsistent class file
411 ReferenceBinding type = packageBinding.getType0(compoundName[i]);
412 if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding))
415 PackageBinding parent = packageBinding;
416 if ((packageBinding = parent.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) {
417 // if the package is unknown, check to see if a type exists which would collide with the new package
418 // catches the case of a package statement of: package java.lang.Object;
419 // since the package can be added after a set of source files have already been compiled, we need
420 // whenever a package statement is encountered
421 if (nameEnvironment.findType(compoundName[i], parent.compoundName) != null)
424 packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this);
425 parent.addPackage(packageBinding);
428 return packageBinding;
431 public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] originalArguments, ReferenceBinding enclosingType) {
433 // relocalize wildcard onto genericType (could come from other types)
434 TypeBinding[] typeArguments = originalArguments;
435 for (int i = 0, length = typeArguments == null ? 0 : typeArguments.length; i < length; i++) {
436 TypeBinding argument = originalArguments[i];
437 if (argument.isWildcard()) {
438 WildcardBinding wildcard = (WildcardBinding) argument;
439 if (wildcard.genericType != genericType) { // wildcard comes from different type
440 if (typeArguments == originalArguments) {
441 System.arraycopy(originalArguments, 0, typeArguments = new TypeBinding[length], 0, i);
443 typeArguments[i] = createWildcard(genericType, i, wildcard.bound, wildcard.kind);
444 } else if (typeArguments != originalArguments) {
445 typeArguments[i] = argument;
447 } else if (typeArguments != originalArguments) {
448 typeArguments[i] = argument;
452 // cached info is array of already created parameterized types for this type
453 ParameterizedTypeBinding[] cachedInfo = (ParameterizedTypeBinding[])this.uniqueParameterizedTypeBindings.get(genericType);
454 int argLength = typeArguments == null ? 0: typeArguments.length;
455 boolean needToGrow = false;
456 if (cachedInfo != null){
458 // iterate existing parameterized for reusing one with same type arguments if any
459 for (int i = 0, max = cachedInfo.length; i < max; i++){
460 ParameterizedTypeBinding cachedType = cachedInfo[i];
461 if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
462 if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
463 TypeBinding[] cachedArguments = cachedType.arguments;
464 int cachedArgLength = cachedArguments == null ? 0 : cachedArguments.length;
465 if (argLength != cachedArgLength) continue nextCachedType; // would be an error situation (from unresolved binaries)
466 for (int j = 0; j < cachedArgLength; j++){
467 if (typeArguments[j] != cachedArguments[j]) continue nextCachedType;
469 // all arguments match, reuse current
474 cachedInfo = new ParameterizedTypeBinding[1];
475 this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
479 int length = cachedInfo.length;
480 System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedTypeBinding[length+1], 0, length);
481 this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
484 ParameterizedTypeBinding parameterizedType = new ParameterizedTypeBinding(genericType,typeArguments, enclosingType, this);
485 cachedInfo[cachedInfo.length-1] = parameterizedType;
486 return parameterizedType;
489 public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
490 // cached info is array of already created raw types for this type
491 RawTypeBinding[] cachedInfo = (RawTypeBinding[])this.uniqueRawTypeBindings.get(genericType);
492 boolean needToGrow = false;
493 if (cachedInfo != null){
495 // iterate existing parameterized for reusing one with same type arguments if any
496 for (int i = 0, max = cachedInfo.length; i < max; i++){
497 RawTypeBinding cachedType = cachedInfo[i];
498 if (cachedType.type != genericType) continue nextCachedType; // remain of unresolved type
499 if (cachedType.enclosingType() != enclosingType) continue nextCachedType;
500 // all enclosing type match, reuse current
505 cachedInfo = new RawTypeBinding[1];
506 this.uniqueRawTypeBindings.put(genericType, cachedInfo);
510 int length = cachedInfo.length;
511 System.arraycopy(cachedInfo, 0, cachedInfo = new RawTypeBinding[length+1], 0, length);
512 this.uniqueRawTypeBindings.put(genericType, cachedInfo);
515 RawTypeBinding rawType = new RawTypeBinding(genericType, enclosingType, this);
516 cachedInfo[cachedInfo.length-1] = rawType;
521 public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, int kind) {
523 // cached info is array of already created wildcard types for this type
524 WildcardBinding[] cachedInfo = (WildcardBinding[])this.uniqueWildcardBindings.get(genericType);
525 boolean needToGrow = false;
526 if (cachedInfo != null){
528 // iterate existing wildcards for reusing one with same information if any
529 for (int i = 0, max = cachedInfo.length; i < max; i++){
530 WildcardBinding cachedType = cachedInfo[i];
531 if (cachedType.genericType != genericType) continue nextCachedType; // remain of unresolved type
532 if (cachedType.rank != rank) continue nextCachedType;
533 if (cachedType.kind != kind) continue nextCachedType;
534 if (cachedType.bound != bound) continue nextCachedType;
535 // all match, reuse current
540 cachedInfo = new WildcardBinding[1];
541 this.uniqueWildcardBindings.put(genericType, cachedInfo);
545 int length = cachedInfo.length;
546 System.arraycopy(cachedInfo, 0, cachedInfo = new WildcardBinding[length+1], 0, length);
547 this.uniqueWildcardBindings.put(genericType, cachedInfo);
550 WildcardBinding wildcard = new WildcardBinding(genericType, rank, bound, kind, this);
551 cachedInfo[cachedInfo.length-1] = wildcard;
556 * Returns the access restriction associated to a given type, or null if none
558 public AccessRestriction getAccessRestriction(TypeBinding type) {
559 return (AccessRestriction) this.accessRestrictions.get(type);
563 * Answer the type for the compoundName if it exists in the cache.
564 * Answer theNotFoundType if it could not be resolved the first time
565 * it was looked up, otherwise answer null.
567 * NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
568 * assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
571 public ReferenceBinding getCachedType(char[][] compoundName) {
572 if (compoundName.length == 1) {
573 if (defaultPackage == null)
575 return defaultPackage.getType0(compoundName[0]);
578 PackageBinding packageBinding = getPackage0(compoundName[0]);
579 if (packageBinding == null || packageBinding == TheNotFoundPackage)
582 for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
583 if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage)
585 return packageBinding.getType0(compoundName[compoundName.length - 1]);
587 /* Answer the top level package named name if it exists in the cache.
588 * Answer theNotFoundPackage if it could not be resolved the first time
589 * it was looked up, otherwise answer null.
591 * NOTE: Senders must convert theNotFoundPackage into a real problem
592 * package if its to returned.
595 PackageBinding getPackage0(char[] name) {
596 return knownPackages.get(name);
598 /* Answer the top level package named name.
599 * Ask the oracle for the package if its not in the cache.
600 * Answer null if the package cannot be found.
603 PackageBinding getTopLevelPackage(char[] name) {
604 PackageBinding packageBinding = getPackage0(name);
605 if (packageBinding != null) {
606 if (packageBinding == TheNotFoundPackage)
608 return packageBinding;
611 if (nameEnvironment.isPackage(null, name)) {
612 knownPackages.put(name, packageBinding = new PackageBinding(name, this));
613 return packageBinding;
616 knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time
619 /* Answer the type corresponding to the compoundName.
620 * Ask the name environment for the type if its not in the cache.
621 * Answer null if the type cannot be found... likely a fatal error.
624 public ReferenceBinding getType(char[][] compoundName) {
625 ReferenceBinding referenceBinding;
627 if (compoundName.length == 1) {
628 if (defaultPackage == null)
631 if ((referenceBinding = defaultPackage.getType0(compoundName[0])) == null) {
632 PackageBinding packageBinding = getPackage0(compoundName[0]);
633 if (packageBinding != null && packageBinding != TheNotFoundPackage)
634 return null; // collides with a known package... should not call this method in such a case
635 referenceBinding = askForType(defaultPackage, compoundName[0]);
638 PackageBinding packageBinding = getPackage0(compoundName[0]);
639 if (packageBinding == TheNotFoundPackage)
642 if (packageBinding != null) {
643 for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) {
644 if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null)
646 if (packageBinding == TheNotFoundPackage)
651 if (packageBinding == null)
652 referenceBinding = askForType(compoundName);
653 else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null)
654 referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]);
657 if (referenceBinding == null || referenceBinding == TheNotFoundType)
659 referenceBinding = BinaryTypeBinding.resolveType(referenceBinding, this, false); // no raw conversion for now
661 // compoundName refers to a nested type incorrectly (for example, package1.A$B)
662 if (referenceBinding.isNestedType())
663 return new ProblemReferenceBinding(compoundName, InternalNameProvided);
664 return referenceBinding;
666 private TypeBinding[] getTypeArgumentsFromSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, ReferenceBinding genericType) {
667 java.util.ArrayList args = new java.util.ArrayList(2);
670 args.add(getTypeFromVariantTypeSignature(wrapper, staticVariables, enclosingType, genericType, rank++));
671 } while (wrapper.signature[wrapper.start] != '>');
672 wrapper.start++; // skip '>'
673 TypeBinding[] typeArguments = new TypeBinding[args.size()];
674 args.toArray(typeArguments);
675 return typeArguments;
677 /* Answer the type corresponding to the name from the binary file.
678 * Does not ask the oracle for the type if its not found in the cache... instead an
679 * unresolved type is returned which must be resolved before used.
681 * NOTE: Does NOT answer base types nor array types!
683 * NOTE: Aborts compilation if the class file cannot be found.
686 ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized) {
688 end = signature.length;
690 char[][] compoundName = CharOperation.splitOn('/', signature, start, end);
691 ReferenceBinding binding = getCachedType(compoundName);
692 if (binding == null) {
693 PackageBinding packageBinding = computePackageFrom(compoundName);
694 binding = new UnresolvedReferenceBinding(compoundName, packageBinding);
695 packageBinding.addType(binding);
696 } else if (binding == TheNotFoundType) {
697 problemReporter.isClassPathCorrect(compoundName, null);
698 return null; // will not get here since the above error aborts the compilation
699 } else if (!isParameterized && binding.isGenericType()) {
700 // check raw type, only for resolved types
701 binding = createRawType(binding, binding.enclosingType());
705 /* Answer the type corresponding to the signature from the binary file.
706 * Does not ask the oracle for the type if its not found in the cache... instead an
707 * unresolved type is returned which must be resolved before used.
709 * NOTE: Does answer base types & array types.
711 * NOTE: Aborts compilation if the class file cannot be found.
714 TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean isParameterized, TypeBinding enclosingType) {
716 while (signature[start] == '[') {
721 end = signature.length - 1;
723 // Just switch on signature[start] - the L case is the else
724 TypeBinding binding = null;
726 switch (signature[start]) {
728 binding = IntBinding;
731 binding = BooleanBinding;
734 binding = VoidBinding;
737 binding = CharBinding;
740 binding = DoubleBinding;
743 binding = ByteBinding;
746 binding = FloatBinding;
749 binding = LongBinding;
752 binding = ShortBinding;
755 problemReporter.corruptedSignature(enclosingType, signature, start);
756 // will never reach here, since error will cause abort
759 binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized); // skip leading 'L' or 'T'
764 return createArrayType(binding, dimension);
766 TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType) {
767 // TypeVariableSignature = 'T' Identifier ';'
768 // ArrayTypeSignature = '[' TypeSignature
769 // ClassTypeSignature = 'L' Identifier TypeArgs(optional) ';'
770 // or ClassTypeSignature '.' 'L' Identifier TypeArgs(optional) ';'
771 // TypeArgs = '<' VariantTypeSignature VariantTypeSignatures '>'
773 while (wrapper.signature[wrapper.start] == '[') {
778 if (wrapper.signature[wrapper.start] == 'T') {
779 int varStart = wrapper.start + 1;
780 int varEnd = wrapper.computeEnd();
781 for (int i = staticVariables.length; --i >= 0;)
782 if (CharOperation.equals(staticVariables[i].sourceName, wrapper.signature, varStart, varEnd))
783 return dimension == 0 ? (TypeBinding) staticVariables[i] : createArrayType(staticVariables[i], dimension);
784 ReferenceBinding initialType = enclosingType;
786 if (enclosingType instanceof BinaryTypeBinding) { // per construction can only be binary type binding
787 TypeVariableBinding[] enclosingVariables = ((BinaryTypeBinding)enclosingType).typeVariables; // do not trigger resolution of variables
788 for (int i = enclosingVariables.length; --i >= 0;)
789 if (CharOperation.equals(enclosingVariables[i].sourceName, wrapper.signature, varStart, varEnd))
790 return dimension == 0 ? (TypeBinding) enclosingVariables[i] : createArrayType(enclosingVariables[i], dimension);
792 } while ((enclosingType = enclosingType.enclosingType()) != null);
793 problemReporter.undefinedTypeVariableSignature(CharOperation.subarray(wrapper.signature, varStart, varEnd), initialType);
794 return null; // cannot reach this, since previous problem will abort compilation
796 boolean isParameterized;
797 TypeBinding type = getTypeFromSignature(wrapper.signature, wrapper.start, wrapper.computeEnd(), isParameterized = (wrapper.end == wrapper.bracket), enclosingType);
798 if (!isParameterized)
799 return dimension == 0 ? type : createArrayType(type, dimension);
801 // type must be a ReferenceBinding at this point, cannot be a BaseTypeBinding or ArrayTypeBinding
802 ReferenceBinding actualType = (ReferenceBinding) type;
803 TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType);
804 ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, null);
806 while (wrapper.signature[wrapper.start] == '.') {
807 wrapper.start++; // skip '.'
808 char[] memberName = wrapper.nextWord();
809 BinaryTypeBinding.resolveType(parameterizedType, this, false);
810 ReferenceBinding memberType = parameterizedType.type.getMemberType(memberName);
811 if (wrapper.signature[wrapper.start] == '<') {
812 wrapper.start++; // skip '<'
813 typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType);
815 typeArguments = null;
817 parameterizedType = createParameterizedType(memberType, typeArguments, parameterizedType);
819 wrapper.start++; // skip ';'
820 return dimension == 0 ? (TypeBinding) parameterizedType : createArrayType(parameterizedType, dimension);
822 TypeBinding getTypeFromVariantTypeSignature(
823 SignatureWrapper wrapper,
824 TypeVariableBinding[] staticVariables,
825 ReferenceBinding enclosingType,
826 ReferenceBinding genericType,
828 // VariantTypeSignature = '-' TypeSignature
829 // or '+' TypeSignature
832 switch (wrapper.signature[wrapper.start]) {
836 TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
837 return createWildcard(genericType, rank, bound, Wildcard.SUPER);
841 bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
842 return createWildcard(genericType, rank, bound, Wildcard.EXTENDS);
846 return createWildcard(genericType, rank, null, Wildcard.UNBOUND);
848 return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
851 public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
852 if (options.sourceLevel < ClassFileConstants.JDK1_5 || left.isBaseType() == right.isBaseType())
855 TypeBinding convertedType = computeBoxingType(left);
856 return convertedType == right || convertedType.isCompatibleWith(right);
858 /* Ask the oracle if a package exists named name in the package named compoundName.
860 boolean isPackage(char[][] compoundName, char[] name) {
861 if (compoundName == null || compoundName.length == 0)
862 return nameEnvironment.isPackage(null, name);
863 return nameEnvironment.isPackage(compoundName, name);
865 // The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
867 public MethodVerifier methodVerifier() {
868 if (verifier == null)
869 verifier = this.options.sourceLevel < ClassFileConstants.JDK1_5
870 ? new MethodVerifier(this)
871 : new MethodVerifier15(this);
874 public void reset() {
875 this.defaultPackage = new PackageBinding(this); // assume the default package always exists
876 this.defaultImports = null;
877 this.knownPackages = new HashtableOfPackage();
878 this.accessRestrictions = new HashMap(3);
880 this.verifier = null;
881 for (int i = this.uniqueArrayBindings.length; --i >= 0;) {
882 ArrayBinding[] arrayBindings = this.uniqueArrayBindings[i];
883 if (arrayBindings != null)
884 for (int j = arrayBindings.length; --j >= 0;)
885 arrayBindings[j] = null;
887 this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
888 this.uniqueRawTypeBindings = new SimpleLookupTable(3);
889 this.uniqueWildcardBindings = new SimpleLookupTable(3);
891 for (int i = this.units.length; --i >= 0;)
892 this.units[i] = null;
893 this.lastUnitIndex = -1;
894 this.lastCompletedUnitIndex = -1;
895 this.unitBeingCompleted = null; // in case AbortException occurred
897 // name environment has a longer life cycle, and must be reset in
898 // the code which created it.
901 * Associate a given type with some access restriction
902 * (did not store the restriction directly into binding, since sparse information)
904 public void setAccessRestriction(ReferenceBinding type, AccessRestriction accessRestriction) {
905 if (accessRestriction == null) return;
906 type.modifiers |= CompilerModifiers.AccRestrictedAccess;
907 this.accessRestrictions.put(type, accessRestriction);
910 void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
911 // walk all the unique collections & replace the unresolvedType with the resolvedType
912 // must prevent 2 entries so == still works (1 containing the unresolvedType and the other containing the resolvedType)
913 if (this.uniqueParameterizedTypeBindings.get(unresolvedType) != null) { // update the key
914 Object[] keys = this.uniqueParameterizedTypeBindings.keyTable;
915 for (int i = 0, l = keys.length; i < l; i++) {
916 if (keys[i] == unresolvedType) {
917 keys[i] = resolvedType; // hashCode is based on compoundName so this works - cannot be raw since type of parameterized type
923 if (this.uniqueWildcardBindings.get(unresolvedType) != null) { // update the key
924 Object[] keys = this.uniqueWildcardBindings.keyTable;
925 for (int i = 0, l = keys.length; i < l; i++) {
926 if (keys[i] == unresolvedType) {
927 keys[i] = resolvedType; // hashCode is based on compoundName so this works