added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / LookupEnvironment.java
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 java.util.HashMap;
14 import java.util.Map;
15
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;
26
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);
34         
35         /**
36          * Map from typeBinding -> accessRestriction rule
37          */
38         private Map accessRestrictions;
39         ImportBinding[] defaultImports;
40
41         PackageBinding defaultPackage;
42         HashtableOfPackage knownPackages;
43         private int lastCompletedUnitIndex = -1;
44         private int lastUnitIndex = -1;
45
46         public INameEnvironment nameEnvironment;
47         public CompilerOptions options;
48         public ProblemReporter problemReporter;
49
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;
54
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;
65         
66         public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
67
68         private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
69         private MethodVerifier verifier;
70
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);
85 }
86
87 /**
88  * Ask the name environment for a type which corresponds to the compoundName.
89  * Answer null if the name cannot be found.
90  */
91
92 public ReferenceBinding askForType(char[][] compoundName) {
93         NameEnvironmentAnswer answer = nameEnvironment.findType(compoundName);
94         if (answer == null)
95                 return null;
96
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());
106
107         return getCachedType(compoundName);
108 }
109 /* Ask the oracle for a type named name in the packageBinding.
110 * Answer null if the name cannot be found.
111 */
112
113 ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
114         if (packageBinding == null) {
115                 if (defaultPackage == null)
116                         return null;
117                 packageBinding = defaultPackage;
118         }
119         NameEnvironmentAnswer answer = nameEnvironment.findType(name, packageBinding.compoundName);
120         if (answer == null)
121                 return null;
122
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());
132
133         return packageBinding.getType0(name);
134 }
135 /* Create the initial type bindings for the compilation unit.
136 *
137 * See completeTypeBindings() for a description of the remaining steps
138 *
139 * NOTE: This method can be called multiple times as additional source files are needed
140 */
141
142 public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
143         CompilationUnitScope scope = new CompilationUnitScope(unit, this);
144         scope.buildTypeBindings(accessRestriction);
145
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;
150 }
151 /* Cache the binary type since we know it is needed during this compile.
152 *
153 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
154 */
155
156 public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, AccessRestriction accessRestriction) {
157         return cacheBinaryType(binaryType, true, accessRestriction);
158 }
159 /* Cache the binary type since we know it is needed during this compile.
160 *
161 * Answer the created BinaryTypeBinding or null if the type is already in the cache.
162 */
163
164 public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
165         char[][] compoundName = CharOperation.splitOn('/', binaryType.getName());
166         ReferenceBinding existingType = getCachedType(compoundName);
167
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
172 }
173 /*
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
177 */
178
179 /* We know each known compilationUnit is free of errors at this point...
180 *
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)
184 */
185
186 public void completeTypeBindings() {
187         stepCompleted = BUILD_TYPE_HIERARCHY;
188         
189         for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
190             (this.unitBeingCompleted = this.units[i]).scope.checkAndSetImports();
191         }
192         stepCompleted = CHECK_AND_SET_IMPORTS;
193
194         for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
195             (this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy();
196         }
197         stepCompleted = CONNECT_TYPE_HIERARCHY;
198
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
202         }
203         stepCompleted = BUILD_FIELDS_AND_METHODS;
204         this.lastCompletedUnitIndex = this.lastUnitIndex;
205         this.unitBeingCompleted = null;
206 }
207 /*
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
211 */
212
213 /*
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)
217 */
218
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();
225         } else {
226                 if (parsedUnit.scope == null) return; // parsing errors were too severe
227                 
228                 if (stepCompleted >= CHECK_AND_SET_IMPORTS)
229                         (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
230
231                 if (stepCompleted >= CONNECT_TYPE_HIERARCHY)
232                         (this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy();
233                 
234                 this.unitBeingCompleted = null;
235         }
236 }
237 /*
238 * Used by other compiler tools which do not start by calling completeTypeBindings().
239 *
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
243 */
244
245 public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) {
246         if (parsedUnit.scope == null) return; // parsing errors were too severe
247
248         (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
249         parsedUnit.scope.connectTypeHierarchy();
250         if (buildFieldsAndMethods)
251                 parsedUnit.scope.buildFieldsAndMethods();
252         this.unitBeingCompleted = null;
253 }
254 public TypeBinding computeBoxingType(TypeBinding type) {
255         TypeBinding boxedType;
256         switch (type.id) {
257                 case TypeIds.T_JavaLangBoolean :
258                         return BooleanBinding;
259                 case TypeIds.T_JavaLangByte :
260                         return ByteBinding;
261                 case TypeIds.T_JavaLangCharacter :
262                         return CharBinding;
263                 case TypeIds.T_JavaLangShort :
264                         return ShortBinding;
265                 case TypeIds.T_JavaLangDouble :
266                         return DoubleBinding;
267                 case TypeIds.T_JavaLangFloat :
268                         return FloatBinding;
269                 case TypeIds.T_JavaLangInteger :
270                         return IntBinding;
271                 case TypeIds.T_JavaLangLong :
272                         return LongBinding;
273                 case TypeIds.T_JavaLangVoid :
274                         return VoidBinding;
275
276                 case TypeIds.T_int :
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);                              
312         }
313         return type;
314 }       
315 private PackageBinding computePackageFrom(char[][] constantPoolName) {
316         if (constantPoolName.length == 1)
317                 return defaultPackage;
318
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);
323         }
324
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);
330                 }
331         }
332         return packageBinding;
333 }
334
335 /* Used to guarantee array type identity.
336 */
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);
340
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];
348         } else {
349                 System.arraycopy(
350                         uniqueArrayBindings, 0, 
351                         uniqueArrayBindings = new ArrayBinding[dimensionCount][], 0, 
352                         length); 
353                 uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
354         }
355
356         // find the cached array binding for this leaf component type (if any)
357         int index = -1;
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;
365         }
366
367         // no matching array, no space left
368         System.arraycopy(
369                 arrayBindings, 0,
370                 (arrayBindings = new ArrayBinding[length * 2]), 0,
371                 length); 
372         uniqueArrayBindings[dimIndex] = arrayBindings;
373         return arrayBindings[length] = new ArrayBinding(type, dimensionCount, this);
374 }
375 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
376         return createBinaryTypeFrom(binaryType, packageBinding, true, accessRestriction);
377 }
378 public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
379         BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this);
380         
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;
387
388                 ((UnresolvedReferenceBinding) cachedType).setResolvedType(binaryBinding, this);
389         }
390
391         packageBinding.addType(binaryBinding);
392         setAccessRestriction(binaryBinding, accessRestriction);
393         binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
394         return binaryBinding;
395 }
396 /* Used to create packages from the package statement.
397 */
398
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);
404         }
405
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))
413                         return null;
414
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)
422                                 return null;
423
424                         packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this);
425                         parent.addPackage(packageBinding);
426                 }
427         }
428         return packageBinding;
429 }
430
431 public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] originalArguments, ReferenceBinding enclosingType) {
432
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);
442                                 }
443                                 typeArguments[i] = createWildcard(genericType, i, wildcard.bound, wildcard.kind);
444                         } else if (typeArguments != originalArguments) {
445                                 typeArguments[i] = argument;
446                         }
447                 } else if (typeArguments != originalArguments) {
448                         typeArguments[i] = argument;
449                 }
450         }
451         
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){
457                 nextCachedType : 
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;
468                                 }
469                                 // all arguments match, reuse current
470                                 return cachedType;
471                 }
472                 needToGrow = true;
473         } else {
474                 cachedInfo = new ParameterizedTypeBinding[1];
475                 this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
476         }
477         // grow cache ?
478         if (needToGrow){
479                 int length = cachedInfo.length;
480                 System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedTypeBinding[length+1], 0, length);
481                 this.uniqueParameterizedTypeBindings.put(genericType, cachedInfo);
482         }
483         // add new binding
484         ParameterizedTypeBinding parameterizedType = new ParameterizedTypeBinding(genericType,typeArguments, enclosingType, this);
485         cachedInfo[cachedInfo.length-1] = parameterizedType;
486         return parameterizedType;
487 }
488
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){
494                 nextCachedType : 
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
501                                 return cachedType;
502                 }
503                 needToGrow = true;
504         } else {
505                 cachedInfo = new RawTypeBinding[1];
506                 this.uniqueRawTypeBindings.put(genericType, cachedInfo);
507         }
508         // grow cache ?
509         if (needToGrow){
510                 int length = cachedInfo.length;
511                 System.arraycopy(cachedInfo, 0, cachedInfo = new RawTypeBinding[length+1], 0, length);
512                 this.uniqueRawTypeBindings.put(genericType, cachedInfo);
513         }
514         // add new binding
515         RawTypeBinding rawType = new RawTypeBinding(genericType, enclosingType, this);
516         cachedInfo[cachedInfo.length-1] = rawType;
517         return rawType;
518         
519 }
520
521 public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, int kind) {
522         
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){
527                 nextCachedType : 
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
536                                 return cachedType;
537                 }
538                 needToGrow = true;
539         } else {
540                 cachedInfo = new WildcardBinding[1];
541                 this.uniqueWildcardBindings.put(genericType, cachedInfo);
542         }
543         // grow cache ?
544         if (needToGrow){
545                 int length = cachedInfo.length;
546                 System.arraycopy(cachedInfo, 0, cachedInfo = new WildcardBinding[length+1], 0, length);
547                 this.uniqueWildcardBindings.put(genericType, cachedInfo);
548         }
549         // add new binding
550         WildcardBinding wildcard = new WildcardBinding(genericType, rank, bound, kind, this);
551         cachedInfo[cachedInfo.length-1] = wildcard;
552         return wildcard;
553 }
554
555 /**
556  * Returns the access restriction associated to a given type, or null if none
557  */
558 public AccessRestriction getAccessRestriction(TypeBinding type) {
559         return (AccessRestriction) this.accessRestrictions.get(type);
560 }
561
562 /**
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.
566  *
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.
569  */
570
571 public ReferenceBinding getCachedType(char[][] compoundName) {
572         if (compoundName.length == 1) {
573                 if (defaultPackage == null)
574                         return null;
575                 return defaultPackage.getType0(compoundName[0]);
576         }
577
578         PackageBinding packageBinding = getPackage0(compoundName[0]);
579         if (packageBinding == null || packageBinding == TheNotFoundPackage)
580                 return null;
581
582         for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
583                 if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage)
584                         return null;
585         return packageBinding.getType0(compoundName[compoundName.length - 1]);
586 }
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.
590 *
591 * NOTE: Senders must convert theNotFoundPackage into a real problem
592 * package if its to returned.
593 */
594
595 PackageBinding getPackage0(char[] name) {
596         return knownPackages.get(name);
597 }
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.
601 */
602
603 PackageBinding getTopLevelPackage(char[] name) {
604         PackageBinding packageBinding = getPackage0(name);
605         if (packageBinding != null) {
606                 if (packageBinding == TheNotFoundPackage)
607                         return null;
608                 return packageBinding;
609         }
610
611         if (nameEnvironment.isPackage(null, name)) {
612                 knownPackages.put(name, packageBinding = new PackageBinding(name, this));
613                 return packageBinding;
614         }
615
616         knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time
617         return null;
618 }
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.
622 */
623
624 public ReferenceBinding getType(char[][] compoundName) {
625         ReferenceBinding referenceBinding;
626
627         if (compoundName.length == 1) {
628                 if (defaultPackage == null)
629                         return null;
630
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]);
636                 }
637         } else {
638                 PackageBinding packageBinding = getPackage0(compoundName[0]);
639                 if (packageBinding == TheNotFoundPackage)
640                         return null;
641
642                 if (packageBinding != null) {
643                         for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) {
644                                 if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null)
645                                         break;
646                                 if (packageBinding == TheNotFoundPackage)
647                                         return null;
648                         }
649                 }
650
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]);
655         }
656
657         if (referenceBinding == null || referenceBinding == TheNotFoundType)
658                 return null;
659         referenceBinding = BinaryTypeBinding.resolveType(referenceBinding, this, false); // no raw conversion for now
660
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;
665 }
666 private TypeBinding[] getTypeArgumentsFromSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, ReferenceBinding genericType) {
667         java.util.ArrayList args = new java.util.ArrayList(2);
668         int rank = 0;
669         do {
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;
676 }
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.
680 *
681 * NOTE: Does NOT answer base types nor array types!
682 *
683 * NOTE: Aborts compilation if the class file cannot be found.
684 */
685
686 ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized) {
687         if (end == -1)
688                 end = signature.length;
689
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());
702         }
703         return binding;
704 }
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.
708 *
709 * NOTE: Does answer base types & array types.
710 *
711 * NOTE: Aborts compilation if the class file cannot be found.
712 */
713
714 TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean isParameterized, TypeBinding enclosingType) {
715         int dimension = 0;
716         while (signature[start] == '[') {
717                 start++;
718                 dimension++;
719         }
720         if (end == -1)
721                 end = signature.length - 1;
722
723         // Just switch on signature[start] - the L case is the else
724         TypeBinding binding = null;
725         if (start == end) {
726                 switch (signature[start]) {
727                         case 'I' :
728                                 binding = IntBinding;
729                                 break;
730                         case 'Z' :
731                                 binding = BooleanBinding;
732                                 break;
733                         case 'V' :
734                                 binding = VoidBinding;
735                                 break;
736                         case 'C' :
737                                 binding = CharBinding;
738                                 break;
739                         case 'D' :
740                                 binding = DoubleBinding;
741                                 break;
742                         case 'B' :
743                                 binding = ByteBinding;
744                                 break;
745                         case 'F' :
746                                 binding = FloatBinding;
747                                 break;
748                         case 'J' :
749                                 binding = LongBinding;
750                                 break;
751                         case 'S' :
752                                 binding = ShortBinding;
753                                 break;
754                         default :
755                                 problemReporter.corruptedSignature(enclosingType, signature, start);
756                                 // will never reach here, since error will cause abort
757                 }
758         } else {
759                 binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized); // skip leading 'L' or 'T'
760         }
761
762         if (dimension == 0)
763                 return binding;
764         return createArrayType(binding, dimension);
765 }
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 '>'
772         int dimension = 0;
773         while (wrapper.signature[wrapper.start] == '[') {
774                 wrapper.start++;
775                 dimension++;
776         }
777
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;
785                 do {
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);
791                     }
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
795         }
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);
800
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);
805
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);
814                 } else {
815                         typeArguments = null;
816                 }
817                 parameterizedType = createParameterizedType(memberType, typeArguments, parameterizedType);
818         }
819         wrapper.start++; // skip ';'
820         return dimension == 0 ? (TypeBinding) parameterizedType : createArrayType(parameterizedType, dimension);
821 }
822 TypeBinding getTypeFromVariantTypeSignature(
823         SignatureWrapper wrapper,
824         TypeVariableBinding[] staticVariables,
825         ReferenceBinding enclosingType,
826         ReferenceBinding genericType,
827         int rank) {
828         // VariantTypeSignature = '-' TypeSignature
829         //   or '+' TypeSignature
830         //   or TypeSignature
831         //   or '*'
832         switch (wrapper.signature[wrapper.start]) {
833                 case '-' :
834                         // ? super aType
835                         wrapper.start++;
836                         TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
837                         return createWildcard(genericType, rank, bound, Wildcard.SUPER);
838                 case '+' :
839                         // ? extends aType
840                         wrapper.start++;
841                         bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
842                         return createWildcard(genericType, rank, bound, Wildcard.EXTENDS);
843                 case '*' :
844                         // ?
845                         wrapper.start++;
846                         return createWildcard(genericType, rank, null, Wildcard.UNBOUND);
847                 default :
848                         return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType);
849         }
850 }
851 public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
852         if (options.sourceLevel < ClassFileConstants.JDK1_5 || left.isBaseType() == right.isBaseType())
853                 return false;
854
855         TypeBinding convertedType = computeBoxingType(left);
856         return convertedType == right || convertedType.isCompatibleWith(right);
857 }
858 /* Ask the oracle if a package exists named name in the package named compoundName.
859 */
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);
864 }
865 // The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
866
867 public MethodVerifier methodVerifier() {
868         if (verifier == null)
869                 verifier = this.options.sourceLevel < ClassFileConstants.JDK1_5
870                         ? new MethodVerifier(this)
871                         : new MethodVerifier15(this);
872         return verifier;
873 }
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);
879
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;
886         }
887         this.uniqueParameterizedTypeBindings = new SimpleLookupTable(3);
888         this.uniqueRawTypeBindings = new SimpleLookupTable(3);
889         this.uniqueWildcardBindings = new SimpleLookupTable(3);
890         
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
896
897         // name environment has a longer life cycle, and must be reset in
898         // the code which created it.
899 }
900 /**
901  * Associate a given type with some access restriction
902  * (did not store the restriction directly into binding, since sparse information)
903  */
904 public void setAccessRestriction(ReferenceBinding type, AccessRestriction accessRestriction) {
905         if (accessRestriction == null) return;
906         type.modifiers |= CompilerModifiers.AccRestrictedAccess;
907         this.accessRestrictions.put(type, accessRestriction);
908 }
909
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
918                                 break;
919                         }
920                 }
921         }
922
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
928                                 break;
929                         }
930                 }
931         }
932 }
933 }