added -J option to preserve unmodified files in preexisting jarfile
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / Scope.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.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17
18 import org.eclipse.jdt.core.compiler.CharOperation;
19 import org.eclipse.jdt.internal.compiler.ast.*;
20 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
21 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
22 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
23 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
24 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
25 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
26
27 public abstract class Scope
28         implements BaseTypes, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
29
30         public final static int BLOCK_SCOPE = 1;
31         public final static int CLASS_SCOPE = 3;
32         public final static int COMPILATION_UNIT_SCOPE = 4;
33         public final static int METHOD_SCOPE = 2;
34
35         public final static int NOT_COMPATIBLE = -1;
36         public final static int COMPATIBLE = 0;
37         public final static int AUTOBOX_COMPATIBLE = 1;
38         public final static int VARARGS_COMPATIBLE = 2;
39
40    /* Answer an int describing the relationship between the given types.
41         *
42         *               NotRelated 
43         *               EqualOrMoreSpecific : left is compatible with right
44         *               MoreGeneric : right is compatible with left
45         */
46         public static int compareTypes(TypeBinding left, TypeBinding right) {
47                 if (left.isCompatibleWith(right))
48                         return EqualOrMoreSpecific;
49                 if (right.isCompatibleWith(left))
50                         return MoreGeneric;
51                 return NotRelated;
52         }
53
54         /**
55          * Returns an array of types, where original types got substituted given a substitution.
56          * Only allocate an array if anything is different.
57          */
58         public static ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
59             ReferenceBinding[] substitutedTypes = originalTypes;
60             for (int i = 0, length = originalTypes.length; i < length; i++) {
61                 ReferenceBinding originalType = originalTypes[i];
62                 ReferenceBinding substitutedParameter = (ReferenceBinding)substitution.substitute(originalType);
63                 if (substitutedParameter != originalType) {
64                     if (substitutedTypes == originalTypes) {
65                         System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
66                     }
67                     substitutedTypes[i] = substitutedParameter;
68                 } else if (substitutedTypes != originalTypes) {
69                     substitutedTypes[i] = originalType;
70                 }
71             }
72             return substitutedTypes;
73         }
74
75         /**
76          * Returns an array of types, where original types got substituted given a substitution.
77          * Only allocate an array if anything is different.
78          */
79         public static TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
80             TypeBinding[] substitutedTypes = originalTypes;
81             for (int i = 0, length = originalTypes.length; i < length; i++) {
82                 TypeBinding originalType = originalTypes[i];
83                 TypeBinding substitutedParameter = substitution.substitute(originalType);
84                 if (substitutedParameter != originalType) {
85                     if (substitutedTypes == originalTypes) {
86                         System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
87                     }
88                     substitutedTypes[i] = substitutedParameter;
89                 } else if (substitutedTypes != originalTypes) {
90                     substitutedTypes[i] = originalType;
91                 }
92             }
93             return substitutedTypes;
94         }
95
96         public int kind;
97         public Scope parent;
98
99         protected Scope(int kind, Scope parent) {
100                 this.kind = kind;
101                 this.parent = parent;
102         }
103
104         /*
105          * Boxing primitive
106          */
107         public int boxing(int id) {
108                 switch (id) {
109                         case T_int :
110                                 return T_JavaLangInteger;
111                         case T_byte :
112                                 return T_JavaLangByte;
113                         case T_short :
114                                 return T_JavaLangShort;
115                         case T_char :
116                                 return T_JavaLangCharacter;
117                         case T_long :
118                                 return T_JavaLangLong;
119                         case T_float :
120                                 return T_JavaLangFloat;
121                         case T_double :
122                                 return T_JavaLangDouble;
123                         case T_boolean :
124                                 return T_JavaLangBoolean;
125                         case T_void :
126                                 return T_JavaLangVoid;
127                 }
128                 return id;
129         }
130         /*
131          * Boxing primitive
132          */
133         public TypeBinding boxing(TypeBinding type) {
134                 TypeBinding boxedType;
135                 switch (type.id) {
136                         case T_int :
137                                 boxedType = environment().getType(JAVA_LANG_INTEGER);
138                                 if (boxedType != null) return boxedType;
139                                 return new ProblemReferenceBinding(     JAVA_LANG_INTEGER, NotFound);                           
140                         case T_byte :
141                                 boxedType = environment().getType(JAVA_LANG_BYTE);
142                                 if (boxedType != null) return boxedType;
143                                 return new ProblemReferenceBinding(     JAVA_LANG_BYTE, NotFound);                              
144                         case T_short :
145                                 boxedType = environment().getType(JAVA_LANG_SHORT);
146                                 if (boxedType != null) return boxedType;
147                                 return new ProblemReferenceBinding(     JAVA_LANG_SHORT, NotFound);                             
148                         case T_char :
149                                 boxedType = environment().getType(JAVA_LANG_CHARACTER);
150                                 if (boxedType != null) return boxedType;
151                                 return new ProblemReferenceBinding(     JAVA_LANG_CHARACTER, NotFound);                         
152                         case T_long :
153                                 boxedType = environment().getType(JAVA_LANG_LONG);
154                                 if (boxedType != null) return boxedType;
155                                 return new ProblemReferenceBinding(     JAVA_LANG_LONG, NotFound);                              
156                         case T_float :
157                                 boxedType = environment().getType(JAVA_LANG_FLOAT);
158                                 if (boxedType != null) return boxedType;
159                                 return new ProblemReferenceBinding(     JAVA_LANG_FLOAT, NotFound);                             
160                         case T_double :
161                                 boxedType = environment().getType(JAVA_LANG_DOUBLE);
162                                 if (boxedType != null) return boxedType;
163                                 return new ProblemReferenceBinding(     JAVA_LANG_DOUBLE, NotFound);                            
164                         case T_boolean :
165                                 boxedType = environment().getType(JAVA_LANG_BOOLEAN);
166                                 if (boxedType != null) return boxedType;
167                                 return new ProblemReferenceBinding(     JAVA_LANG_BOOLEAN, NotFound);                           
168                         case T_void :
169                                 boxedType = environment().getType(JAVA_LANG_VOID);
170                                 if (boxedType != null) return boxedType;
171                                 return new ProblemReferenceBinding(     JAVA_LANG_VOID, NotFound);                              
172                 }
173                 return type;
174         }       
175
176         public final ClassScope classScope() {
177                 Scope scope = this;
178                 do {
179                         if (scope instanceof ClassScope)
180                                 return (ClassScope) scope;
181                         scope = scope.parent;
182                 } while (scope != null);
183                 return null;
184         }       
185
186         /* Answer an int describing the relationship between the given type and unchecked exceptions.
187         *
188         *       NotRelated 
189         *       EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
190         *       MoreGeneric : type is a supertype of an actual unchecked exception type
191         */
192         public int compareUncheckedException(ReferenceBinding type) {
193                 int comparison = compareTypes(type, getJavaLangRuntimeException());
194                 if (comparison != 0) return comparison;
195                 return compareTypes(type, getJavaLangError());
196         }
197
198         public final CompilationUnitScope compilationUnitScope() {
199                 Scope lastScope = null;
200                 Scope scope = this;
201                 do {
202                         lastScope = scope;
203                         scope = scope.parent;
204                 } while (scope != null);
205                 return (CompilationUnitScope) lastScope;
206         }
207
208         /**
209          * Internal use only
210          * Given a method, returns null if arguments cannot be converted to parameters.
211          * Will answer a subsituted method in case the method was generic and type inference got triggered;
212          * in case the method was originally compatible, then simply answer it back.
213          */
214         protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite) {
215
216                 TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments();
217                 TypeBinding[] parameters = method.parameters;
218                 TypeVariableBinding[] typeVariables = method.typeVariables;
219                 if (parameters == arguments
220                         && (method.returnType.tagBits & HasTypeVariable) == 0 
221                         && genericTypeArguments == null
222                         && typeVariables == NoTypeVariables)
223                                 return method;
224
225                 int argLength = arguments.length;
226                 int paramLength = parameters.length;
227                 boolean isVarArgs = method.isVarargs();
228                 if (argLength != paramLength)
229                         if (!isVarArgs || argLength < paramLength - 1)
230                                 return null; // incompatible
231
232                 if (typeVariables != NoTypeVariables) { // generic method
233                         method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite);
234                         if (method == null) return null; // incompatible
235                         if (!method.isValidBinding()) return method; // bound check issue is taking precedence
236                         parameters = method.parameters; // reacquire them after type inference has performed
237                 } else if (genericTypeArguments != null) {
238                         if (method instanceof ParameterizedGenericMethodBinding) {
239                                 if (!((ParameterizedGenericMethodBinding) method).wasInferred) {
240                                         // attempt to invoke generic method of raw type with type hints <String>foo()
241                                         return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeArgumentsForRawGenericMethod);
242                                 }
243                         } else {
244                                 return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeParameterArityMismatch);
245                         }
246                 }
247
248                 if (parameterCompatibilityLevel(method, arguments) > NOT_COMPATIBLE)
249                         return method;
250                 if (genericTypeArguments != null)
251                         return new ProblemMethodBinding(method, method.selector, arguments, ParameterizedMethodTypeMismatch);
252                 return null; // incompatible
253         }
254         
255         protected boolean connectTypeVariables(TypeParameter[] typeParameters) {
256                 boolean noProblems = true;
257                 if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) return true;
258
259                 nextVariable : for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
260                         TypeParameter typeParameter = typeParameters[i];
261                         TypeVariableBinding typeVariable = typeParameter.binding;
262                         if (typeVariable == null) return false;
263
264                         typeVariable.superclass = getJavaLangObject();
265                         typeVariable.superInterfaces = NoSuperInterfaces;
266                         // set firstBound to the binding of the first explicit bound in parameter declaration
267                         typeVariable.firstBound = null; // first bound used to compute erasure
268
269                         TypeReference typeRef = typeParameter.type;
270                         if (typeRef == null)
271                                 continue nextVariable;
272                         ReferenceBinding superType = this.kind == METHOD_SCOPE
273                                 ? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false/*no bound check*/)
274                                 : (ReferenceBinding) typeRef.resolveType((ClassScope)this);
275                         if (superType == null) {
276                                 typeVariable.tagBits |= HierarchyHasProblems;
277                                 noProblems = false;
278                                 continue nextVariable;
279                         }
280                         if (superType.isTypeVariable()) {
281                                 TypeVariableBinding varSuperType = (TypeVariableBinding) superType;
282                                 if (varSuperType.rank >= typeVariable.rank && varSuperType.declaringElement == typeVariable.declaringElement) {
283                                         problemReporter().forwardTypeVariableReference(typeParameter, varSuperType);
284                                         typeVariable.tagBits |= HierarchyHasProblems;
285                                         noProblems = false;
286                                         continue nextVariable;
287                                 }
288                         }
289                         if (superType.isFinal())
290                                 problemReporter().finalVariableBound(typeVariable, typeRef);
291                         typeRef.resolvedType = superType; // hold onto the problem type
292                         if (superType.isClass()) {
293                                 typeVariable.superclass = superType;
294                         } else {
295                                 typeVariable.superInterfaces = new ReferenceBinding[] {superType};
296                                 typeVariable.modifiers |= AccInterface;
297                         }
298                         typeVariable.firstBound = superType; // first bound used to compute erasure
299
300                         TypeReference[] boundRefs = typeParameter.bounds;
301                         if (boundRefs != null) {
302                                 for (int j = 0, k = boundRefs.length; j < k; j++) {
303                                         typeRef = boundRefs[j];
304                                         superType = this.kind == METHOD_SCOPE
305                                                 ? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false)
306                                                 : (ReferenceBinding) typeRef.resolveType((ClassScope)this);
307                                         if (superType == null) {
308                                                 typeVariable.tagBits |= HierarchyHasProblems;
309                                                 noProblems = false;
310                                                 continue nextVariable;
311                                         }
312                                         typeRef.resolvedType = superType; // hold onto the problem type
313                                         if (superType.isClass()) {
314                                                 problemReporter().boundsMustBeAnInterface(typeRef, superType);
315                                                 typeVariable.tagBits |= HierarchyHasProblems;
316                                                 noProblems = false;
317                                                 continue nextVariable;
318                                         }
319                                         if (superType.isParameterizedType()) {
320                                                 ReferenceBinding match = typeVariable.superclass.findSuperTypeErasingTo((ReferenceBinding) superType.erasure());
321                                                 boolean isCollision = match != null && match != superType;
322                                                 for (int index = typeVariable.superInterfaces.length; !isCollision && --index >= 0;) {
323                                                         ReferenceBinding temp = typeVariable.superInterfaces[index];
324                                                         isCollision = superType != temp && superType.erasure() == temp.erasure();
325                                                 }
326                                                 if (isCollision) {
327                                                         problemReporter().boundHasConflictingArguments(typeRef, superType);
328                                                         typeVariable.tagBits |= HierarchyHasProblems;
329                                                         noProblems = false;
330                                                         continue nextVariable;
331                                                 }
332                                         }
333                                         int size = typeVariable.superInterfaces.length;
334                                         System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.superInterfaces = new ReferenceBinding[size + 1], 0, size);
335                                         typeVariable.superInterfaces[size] = superType;
336                                 }
337                         }
338                 }
339                 return noProblems;
340         }
341
342         public TypeBinding convertToRawType(TypeBinding type) {
343                 int dimension = type.dimensions();
344                 TypeBinding originalType = type.leafComponentType();
345                 if (originalType instanceof ReferenceBinding) {
346                         ReferenceBinding convertedType = (ReferenceBinding) originalType;
347                         ReferenceBinding originalEnclosing = originalType.enclosingType();
348                         ReferenceBinding convertedEnclosing = originalEnclosing;
349                         if (originalEnclosing != null && convertedType.isStatic() && originalEnclosing.isGenericType()) {
350                                 convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
351                         }
352                         if (originalType.isGenericType()) {
353                                 convertedType = environment().createRawType(convertedType, convertedEnclosing);
354                         } else if (originalEnclosing != convertedEnclosing) {
355                                 convertedType = createParameterizedType(convertedType, null, convertedEnclosing);
356                         }
357                         if (originalType != convertedType) {
358                                 return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType;
359                         }
360                 }
361                 return type;
362         }
363 //              TypeBinding leafType = type.leafComponentType();
364 //              int dimension = type.dimensions();
365 //              ReferenceBinding originalEnclosing = leafType.enclosingType();
366 //              ReferenceBinding convertedEnclosing = originalEnclosing;
367 //              if (originalEnclosing != null && ((ReferenceBinding)leafType).isStatic()) {
368 //                      convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
369 //              }
370 //              if (leafType.isGenericType()) {
371 //                      type = environment().createRawType((ReferenceBinding) leafType, convertedEnclosing);
372 //                      if (dimension > 0) 
373 //                              type = createArrayType(type, dimension);
374 //              } else if (originalEnclosing != convertedEnclosing) {
375 //                      type = createParameterizedType((ReferenceBinding)leafType, null, convertedEnclosing);
376 //                      if (dimension > 0) 
377 //                              type = createArrayType(type, dimension);
378 //              }
379 //          return type;
380
381         public ArrayBinding createArrayType(TypeBinding type, int dimension) {
382                 if (type.isValidBinding())
383                         return environment().createArrayType(type, dimension);
384                 // do not cache obvious invalid types
385                 return new ArrayBinding(type, dimension, environment());
386         }
387         
388         public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] arguments, ReferenceBinding enclosingType) {
389                 valid: {
390                         if (!genericType.isValidBinding()) break valid;
391                         for (int i = 0, max = arguments == null ? 0 : arguments.length; i < max; i++)
392                                 if (!arguments[i].isValidBinding()) break valid;
393                         return environment().createParameterizedType(genericType, arguments, enclosingType);
394                 }
395                 return new ParameterizedTypeBinding(genericType, arguments, enclosingType, environment());
396         }
397         
398         public TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) {
399
400                 PackageBinding unitPackage = compilationUnitScope().fPackage;
401                 
402                 // do not construct type variables if source < 1.5
403                 if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5)
404                         return NoTypeVariables;
405                 TypeVariableBinding[] typeVariableBindings = NoTypeVariables;
406                 
407                 int length = typeParameters.length;
408                 typeVariableBindings = new TypeVariableBinding[length];
409                 HashtableOfObject knownTypeParameterNames = new HashtableOfObject(length);
410                 int count = 0;
411                 nextParameter : for (int i = 0; i < length; i++) {
412                         TypeParameter typeParameter = typeParameters[i];
413                         TypeVariableBinding parameterBinding = new TypeVariableBinding(typeParameter.name, declaringElement, i);
414                         parameterBinding.fPackage = unitPackage;
415                         typeParameter.binding = parameterBinding;
416                         
417                         if (knownTypeParameterNames.containsKey(typeParameter.name)) {
418                                 TypeVariableBinding previousBinding = (TypeVariableBinding) knownTypeParameterNames.get(typeParameter.name);
419                                 if (previousBinding != null) {
420                                         for (int j = 0; j < i; j++) {
421                                                 TypeParameter previousParameter = typeParameters[j];
422                                                 if (previousParameter.binding == previousBinding) {
423                                                         problemReporter().duplicateTypeParameterInType(previousParameter);
424                                                         previousParameter.binding = null;
425                                                         break;
426                                                 }
427                                         }
428                                 }
429                                 knownTypeParameterNames.put(typeParameter.name, null); // ensure that the duplicate parameter is found & removed
430                                 problemReporter().duplicateTypeParameterInType(typeParameter);
431                                 typeParameter.binding = null;
432                         } else {
433                                 knownTypeParameterNames.put(typeParameter.name, parameterBinding);
434                                 // remember that we have seen a field with this name
435                                 if (parameterBinding != null)
436                                         typeVariableBindings[count++] = parameterBinding;
437                         }
438 //                              TODO should offer warnings to inform about hiding declaring, enclosing or member types                          
439 //                              ReferenceBinding type = sourceType;
440 //                              // check that the member does not conflict with an enclosing type
441 //                              do {
442 //                                      if (CharOperation.equals(type.sourceName, memberContext.name)) {
443 //                                              problemReporter().hidingEnclosingType(memberContext);
444 //                                              continue nextParameter;
445 //                                      }
446 //                                      type = type.enclosingType();
447 //                              } while (type != null);
448 //                              // check that the member type does not conflict with another sibling member type
449 //                              for (int j = 0; j < i; j++) {
450 //                                      if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
451 //                                              problemReporter().duplicateNestedType(memberContext);
452 //                                              continue nextParameter;
453 //                                      }
454 //                              }
455                 }
456                 if (count != length) {
457                         System.arraycopy(typeVariableBindings, 0, typeVariableBindings = new TypeVariableBinding[count], 0, count);
458                 }
459                 return typeVariableBindings;
460         }
461
462         public final ClassScope enclosingClassScope() {
463                 Scope scope = this;
464                 while ((scope = scope.parent) != null) {
465                         if (scope instanceof ClassScope) return (ClassScope) scope;
466                 }
467                 return null; // may answer null if no type around
468         }
469
470         public final MethodScope enclosingMethodScope() {
471                 Scope scope = this;
472                 while ((scope = scope.parent) != null) {
473                         if (scope instanceof MethodScope) return (MethodScope) scope;
474                 }
475                 return null; // may answer null if no method around
476         }
477
478         /* Answer the receiver's enclosing source type.
479         */
480         public final SourceTypeBinding enclosingSourceType() {
481                 Scope scope = this;
482                 do {
483                         if (scope instanceof ClassScope)
484                                 return ((ClassScope) scope).referenceContext.binding;
485                         scope = scope.parent;
486                 } while (scope != null);
487                 return null;
488         }
489         public final LookupEnvironment environment() {
490                 Scope scope, unitScope = this;
491                 while ((scope = unitScope.parent) != null)
492                         unitScope = scope;
493                 return ((CompilationUnitScope) unitScope).environment;
494         }
495
496         // abstract method lookup lookup (since maybe missing default abstract methods)
497         public MethodBinding findDefaultAbstractMethod(
498                 ReferenceBinding receiverType, 
499                 char[] selector,
500                 TypeBinding[] argumentTypes,
501                 InvocationSite invocationSite,
502                 ReferenceBinding classHierarchyStart,
503                 MethodBinding matchingMethod,
504                 ObjectVector found) {
505
506                 int startFoundSize = found.size;
507                 ReferenceBinding currentType = classHierarchyStart;
508                 while (currentType != null) {
509                         matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
510                         currentType = currentType.superclass();
511                 }
512                 CompilationUnitScope unitScope = compilationUnitScope();
513                 int foundSize = found.size;
514                 if (foundSize == startFoundSize) {
515                         if (matchingMethod != null)
516                                 unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
517                         return matchingMethod; // maybe null
518                 }
519                 MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
520                 int candidatesCount = 0;
521                 MethodBinding problemMethod = null;
522                 // argument type compatibility check
523                 for (int i = startFoundSize; i < foundSize; i++) {
524                         MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
525                         MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
526                         if (compatibleMethod != null) {
527                                 if (compatibleMethod.isValidBinding())
528                                         candidates[candidatesCount++] = compatibleMethod;
529                                 else if (problemMethod == null)
530                                         problemMethod = compatibleMethod;
531                         }
532                 }
533
534                 if (candidatesCount == 1) {
535                         unitScope.recordTypeReferences(candidates[0].thrownExceptions);
536                         return candidates[0]; 
537                 }
538                 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
539                         if (problemMethod != null) return problemMethod;
540                         int argLength = argumentTypes.length;
541                         nextMethod : for (int i = 0; i < foundSize; i++) {
542                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
543                                 TypeBinding[] params = methodBinding.parameters;
544                                 int paramLength = params.length;
545                                 nextArg: for (int a = 0; a < argLength; a++) {
546                                         TypeBinding arg = argumentTypes[a];
547                                         for (int p = 0; p < paramLength; p++)
548                                                 if (params[p] == arg)
549                                                         continue nextArg;
550                                         continue nextMethod;
551                                 }
552                                 return methodBinding;
553                         }
554                         return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
555                 }
556                 // no need to check for visibility - interface methods are public
557                 boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
558                 if (isCompliant14)
559                         return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite);
560                 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite);
561         }
562
563         // Internal use only
564         public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
565                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
566                         return null; // know it has no member types (nor inherited member types)
567
568                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
569                 CompilationUnitScope unitScope = compilationUnitScope();
570                 unitScope.recordReference(enclosingType, typeName);
571                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
572                 if (memberType != null) {
573                         unitScope.recordTypeReference(memberType);
574                         if (enclosingSourceType == null
575                                 ? memberType.canBeSeenBy(getCurrentPackage())
576                                 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
577                                         return memberType;
578                         return new ProblemReferenceBinding(typeName, memberType, NotVisible);
579                 }
580                 return null;
581         }
582
583         // Internal use only
584         public MethodBinding findExactMethod(
585                 ReferenceBinding receiverType,
586                 char[] selector,
587                 TypeBinding[] argumentTypes,
588                 InvocationSite invocationSite) {
589
590                 CompilationUnitScope unitScope = compilationUnitScope();
591                 unitScope.recordTypeReferences(argumentTypes);
592                 MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope);
593                 if (exactMethod != null) {
594                         unitScope.recordTypeReferences(exactMethod.thrownExceptions);
595                         // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type)
596                         if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) {
597                                 if (receiverType.id != T_JavaLangObject
598                                         && argumentTypes == NoParameters
599                                     && CharOperation.equals(selector, GETCLASS)
600                                     && exactMethod.returnType.isParameterizedType()/*1.5*/) {
601                                                 return ParameterizedMethodBinding.instantiateGetClass(receiverType, exactMethod, this);
602                             }
603                                 // targeting a generic method could find an exact match with variable return type
604                                 if (exactMethod.typeVariables != NoTypeVariables || invocationSite.genericTypeArguments() != null)
605                                         exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite);
606                                 return exactMethod;
607                         }
608                 }
609                 return null;
610         }
611
612         // Internal use only
613         /*      Answer the field binding that corresponds to fieldName.
614                 Start the lookup at the receiverType.
615                 InvocationSite implements
616                         isSuperAccess(); this is used to determine if the discovered field is visible.
617                 Only fields defined by the receiverType or its supertypes are answered;
618                 a field of an enclosing type will not be found using this API.
619         
620                 If no visible field is discovered, null is answered.
621         */
622         public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
623                 if (receiverType.isBaseType()) return null;
624
625                 CompilationUnitScope unitScope = compilationUnitScope();
626                 unitScope.recordTypeReference(receiverType);
627                 if (receiverType.isArrayType()) {
628                         TypeBinding leafType = receiverType.leafComponentType();
629                         if (leafType instanceof ReferenceBinding)
630                                 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
631                                         return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
632                         if (CharOperation.equals(fieldName, LENGTH))
633                                 return ArrayBinding.ArrayLength;
634                         return null;
635                 }
636
637                 ReferenceBinding currentType = (ReferenceBinding) receiverType;
638                 if (!currentType.canBeSeenBy(this))
639                         return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
640
641                 FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
642                 if (field != null) {
643                         if (invocationSite == null
644                                 ? field.canBeSeenBy(getCurrentPackage())
645                                 : field.canBeSeenBy(currentType, invocationSite, this))
646                                         return field;
647                         return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible);
648                 }
649                 // collect all superinterfaces of receiverType until the field is found in a supertype
650                 ReferenceBinding[][] interfacesToVisit = null;
651                 int lastPosition = -1;
652                 FieldBinding visibleField = null;
653                 boolean keepLooking = true;
654                 boolean notVisible = false;
655                 // we could hold onto the not visible field for extra error reporting
656                 while (keepLooking) {
657                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
658                         if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
659                                 ((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
660                                 itsInterfaces = currentType.superInterfaces();
661                         }
662                         if (itsInterfaces != NoSuperInterfaces) {
663                                 if (interfacesToVisit == null)
664                                         interfacesToVisit = new ReferenceBinding[5][];
665                                 if (++lastPosition == interfacesToVisit.length)
666                                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
667                                 interfacesToVisit[lastPosition] = itsInterfaces;
668                         }
669                         if ((currentType = currentType.superclass()) == null)
670                                 break;
671
672                         unitScope.recordTypeReference(currentType);
673                         if ((field = currentType.getField(fieldName, needResolve)) != null) {
674                                 keepLooking = false;
675                                 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
676                                         if (visibleField == null)
677                                                 visibleField = field;
678                                         else
679                                                 return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
680                                 } else {
681                                         notVisible = true;
682                                 }
683                         }
684                 }
685
686                 // walk all visible interfaces to find ambiguous references
687                 if (interfacesToVisit != null) {
688                         ProblemFieldBinding ambiguous = null;
689                         done : for (int i = 0; i <= lastPosition; i++) {
690                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
691                                 for (int j = 0, length = interfaces.length; j < length; j++) {
692                                         ReferenceBinding anInterface = interfaces[j];
693                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
694                                                 // if interface as not already been visited
695                                                 anInterface.tagBits |= InterfaceVisited;
696                                                 unitScope.recordTypeReference(anInterface);
697                                                 if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
698                                                         if (visibleField == null) {
699                                                                 visibleField = field;
700                                                         } else {
701                                                                 ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
702                                                                 break done;
703                                                         }
704                                                 } else {
705                                                         ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
706                                                         if (itsInterfaces != NoSuperInterfaces) {
707                                                                 if (++lastPosition == interfacesToVisit.length)
708                                                                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
709                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
710                                                         }
711                                                 }
712                                         }
713                                 }
714                         }
715
716                         // bit reinitialization
717                         for (int i = 0; i <= lastPosition; i++) {
718                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
719                                 for (int j = 0, length = interfaces.length; j < length; j++)
720                                         interfaces[j].tagBits &= ~InterfaceVisited;
721                         }
722                         if (ambiguous != null)
723                                 return ambiguous;
724                 }
725
726                 if (visibleField != null)
727                         return visibleField;
728                 if (notVisible)
729                         return new ProblemFieldBinding(currentType, fieldName, NotVisible);
730                 return null;
731         }
732
733         // Internal use only
734         public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
735                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
736                         return null; // know it has no member types (nor inherited member types)
737
738                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
739                 PackageBinding currentPackage = getCurrentPackage();
740                 CompilationUnitScope unitScope = compilationUnitScope();
741                 unitScope.recordReference(enclosingType, typeName);
742                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
743                 if (memberType != null) {
744                         unitScope.recordTypeReference(memberType);
745                         if (enclosingSourceType == null
746                                 ? memberType.canBeSeenBy(currentPackage)
747                                 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
748                                         return memberType;
749                         return new ProblemReferenceBinding(typeName, memberType, NotVisible);
750                 }
751
752                 // collect all superinterfaces of receiverType until the memberType is found in a supertype
753                 ReferenceBinding currentType = enclosingType;
754                 ReferenceBinding[][] interfacesToVisit = null;
755                 int lastPosition = -1;
756                 ReferenceBinding visibleMemberType = null;
757                 boolean keepLooking = true;
758                 ReferenceBinding notVisible = null;
759                 // we could hold onto the not visible field for extra error reporting
760                 while (keepLooking) {
761                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
762                         if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
763                                 ((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
764                                 itsInterfaces = currentType.superInterfaces();
765                         }
766                         if (itsInterfaces != NoSuperInterfaces) {
767                                 if (interfacesToVisit == null)
768                                         interfacesToVisit = new ReferenceBinding[5][];
769                                 if (++lastPosition == interfacesToVisit.length)
770                                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
771                                 interfacesToVisit[lastPosition] = itsInterfaces;
772                         }
773                         if ((currentType = currentType.superclass()) == null)
774                                 break;
775
776                         unitScope.recordReference(currentType, typeName);
777                         if ((memberType = currentType.getMemberType(typeName)) != null) {
778                                 unitScope.recordTypeReference(memberType);
779                                 keepLooking = false;
780                                 if (enclosingSourceType == null
781                                         ? memberType.canBeSeenBy(currentPackage)
782                                         : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
783                                                 if (visibleMemberType == null)
784                                                         visibleMemberType = memberType;
785                                                 else
786                                                         return new ProblemReferenceBinding(typeName, Ambiguous);
787                                 } else {
788                                         notVisible = memberType;
789                                 }
790                         }
791                 }
792                 // walk all visible interfaces to find ambiguous references
793                 if (interfacesToVisit != null) {
794                         ProblemReferenceBinding ambiguous = null;
795                         done : for (int i = 0; i <= lastPosition; i++) {
796                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
797                                 for (int j = 0, length = interfaces.length; j < length; j++) {
798                                         ReferenceBinding anInterface = interfaces[j];
799                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
800                                                 // if interface as not already been visited
801                                                 anInterface.tagBits |= InterfaceVisited;
802                                                 unitScope.recordReference(anInterface, typeName);
803                                                 if ((memberType = anInterface.getMemberType(typeName)) != null) {
804                                                         unitScope.recordTypeReference(memberType);
805                                                         if (visibleMemberType == null) {
806                                                                 visibleMemberType = memberType;
807                                                         } else {
808                                                                 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
809                                                                 break done;
810                                                         }
811                                                 } else {
812                                                         ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
813                                                         if (itsInterfaces != NoSuperInterfaces) {
814                                                                 if (++lastPosition == interfacesToVisit.length)
815                                                                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
816                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
817                                                         }
818                                                 }
819                                         }
820                                 }
821                         }
822
823                         // bit reinitialization
824                         for (int i = 0; i <= lastPosition; i++) {
825                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
826                                 for (int j = 0, length = interfaces.length; j < length; j++)
827                                         interfaces[j].tagBits &= ~InterfaceVisited;
828                         }
829                         if (ambiguous != null)
830                                 return ambiguous;
831                 }
832                 if (visibleMemberType != null)
833                         return visibleMemberType;
834                 if (notVisible != null)
835                         return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
836                 return null;
837         }
838
839         // Internal use only
840         public MethodBinding findMethod(
841                 ReferenceBinding receiverType,
842                 char[] selector,
843                 TypeBinding[] argumentTypes,
844                 InvocationSite invocationSite) {
845
846                 ReferenceBinding currentType = receiverType;
847                 MethodBinding matchingMethod = null;
848                 ObjectVector found = new ObjectVector(); //TODO (kent) should rewrite to remove #matchingMethod since found is allocated anyway
849
850                 CompilationUnitScope unitScope = compilationUnitScope();
851                 unitScope.recordTypeReferences(argumentTypes);
852
853                 if (currentType.isInterface()) {
854                         unitScope.recordTypeReference(currentType);
855                         MethodBinding[] currentMethods = currentType.getMethods(selector);
856                         int currentLength = currentMethods.length;
857                         if (currentLength == 1) {
858                                 matchingMethod = currentMethods[0];
859                         } else if (currentLength > 1) {
860                                 found.addAll(currentMethods);
861                         }
862                         matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
863                         currentType = getJavaLangObject();
864                 }
865
866                 boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
867                 // superclass lookup
868                 ReferenceBinding classHierarchyStart = currentType;
869                 while (currentType != null) {
870                         unitScope.recordTypeReference(currentType);
871                         MethodBinding[] currentMethods = currentType.getMethods(selector);
872                         int currentLength = currentMethods.length;
873
874                         if (isCompliant14 && matchingMethod != null || found.size > 0) {
875                                 nextMethod: for (int i = 0; i < currentLength; i++) {
876                                         MethodBinding currentMethod = currentMethods[i];
877                                         // if 1.4 compliant, must filter out redundant protected methods from superclasses
878                                         // protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
879                                         // when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
880                                         // if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
881                                         // BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
882                                         if (matchingMethod != null) {
883                                                 if (currentMethod.areParametersEqual(matchingMethod)) {
884                                                         currentLength--;
885                                                         currentMethods[i] = null; // discard this match
886                                                         continue nextMethod;
887                                                 }
888                                         } else {
889                                                 for (int j = 0, max = found.size; j < max; j++) {
890                                                         if (((MethodBinding) found.elementAt(j)).areParametersEqual(currentMethod)) {
891                                                                 currentLength--;
892                                                                 currentMethods[i] = null;
893                                                                 continue nextMethod;
894                                                         }
895                                                 }
896                                         }
897                                 }
898                         }
899
900                         if (currentLength == 1 && matchingMethod == null && found.size == 0) {
901                                 matchingMethod = currentMethods[0];
902                         } else if (currentLength > 0) {
903                                 if (matchingMethod != null) {
904                                         found.add(matchingMethod);
905                                         matchingMethod = null;
906                                 }
907                                 // append currentMethods, filtering out null entries
908                                 int maxMethod = currentMethods.length;
909                                 if (maxMethod == currentLength) { // no method was eliminated for 1.4 compliance (see above)
910                                         found.addAll(currentMethods);
911                                 } else {
912                                         for (int i = 0, max = currentMethods.length; i < max; i++) {
913                                                 MethodBinding currentMethod = currentMethods[i];
914                                                 if (currentMethod != null) found.add(currentMethod);
915                                         }
916                                 }
917                         }
918                         currentType = currentType.superclass();
919                 }
920
921                 // if found several candidates, then eliminate those not matching argument types
922                 int foundSize = found.size;
923                 MethodBinding[] candidates = null;
924                 int candidatesCount = 0;
925                 boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ?
926                 MethodBinding problemMethod = null;
927                 if (foundSize > 0) {
928                         // argument type compatibility check
929                         for (int i = 0; i < foundSize; i++) {
930                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
931                                 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
932                                 if (compatibleMethod != null) {
933                                         if (compatibleMethod.isValidBinding()) {
934                                                 switch (candidatesCount) {
935                                                         case 0: 
936                                                                 matchingMethod = compatibleMethod; // if only one match, reuse matchingMethod
937                                                                 checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
938                                                                 break;
939                                                         case 1:
940                                                                 candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
941                                                                 candidates[0] = matchingMethod; // copy back
942                                                                 matchingMethod = null;
943                                                                 // fall through
944                                                         default:
945                                                                 candidates[candidatesCount] = compatibleMethod;
946                                                 }
947                                                 candidatesCount++;
948                                         } else if (problemMethod == null) {
949                                                 problemMethod = compatibleMethod;
950                                         }
951                                 }
952                         }
953                 }
954                 if (candidatesCount > 0)
955                         problemMethod = null; // forget the problem method if candidates were found
956
957                 // if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod
958                 if (matchingMethod != null) {
959                         if (!checkedMatchingMethod) {
960                                 MethodBinding compatibleMethod = computeCompatibleMethod(matchingMethod, argumentTypes, invocationSite);
961                                 if (compatibleMethod != null) {
962                                         if (compatibleMethod.isValidBinding()) {
963                                                 matchingMethod = compatibleMethod;
964                                                 checkedMatchingMethod = true;
965                                         } else {
966                                                 problemMethod = compatibleMethod;
967                                         }
968                                 }
969                         }
970                         if (checkedMatchingMethod) {
971                                 // (if no default abstract) must explicitly look for one instead, which could be a better match
972                                 if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
973                                         // ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
974                                         MethodBinding interfaceMethod =
975                                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);                                             
976                                         if (interfaceMethod != null) return interfaceMethod;
977                                         unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
978                                         return matchingMethod;
979                                 }
980                         } 
981                         matchingMethod =
982                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
983                         if (matchingMethod != null) return matchingMethod;
984                         return problemMethod;
985                 }
986
987                 // no match was found, try to find a close match when the parameter order is wrong or missing some parameters
988                 if (candidatesCount == 0) {
989                         MethodBinding interfaceMethod =
990                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
991                         if (interfaceMethod != null) return interfaceMethod;
992                         if (problemMethod != null) return problemMethod;
993
994                         int argLength = argumentTypes.length;
995                         foundSize = found.size;
996                         nextMethod : for (int i = 0; i < foundSize; i++) {
997                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
998                                 TypeBinding[] params = methodBinding.parameters;
999                                 int paramLength = params.length;
1000                                 nextArg: for (int a = 0; a < argLength; a++) {
1001                                         TypeBinding arg = argumentTypes[a];
1002                                         for (int p = 0; p < paramLength; p++)
1003                                                 if (params[p] == arg)
1004                                                         continue nextArg;
1005                                         continue nextMethod;
1006                                 }
1007                                 return methodBinding;
1008                         }
1009                         if (found.size == 0) return null;
1010                         return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
1011                 }
1012
1013                 // check for duplicate parameterized methods
1014                 if (unitScope.environment.options.sourceLevel >= ClassFileConstants.JDK1_5) {
1015                         for (int i = 0; i < candidatesCount; i++) {
1016                                 MethodBinding current = candidates[i];
1017                                 if (current instanceof ParameterizedGenericMethodBinding)
1018                                         current = ((ParameterizedGenericMethodBinding) current).originalMethod;
1019                                 if (current instanceof ParameterizedMethodBinding)
1020                                         for (int j = i + 1; j < candidatesCount; j++)
1021                                                 if (current.declaringClass == candidates[j].declaringClass && current.areParametersEqual(candidates[j]))
1022                                                         return new ProblemMethodBinding(candidates[i].selector, candidates[i].parameters, Ambiguous);
1023                         }
1024                 }
1025
1026                 // tiebreak using visibility check
1027                 int visiblesCount = 0;
1028                 for (int i = 0; i < candidatesCount; i++) {
1029                         MethodBinding methodBinding = candidates[i];
1030                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
1031                                 if (visiblesCount != i) {
1032                                         candidates[i] = null;
1033                                         candidates[visiblesCount] = methodBinding;
1034                                 }
1035                                 visiblesCount++;
1036                         }
1037                 }
1038                 if (visiblesCount == 1) {
1039                         unitScope.recordTypeReferences(candidates[0].thrownExceptions);
1040                         return candidates[0];
1041                 }
1042                 if (visiblesCount == 0) {
1043                         MethodBinding interfaceMethod =
1044                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
1045                         if (interfaceMethod != null) return interfaceMethod;
1046                         return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
1047                 }
1048                 if (isCompliant14)
1049                         return mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite);
1050                 return candidates[0].declaringClass.isClass()
1051                         ? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
1052                         : mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
1053         }
1054         
1055         // Internal use only
1056         public MethodBinding findMethodForArray(
1057                 ArrayBinding receiverType,
1058                 char[] selector,
1059                 TypeBinding[] argumentTypes,
1060                 InvocationSite invocationSite) {
1061
1062                 TypeBinding leafType = receiverType.leafComponentType();
1063                 if (leafType instanceof ReferenceBinding) {
1064                         if (!((ReferenceBinding) leafType).canBeSeenBy(this))
1065                                 return new ProblemMethodBinding(selector, TypeConstants.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
1066                 }
1067
1068                 ReferenceBinding object = getJavaLangObject();
1069                 MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
1070                 if (methodBinding != null) {
1071                         // handle the method clone() specially... cannot be protected or throw exceptions
1072                         if (argumentTypes == NoParameters) {
1073                             switch (selector[0]) {
1074                                 case 'c': 
1075                                     if (CharOperation.equals(selector, CLONE)) {
1076                                                         return new UpdatedMethodBinding(
1077                                                                 environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
1078                                                                 (methodBinding.modifiers & ~AccProtected) | AccPublic,
1079                                                                 CLONE,
1080                                                                 methodBinding.returnType,
1081                                                                 argumentTypes,
1082                                                                 null,
1083                                                                 object);
1084                                     }
1085                                     break;
1086                                 case 'g': 
1087                                     if (CharOperation.equals(selector, GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) {
1088                                                         return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this);
1089                                     }
1090                                     break;
1091                             }
1092                         }
1093                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
1094                                 return methodBinding;
1095                 }
1096                 // answers closest approximation, may not check argumentTypes or visibility
1097                 methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
1098                 if (methodBinding == null)
1099                         return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1100                 if (methodBinding.isValidBinding()) {
1101                         MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1102                         if (compatibleMethod == null)
1103                                 return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
1104                         if (!compatibleMethod.isValidBinding())
1105                                 return compatibleMethod;
1106
1107                         methodBinding = compatibleMethod;
1108                         if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
1109                                 return new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
1110                 }
1111                 return methodBinding;
1112         }
1113
1114         public MethodBinding findMethodInSuperInterfaces(
1115                 ReferenceBinding currentType,
1116                 char[] selector,
1117                 ObjectVector found,
1118                 MethodBinding matchingMethod) {
1119
1120                 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1121                 if (itsInterfaces != NoSuperInterfaces) {
1122                         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
1123                         int lastPosition = -1;
1124                         if (++lastPosition == interfacesToVisit.length)
1125                                 System.arraycopy(
1126                                         interfacesToVisit, 0,
1127                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
1128                                         lastPosition);
1129                         interfacesToVisit[lastPosition] = itsInterfaces;
1130
1131                         for (int i = 0; i <= lastPosition; i++) {
1132                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1133                                 for (int j = 0, length = interfaces.length; j < length; j++) {
1134                                         currentType = interfaces[j];
1135                                         if ((currentType.tagBits & InterfaceVisited) == 0) {
1136                                                 // if interface as not already been visited
1137                                                 currentType.tagBits |= InterfaceVisited;
1138
1139                                                 compilationUnitScope().recordTypeReference(currentType);
1140                                                 MethodBinding[] currentMethods = currentType.getMethods(selector);
1141                                                 int currentLength = currentMethods.length;
1142                                                 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
1143                                                         matchingMethod = currentMethods[0];
1144                                                 } else if (currentLength > 0) {
1145                                                         if (matchingMethod != null) {
1146                                                                 found.add(matchingMethod);
1147                                                                 matchingMethod = null;
1148                                                         }
1149                                                         found.addAll(currentMethods);
1150                                                 }
1151                                                 itsInterfaces = currentType.superInterfaces();
1152                                                 if (itsInterfaces != NoSuperInterfaces) {
1153                                                         if (++lastPosition == interfacesToVisit.length)
1154                                                                 System.arraycopy(
1155                                                                         interfacesToVisit, 0,
1156                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
1157                                                                         lastPosition);
1158                                                         interfacesToVisit[lastPosition] = itsInterfaces;
1159                                                 }
1160                                         }
1161                                 }
1162                         }
1163
1164                         // bit reinitialization
1165                         for (int i = 0; i <= lastPosition; i++) {
1166                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
1167                                 for (int j = 0, length = interfaces.length; j < length; j++)
1168                                         interfaces[j].tagBits &= ~InterfaceVisited;
1169                         }
1170                 }
1171                 return matchingMethod;
1172         }
1173
1174         // Internal use only
1175         public ReferenceBinding findType(
1176                 char[] typeName,
1177                 PackageBinding declarationPackage,
1178                 PackageBinding invocationPackage) {
1179
1180                 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
1181                 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
1182                 if (typeBinding == null)
1183                         return null;
1184
1185                 if (typeBinding.isValidBinding()) {
1186                         if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
1187                                 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
1188                 }
1189                 return typeBinding;
1190         }
1191
1192         public LocalVariableBinding findVariable(char[] variable) {
1193
1194                 return null;
1195         }
1196         
1197         public static TypeBinding getBaseType(char[] name) {
1198                 // list should be optimized (with most often used first)
1199                 int length = name.length;
1200                 if (length > 2 && length < 8) {
1201                         switch (name[0]) {
1202                                 case 'i' :
1203                                         if (length == 3 && name[1] == 'n' && name[2] == 't')
1204                                                 return IntBinding;
1205                                         break;
1206                                 case 'v' :
1207                                         if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
1208                                                 return VoidBinding;
1209                                         break;
1210                                 case 'b' :
1211                                         if (length == 7
1212                                                 && name[1] == 'o'
1213                                                 && name[2] == 'o'
1214                                                 && name[3] == 'l'
1215                                                 && name[4] == 'e'
1216                                                 && name[5] == 'a'
1217                                                 && name[6] == 'n')
1218                                                 return BooleanBinding;
1219                                         if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
1220                                                 return ByteBinding;
1221                                         break;
1222                                 case 'c' :
1223                                         if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
1224                                                 return CharBinding;
1225                                         break;
1226                                 case 'd' :
1227                                         if (length == 6
1228                                                 && name[1] == 'o'
1229                                                 && name[2] == 'u'
1230                                                 && name[3] == 'b'
1231                                                 && name[4] == 'l'
1232                                                 && name[5] == 'e')
1233                                                 return DoubleBinding;
1234                                         break;
1235                                 case 'f' :
1236                                         if (length == 5
1237                                                 && name[1] == 'l'
1238                                                 && name[2] == 'o'
1239                                                 && name[3] == 'a'
1240                                                 && name[4] == 't')
1241                                                 return FloatBinding;
1242                                         break;
1243                                 case 'l' :
1244                                         if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
1245                                                 return LongBinding;
1246                                         break;
1247                                 case 's' :
1248                                         if (length == 5
1249                                                 && name[1] == 'h'
1250                                                 && name[2] == 'o'
1251                                                 && name[3] == 'r'
1252                                                 && name[4] == 't')
1253                                                 return ShortBinding;
1254                         }
1255                 }
1256                 return null;
1257         }
1258
1259         /* API
1260          *      
1261          *      Answer the binding that corresponds to the argument name.
1262          *      flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
1263          *      Only bindings corresponding to the mask can be answered.
1264          *
1265          *      For example, getBinding("foo", VARIABLE, site) will answer
1266          *      the binding for the field or local named "foo" (or an error binding if none exists).
1267          *      If a type named "foo" exists, it will not be detected (and an error binding will be answered)
1268          *
1269          *      The VARIABLE mask has precedence over the TYPE mask.
1270          *
1271          *      If the VARIABLE mask is not set, neither fields nor locals will be looked for.
1272          *
1273          *      InvocationSite implements:
1274          *              isSuperAccess(); this is used to determine if the discovered field is visible.
1275          *
1276          *      Limitations: cannot request FIELD independently of LOCAL, or vice versa
1277          */
1278         public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
1279
1280                 try {
1281                         Binding binding = null;
1282                         FieldBinding problemField = null;
1283                         if ((mask & Binding.VARIABLE) != 0) {
1284                                 boolean insideStaticContext = false;
1285                                 boolean insideConstructorCall = false;
1286
1287                                 FieldBinding foundField = null;
1288                                 // can be a problem field which is answered if a valid field is not found
1289                                 ProblemFieldBinding foundInsideProblem = null;
1290                                 // inside Constructor call or inside static context
1291                                 Scope scope = this;
1292                                 int depth = 0;
1293                                 int foundDepth = 0;
1294                                 ReferenceBinding foundActualReceiverType = null;
1295                                 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1296                                         switch (scope.kind) {
1297                                                 case METHOD_SCOPE :
1298                                                         MethodScope methodScope = (MethodScope) scope;
1299                                                         insideStaticContext |= methodScope.isStatic;
1300                                                         insideConstructorCall |= methodScope.isConstructorCall;
1301                                                         // Fall through... could duplicate the code below to save a cast - questionable optimization
1302                                                 case BLOCK_SCOPE :
1303                                                         LocalVariableBinding variableBinding = scope.findVariable(name);
1304                                                         // looks in this scope only
1305                                                         if (variableBinding != null) {
1306                                                                 if (foundField != null && foundField.isValidBinding())
1307                                                                         return new ProblemFieldBinding(
1308                                                                                 foundField, // closest match
1309                                                                                 foundField.declaringClass,
1310                                                                                 name,
1311                                                                                 InheritedNameHidesEnclosingName);
1312                                                                 if (depth > 0)
1313                                                                         invocationSite.setDepth(depth);
1314                                                                 return variableBinding;
1315                                                         }
1316                                                         break;
1317                                                 case CLASS_SCOPE :
1318                                                         ClassScope classScope = (ClassScope) scope;
1319                                                         SourceTypeBinding enclosingType = classScope.referenceContext.binding;
1320                                                         FieldBinding fieldBinding = classScope.findField(enclosingType, name, invocationSite, needResolve);
1321                                                         // Use next line instead if willing to enable protected access accross inner types
1322                                                         // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
1323                                                         
1324 //                                                      SourceTypeBinding initialType = this.enclosingSourceType();
1325 //                                                      if ((fieldBinding == null || !fieldBinding.isValidBinding()) && enclosingType.hasMemberTypes()) { // check member enums
1326 //                                                              ReferenceBinding[] memberTypes = enclosingType.memberTypes();
1327 //                                                              for (int i = 0, length = memberTypes.length; i < length; i++) {
1328 //                                                                      ReferenceBinding memberType = memberTypes[i];
1329 //                                                                      if (memberType != initialType && memberType.isEnum()) { // do not find one's field through its enclosing members
1330 //                                                                              FieldBinding enumField = ((SourceTypeBinding)memberType).scope.findField(memberType, name, invocationSite, needResolve);
1331 //                                                                              if (enumField != null && (enumField.modifiers & AccEnum) != 0) {
1332 //                                                                                      // grant access to enum constants of enclosing members
1333 //                                                                                      // TODO (kent) need to revisit to see whether should walk sibling enums and issue an ambiguous match
1334 //                                                                                      return enumField;
1335 //                                                                              }
1336 //                                                                      }
1337 //                                                              }
1338 //                                                      }
1339                                                         if (fieldBinding != null) { // skip it if we did not find anything
1340                                                                 if (fieldBinding.problemId() == Ambiguous) {
1341                                                                         if (foundField == null || foundField.problemId() == NotVisible)
1342                                                                                 // supercedes any potential InheritedNameHidesEnclosingName problem
1343                                                                                 return fieldBinding;
1344                                                                         // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
1345                                                                         return new ProblemFieldBinding(
1346                                                                                 foundField, // closest match
1347                                                                                 foundField.declaringClass,
1348                                                                                 name,
1349                                                                                 InheritedNameHidesEnclosingName);
1350                                                                 }
1351
1352                                                                 ProblemFieldBinding insideProblem = null;
1353                                                                 if (fieldBinding.isValidBinding()) {
1354                                                                         if (!fieldBinding.isStatic()) {
1355                                                                                 if (insideConstructorCall) {
1356                                                                                         insideProblem =
1357                                                                                                 new ProblemFieldBinding(
1358                                                                                                         fieldBinding, // closest match
1359                                                                                                         fieldBinding.declaringClass,
1360                                                                                                         name,
1361                                                                                                         NonStaticReferenceInConstructorInvocation);
1362                                                                                 } else if (insideStaticContext) {
1363                                                                                         insideProblem =
1364                                                                                                 new ProblemFieldBinding(
1365                                                                                                         fieldBinding, // closest match
1366                                                                                                         fieldBinding.declaringClass,
1367                                                                                                         name,
1368                                                                                                         NonStaticReferenceInStaticContext);
1369                                                                                 }
1370                                                                         }
1371                                                                         if (enclosingType == fieldBinding.declaringClass || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
1372                                                                                 // found a valid field in the 'immediate' scope (ie. not inherited)
1373                                                                                 // OR in 1.4 mode (inherited shadows enclosing)
1374                                                                                 if (foundField == null) {
1375                                                                                         if (depth > 0){
1376                                                                                                 invocationSite.setDepth(depth);
1377                                                                                                 invocationSite.setActualReceiverType(enclosingType);
1378                                                                                         }
1379                                                                                         // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
1380                                                                                         return insideProblem == null ? fieldBinding : insideProblem;
1381                                                                                 }
1382                                                                                 if (foundField.isValidBinding())
1383                                                                                         // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
1384                                                                                         if (foundField.declaringClass != fieldBinding.declaringClass)
1385                                                                                                 // ie. have we found the same field - do not trust field identity yet
1386                                                                                                 return new ProblemFieldBinding(
1387                                                                                                         foundField, // closest match
1388                                                                                                         foundField.declaringClass,
1389                                                                                                         name,
1390                                                                                                         InheritedNameHidesEnclosingName);
1391                                                                         }
1392                                                                 }
1393
1394                                                                 if (foundField == null || (foundField.problemId() == NotVisible && fieldBinding.problemId() != NotVisible)) {
1395                                                                         // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
1396                                                                         foundDepth = depth;
1397                                                                         foundActualReceiverType = enclosingType;
1398                                                                         foundInsideProblem = insideProblem;
1399                                                                         foundField = fieldBinding;
1400                                                                 }
1401                                                         }
1402                                                         depth++;
1403                                                         insideStaticContext |= enclosingType.isStatic();
1404                                                         // 1EX5I8Z - accessing outer fields within a constructor call is permitted
1405                                                         // in order to do so, we change the flag as we exit from the type, not the method
1406                                                         // itself, because the class scope is used to retrieve the fields.
1407                                                         MethodScope enclosingMethodScope = scope.methodScope();
1408                                                         insideConstructorCall =
1409                                                                 enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
1410                                                         break;
1411                                                 case COMPILATION_UNIT_SCOPE :
1412                                                         break done;
1413                                         }
1414                                         scope = scope.parent;
1415                                 }
1416
1417                                 if (foundInsideProblem != null)
1418                                         return foundInsideProblem;
1419                                 if (foundField != null) {
1420                                         if (foundField.isValidBinding()) {
1421                                                 if (foundDepth > 0) {
1422                                                         invocationSite.setDepth(foundDepth);
1423                                                         invocationSite.setActualReceiverType(foundActualReceiverType);
1424                                                 }
1425                                                 return foundField;
1426                                         }
1427                                         problemField = foundField;
1428                                 }
1429
1430                                 if (environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
1431                                         // at this point the scope is a compilation unit scope & need to check for imported static fields
1432                                         CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1433                                         ImportBinding[] imports = unitScope.imports;
1434                                         if (imports != null) {
1435                                                 // check single static imports
1436                                                 for (int i = 0, length = imports.length; i < length; i++) {
1437                                                         ImportBinding importBinding = imports[i];
1438                                                         if (importBinding.isStatic() && !importBinding.onDemand) {
1439                                                                 if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
1440                                                                         if (unitScope.resolveSingleImport(importBinding) != null && importBinding.resolvedImport instanceof FieldBinding) {
1441                                                                                 ImportReference importReference = importBinding.reference;
1442                                                                                 if (importReference != null) importReference.used = true;
1443                                                                                 return importBinding.resolvedImport; // already know its visible
1444                                                                         }
1445                                                                 }
1446                                                         }
1447                                                 }
1448                                                 // check on demand imports
1449                                                 boolean foundInImport = false;
1450                                                 for (int i = 0, length = imports.length; i < length; i++) {
1451                                                         ImportBinding importBinding = imports[i];
1452                                                         if (importBinding.isStatic() && importBinding.onDemand) {
1453                                                                 Binding resolvedImport = importBinding.resolvedImport;
1454                                                                 if (resolvedImport instanceof ReferenceBinding) {
1455                                                                         FieldBinding temp = findField((ReferenceBinding) resolvedImport, name, invocationSite, needResolve);
1456                                                                         if (temp != null) {
1457                                                                                 if (!temp.isValidBinding()) {
1458                                                                                         problemField = temp;
1459                                                                                 } else if (temp.isStatic()) {
1460                                                                                         ImportReference importReference = importBinding.reference;
1461                                                                                         if (importReference != null) importReference.used = true;
1462                                                                                         if (foundInImport)
1463                                                                                                 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1464                                                                                                 return new ProblemReferenceBinding(name, Ambiguous);
1465                                                                                         foundField = temp;
1466                                                                                         foundInImport = true;
1467                                                                                 }
1468                                                                         }
1469                                                                 }
1470                                                         }
1471                                                 }
1472                                                 if (foundField != null) return foundField;
1473                                         }
1474                                 }
1475                         }
1476
1477                         // We did not find a local or instance variable.
1478                         if ((mask & Binding.TYPE) != 0) {
1479                                 if ((binding = getBaseType(name)) != null)
1480                                         return binding;
1481                                 binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
1482                                 if (binding.isValidBinding() || mask == Binding.TYPE)
1483                                         return binding;
1484                                 // answer the problem type binding if we are only looking for a type
1485                         } else if ((mask & Binding.PACKAGE) != 0) {
1486                                 compilationUnitScope().recordSimpleReference(name);
1487                                 if ((binding = environment().getTopLevelPackage(name)) != null)
1488                                         return binding;
1489                         }
1490                         if (problemField != null) return problemField;
1491                         return new ProblemBinding(name, enclosingSourceType(), NotFound);
1492                 } catch (AbortCompilation e) {
1493                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1494                         throw e;
1495                 }
1496         }
1497
1498         public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1499                 try {
1500                         CompilationUnitScope unitScope = compilationUnitScope();
1501                         unitScope.recordTypeReference(receiverType);
1502                         unitScope.recordTypeReferences(argumentTypes);
1503                         MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
1504                         if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) {
1505                             // targeting a non generic constructor with type arguments ?
1506                             if (invocationSite.genericTypeArguments() != null)
1507                                 methodBinding = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);                          
1508                                 return methodBinding;
1509                         }
1510                         MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
1511                         if (methods == NoMethods)
1512                                 return new ProblemMethodBinding(
1513                                         TypeConstants.INIT,
1514                                         argumentTypes,
1515                                         NotFound);
1516
1517                         MethodBinding[] compatible = new MethodBinding[methods.length];
1518                         int compatibleIndex = 0;
1519                         MethodBinding problemMethod = null;
1520                         for (int i = 0, length = methods.length; i < length; i++) {
1521                                 MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
1522                                 if (compatibleMethod != null) {
1523                                         if (compatibleMethod.isValidBinding())
1524                                                 compatible[compatibleIndex++] = compatibleMethod;
1525                                         else if (problemMethod == null)
1526                                                 problemMethod = compatibleMethod;
1527                                 }
1528                         }
1529                         if (compatibleIndex == 0) {
1530                                 if (problemMethod == null)
1531                                         return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, NotFound);
1532                                 return problemMethod;
1533                         }
1534                         // need a more descriptive error... cannot convert from X to Y
1535         
1536                         MethodBinding[] visible = new MethodBinding[compatibleIndex];
1537                         int visibleIndex = 0;
1538                         for (int i = 0; i < compatibleIndex; i++) {
1539                                 MethodBinding method = compatible[i];
1540                                 if (method.canBeSeenBy(invocationSite, this))
1541                                         visible[visibleIndex++] = method;
1542                         }
1543                         if (visibleIndex == 1) return visible[0];
1544                         if (visibleIndex == 0)
1545                                 return new ProblemMethodBinding(
1546                                         compatible[0],
1547                                         TypeConstants.INIT,
1548                                         compatible[0].parameters,
1549                                         NotVisible);
1550                         // all of visible are from the same declaringClass, even before 1.4 we can call this method instead of mostSpecificClassMethodBinding
1551                         return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite);
1552                 } catch (AbortCompilation e) {
1553                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1554                         throw e;
1555                 }
1556         }
1557
1558         public final PackageBinding getCurrentPackage() {
1559                 Scope scope, unitScope = this;
1560                 while ((scope = unitScope.parent) != null)
1561                         unitScope = scope;
1562                 return ((CompilationUnitScope) unitScope).fPackage;
1563         }
1564
1565         /**
1566          * Returns the modifiers of the innermost enclosing declaration.
1567          * @return modifiers
1568          */
1569         public int getDeclarationModifiers(){
1570                 switch(this.kind){
1571                         case Scope.BLOCK_SCOPE :
1572                         case Scope.METHOD_SCOPE :
1573                                 MethodScope methodScope = methodScope();
1574                                 if (!methodScope.isInsideInitializer()){
1575                                         // check method modifiers to see if deprecated
1576                                         MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1577                                         if (context != null)
1578                                                 return context.modifiers;
1579                                 } else {
1580                                         SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
1581
1582                                         // inside field declaration ? check field modifier to see if deprecated
1583                                         if (methodScope.initializedField != null)
1584                                                 return methodScope.initializedField.modifiers;
1585                                         if (type != null)
1586                                                 return type.modifiers;
1587                                 }
1588                                 break;
1589                         case Scope.CLASS_SCOPE :
1590                                 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1591                                 if (context != null)
1592                                         return context.modifiers;
1593                                 break;
1594                 }
1595                 return -1;
1596         }
1597
1598         public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
1599                 try {
1600                         FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/);
1601                         if (field != null) return field;
1602         
1603                         return new ProblemFieldBinding(
1604                                 receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
1605                                 fieldName,
1606                                 NotFound);
1607                 } catch (AbortCompilation e) {
1608                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1609                         throw e;
1610                 }                       
1611         }
1612
1613         /* API
1614          *      
1615          *      Answer the method binding that corresponds to selector, argumentTypes.
1616          *      Start the lookup at the enclosing type of the receiver.
1617          *      InvocationSite implements 
1618          *              isSuperAccess(); this is used to determine if the discovered method is visible.
1619          *              setDepth(int); this is used to record the depth of the discovered method
1620          *                      relative to the enclosing type of the receiver. (If the method is defined
1621          *                      in the enclosing type of the receiver, the depth is 0; in the next enclosing
1622          *                      type, the depth is 1; and so on
1623          * 
1624          *      If no visible method is discovered, an error binding is answered.
1625          */
1626         public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1627
1628                 boolean insideStaticContext = false;
1629                 boolean insideConstructorCall = false;
1630                 MethodBinding foundMethod = null;
1631                 MethodBinding foundFuzzyProblem = null;
1632                 // the weird method lookup case (matches method name in scope, then arg types, then visibility)
1633                 MethodBinding foundInsideProblem = null;
1634                 // inside Constructor call or inside static context
1635                 Scope scope = this;
1636                 int depth = 0;
1637                 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1638                         switch (scope.kind) {
1639                                 case METHOD_SCOPE :
1640                                         MethodScope methodScope = (MethodScope) scope;
1641                                         insideStaticContext |= methodScope.isStatic;
1642                                         insideConstructorCall |= methodScope.isConstructorCall;
1643                                         break;
1644                                 case CLASS_SCOPE :
1645                                         ClassScope classScope = (ClassScope) scope;
1646                                         SourceTypeBinding receiverType = classScope.referenceContext.binding;
1647                                         boolean isExactMatch = true;
1648                                         // retrieve an exact visible match (if possible)
1649                                         // compilationUnitScope().recordTypeReference(receiverType);   not needed since receiver is the source type
1650                                         MethodBinding methodBinding =
1651                                                 (foundMethod == null)
1652                                                         ? classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite)
1653                                                         : classScope.findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite);
1654                                         if (methodBinding == null) {
1655                                                 // answers closest approximation, may not check argumentTypes or visibility
1656                                                 isExactMatch = false;
1657                                                 methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
1658                                                 // methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
1659                                         }
1660                                         if (methodBinding != null) { // skip it if we did not find anything
1661                                                 if (methodBinding.problemId() == Ambiguous) {
1662                                                         if (foundMethod == null || foundMethod.problemId() == NotVisible) {
1663                                                                 // supercedes any potential InheritedNameHidesEnclosingName problem
1664                                                                 return methodBinding;
1665                                                         }
1666                                                         // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
1667                                                         return new ProblemMethodBinding(
1668                                                                 methodBinding, // closest match
1669                                                                 selector,
1670                                                                 argumentTypes,
1671                                                                 InheritedNameHidesEnclosingName);
1672                                                 }
1673                                                 MethodBinding fuzzyProblem = null;
1674                                                 MethodBinding insideProblem = null;
1675                                                 if (methodBinding.isValidBinding()) {
1676                                                         if (!isExactMatch) {
1677                                                                 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1678                                                                 if (compatibleMethod == null) {
1679                                                                         if (foundMethod == null || foundMethod.problemId() == NotVisible)
1680                                                                                 // inherited mismatch is reported directly, not looking at enclosing matches
1681                                                                                 return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
1682                                                                         // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
1683                                                                         fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
1684                                                                 } else if (!compatibleMethod.isValidBinding()) {
1685                                                                         fuzzyProblem = compatibleMethod;
1686                                                                 } else {
1687                                                                         methodBinding = compatibleMethod;
1688                                                                         if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
1689                                                                                 // using <classScope> instead of <this> for visibility check does grant all access to innerclass
1690                                                                                 fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
1691                                                                         }
1692                                                                 }
1693                                                         }
1694                                                         if (fuzzyProblem == null && !methodBinding.isStatic()) {
1695                                                                 if (insideConstructorCall) {
1696                                                                         insideProblem =
1697                                                                                 new ProblemMethodBinding(
1698                                                                                         methodBinding, // closest match
1699                                                                                         methodBinding.selector,
1700                                                                                         methodBinding.parameters,
1701                                                                                         NonStaticReferenceInConstructorInvocation);
1702                                                                 } else if (insideStaticContext) {
1703                                                                         insideProblem =
1704                                                                                 new ProblemMethodBinding(
1705                                                                                         methodBinding, // closest match
1706                                                                                         methodBinding.selector,
1707                                                                                         methodBinding.parameters,
1708                                                                                         NonStaticReferenceInStaticContext);
1709                                                                 }
1710                                                         }
1711
1712                                                         if (receiverType == methodBinding.declaringClass
1713                                                                 || (receiverType.getMethods(selector)) != NoMethods
1714                                                                 || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)) {
1715                                                                 // found a valid method in the 'immediate' scope (ie. not inherited)
1716                                                                 // OR the receiverType implemented a method with the correct name
1717                                                                 // OR in 1.4 mode (inherited visible shadows enclosing)
1718                                                                 if (foundMethod == null) {
1719                                                                         if (depth > 0){
1720                                                                                 invocationSite.setDepth(depth);
1721                                                                                 invocationSite.setActualReceiverType(receiverType);
1722                                                                         }
1723                                                                         // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
1724                                                                         if (fuzzyProblem != null)
1725                                                                                 return fuzzyProblem;
1726                                                                         if (insideProblem != null)
1727                                                                                 return insideProblem;
1728                                                                         return methodBinding;
1729                                                                 }
1730                                                                 // if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
1731                                                                 // NOTE: Unlike fields, a non visible method hides a visible method
1732                                                                 if (foundMethod.declaringClass != methodBinding.declaringClass)
1733                                                                         // ie. have we found the same method - do not trust field identity yet
1734                                                                         return new ProblemMethodBinding(
1735                                                                                 methodBinding, // closest match
1736                                                                                 methodBinding.selector,
1737                                                                                 methodBinding.parameters,
1738                                                                                 InheritedNameHidesEnclosingName);
1739                                                         }
1740                                                 }
1741
1742                                                 if (foundMethod == null || (foundMethod.problemId() == NotVisible && methodBinding.problemId() != NotVisible)) {
1743                                                         // only remember the methodBinding if its the first one found or the previous one was not visible & methodBinding is...
1744                                                         // remember that private methods are visible if defined directly by an enclosing class
1745                                                         if (depth > 0) {
1746                                                                 invocationSite.setDepth(depth);
1747                                                                 invocationSite.setActualReceiverType(receiverType);
1748                                                         }
1749                                                         foundFuzzyProblem = fuzzyProblem;
1750                                                         foundInsideProblem = insideProblem;
1751                                                         if (fuzzyProblem == null)
1752                                                                 foundMethod = methodBinding; // only keep it if no error was found
1753                                                 }
1754                                         }
1755                                         depth++;
1756                                         insideStaticContext |= receiverType.isStatic();
1757                                         // 1EX5I8Z - accessing outer fields within a constructor call is permitted
1758                                         // in order to do so, we change the flag as we exit from the type, not the method
1759                                         // itself, because the class scope is used to retrieve the fields.
1760                                         MethodScope enclosingMethodScope = scope.methodScope();
1761                                         insideConstructorCall =
1762                                                 enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
1763                                         break;
1764                                 case COMPILATION_UNIT_SCOPE :
1765                                         break done;
1766                         }
1767                         scope = scope.parent;
1768                 }
1769
1770                 if (foundFuzzyProblem != null)
1771                         return foundFuzzyProblem;
1772                 if (foundInsideProblem != null)
1773                         return foundInsideProblem;
1774                 if (foundMethod != null)
1775                         return foundMethod;
1776
1777                 if (insideStaticContext && environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
1778                         // at this point the scope is a compilation unit scope & need to check for imported static methods
1779                         CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1780                         ImportBinding[] imports = unitScope.imports;
1781                         if (imports != null) {
1782                                 // check on demand imports
1783                                 boolean foundInImport = false;
1784                                 for (int i = 0, length = imports.length; i < length; i++) {
1785                                         ImportBinding importBinding = imports[i];
1786                                         if (importBinding.isStatic() && importBinding.onDemand) {
1787                                                 Binding resolvedImport = importBinding.resolvedImport;
1788                                                 if (resolvedImport instanceof ReferenceBinding) {
1789                                                         // answers closest approximation, may not check argumentTypes or visibility
1790                                                         MethodBinding temp = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite);
1791                                                         if (temp != null) {
1792                                                                 if (!temp.isValidBinding()) {
1793                                                                         if (foundMethod == null)
1794                                                                                 foundMethod = temp;
1795                                                                 } else if (temp.isStatic()) {
1796                                                                         MethodBinding compatibleMethod = computeCompatibleMethod(temp, argumentTypes, invocationSite);
1797                                                                         if (compatibleMethod != null) {
1798                                                                                 if (compatibleMethod.isValidBinding()) {
1799                                                                                         if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
1800                                                                                                 ImportReference importReference = importBinding.reference;
1801                                                                                                 if (importReference != null) importReference.used = true;
1802                                                                                                 if (foundInImport)
1803                                                                                                         // Answer error binding -- import on demand conflict; name found in two import on demand types.
1804                                                                                                         return new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, Ambiguous);
1805                                                                                                 foundMethod = compatibleMethod;
1806                                                                                                 foundInImport = true;
1807                                                                                         } else if (foundMethod == null) {
1808                                                                                                 foundMethod = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, NotVisible);
1809                                                                                         }
1810                                                                                 }
1811                                                                         } else if (foundMethod == null) {
1812                                                                                 foundMethod = new ProblemMethodBinding(temp, selector, argumentTypes, NotFound);
1813                                                                         }
1814                                                                 }
1815                                                         }
1816                                                 }
1817                                         }
1818                                 }
1819                         }
1820                         if (foundMethod != null)
1821                                 return foundMethod;
1822                 }
1823                 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1824         }
1825
1826         public final ReferenceBinding getJavaIoSerializable() {
1827                 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
1828                 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
1829                 if (type != null) return type;
1830         
1831                 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
1832                 return null; // will not get here since the above error aborts the compilation
1833         }
1834         
1835         public final ReferenceBinding getJavaLangAnnotationAnnotation() {
1836                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ANNOTATION_ANNOTATION);
1837                 ReferenceBinding type = environment().getType(JAVA_LANG_ANNOTATION_ANNOTATION);
1838                 if (type != null) return type;
1839         
1840                 problemReporter().isClassPathCorrect(JAVA_LANG_ANNOTATION_ANNOTATION, referenceCompilationUnit());
1841                 return null; // will not get here since the above error aborts the compilation
1842         }
1843         
1844         public final ReferenceBinding getJavaLangAssertionError() {
1845                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
1846                 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
1847                 if (type != null) return type;
1848                 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
1849                 return null; // will not get here since the above error aborts the compilation
1850         }
1851
1852         public final ReferenceBinding getJavaLangClass() {
1853                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
1854                 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
1855                 if (type != null) return type;
1856         
1857                 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
1858                 return null; // will not get here since the above error aborts the compilation
1859         }
1860
1861         public final ReferenceBinding getJavaLangCloneable() {
1862                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
1863                 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
1864                 if (type != null) return type;
1865         
1866                 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
1867                 return null; // will not get here since the above error aborts the compilation
1868         }
1869         public final ReferenceBinding getJavaLangEnum() {
1870                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ENUM);
1871                 ReferenceBinding type = environment().getType(JAVA_LANG_ENUM);
1872                 if (type != null) return type;
1873         
1874                 problemReporter().isClassPathCorrect(JAVA_LANG_ENUM, referenceCompilationUnit());
1875                 return null; // will not get here since the above error aborts the compilation
1876         }
1877         public final ReferenceBinding getJavaLangError() {
1878                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
1879                 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
1880                 if (type != null) return type;
1881         
1882                 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
1883                 return null; // will not get here since the above error aborts the compilation
1884         }
1885         public final ReferenceBinding getJavaLangIterable() {
1886                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ITERABLE);
1887                 ReferenceBinding type = environment().getType(JAVA_LANG_ITERABLE);
1888                 if (type != null) return type;
1889         
1890                 problemReporter().isClassPathCorrect(JAVA_LANG_ITERABLE, referenceCompilationUnit());
1891                 return null; // will not get here since the above error aborts the compilation
1892         }
1893         public final ReferenceBinding getJavaLangObject() {
1894                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
1895                 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
1896                 if (type != null) return type;
1897         
1898                 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
1899                 return null; // will not get here since the above error aborts the compilation
1900         }
1901
1902         public final ReferenceBinding getJavaLangRuntimeException() {
1903                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
1904                 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
1905                 if (type != null) return type;
1906         
1907                 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
1908                 return null; // will not get here since the above error aborts the compilation
1909         }
1910
1911         public final ReferenceBinding getJavaLangString() {
1912                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
1913                 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
1914                 if (type != null) return type;
1915         
1916                 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
1917                 return null; // will not get here since the above error aborts the compilation
1918         }
1919
1920         public final ReferenceBinding getJavaLangThrowable() {
1921                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
1922                 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
1923                 if (type != null) return type;
1924         
1925                 problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
1926                 return null; // will not get here since the above error aborts the compilation
1927         }
1928         public final ReferenceBinding getJavaUtilIterator() {
1929                 compilationUnitScope().recordQualifiedReference(JAVA_UTIL_ITERATOR);
1930                 ReferenceBinding type = environment().getType(JAVA_UTIL_ITERATOR);
1931                 if (type != null) return type;
1932         
1933                 problemReporter().isClassPathCorrect(JAVA_UTIL_ITERATOR, referenceCompilationUnit());
1934                 return null; // will not get here since the above error aborts the compilation
1935         }
1936
1937         /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
1938         */
1939         public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
1940                 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
1941                 if (memberType != null) return memberType;
1942                 return new ProblemReferenceBinding(typeName, NotFound);
1943         }
1944
1945         public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1946                 try {
1947                         if (receiverType.isBaseType())
1948                                 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1949
1950                         compilationUnitScope().recordTypeReference(receiverType);
1951                         if (receiverType.isArrayType())
1952                                 return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
1953
1954                         ReferenceBinding currentType = (ReferenceBinding) receiverType;
1955                         if (!currentType.canBeSeenBy(this))
1956                                 return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
1957         
1958                         // retrieve an exact visible match (if possible)
1959                         MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
1960                         if (methodBinding != null) return methodBinding;
1961         
1962                         // TODO (kent) performance - we are accumulating super methods which are *hidden* during the walk (see testcase from bug 69141)
1963                         // answers closest approximation, may not check argumentTypes or visibility
1964                         methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
1965                         if (methodBinding == null)
1966                                 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1967                         if (methodBinding.isValidBinding()) {
1968                                 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1969                                 if (compatibleMethod == null)
1970                                         return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
1971                                 if (!compatibleMethod.isValidBinding())
1972                                         return compatibleMethod;
1973         
1974                                 methodBinding = compatibleMethod;
1975                                 if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
1976                                         return new ProblemMethodBinding( methodBinding, selector, methodBinding.parameters, NotVisible);
1977                         }
1978                         return methodBinding;
1979                 } catch (AbortCompilation e) {
1980                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1981                         throw e;
1982                 }
1983         }
1984
1985         /* Answer the package from the compoundName or null if it begins with a type.
1986         * Intended to be used while resolving a qualified type name.
1987         *
1988         * NOTE: If a problem binding is returned, senders should extract the compound name
1989         * from the binding & not assume the problem applies to the entire compoundName.
1990         */
1991         public final Binding getPackage(char[][] compoundName) {
1992                 compilationUnitScope().recordQualifiedReference(compoundName);
1993                 Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
1994                 if (binding == null)
1995                         return new ProblemReferenceBinding(compoundName[0], NotFound);
1996                 if (!binding.isValidBinding())
1997                         return (ReferenceBinding) binding;
1998
1999                 if (!(binding instanceof PackageBinding)) return null; // compoundName does not start with a package
2000
2001                 int currentIndex = 1;
2002                 PackageBinding packageBinding = (PackageBinding) binding;
2003                 while (currentIndex < compoundName.length) {
2004                         binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
2005                         if (binding == null)
2006                                 return new ProblemReferenceBinding(
2007                                         CharOperation.subarray(compoundName, 0, currentIndex),
2008                                         NotFound);
2009                         if (!binding.isValidBinding())
2010                                 return new ProblemReferenceBinding(
2011                                         CharOperation.subarray(compoundName, 0, currentIndex),
2012                                         binding.problemId());
2013                         if (!(binding instanceof PackageBinding))
2014                                 return packageBinding;
2015                         packageBinding = (PackageBinding) binding;
2016                 }
2017                 return new ProblemReferenceBinding(compoundName, NotFound);
2018         }
2019
2020         /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
2021         * The name provided is a simple source name (e.g., "Object" , "Point", ...)
2022         */
2023         // The return type of this method could be ReferenceBinding if we did not answer base types.
2024         // NOTE: We could support looking for Base Types last in the search, however any code using
2025         // this feature would be extraordinarily slow.  Therefore we don't do this
2026         public final TypeBinding getType(char[] name) {
2027                 // Would like to remove this test and require senders to specially handle base types
2028                 TypeBinding binding = getBaseType(name);
2029                 if (binding != null) return binding;
2030                 return (ReferenceBinding) getTypeOrPackage(name, Binding.TYPE);
2031         }
2032
2033         /* Answer the type binding that corresponds to the given name, starting the lookup in the receiver
2034         * or the packageBinding if provided.
2035         * The name provided is a simple source name (e.g., "Object" , "Point", ...)
2036         */
2037         public final TypeBinding getType(char[] name, PackageBinding packageBinding) {
2038                 if (packageBinding == null)
2039                         return getType(name);
2040
2041                 Binding binding = packageBinding.getTypeOrPackage(name);
2042                 if (binding == null)
2043                         return new ProblemReferenceBinding(
2044                                 CharOperation.arrayConcat(packageBinding.compoundName, name),
2045                                 NotFound);
2046                 if (!binding.isValidBinding())
2047                         return new ProblemReferenceBinding(
2048                                 CharOperation.arrayConcat(packageBinding.compoundName, name),
2049                                 binding.problemId());
2050
2051                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
2052                 if (!typeBinding.canBeSeenBy(this))
2053                         return new ProblemReferenceBinding(
2054                                 CharOperation.arrayConcat(packageBinding.compoundName, name),
2055                                 typeBinding,
2056                                 NotVisible);
2057                 return typeBinding;
2058         }
2059
2060         /* Answer the type binding corresponding to the compoundName.
2061         *
2062         * NOTE: If a problem binding is returned, senders should extract the compound name
2063         * from the binding & not assume the problem applies to the entire compoundName.
2064         */
2065         public final TypeBinding getType(char[][] compoundName, int typeNameLength) {
2066                 if (typeNameLength == 1) {
2067                         // Would like to remove this test and require senders to specially handle base types
2068                         TypeBinding binding = getBaseType(compoundName[0]);
2069                         if (binding != null) return binding;
2070                 }
2071
2072                 CompilationUnitScope unitScope = compilationUnitScope();
2073                 unitScope.recordQualifiedReference(compoundName);
2074                 Binding binding =
2075                         getTypeOrPackage(compoundName[0], typeNameLength == 1 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
2076                 if (binding == null)
2077                         return new ProblemReferenceBinding(compoundName[0], NotFound);
2078                 if (!binding.isValidBinding())
2079                         return (ReferenceBinding) binding;
2080
2081                 int currentIndex = 1;
2082                 boolean checkVisibility = false;
2083                 if (binding instanceof PackageBinding) {
2084                         PackageBinding packageBinding = (PackageBinding) binding;
2085                         while (currentIndex < typeNameLength) {
2086                                 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
2087                                 if (binding == null)
2088                                         return new ProblemReferenceBinding(
2089                                                 CharOperation.subarray(compoundName, 0, currentIndex),
2090                                                 NotFound);
2091                                 if (!binding.isValidBinding())
2092                                         return new ProblemReferenceBinding(
2093                                                 CharOperation.subarray(compoundName, 0, currentIndex),
2094                                                 binding.problemId());
2095                                 if (!(binding instanceof PackageBinding))
2096                                         break;
2097                                 packageBinding = (PackageBinding) binding;
2098                         }
2099                         if (binding instanceof PackageBinding)
2100                                 return new ProblemReferenceBinding(
2101                                         CharOperation.subarray(compoundName, 0, currentIndex),
2102                                         NotFound);
2103                         checkVisibility = true;
2104                 }
2105
2106                 // binding is now a ReferenceBinding
2107                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
2108                 unitScope.recordTypeReference(typeBinding);
2109                 if (checkVisibility) // handles the fall through case
2110                         if (!typeBinding.canBeSeenBy(this))
2111                                 return new ProblemReferenceBinding(
2112                                         CharOperation.subarray(compoundName, 0, currentIndex),
2113                                         typeBinding,
2114                                         NotVisible);
2115
2116                 while (currentIndex < typeNameLength) {
2117                         typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
2118                         if (!typeBinding.isValidBinding()) {
2119                                 if (typeBinding instanceof ProblemReferenceBinding) {
2120                                         ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding;
2121                                         return new ProblemReferenceBinding(
2122                                                 CharOperation.subarray(compoundName, 0, currentIndex),
2123                                                 problemBinding.original,
2124                                                 typeBinding.problemId());
2125                                 }
2126                                 return new ProblemReferenceBinding(
2127                                         CharOperation.subarray(compoundName, 0, currentIndex),
2128                                         typeBinding.problemId());
2129                         }
2130                 }
2131                 return typeBinding;
2132         }
2133
2134         /* Internal use only 
2135         */
2136         final Binding getTypeOrPackage(char[] name, int mask) {
2137                 Scope scope = this;
2138                 ReferenceBinding foundType = null;
2139                 boolean insideStaticContext = false;
2140                 if ((mask & Binding.TYPE) == 0) {
2141                         Scope next = scope;
2142                         while ((next = scope.parent) != null)
2143                                 scope = next;
2144                 } else {
2145                         done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
2146                                 switch (scope.kind) {
2147                                         case METHOD_SCOPE :
2148                                                 MethodScope methodScope = (MethodScope) scope;
2149                                                 AbstractMethodDeclaration methodDecl = methodScope.referenceMethod();
2150                                                 if (methodDecl != null && methodDecl.binding != null) {
2151                                                         TypeVariableBinding typeVariable = methodDecl.binding.getTypeVariable(name);
2152                                                         if (typeVariable != null)       return typeVariable;
2153                                                 }
2154                                                 insideStaticContext |= methodScope.isStatic;
2155                                         case BLOCK_SCOPE :
2156                                                 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
2157                                                 if (localType != null) {
2158                                                         if (foundType != null && foundType != localType)
2159                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2160                                                         return localType;
2161                                                 }
2162                                                 break;
2163                                         case CLASS_SCOPE :
2164                                                 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
2165                                                 if (sourceType.isHierarchyBeingConnected()) {
2166                                                         // type variables take precedence over the source type, ex. class X <X> extends X == class X <Y> extends Y 
2167                                                         TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
2168                                                         if (typeVariable != null)
2169                                                                 return typeVariable;
2170                                                         if (CharOperation.equals(name, sourceType.sourceName))
2171                                                                 return sourceType;
2172                                                         break;
2173                                                 }
2174                                                 // type variables take precedence over member types
2175                                                 TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
2176                                                 if (typeVariable != null) {
2177                                                         if (insideStaticContext) // do not consider this type modifiers: access is legite within same type
2178                                                                 return new ProblemReferenceBinding(name, NonStaticReferenceInStaticContext);
2179                                                         return typeVariable;
2180                                                 }
2181                                                 insideStaticContext |= (sourceType.modifiers & AccStatic) != 0; // not isStatic()
2182                                                 // 6.5.5.1 - member types have precedence over top-level type in same unit
2183                                                 ReferenceBinding memberType = findMemberType(name, sourceType);
2184                                                 if (memberType != null) { // skip it if we did not find anything
2185                                                         if (memberType.problemId() == Ambiguous) {
2186                                                                 if (foundType == null || foundType.problemId() == NotVisible)
2187                                                                         // supercedes any potential InheritedNameHidesEnclosingName problem
2188                                                                         return memberType;
2189                                                                 // make the user qualify the type, likely wants the first inherited type
2190                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2191                                                         }
2192                                                         if (memberType.isValidBinding()) {
2193                                                                 if (sourceType == memberType.enclosingType()
2194                                                                                 || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
2195                                                                         // found a valid type in the 'immediate' scope (ie. not inherited)
2196                                                                         // OR in 1.4 mode (inherited shadows enclosing)
2197                                                                         if (foundType == null)
2198                                                                                 return memberType; 
2199                                                                         // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
2200                                                                         if (foundType.isValidBinding() && foundType != memberType)
2201                                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2202                                                                 }
2203                                                         }
2204                                                         if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
2205                                                                 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
2206                                                                 foundType = memberType;
2207                                                 }
2208                                                 if (CharOperation.equals(sourceType.sourceName, name)) {
2209                                                         if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
2210                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2211                                                         return sourceType;
2212                                                 }
2213                                                 break;
2214                                         case COMPILATION_UNIT_SCOPE :
2215                                                 break done;
2216                                 }
2217                                 scope = scope.parent;
2218                         }
2219                         if (foundType != null && foundType.problemId() != NotVisible)
2220                                 return foundType;
2221                 }
2222
2223                 // at this point the scope is a compilation unit scope
2224                 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
2225                 PackageBinding currentPackage = unitScope.fPackage; 
2226                 // ask for the imports + name
2227                 if ((mask & Binding.TYPE) != 0) {
2228                         // check single type imports.
2229
2230                         ImportBinding[] imports = unitScope.imports;
2231                         if (imports != null) {
2232                                 HashtableOfObject typeImports = unitScope.resolvedSingeTypeImports;
2233                                 if (typeImports != null) {
2234                                         ImportBinding typeImport = (ImportBinding) typeImports.get(name);
2235                                         if (typeImport != null) {
2236                                                 ImportReference importReference = typeImport.reference;
2237                                                 if (importReference != null) importReference.used = true;
2238                                                 return typeImport.resolvedImport; // already know its visible
2239                                         }
2240                                 } else {
2241                                         // walk all the imports since resolvedSingeTypeImports is not yet initialized
2242                                         for (int i = 0, length = imports.length; i < length; i++) {
2243                                                 ImportBinding typeImport = imports[i];
2244                                                 if (!typeImport.onDemand) {
2245                                                         if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
2246                                                                 if (unitScope.resolveSingleImport(typeImport) != null) {
2247                                                                         ImportReference importReference = typeImport.reference;
2248                                                                         if (importReference != null)
2249                                                                                 importReference.used = true;
2250                                                                         return typeImport.resolvedImport; // already know its visible
2251                                                                 }
2252                                                         }
2253                                                 }
2254                                         }
2255                                 }
2256                         }
2257                         // check if the name is in the current package, skip it if its a sub-package
2258                         unitScope.recordReference(currentPackage.compoundName, name);
2259                         Binding binding = currentPackage.getTypeOrPackage(name);
2260                         if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
2261
2262                         // check on demand imports
2263                         if (imports != null) {
2264                                 boolean foundInImport = false;
2265                                 ReferenceBinding type = null;
2266                                 for (int i = 0, length = imports.length; i < length; i++) {
2267                                         ImportBinding someImport = imports[i];
2268                                         if (someImport.onDemand) {
2269                                                 Binding resolvedImport = someImport.resolvedImport;
2270                                                 ReferenceBinding temp = resolvedImport instanceof PackageBinding
2271                                                         ? findType(name, (PackageBinding) resolvedImport, currentPackage)
2272                                                         : (someImport.isStatic()
2273                                                                 ? findMemberType(name, (ReferenceBinding) resolvedImport) // static imports are allowed to see inherited member types
2274                                                                 : findDirectMemberType(name, (ReferenceBinding) resolvedImport));
2275                                                 if (temp != null) {
2276                                                         if (temp.isValidBinding()) {
2277                                                                 ImportReference importReference = someImport.reference;
2278                                                                 if (importReference != null) importReference.used = true;
2279                                                                 if (foundInImport)
2280                                                                         // Answer error binding -- import on demand conflict; name found in two import on demand packages.
2281                                                                         return new ProblemReferenceBinding(name, Ambiguous);
2282                                                                 type = temp;
2283                                                                 foundInImport = true;
2284                                                         } else if (foundType == null) {
2285                                                                 foundType = temp;
2286                                                         }
2287                                                 }
2288                                         }
2289                                 }
2290                                 if (type != null) return type;
2291                         }
2292                 }
2293
2294                 unitScope.recordSimpleReference(name);
2295                 if ((mask & Binding.PACKAGE) != 0) {
2296                         PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
2297                         if (packageBinding != null) return packageBinding;
2298                 }
2299
2300                 // Answer error binding -- could not find name
2301                 if (foundType != null) return foundType; // problem type from above
2302                 return new ProblemReferenceBinding(name, NotFound);
2303         }
2304
2305         // Added for code assist... NOT Public API
2306         // DO NOT USE to resolve import references since this method assumes 'A.B' is relative to a single type import of 'p1.A'
2307         // when it may actually mean the type B in the package A
2308         // use CompilationUnitScope.getImport(char[][]) instead
2309         public final Binding getTypeOrPackage(char[][] compoundName) {
2310                 int nameLength = compoundName.length;
2311                 if (nameLength == 1) {
2312                         TypeBinding binding = getBaseType(compoundName[0]);
2313                         if (binding != null) return binding;
2314                 }
2315                 Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
2316                 if (!binding.isValidBinding()) return binding;
2317
2318                 int currentIndex = 1;
2319                 boolean checkVisibility = false;
2320                 if (binding instanceof PackageBinding) {
2321                         PackageBinding packageBinding = (PackageBinding) binding;
2322
2323                         while (currentIndex < nameLength) {
2324                                 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
2325                                 if (binding == null)
2326                                         return new ProblemReferenceBinding(
2327                                                 CharOperation.subarray(compoundName, 0, currentIndex),
2328                                                 NotFound);
2329                                 if (!binding.isValidBinding())
2330                                         return new ProblemReferenceBinding(
2331                                                 CharOperation.subarray(compoundName, 0, currentIndex),
2332                                                 binding.problemId());
2333                                 if (!(binding instanceof PackageBinding))
2334                                         break;
2335                                 packageBinding = (PackageBinding) binding;
2336                         }
2337                         if (binding instanceof PackageBinding) return binding;
2338                         checkVisibility = true;
2339                 }
2340                 // binding is now a ReferenceBinding
2341                 ReferenceBinding qualifiedType = null;
2342
2343                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
2344                 if (typeBinding.isGenericType()) {
2345                         qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
2346                 } else {
2347                         qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
2348                                 ? this.createParameterizedType(typeBinding, null, qualifiedType)
2349                                 : typeBinding;
2350                 }
2351
2352                 if (checkVisibility) // handles the fall through case
2353                         if (!typeBinding.canBeSeenBy(this))
2354                                 return new ProblemReferenceBinding(
2355                                         CharOperation.subarray(compoundName, 0, currentIndex),
2356                                         typeBinding,
2357                                         NotVisible);
2358
2359                 while (currentIndex < nameLength) {
2360                         typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
2361
2362                         if (typeBinding.isGenericType()) {
2363                                 qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
2364                         } else {
2365                                 qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
2366                                         ? this.createParameterizedType(typeBinding, null, qualifiedType)
2367                                         : typeBinding;
2368                         }
2369
2370                         // checks visibility
2371                         if (!qualifiedType.isValidBinding())
2372                                 return new ProblemReferenceBinding(
2373                                         CharOperation.subarray(compoundName, 0, currentIndex),
2374                                         qualifiedType.problemId());
2375                 }
2376                 return qualifiedType;
2377         }
2378         
2379         // 5.1.10
2380         public TypeBinding[] greaterLowerBound(TypeBinding[] types) {
2381                 if (types == null) return null;
2382                 int length = types.length;
2383                 TypeBinding[] result = types;
2384                 int removed = 0;
2385                 for (int i = 0; i < length; i++) {
2386                         TypeBinding iType = result[i];
2387                         for (int j = 0; j < length; j++) {
2388                                 if (i == j) continue;
2389                                 TypeBinding jType = result[j];
2390                                 if (jType == null) continue;
2391                                 if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
2392                                         if (result == types) { // defensive copy
2393                                                 System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
2394                                         }
2395                                         result[j] = null;
2396                                         removed ++;
2397                                 }
2398                         }
2399                 }
2400                 if (removed == 0) return result;
2401                 TypeBinding[] trimmedResult = new TypeBinding[length - removed];
2402                 for (int i = 0, index = 0; i < length; i++) {
2403                         TypeBinding iType = result[i];
2404                         if (iType != null) {
2405                                 trimmedResult[index++] = iType;
2406                         }
2407                 }
2408                 return trimmedResult;
2409         }
2410
2411         public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
2412                 return left.isBaseType() != right.isBaseType() && environment().isBoxingCompatibleWith(left, right);
2413         }
2414
2415         /* Answer true if the scope is nested inside a given field declaration.
2416          * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed 
2417          * e.g. during name resolution.
2418         */
2419         public final boolean isDefinedInField(FieldBinding field) {
2420                 Scope scope = this;
2421                 do {
2422                         if (scope instanceof MethodScope) {
2423                                 MethodScope methodScope = (MethodScope) scope;
2424                                 if (methodScope.initializedField == field) return true;
2425                         }
2426                         scope = scope.parent;
2427                 } while (scope != null);
2428                 return false;
2429         }
2430
2431         /* Answer true if the scope is nested inside a given method declaration
2432         */
2433         public final boolean isDefinedInMethod(MethodBinding method) {
2434                 Scope scope = this;
2435                 do {
2436                         if (scope instanceof MethodScope) {
2437                                 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
2438                                 if (refContext instanceof AbstractMethodDeclaration)
2439                                         if (((AbstractMethodDeclaration) refContext).binding == method)
2440                                                 return true;
2441                         }
2442                         scope = scope.parent;
2443                 } while (scope != null);
2444                 return false;
2445         }
2446
2447         /* Answer whether the type is defined in the same compilation unit as the receiver
2448         */
2449         public final boolean isDefinedInSameUnit(ReferenceBinding type) {
2450                 // find the outer most enclosing type
2451                 ReferenceBinding enclosingType = type;
2452                 while ((type = enclosingType.enclosingType()) != null)
2453                         enclosingType = type;
2454
2455                 // find the compilation unit scope
2456                 Scope scope, unitScope = this;
2457                 while ((scope = unitScope.parent) != null)
2458                         unitScope = scope;
2459
2460                 // test that the enclosingType is not part of the compilation unit
2461                 SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
2462                 for (int i = topLevelTypes.length; --i >= 0;)
2463                         if (topLevelTypes[i] == enclosingType)
2464                                 return true;
2465                 return false;
2466         }
2467                 
2468         /* Answer true if the scope is nested inside a given type declaration
2469         */
2470         public final boolean isDefinedInType(ReferenceBinding type) {
2471                 Scope scope = this;
2472                 do {
2473                         if (scope instanceof ClassScope)
2474                                 if (((ClassScope) scope).referenceContext.binding == type)
2475                                         return true;
2476                         scope = scope.parent;
2477                 } while (scope != null);
2478                 return false;
2479         }
2480
2481         public boolean isInsideDeprecatedCode(){
2482                 switch(this.kind){
2483                         case Scope.BLOCK_SCOPE :
2484                         case Scope.METHOD_SCOPE :
2485                                 MethodScope methodScope = methodScope();
2486                                 if (!methodScope.isInsideInitializer()){
2487                                         // check method modifiers to see if deprecated
2488                                         MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
2489                                         if (context != null && context.isViewedAsDeprecated())
2490                                                 return true;
2491                                 } else {
2492                                         SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
2493                                         // inside field declaration ? check field modifier to see if deprecated
2494                                         if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated())
2495                                                 return true;
2496                                         if (type != null && type.isViewedAsDeprecated())
2497                                                 return true;
2498                                 }
2499                                 break;
2500                         case Scope.CLASS_SCOPE :
2501                                 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
2502                                 if (context != null && context.isViewedAsDeprecated())
2503                                         return true;
2504                                 break;
2505                 }
2506                 return false;
2507         }
2508         private TypeBinding leastContainingInvocation(TypeBinding mec, List invocations) {
2509                 int length = invocations.size();
2510                 if (length == 0) return mec;
2511                 if (length == 1) return (TypeBinding) invocations.get(0);
2512                 int argLength = mec.typeVariables().length;
2513                 if (argLength == 0) return mec; // should be caught by no invocation check
2514
2515                 // infer proper parameterized type from invocations
2516                 TypeBinding[] bestArguments = new TypeBinding[argLength];
2517                 for (int i = 0; i < length; i++) {
2518                         TypeBinding invocation = (TypeBinding)invocations.get(i);
2519                         TypeVariableBinding[] invocationVariables = invocation.typeVariables();
2520                         if (invocation.isGenericType()) {
2521                                 for (int j = 0; j < argLength; j++) {
2522                                         TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], invocationVariables[j], (ReferenceBinding) mec, j);
2523                                         if (bestArgument == null) return null;
2524                                         bestArguments[j] = bestArgument;
2525                                 }
2526                         } else if (invocation.isParameterizedType()) {
2527                                 ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)invocation;
2528                                 for (int j = 0; j < argLength; j++) {
2529                                         TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], parameterizedType.arguments[j], (ReferenceBinding) mec, j);
2530                                         if (bestArgument == null) return null;
2531                                         bestArguments[j] = bestArgument;
2532                                 }
2533                         } else if (invocation.isRawType()) {
2534                                 return invocation; // raw type is taking precedence
2535                         }
2536                 }
2537                 return createParameterizedType((ReferenceBinding) mec.erasure(), bestArguments, null);
2538         }
2539         
2540         // JLS 15.12.2
2541         private TypeBinding leastContainingTypeArgument(TypeBinding u, TypeBinding v, ReferenceBinding genericType, int rank) {
2542                 if (u == null) return v;
2543                 if (u == v) return u;
2544                 if (v.isWildcard()) {
2545                         WildcardBinding wildV = (WildcardBinding) v;
2546                         if (u.isWildcard()) {
2547                                 WildcardBinding wildU = (WildcardBinding) u;
2548                                 switch (wildU.kind) {
2549                                         // ? extends U
2550                                         case Wildcard.EXTENDS :
2551                                                 switch(wildV.kind) {
2552                                                         // ? extends U, ? extends V
2553                                                         case Wildcard.EXTENDS :  
2554                                                                 TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound,wildV.bound});
2555                                                                 if (lub == null) return null;
2556                                                                 return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);  
2557                                                         // ? extends U, ? SUPER V
2558                                                         case Wildcard.SUPER : 
2559                                                                 if (wildU.bound == wildV.bound) return wildU.bound;
2560                                                                 return environment().createWildcard(genericType, rank, null, Wildcard.UNBOUND);
2561                                                 }
2562                                                 break;
2563                                                 // ? super U
2564                                         case Wildcard.SUPER : 
2565                                                 // ? super U, ? super V
2566                                                 if (wildU.kind == Wildcard.SUPER) {
2567                                                         TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound});
2568                                                         if (glb == null) return null;
2569                                                         return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2570                                                 }
2571                                 }                               
2572                         } else {
2573                                 switch (wildV.kind) {
2574                                         // U, ? extends V
2575                                         case Wildcard.EXTENDS :
2576                                                 TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,wildV.bound});
2577                                                 if (lub == null) return null;
2578                                                 return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);  
2579                                         // U, ? super V
2580                                         case Wildcard.SUPER :
2581                                                 TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound});
2582                                                 if (glb == null) return null;
2583                                                 return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2584                                         case Wildcard.UNBOUND :
2585                                 }
2586                         }
2587                 } else if (u.isWildcard()) {
2588                         WildcardBinding wildU = (WildcardBinding) u;
2589                         switch (wildU.kind) {
2590                                 // U, ? extends V
2591                                 case Wildcard.EXTENDS :
2592                                         TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound, v});
2593                                         if (lub == null) return null;
2594                                         return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);  
2595                                 // U, ? super V
2596                                 case Wildcard.SUPER :
2597                                         TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v});
2598                                         if (glb == null) return null;
2599                                         return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds                
2600                                 case Wildcard.UNBOUND :
2601                         }
2602                 }
2603                 TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,v});
2604                 if (lub == null) return null;
2605                 return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
2606         }
2607
2608         // 15.12.2
2609         public TypeBinding lowerUpperBound(TypeBinding[] types) {
2610                 
2611                 if (types.length == 1) {
2612                         TypeBinding type = types[0];
2613                         return type == null ? VoidBinding : type;
2614                 }
2615                 ArrayList invocations = new ArrayList(1);
2616                 TypeBinding mec = minimalErasedCandidate(types, invocations);
2617                 return leastContainingInvocation(mec, invocations);
2618         }
2619         
2620         public final MethodScope methodScope() {
2621                 Scope scope = this;
2622                 do {
2623                         if (scope instanceof MethodScope)
2624                                 return (MethodScope) scope;
2625                         scope = scope.parent;
2626                 } while (scope != null);
2627                 return null;
2628         }
2629
2630         /**
2631          * Returns the most specific type compatible with all given types.
2632          * (i.e. most specific common super type)
2633          * If no types is given, will return VoidBinding. If not compatible 
2634          * reference type is found, returns null.
2635          */
2636         private TypeBinding minimalErasedCandidate(TypeBinding[] types, List invocations) {
2637                 Map allInvocations = new HashMap(2);
2638                 int length = types.length;
2639                 int indexOfFirst = -1, actualLength = 0;
2640                 for (int i = 0; i < length; i++) {
2641                         TypeBinding type = types[i];
2642                         if (type == null) continue;
2643                         if (type.isBaseType()) return null;
2644                         if (indexOfFirst < 0) indexOfFirst = i;
2645                         actualLength ++;
2646                 }
2647                 switch (actualLength) {
2648                         case 0: return VoidBinding;
2649                         case 1: return types[indexOfFirst];
2650                 }
2651
2652                 // record all supertypes of type
2653                 // intersect with all supertypes of otherType
2654                 TypeBinding firstType = types[indexOfFirst];
2655                 TypeBinding[] superTypes;
2656                 int superLength;
2657                 if (firstType.isBaseType()) {
2658                         return null; 
2659                 } else if (firstType.isArrayType()) {
2660                         superLength = 4;
2661                         if (firstType.erasure() != firstType) {
2662                                 ArrayList someInvocations = new ArrayList(1);
2663                                 someInvocations.add(firstType);
2664                                 allInvocations.put(firstType.erasure(), someInvocations);
2665                         }
2666                         superTypes = new TypeBinding[] {
2667                                         firstType.erasure(), 
2668                                         getJavaIoSerializable(),
2669                                         getJavaLangCloneable(),
2670                                         getJavaLangObject(),
2671                         };
2672                 } else {
2673                         ArrayList typesToVisit = new ArrayList(5);
2674                         if (firstType.erasure() != firstType) {
2675                                 ArrayList someInvocations = new ArrayList(1);
2676                                 someInvocations.add(firstType);
2677                                 allInvocations.put(firstType.erasure(), someInvocations);
2678                         }                       
2679                         typesToVisit.add(firstType.erasure());
2680                         ReferenceBinding currentType = (ReferenceBinding)firstType;
2681                         for (int i = 0, max = 1; i < max; i++) {
2682                                 currentType = (ReferenceBinding) typesToVisit.get(i);
2683                                 TypeBinding itsSuperclass = currentType.superclass();
2684                                 if (itsSuperclass != null) {
2685                                         TypeBinding itsSuperclassErasure = itsSuperclass.erasure();
2686                                         if (!typesToVisit.contains(itsSuperclassErasure)) {
2687                                                 if (itsSuperclassErasure != itsSuperclass) {
2688                                                         ArrayList someInvocations = new ArrayList(1);
2689                                                         someInvocations.add(itsSuperclass);
2690                                                         allInvocations.put(itsSuperclassErasure, someInvocations);
2691                                                 }
2692                                                 typesToVisit.add(itsSuperclassErasure);
2693                                                 max++;
2694                                         }
2695                                 }
2696                                 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
2697                                 for (int j = 0, count = itsInterfaces.length; j < count; j++) {
2698                                         TypeBinding itsInterface = itsInterfaces[j];
2699                                         TypeBinding itsInterfaceErasure = itsInterface.erasure();
2700                                         if (!typesToVisit.contains(itsInterfaceErasure)) {
2701                                                 if (itsInterfaceErasure != itsInterface) {
2702                                                         ArrayList someInvocations = new ArrayList(1);
2703                                                         someInvocations.add(itsInterface);
2704                                                         allInvocations.put(itsInterfaceErasure, someInvocations);
2705                                                 }                                               
2706                                                 typesToVisit.add(itsInterfaceErasure);
2707                                                 max++;
2708                                         }
2709                                 }
2710                         }
2711                         superLength = typesToVisit.size();
2712                         superTypes = new TypeBinding[superLength];
2713                         typesToVisit.toArray(superTypes);
2714                 }
2715                 int remaining = superLength;
2716                 nextOtherType: for (int i = indexOfFirst+1; i < length; i++) {
2717                         TypeBinding otherType = types[i];
2718                         if (otherType == null)
2719                                 continue nextOtherType;
2720                         else if (otherType.isArrayType()) {
2721                                 nextSuperType: for (int j = 0; j < superLength; j++) {
2722                                         TypeBinding superType = superTypes[j];
2723                                         if (superType == null || superType == otherType) continue nextSuperType;
2724                                         switch (superType.id) {
2725                                                 case T_JavaIoSerializable :
2726                                                 case T_JavaLangCloneable :
2727                                                 case T_JavaLangObject :
2728                                                         continue nextSuperType;
2729                                         }
2730                                         superTypes[j] = null;
2731                                         if (--remaining == 0) return null;
2732                                         
2733                                 }
2734                                 continue nextOtherType;
2735                         }
2736                         ReferenceBinding otherRefType = (ReferenceBinding) otherType;
2737                         nextSuperType: for (int j = 0; j < superLength; j++) {
2738                                 TypeBinding superType = superTypes[j];
2739                                 if (superType == null) continue nextSuperType;
2740                                 if (otherRefType.erasure().isCompatibleWith(superType)) {
2741                                         TypeBinding match = otherRefType.findSuperTypeErasingTo((ReferenceBinding)superType);
2742                                                 if (match != null && match.erasure() != match) { // match can be null: interface.findSuperTypeErasingTo(Object)
2743                                                         ArrayList someInvocations = (ArrayList) allInvocations.get(superType);
2744                                                         if (someInvocations == null) someInvocations = new ArrayList(1);
2745                                                         someInvocations.add(match);
2746                                                         allInvocations.put(superType, someInvocations);
2747                                                 }                                               
2748                                         break nextSuperType;
2749                                 } else {
2750                                         superTypes[j] = null;
2751                                         if (--remaining == 0) return null;
2752                                 }
2753                         }                               
2754                 }
2755                 // per construction, first non-null supertype is most specific common supertype
2756                 for (int i = 0; i < superLength; i++) {
2757                         TypeBinding superType = superTypes[i];
2758                         if (superType != null) {
2759                                 List matchingInvocations = (List)allInvocations.get(superType);
2760                                 if (matchingInvocations != null) invocations.addAll(matchingInvocations);
2761                                 return superType;
2762                         }
2763                 }
2764                 return null;
2765         }
2766         
2767         // Internal use only
2768         /* All methods in visible are acceptable matches for the method in question...
2769         * The methods defined by the receiver type appear before those defined by its
2770         * superclass and so on. We want to find the one which matches best.
2771         *
2772         * Since the receiver type is a class, we know each method's declaring class is
2773         * either the receiver type or one of its superclasses. It is an error if the best match
2774         * is defined by a superclass, when a lesser match is defined by the receiver type
2775         * or a closer superclass.
2776         */
2777         protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
2778                 MethodBinding problemMethod = null;
2779                 MethodBinding previous = null;
2780                 nextVisible : for (int i = 0; i < visibleSize; i++) {
2781                         MethodBinding method = visible[i];
2782                         if (previous != null && method.declaringClass != previous.declaringClass)
2783                                 break; // cannot answer a method farther up the hierarchy than the first method found
2784
2785                         if (!method.isStatic()) previous = method; // no ambiguity for static methods
2786                         for (int j = 0; j < visibleSize; j++) {
2787                                 if (i == j) continue;
2788                                 if (!visible[j].areParametersCompatibleWith(method.parameters))
2789                                         continue nextVisible;
2790                         }
2791                         compilationUnitScope().recordTypeReferences(method.thrownExceptions);
2792                         return method;
2793                 }
2794                 if (problemMethod == null)
2795                         return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
2796                 return problemMethod;
2797         }
2798         
2799         // Internal use only
2800         /* All methods in visible are acceptable matches for the method in question...
2801         * Since the receiver type is an interface, we ignore the possibility that 2 inherited
2802         * but unrelated superinterfaces may define the same method in acceptable but
2803         * not identical ways... we just take the best match that we find since any class which
2804         * implements the receiver interface MUST implement all signatures for the method...
2805         * in which case the best match is correct.
2806         *
2807         * NOTE: This is different than javac... in the following example, the message send of
2808         * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
2809         * interface I MUST implement both signatures for bar. If this class was the receiver of
2810         * the message send instead of the interface I, then no problem would be reported.
2811         *
2812         interface I1 {
2813                 void bar(J j);
2814         }
2815         interface I2 {
2816         //      void bar(J j);
2817                 void bar(Object o);
2818         }
2819         interface I extends I1, I2 {}
2820         interface J {}
2821         
2822         class X implements J {}
2823         
2824         class Y extends X {
2825                 public void foo(I i, X x) { i.bar(x); }
2826         }
2827         */
2828         protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
2829                 MethodBinding problemMethod = null;
2830                 nextVisible : for (int i = 0; i < visibleSize; i++) {
2831                         MethodBinding method = visible[i];
2832                         for (int j = 0; j < visibleSize; j++) {
2833                                 if (i == j) continue;
2834                                 if (!visible[j].areParametersCompatibleWith(method.parameters))
2835                                         continue nextVisible;
2836                         }
2837                         compilationUnitScope().recordTypeReferences(method.thrownExceptions);
2838                         return method;
2839                 }
2840                 if (problemMethod == null)
2841                         return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
2842                 return problemMethod;
2843         }
2844
2845         protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
2846                 int[] compatibilityLevels = new int[visibleSize];
2847                 for (int i = 0; i < visibleSize; i++)
2848                         compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes);
2849
2850                 for (int level = 0; level <= 2; level++) {
2851                         nextVisible : for (int i = 0; i < visibleSize; i++) {
2852                                 if (compatibilityLevels[i] != level) continue nextVisible; // skip this method for now
2853                                 MethodBinding method = visible[i];
2854                                 for (int j = 0; j < visibleSize; j++) {
2855                                         if (i == j || compatibilityLevels[j] != level) continue;
2856                                         // tiebreak generic methods using variant where type params are substituted by their erasures
2857                                         if (!visible[j].tiebreakMethod().areParametersCompatibleWith(method.tiebreakMethod().parameters)) {
2858                                                 if (method.isVarargs() && visible[j].isVarargs()) {
2859                                                         int paramLength = method.parameters.length;
2860                                                         if (paramLength == visible[j].parameters.length && paramLength == argumentTypes.length + 1) {
2861                                                                 TypeBinding elementsType = ((ArrayBinding) visible[j].parameters[paramLength - 1]).elementsType();
2862                                                                 if (method.parameters[paramLength - 1].isCompatibleWith(elementsType))
2863                                                                         continue; // special case to choose between 2 varargs methods when the last arg is missing
2864                                                         }
2865                                                 }
2866                                                 continue nextVisible;
2867                                         }
2868                                 }
2869                                 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
2870                                 return method;
2871                         }
2872                 }
2873                 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
2874         }       
2875
2876         public final ClassScope outerMostClassScope() {
2877                 ClassScope lastClassScope = null;
2878                 Scope scope = this;
2879                 do {
2880                         if (scope instanceof ClassScope)
2881                                 lastClassScope = (ClassScope) scope;
2882                         scope = scope.parent;
2883                 } while (scope != null);
2884                 return lastClassScope; // may answer null if no class around
2885         }
2886
2887         public final MethodScope outerMostMethodScope() {
2888                 MethodScope lastMethodScope = null;
2889                 Scope scope = this;
2890                 do {
2891                         if (scope instanceof MethodScope)
2892                                 lastMethodScope = (MethodScope) scope;
2893                         scope = scope.parent;
2894                 } while (scope != null);
2895                 return lastMethodScope; // may answer null if no method around
2896         }
2897
2898         protected int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
2899                 TypeBinding[] parameters = method.parameters;
2900                 int paramLength = parameters.length;
2901                 int argLength = arguments.length;
2902                 int lastIndex = argLength;
2903                 int level = COMPATIBLE; // no autoboxing or varargs support needed
2904                 if (method.isVarargs()) {
2905                         lastIndex = paramLength - 1;
2906                         if (paramLength == argLength) { // accept X or X[] but not X[][]
2907                                 TypeBinding param = parameters[lastIndex]; // is an ArrayBinding by definition
2908                                 TypeBinding arg = arguments[lastIndex];
2909                                 if (param != arg && !arg.isCompatibleWith(param)) {
2910                                         if (isBoxingCompatibleWith(arg, param)) {
2911                                                 level = AUTOBOX_COMPATIBLE; // autoboxing support needed
2912                                         } else {
2913                                                 // expect X[], called with X
2914                                                 param = ((ArrayBinding) param).elementsType();
2915                                                 if (!arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
2916                                                         return NOT_COMPATIBLE;
2917                                                 level = VARARGS_COMPATIBLE; // varargs support needed
2918                                         }
2919                                 }
2920                         } else {
2921                                 if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
2922                                         TypeBinding param = ((ArrayBinding) parameters[lastIndex]).elementsType();
2923                                         for (int i = lastIndex; i < argLength; i++) {
2924                                                 TypeBinding arg = arguments[i];
2925                                                 if (param != arg && !arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
2926                                                         return NOT_COMPATIBLE;
2927                                         }
2928                                 }  else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
2929                                         return NOT_COMPATIBLE;
2930                                 }
2931                                 level = VARARGS_COMPATIBLE; // varargs support needed
2932                         }
2933                         // now compare standard arguments from 0 to lastIndex
2934                 }
2935                 for (int i = 0; i < lastIndex; i++) {
2936                         TypeBinding param = parameters[i];
2937                         TypeBinding arg = arguments[i];
2938                         if (arg != param && !arg.isCompatibleWith(param)) {
2939                                 if (!isBoxingCompatibleWith(arg, param))
2940                                         return NOT_COMPATIBLE;
2941                                 level = AUTOBOX_COMPATIBLE; // autoboxing support needed
2942                         }
2943                 }
2944                 return level;
2945         }
2946
2947         public abstract ProblemReporter problemReporter();
2948
2949         public final CompilationUnitDeclaration referenceCompilationUnit() {
2950                 Scope scope, unitScope = this;
2951                 while ((scope = unitScope.parent) != null)
2952                         unitScope = scope;
2953                 return ((CompilationUnitScope) unitScope).referenceContext;
2954         }
2955         // start position in this scope - for ordering scopes vs. variables
2956         int startIndex() {
2957                 return 0;
2958         }
2959         
2960         /**
2961          * Returns the immediately enclosing switchCase statement (carried by closest blockScope),
2962          */
2963         public CaseStatement switchCase() {
2964                 Scope scope = this;
2965                 do {
2966                         if (scope instanceof BlockScope)
2967                                 return ((BlockScope) scope).switchCase;
2968                         scope = scope.parent;
2969                 } while (scope != null);
2970                 return null;
2971         }
2972         /*
2973          * Unboxing primitive
2974          */
2975         public int unboxing(int id) {
2976                 switch (id) {
2977                         case T_JavaLangInteger :
2978                                 return T_int;
2979                         case T_JavaLangByte :
2980                                 return T_byte;
2981                         case T_JavaLangShort :
2982                                 return T_short;
2983                         case T_JavaLangCharacter :
2984                                 return T_char;
2985                         case T_JavaLangLong :
2986                                 return T_long;
2987                         case T_JavaLangFloat :
2988                                 return T_float;
2989                         case T_JavaLangDouble :
2990                                 return T_double;
2991                         case T_JavaLangBoolean :
2992                                 return T_boolean;
2993                         case T_JavaLangVoid :
2994                                 return T_void;
2995                 }
2996                 return id;
2997         }
2998         /*
2999          * Unboxing primitive
3000          */
3001         public TypeBinding unboxing(TypeBinding type) {
3002                 switch (type.id) {
3003                         case T_JavaLangInteger :
3004                                 return IntBinding;
3005                         case T_JavaLangByte :
3006                                 return ByteBinding;
3007                         case T_JavaLangShort :
3008                                 return ShortBinding;            
3009                         case T_JavaLangCharacter :
3010                                 return CharBinding;                             
3011                         case T_JavaLangLong :
3012                                 return LongBinding;
3013                         case T_JavaLangFloat :
3014                                 return FloatBinding;
3015                         case T_JavaLangDouble :
3016                                 return DoubleBinding;
3017                         case T_JavaLangBoolean :
3018                                 return BooleanBinding;
3019                         case T_JavaLangVoid :
3020                                 return VoidBinding;
3021                 }
3022                 return type;
3023         }               
3024 }