KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > Scope


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-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.*;
14
15 import org.eclipse.jdt.core.compiler.CharOperation;
16 import org.eclipse.jdt.internal.compiler.ast.*;
17 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
19 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
20 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
21 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
22 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
23 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
24 import org.eclipse.jdt.internal.compiler.util.SimpleSet;
25
26 public abstract class Scope implements TypeConstants, TypeIds {
27     
28     /* Scope kinds */
29     public final static int BLOCK_SCOPE = 1;
30     public final static int CLASS_SCOPE = 3;
31     public final static int COMPILATION_UNIT_SCOPE = 4;
32     public final static int METHOD_SCOPE = 2;
33
34     /* Argument Compatibilities */
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     /* Type Compatibilities */
41     public static final int EQUAL_OR_MORE_SPECIFIC = -1;
42     public static final int NOT_RELATED = 0;
43     public static final int MORE_GENERIC = 1;
44
45     public int kind;
46     public Scope parent;
47     
48     /* Answer an int describing the relationship between the given types.
49     *
50     * NOT_RELATED
51     * EQUAL_OR_MORE_SPECIFIC : left is compatible with right
52     * MORE_GENERIC : right is compatible with left
53     */

54     public static int compareTypes(TypeBinding left, TypeBinding right) {
55         if (left.isCompatibleWith(right))
56             return Scope.EQUAL_OR_MORE_SPECIFIC;
57         if (right.isCompatibleWith(left))
58             return Scope.MORE_GENERIC;
59         return Scope.NOT_RELATED;
60     }
61     public static TypeBinding getBaseType(char[] name) {
62         // list should be optimized (with most often used first)
63
int length = name.length;
64         if (length > 2 && length < 8) {
65             switch (name[0]) {
66                 case 'i' :
67                     if (length == 3 && name[1] == 'n' && name[2] == 't')
68                         return TypeBinding.INT;
69                     break;
70                 case 'v' :
71                     if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
72                         return TypeBinding.VOID;
73                     break;
74                 case 'b' :
75                     if (length == 7
76                         && name[1] == 'o'
77                         && name[2] == 'o'
78                         && name[3] == 'l'
79                         && name[4] == 'e'
80                         && name[5] == 'a'
81                         && name[6] == 'n')
82                         return TypeBinding.BOOLEAN;
83                     if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
84                         return TypeBinding.BYTE;
85                     break;
86                 case 'c' :
87                     if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
88                         return TypeBinding.CHAR;
89                     break;
90                 case 'd' :
91                     if (length == 6
92                         && name[1] == 'o'
93                         && name[2] == 'u'
94                         && name[3] == 'b'
95                         && name[4] == 'l'
96                         && name[5] == 'e')
97                         return TypeBinding.DOUBLE;
98                     break;
99                 case 'f' :
100                     if (length == 5
101                         && name[1] == 'l'
102                         && name[2] == 'o'
103                         && name[3] == 'a'
104                         && name[4] == 't')
105                         return TypeBinding.FLOAT;
106                     break;
107                 case 'l' :
108                     if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
109                         return TypeBinding.LONG;
110                     break;
111                 case 's' :
112                     if (length == 5
113                         && name[1] == 'h'
114                         && name[2] == 'o'
115                         && name[3] == 'r'
116                         && name[4] == 't')
117                         return TypeBinding.SHORT;
118             }
119         }
120         return null;
121     }
122
123    // 5.1.10
124
public static ReferenceBinding[] greaterLowerBound(ReferenceBinding[] types) {
125         if (types == null) return null;
126         int length = types.length;
127         if (length == 0) return null;
128         ReferenceBinding[] result = types;
129         int removed = 0;
130         for (int i = 0; i < length; i++) {
131             ReferenceBinding iType = result[i];
132             if (iType == null) continue;
133             for (int j = 0; j < length; j++) {
134                 if (i == j) continue;
135                 ReferenceBinding jType = result[j];
136                 if (jType == null) continue;
137                 if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
138
if (result == types) { // defensive copy
139
System.arraycopy(result, 0, result = new ReferenceBinding[length], 0, length);
140                     }
141                     result[j] = null;
142                     removed ++;
143                 }
144             }
145         }
146         if (removed == 0) return result;
147         if (length == removed) return null;
148         ReferenceBinding[] trimmedResult = new ReferenceBinding[length - removed];
149         for (int i = 0, index = 0; i < length; i++) {
150             ReferenceBinding iType = result[i];
151             if (iType != null) {
152                 trimmedResult[index++] = iType;
153             }
154         }
155         return trimmedResult;
156     }
157     
158     // 5.1.10
159
public static TypeBinding[] greaterLowerBound(TypeBinding[] types) {
160         if (types == null) return null;
161         int length = types.length;
162         if (length == 0) return null;
163         TypeBinding[] result = types;
164         int removed = 0;
165         for (int i = 0; i < length; i++) {
166             TypeBinding iType = result[i];
167             if (iType == null) continue;
168             for (int j = 0; j < length; j++) {
169                 if (i == j) continue;
170                 TypeBinding jType = result[j];
171                 if (jType == null) continue;
172                 if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
173
if (result == types) { // defensive copy
174
System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
175                     }
176                     result[j] = null;
177                     removed ++;
178                 }
179             }
180         }
181         if (removed == 0) return result;
182         if (length == removed) return null;
183         TypeBinding[] trimmedResult = new TypeBinding[length - removed];
184         for (int i = 0, index = 0; i < length; i++) {
185             TypeBinding iType = result[i];
186             if (iType != null) {
187                 trimmedResult[index++] = iType;
188             }
189         }
190         return trimmedResult;
191     }
192     
193     /**
194      * Returns an array of types, where original types got substituted given a substitution.
195      * Only allocate an array if anything is different.
196      */

197     public static ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
198         if (originalTypes == null) return null;
199         ReferenceBinding[] substitutedTypes = originalTypes;
200         for (int i = 0, length = originalTypes.length; i < length; i++) {
201             ReferenceBinding originalType = originalTypes[i];
202             ReferenceBinding substitutedParameter = (ReferenceBinding)substitute(substitution, originalType);
203             if (substitutedParameter != originalType) {
204                 if (substitutedTypes == originalTypes) {
205                     System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
206                 }
207                 substitutedTypes[i] = substitutedParameter;
208             } else if (substitutedTypes != originalTypes) {
209                 substitutedTypes[i] = originalType;
210             }
211         }
212         return substitutedTypes;
213     }
214
215     /**
216      * Returns a type, where original type was substituted using the receiver
217      * parameterized type.
218      * In raw mode, all parameterized type denoting same original type are converted
219      * to raw types. e.g.
220      * class X <T> {
221      * X<T> foo;
222      * X<String> bar;
223      * } when used in raw fashion, then type of both foo and bar is raw type X.
224      *
225      */

226     public static TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
227         if (originalType == null) return null;
228         switch (originalType.kind()) {
229             
230             case Binding.TYPE_PARAMETER:
231                 return substitution.substitute((TypeVariableBinding) originalType);
232                 
233             case Binding.PARAMETERIZED_TYPE:
234                 ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
235                 ReferenceBinding originalEnclosing = originalType.enclosingType();
236                 ReferenceBinding substitutedEnclosing = originalEnclosing;
237                 if (originalEnclosing != null) {
238                     substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
239                 }
240                 TypeBinding[] originalArguments = originalParameterizedType.arguments;
241                 TypeBinding[] substitutedArguments = originalArguments;
242                 if (originalArguments != null) {
243                     if (substitution.isRawSubstitution()) {
244                         return originalParameterizedType.environment.createRawType(originalParameterizedType.genericType(), substitutedEnclosing);
245                     }
246                     substitutedArguments = substitute(substitution, originalArguments);
247                 }
248                 if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
249 // identicalVariables: { // if substituted with original variables, then answer the generic type itself
250
// if (substitutedEnclosing != null) {
251
// //if (!(substitutedEnclosing instanceof SourceTypeBinding)) break identicalVariables;
252
// if (substitutedEnclosing != originalEnclosing) break identicalVariables;
253
// }
254
// if (originalParameterizedType.type.isBinaryBinding()) break identicalVariables; // generic binary is never used as is, see 85262
255
// TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables();
256
// for (int i = 0, length = originalVariables.length; i < length; i++) {
257
// if (substitutedArguments[i] != originalVariables[i]) break identicalVariables;
258
// }
259
// return originalParameterizedType.type;
260
// }
261
return originalParameterizedType.environment.createParameterizedType(
262                             originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing);
263                 }
264                 break;
265                 
266             case Binding.ARRAY_TYPE:
267                 ArrayBinding originalArrayType = (ArrayBinding) originalType;
268                 TypeBinding originalLeafComponentType = originalArrayType.leafComponentType;
269                 TypeBinding substitute = substitute(substitution, originalLeafComponentType); // substitute could itself be array type
270
if (substitute != originalLeafComponentType) {
271                     return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
272                 }
273                 break;
274
275             case Binding.WILDCARD_TYPE:
276                 WildcardBinding wildcard = (WildcardBinding) originalType;
277                 if (wildcard.boundKind != Wildcard.UNBOUND) {
278                     TypeBinding originalBound = wildcard.bound;
279                     TypeBinding substitutedBound = substitute(substitution, originalBound);
280                     TypeBinding[] originalOtherBounds = wildcard.otherBounds;
281                     TypeBinding[] substitutedOtherBounds = substitute(substitution, originalOtherBounds);
282                     if (substitutedBound != originalBound || originalOtherBounds != substitutedOtherBounds) {
283                         return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, substitutedOtherBounds, wildcard.boundKind);
284                     }
285                 }
286                 break;
287
288             case Binding.TYPE:
289                 if (!originalType.isMemberType()) break;
290                 ReferenceBinding originalReferenceType = (ReferenceBinding) originalType;
291                 originalEnclosing = originalType.enclosingType();
292                 substitutedEnclosing = originalEnclosing;
293                 if (originalEnclosing != null) {
294                     substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
295                 }
296                 
297                 // treat as if parameterized with its type variables (non generic type gets 'null' arguments)
298
if (substitutedEnclosing != originalEnclosing) {
299                     return substitution.isRawSubstitution()
300                         ? substitution.environment().createRawType(originalReferenceType, substitutedEnclosing)
301                         : substitution.environment().createParameterizedType(originalReferenceType, null, substitutedEnclosing);
302                 }
303                 break;
304             case Binding.GENERIC_TYPE:
305                 originalReferenceType = (ReferenceBinding) originalType;
306                 originalEnclosing = originalType.enclosingType();
307                 substitutedEnclosing = originalEnclosing;
308                 if (originalEnclosing != null) {
309                     substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
310                 }
311                 
312                 if (substitution.isRawSubstitution()) {
313                     return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing);
314                 }
315                 // treat as if parameterized with its type variables (non generic type gets 'null' arguments)
316
originalArguments = originalReferenceType.typeVariables();
317                 substitutedArguments = substitute(substitution, originalArguments);
318 // if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
319
return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing);
320 // }
321
// break;
322
}
323         return originalType;
324     }
325
326     /**
327      * Returns an array of types, where original types got substituted given a substitution.
328      * Only allocate an array if anything is different.
329      */

330     public static TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
331         if (originalTypes == null) return null;
332         TypeBinding[] substitutedTypes = originalTypes;
333         for (int i = 0, length = originalTypes.length; i < length; i++) {
334             TypeBinding originalType = originalTypes[i];
335             TypeBinding substitutedParameter = substitute(substitution, originalType);
336             if (substitutedParameter != originalType) {
337                 if (substitutedTypes == originalTypes) {
338                     System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
339                 }
340                 substitutedTypes[i] = substitutedParameter;
341             } else if (substitutedTypes != originalTypes) {
342                 substitutedTypes[i] = originalType;
343             }
344         }
345         return substitutedTypes;
346     }
347
348     protected Scope(int kind, Scope parent) {
349         this.kind = kind;
350         this.parent = parent;
351     }
352
353     /*
354      * Boxing primitive
355      */

356     public TypeBinding boxing(TypeBinding type) {
357         if (type.isBaseType())
358             return environment().computeBoxingType(type);
359         return type;
360     }
361
362     public final ClassScope classScope() {
363         Scope scope = this;
364         do {
365             if (scope instanceof ClassScope)
366                 return (ClassScope) scope;
367             scope = scope.parent;
368         } while (scope != null);
369         return null;
370     }
371     
372     public final CompilationUnitScope compilationUnitScope() {
373         Scope lastScope = null;
374         Scope scope = this;
375         do {
376             lastScope = scope;
377             scope = scope.parent;
378         } while (scope != null);
379         return (CompilationUnitScope) lastScope;
380     }
381     
382     /**
383      * Finds the most specific compiler options
384      */

385     public final CompilerOptions compilerOptions() {
386
387         return compilationUnitScope().environment.globalOptions;
388     }
389
390     /**
391      * Internal use only
392      * Given a method, returns null if arguments cannot be converted to parameters.
393      * Will answer a subsituted method in case the method was generic and type inference got triggered;
394      * in case the method was originally compatible, then simply answer it back.
395      */

396     protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite) {
397
398         TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments();
399         TypeBinding[] parameters = method.parameters;
400         TypeVariableBinding[] typeVariables = method.typeVariables;
401         if (parameters == arguments
402             && (method.returnType.tagBits & TagBits.HasTypeVariable) == 0
403             && genericTypeArguments == null
404             && typeVariables == Binding.NO_TYPE_VARIABLES)
405                 return method;
406
407         int argLength = arguments.length;
408         int paramLength = parameters.length;
409         boolean isVarArgs = method.isVarargs();
410         if (argLength != paramLength)
411             if (!isVarArgs || argLength < paramLength - 1)
412                 return null; // incompatible
413

414         if (typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
415
TypeBinding[] newArgs = null;
416             for (int i = 0; i < argLength; i++) {
417                 TypeBinding param = i < paramLength ? parameters[i] : parameters[paramLength - 1];
418                 if (arguments[i].isBaseType() != param.isBaseType()) {
419                     if (newArgs == null) {
420                         newArgs = new TypeBinding[argLength];
421                         System.arraycopy(arguments, 0, newArgs, 0, argLength);
422                     }
423                     newArgs[i] = environment().computeBoxingType(arguments[i]);
424                 }
425             }
426             if (newArgs != null)
427                 arguments = newArgs;
428             method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite);
429             if (method == null) return null; // incompatible
430
if (!method.isValidBinding()) return method; // bound check issue is taking precedence
431
parameters = method.parameters; // reacquire them after type inference has performed
432
} else if (genericTypeArguments != null) {
433             if (method instanceof ParameterizedGenericMethodBinding) {
434                 if (!((ParameterizedGenericMethodBinding) method).wasInferred) {
435                     // attempt to invoke generic method of raw type with type hints <String>foo()
436
return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.TypeArgumentsForRawGenericMethod);
437                 }
438             } else {
439                 return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.TypeParameterArityMismatch);
440             }
441         }
442
443         if (parameterCompatibilityLevel(method, arguments) > NOT_COMPATIBLE)
444             return method;
445         if (genericTypeArguments != null)
446             return new ProblemMethodBinding(method, method.selector, arguments, ProblemReasons.ParameterizedMethodTypeMismatch);
447         return null; // incompatible
448
}
449     
450     protected boolean connectTypeVariables(TypeParameter[] typeParameters, boolean checkForErasedCandidateCollisions) {
451         if (typeParameters == null || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) return true;
452         boolean noProblems = true;
453         Map invocations = new HashMap(2);
454         nextVariable : for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
455             TypeParameter typeParameter = typeParameters[i];
456             TypeVariableBinding typeVariable = typeParameter.binding;
457             if (typeVariable == null) return false;
458
459             typeVariable.superclass = getJavaLangObject();
460             typeVariable.superInterfaces = Binding.NO_SUPERINTERFACES;
461             // set firstBound to the binding of the first explicit bound in parameter declaration
462
typeVariable.firstBound = null; // first bound used to compute erasure
463

464             TypeReference typeRef = typeParameter.type;
465             if (typeRef == null)
466                 continue nextVariable;
467             TypeBinding superType = this.kind == METHOD_SCOPE
468                 ? typeRef.resolveType((BlockScope)this, false/*no bound check*/)
469                 : typeRef.resolveType((ClassScope)this);
470             if (superType == null) {
471                 typeVariable.tagBits |= TagBits.HierarchyHasProblems;
472                 noProblems = false;
473                 continue nextVariable;
474             }
475             typeRef.resolvedType = superType; // hold onto the problem type
476
if (superType.isArrayType()) {
477                 problemReporter().boundCannotBeArray(typeRef, superType);
478                 continue nextVariable;
479             }
480             boolean isTypeVariableFirstBound = superType.isTypeVariable();
481             if (isTypeVariableFirstBound) {
482                 TypeVariableBinding varSuperType = (TypeVariableBinding) superType;
483                 if (varSuperType.rank >= typeVariable.rank && varSuperType.declaringElement == typeVariable.declaringElement) {
484                     problemReporter().forwardTypeVariableReference(typeParameter, varSuperType);
485                     typeVariable.tagBits |= TagBits.HierarchyHasProblems;
486                     noProblems = false;
487                     continue nextVariable;
488                 }
489             }
490             ReferenceBinding superRefType = (ReferenceBinding) superType;
491             if (superRefType.isFinal())
492                 problemReporter().finalVariableBound(typeVariable, typeRef);
493             if (!superType.isInterface()) {
494                 typeVariable.superclass = superRefType;
495             } else {
496                 typeVariable.superInterfaces = new ReferenceBinding[] {superRefType};
497             }
498             typeVariable.firstBound = superRefType; // first bound used to compute erasure
499
TypeReference[] boundRefs = typeParameter.bounds;
500             if (boundRefs != null) {
501                 for (int j = 0, boundLength = boundRefs.length; j < boundLength; j++) {
502                     typeRef = boundRefs[j];
503                     superType = this.kind == METHOD_SCOPE
504                         ? typeRef.resolveType((BlockScope)this, false)
505                         : typeRef.resolveType((ClassScope)this);
506                     if (superType == null) {
507                         typeVariable.tagBits |= TagBits.HierarchyHasProblems;
508                         noProblems = false;
509                         continue nextVariable;
510                     }
511                     typeRef.resolvedType = superType; // hold onto the problem type
512
if (isTypeVariableFirstBound && j == 0) {
513                         problemReporter().noAdditionalBoundAfterTypeVariable(typeRef);
514                     }
515                     if (superType.isArrayType()) {
516                         problemReporter().boundCannotBeArray(typeRef, superType);
517                         continue nextVariable;
518                     }
519                     superRefType = (ReferenceBinding) superType;
520                     if (!superType.isInterface()) {
521                         problemReporter().boundMustBeAnInterface(typeRef, superType);
522                         typeVariable.tagBits |= TagBits.HierarchyHasProblems;
523                         noProblems = false;
524                         continue nextVariable;
525                     }
526                     // check against superclass
527
if (checkForErasedCandidateCollisions && typeVariable.firstBound == typeVariable.superclass) {
528                         if (hasErasedCandidatesCollisions(superType, typeVariable.superclass, invocations, typeVariable, typeRef)) {
529                             noProblems = false;
530                             continue nextVariable;
531                         }
532                     }
533                     // check against superinterfaces
534
for (int index = typeVariable.superInterfaces.length; --index >= 0;) {
535                         ReferenceBinding previousInterface = typeVariable.superInterfaces[index];
536                         if (previousInterface == superRefType) {
537                             problemReporter().duplicateBounds(typeRef, superType);
538                             typeVariable.tagBits |= TagBits.HierarchyHasProblems;
539                             noProblems = false;
540                             continue nextVariable;
541                         }
542                         if (checkForErasedCandidateCollisions) {
543                             if (hasErasedCandidatesCollisions(superType, previousInterface, invocations, typeVariable, typeRef)) {
544                                 noProblems = false;
545                                 continue nextVariable;
546                             }
547                         }
548                     }
549                     int size = typeVariable.superInterfaces.length;
550                     System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.superInterfaces = new ReferenceBinding[size + 1], 0, size);
551                     typeVariable.superInterfaces[size] = superRefType;
552                 }
553             }
554         }
555         return noProblems;
556     }
557
558     public ArrayBinding createArrayType(TypeBinding type, int dimension) {
559         if (type.isValidBinding())
560             return environment().createArrayType(type, dimension);
561         // do not cache obvious invalid types
562
return new ArrayBinding(type, dimension, environment());
563     }
564
565     public TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) {
566         // do not construct type variables if source < 1.5
567
if (typeParameters == null || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5)
568             return Binding.NO_TYPE_VARIABLES;
569
570         PackageBinding unitPackage = compilationUnitScope().fPackage;
571         int length = typeParameters.length;
572         TypeVariableBinding[] typeVariableBindings = new TypeVariableBinding[length];
573         int count = 0;
574         for (int i = 0; i < length; i++) {
575             TypeParameter typeParameter = typeParameters[i];
576             TypeVariableBinding parameterBinding = new TypeVariableBinding(typeParameter.name, declaringElement, i);
577             parameterBinding.fPackage = unitPackage;
578             typeParameter.binding = parameterBinding;
579
580             // detect duplicates, but keep each variable to reduce secondary errors with instantiating this generic type (assume number of variables is correct)
581
for (int j = 0; j < count; j++) {
582                 TypeVariableBinding knownVar = typeVariableBindings[j];
583                 if (CharOperation.equals(knownVar.sourceName, typeParameter.name))
584                     problemReporter().duplicateTypeParameterInType(typeParameter);
585             }
586             typeVariableBindings[count++] = parameterBinding;
587 // TODO should offer warnings to inform about hiding declaring, enclosing or member types
588
// ReferenceBinding type = sourceType;
589
// // check that the member does not conflict with an enclosing type
590
// do {
591
// if (CharOperation.equals(type.sourceName, memberContext.name)) {
592
// problemReporter().hidingEnclosingType(memberContext);
593
// continue nextParameter;
594
// }
595
// type = type.enclosingType();
596
// } while (type != null);
597
// // check that the member type does not conflict with another sibling member type
598
// for (int j = 0; j < i; j++) {
599
// if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
600
// problemReporter().duplicateNestedType(memberContext);
601
// continue nextParameter;
602
// }
603
// }
604
}
605         if (count != length)
606             System.arraycopy(typeVariableBindings, 0, typeVariableBindings = new TypeVariableBinding[count], 0, count);
607         return typeVariableBindings;
608     }
609
610     public final ClassScope enclosingClassScope() {
611         Scope scope = this;
612         while ((scope = scope.parent) != null) {
613             if (scope instanceof ClassScope) return (ClassScope) scope;
614         }
615         return null; // may answer null if no type around
616
}
617     
618     public final MethodScope enclosingMethodScope() {
619         Scope scope = this;
620         while ((scope = scope.parent) != null) {
621             if (scope instanceof MethodScope) return (MethodScope) scope;
622         }
623         return null; // may answer null if no method around
624
}
625
626     /* Answer the scope receiver type (could be parameterized)
627     */

628     public final ReferenceBinding enclosingReceiverType() {
629         Scope scope = this;
630         do {
631             if (scope instanceof ClassScope) {
632                 return environment().convertToParameterizedType(((ClassScope) scope).referenceContext.binding);
633             }
634             scope = scope.parent;
635         } while (scope != null);
636         return null;
637     }
638     /**
639      * Returns the immediately enclosing reference context, starting from current scope parent.
640      * If starting on a class, it will skip current class. If starting on unitScope, returns null.
641      */

642     public ReferenceContext enclosingReferenceContext() {
643         Scope current = this;
644         while ((current = current.parent) != null) {
645             switch(current.kind) {
646                 case METHOD_SCOPE :
647                     return ((MethodScope) current).referenceContext;
648                 case CLASS_SCOPE :
649                     return ((ClassScope) current).referenceContext;
650                 case COMPILATION_UNIT_SCOPE :
651                     return ((CompilationUnitScope) current).referenceContext;
652             }
653         }
654         return null;
655     }
656
657     /* Answer the scope enclosing source type (could be generic)
658     */

659     public final SourceTypeBinding enclosingSourceType() {
660         Scope scope = this;
661         do {
662             if (scope instanceof ClassScope)
663                 return ((ClassScope) scope).referenceContext.binding;
664             scope = scope.parent;
665         } while (scope != null);
666         return null;
667     }
668
669     public final LookupEnvironment environment() {
670         Scope scope, unitScope = this;
671         while ((scope = unitScope.parent) != null)
672             unitScope = scope;
673         return ((CompilationUnitScope) unitScope).environment;
674     }
675
676     // abstract method lookup lookup (since maybe missing default abstract methods)
677
protected MethodBinding findDefaultAbstractMethod(
678         ReferenceBinding receiverType,
679         char[] selector,
680         TypeBinding[] argumentTypes,
681         InvocationSite invocationSite,
682         ReferenceBinding classHierarchyStart,
683         ObjectVector found,
684         MethodBinding concreteMatch) {
685
686         int startFoundSize = found.size;
687         ReferenceBinding currentType = classHierarchyStart;
688         while (currentType != null) {
689             findMethodInSuperInterfaces(currentType, selector, found);
690             currentType = currentType.superclass();
691         }
692         MethodBinding[] candidates = null;
693         int candidatesCount = 0;
694         MethodBinding problemMethod = null;
695         int foundSize = found.size;
696         if (foundSize > startFoundSize) {
697             // argument type compatibility check
698
for (int i = startFoundSize; i < foundSize; i++) {
699                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
700                 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
701                 if (compatibleMethod != null) {
702                     if (compatibleMethod.isValidBinding()) {
703                         if (concreteMatch != null && concreteMatch.declaringClass.findSuperTypeWithSameErasure(compatibleMethod.declaringClass) != null)
704                             if (environment().methodVerifier().doesMethodOverride(concreteMatch, compatibleMethod))
705                                 continue; // can skip this method since concreteMatch overrides it
706
if (candidatesCount == 0) {
707                             candidates = new MethodBinding[foundSize - startFoundSize + 1];
708                             if (concreteMatch != null)
709                                 candidates[candidatesCount++] = concreteMatch;
710                         }
711                         candidates[candidatesCount++] = compatibleMethod;
712                     } else if (problemMethod == null) {
713                         problemMethod = compatibleMethod;
714                     }
715                 }
716             }
717         }
718
719         if (candidatesCount < 2) {
720             if (concreteMatch == null) {
721                 if (candidatesCount == 0)
722                     return problemMethod; // can be null
723
concreteMatch = candidates[0];
724             }
725             compilationUnitScope().recordTypeReferences(concreteMatch.thrownExceptions);
726             return concreteMatch;
727         }
728         // no need to check for visibility - interface methods are public
729
if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
730             return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite, receiverType);
731         return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite);
732     }
733
734     // Internal use only
735
public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
736         if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0)
737             return null; // know it has no member types (nor inherited member types)
738

739         ReferenceBinding enclosingReceiverType = enclosingReceiverType();
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 (enclosingReceiverType == null
746                 ? memberType.canBeSeenBy(getCurrentPackage())
747                 : memberType.canBeSeenBy(enclosingType, enclosingReceiverType))
748                     return memberType;
749             return new ProblemReferenceBinding(typeName, memberType, ProblemReasons.NotVisible);
750         }
751         return null;
752     }
753
754     // Internal use only
755
public MethodBinding findExactMethod(
756         ReferenceBinding receiverType,
757         char[] selector,
758         TypeBinding[] argumentTypes,
759         InvocationSite invocationSite) {
760
761         CompilationUnitScope unitScope = compilationUnitScope();
762         unitScope.recordTypeReferences(argumentTypes);
763         MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope);
764         if (exactMethod != null && exactMethod.typeVariables == Binding.NO_TYPE_VARIABLES && !exactMethod.isBridge()) {
765             // must find both methods for this case: <S extends A> void foo() {} and <N extends B> N foo() { return null; }
766
// or find an inherited method when the exact match is to a bridge method
767
unitScope.recordTypeReferences(exactMethod.thrownExceptions);
768             // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type)
769
if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) {
770                 if (receiverType.id != T_JavaLangObject
771                     && argumentTypes == Binding.NO_PARAMETERS
772                     && CharOperation.equals(selector, GETCLASS)
773                     && exactMethod.returnType.isParameterizedType()/*1.5*/) {
774                         return ParameterizedMethodBinding.instantiateGetClass(receiverType, exactMethod, this);
775                 }
776                 // targeting a generic method could find an exact match with variable return type
777
if (invocationSite.genericTypeArguments() != null) {
778                     exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite);
779                 }
780                 return exactMethod;
781             }
782         }
783         return null;
784     }
785
786     // Internal use only
787
/* Answer the field binding that corresponds to fieldName.
788         Start the lookup at the receiverType.
789         InvocationSite implements
790             isSuperAccess(); this is used to determine if the discovered field is visible.
791         Only fields defined by the receiverType or its supertypes are answered;
792         a field of an enclosing type will not be found using this API.
793     
794         If no visible field is discovered, null is answered.
795     */

796     public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
797
798         CompilationUnitScope unitScope = compilationUnitScope();
799         unitScope.recordTypeReference(receiverType);
800         
801         checkArrayField: {
802             TypeBinding leafType;
803             switch (receiverType.kind()) {
804                 case Binding.BASE_TYPE :
805                     return null;
806                 case Binding.WILDCARD_TYPE :
807                 case Binding.TYPE_PARAMETER : // capture
808
TypeBinding receiverErasure = receiverType.erasure();
809                     if (!receiverErasure.isArrayType())
810                         break checkArrayField;
811                     leafType = receiverErasure.leafComponentType();
812                     break;
813                 case Binding.ARRAY_TYPE :
814                     leafType = receiverType.leafComponentType();
815                     break;
816                 default:
817                     break checkArrayField;
818             }
819             if (leafType instanceof ReferenceBinding)
820                 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
821                     return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ProblemReasons.ReceiverTypeNotVisible);
822             if (CharOperation.equals(fieldName, LENGTH))
823                 return ArrayBinding.ArrayLength;
824             return null;
825         }
826
827         ReferenceBinding currentType = (ReferenceBinding) receiverType;
828         if (!currentType.canBeSeenBy(this))
829             return new ProblemFieldBinding(currentType, fieldName, ProblemReasons.ReceiverTypeNotVisible);
830
831         FieldBinding field = currentType.getField(fieldName, needResolve);
832         if (field != null) {
833             if (invocationSite == null
834                 ? field.canBeSeenBy(getCurrentPackage())
835                 : field.canBeSeenBy(currentType, invocationSite, this))
836                     return field;
837             return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, ProblemReasons.NotVisible);
838         }
839         // collect all superinterfaces of receiverType until the field is found in a supertype
840
ReferenceBinding[] interfacesToVisit = null;
841         int nextPosition = 0;
842         FieldBinding visibleField = null;
843         boolean keepLooking = true;
844         FieldBinding notVisibleField = null;
845         // we could hold onto the not visible field for extra error reporting
846
while (keepLooking) {
847             ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
848             if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
849
((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
850                 itsInterfaces = currentType.superInterfaces();
851             }
852             if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
853                 if (interfacesToVisit == null) {
854                     interfacesToVisit = itsInterfaces;
855                     nextPosition = interfacesToVisit.length;
856                 } else {
857                     int itsLength = itsInterfaces.length;
858                     if (nextPosition + itsLength >= interfacesToVisit.length)
859                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
860                     nextInterface : for (int a = 0; a < itsLength; a++) {
861                         ReferenceBinding next = itsInterfaces[a];
862                         for (int b = 0; b < nextPosition; b++)
863                             if (next == interfacesToVisit[b]) continue nextInterface;
864                         interfacesToVisit[nextPosition++] = next;
865                     }
866                 }
867             }
868             if ((currentType = currentType.superclass()) == null)
869                 break;
870
871             unitScope.recordTypeReference(currentType);
872             if ((field = currentType.getField(fieldName, needResolve)) != null) {
873                 keepLooking = false;
874                 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
875                     if (visibleField == null)
876                         visibleField = field;
877                     else
878                         return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous);
879                 } else {
880                     if (notVisibleField == null)
881                         notVisibleField = field;
882                 }
883             }
884         }
885
886         // walk all visible interfaces to find ambiguous references
887
if (interfacesToVisit != null) {
888             ProblemFieldBinding ambiguous = null;
889             done : for (int i = 0; i < nextPosition; i++) {
890                 ReferenceBinding anInterface = interfacesToVisit[i];
891                 unitScope.recordTypeReference(anInterface);
892                 if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
893                     if (visibleField == null) {
894                         visibleField = field;
895                     } else {
896                         ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous);
897                         break done;
898                     }
899                 } else {
900                     ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
901                     if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
902                         int itsLength = itsInterfaces.length;
903                         if (nextPosition + itsLength >= interfacesToVisit.length)
904                             System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
905                         nextInterface : for (int a = 0; a < itsLength; a++) {
906                             ReferenceBinding next = itsInterfaces[a];
907                             for (int b = 0; b < nextPosition; b++)
908                                 if (next == interfacesToVisit[b]) continue nextInterface;
909                             interfacesToVisit[nextPosition++] = next;
910                         }
911                     }
912                 }
913             }
914             if (ambiguous != null)
915                 return ambiguous;
916         }
917
918         if (visibleField != null)
919             return visibleField;
920         if (notVisibleField != null) {
921             return new ProblemFieldBinding(notVisibleField, currentType, fieldName, ProblemReasons.NotVisible);
922         }
923         return null;
924     }
925     
926     // Internal use only
927
public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
928         if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0)
929             return null; // know it has no member types (nor inherited member types)
930

931         ReferenceBinding enclosingSourceType = enclosingSourceType();
932         PackageBinding currentPackage = getCurrentPackage();
933         CompilationUnitScope unitScope = compilationUnitScope();
934         unitScope.recordReference(enclosingType, typeName);
935         ReferenceBinding memberType = enclosingType.getMemberType(typeName);
936         if (memberType != null) {
937             unitScope.recordTypeReference(memberType);
938             if (enclosingSourceType == null
939                 ? memberType.canBeSeenBy(currentPackage)
940                 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
941                     return memberType;
942             return new ProblemReferenceBinding(typeName, memberType, ProblemReasons.NotVisible);
943         }
944
945         // collect all superinterfaces of receiverType until the memberType is found in a supertype
946
ReferenceBinding currentType = enclosingType;
947         ReferenceBinding[] interfacesToVisit = null;
948         int nextPosition = 0;
949         ReferenceBinding visibleMemberType = null;
950         boolean keepLooking = true;
951         ReferenceBinding notVisible = null;
952         // we could hold onto the not visible field for extra error reporting
953
while (keepLooking) {
954             ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
955             if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
956
ReferenceBinding sourceType = currentType.isParameterizedType()
957                     ? ((ParameterizedTypeBinding) currentType).genericType()
958                     : currentType;
959                 if (sourceType.isHierarchyBeingConnected())
960                     return null; // looking for an undefined member type in its own superclass ref
961
((SourceTypeBinding) sourceType).scope.connectTypeHierarchy();
962                 itsInterfaces = currentType.superInterfaces();
963             }
964             if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
965                 if (interfacesToVisit == null) {
966                     interfacesToVisit = itsInterfaces;
967                     nextPosition = interfacesToVisit.length;
968                 } else {
969                     int itsLength = itsInterfaces.length;
970                     if (nextPosition + itsLength >= interfacesToVisit.length)
971                         System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
972                     nextInterface : for (int a = 0; a < itsLength; a++) {
973                         ReferenceBinding next = itsInterfaces[a];
974                         for (int b = 0; b < nextPosition; b++)
975                             if (next == interfacesToVisit[b]) continue nextInterface;
976                         interfacesToVisit[nextPosition++] = next;
977                     }
978                 }
979             }
980             if ((currentType = currentType.superclass()) == null)
981                 break;
982
983             unitScope.recordReference(currentType, typeName);
984             if ((memberType = currentType.getMemberType(typeName)) != null) {
985                 unitScope.recordTypeReference(memberType);
986                 keepLooking = false;
987                 if (enclosingSourceType == null
988                     ? memberType.canBeSeenBy(currentPackage)
989                     : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
990                         if (visibleMemberType == null)
991                             visibleMemberType = memberType;
992                         else
993                             return new ProblemReferenceBinding(typeName, visibleMemberType, ProblemReasons.Ambiguous);
994                 } else {
995                     notVisible = memberType;
996                 }
997             }
998         }
999         // walk all visible interfaces to find ambiguous references
1000
if (interfacesToVisit != null) {
1001            ProblemReferenceBinding ambiguous = null;
1002            done : for (int i = 0; i < nextPosition; i++) {
1003                ReferenceBinding anInterface = interfacesToVisit[i];
1004                unitScope.recordReference(anInterface, typeName);
1005                if ((memberType = anInterface.getMemberType(typeName)) != null) {
1006                    unitScope.recordTypeReference(memberType);
1007                    if (visibleMemberType == null) {
1008                        visibleMemberType = memberType;
1009                    } else {
1010                        ambiguous = new ProblemReferenceBinding(typeName, visibleMemberType, ProblemReasons.Ambiguous);
1011                        break done;
1012                    }
1013                } else {
1014                    ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
1015                    if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
1016                        int itsLength = itsInterfaces.length;
1017                        if (nextPosition + itsLength >= interfacesToVisit.length)
1018                            System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
1019                        nextInterface : for (int a = 0; a < itsLength; a++) {
1020                            ReferenceBinding next = itsInterfaces[a];
1021                            for (int b = 0; b < nextPosition; b++)
1022                                if (next == interfacesToVisit[b]) continue nextInterface;
1023                            interfacesToVisit[nextPosition++] = next;
1024                        }
1025                    }
1026                }
1027            }
1028            if (ambiguous != null)
1029                return ambiguous;
1030        }
1031        if (visibleMemberType != null)
1032            return visibleMemberType;
1033        if (notVisible != null)
1034            return new ProblemReferenceBinding(typeName, notVisible, ProblemReasons.NotVisible);
1035        return null;
1036    }
1037
1038    // Internal use only - use findMethod()
1039
public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1040        ReferenceBinding currentType = receiverType;
1041        boolean receiverTypeIsInterface = receiverType.isInterface();
1042        ObjectVector found = new ObjectVector(3);
1043        CompilationUnitScope unitScope = compilationUnitScope();
1044        unitScope.recordTypeReferences(argumentTypes);
1045
1046        if (receiverTypeIsInterface) {
1047            unitScope.recordTypeReference(receiverType);
1048            MethodBinding[] receiverMethods = receiverType.getMethods(selector);
1049            if (receiverMethods.length > 0)
1050                found.addAll(receiverMethods);
1051            findMethodInSuperInterfaces(receiverType, selector, found);
1052            currentType = getJavaLangObject();
1053        }
1054
1055        // superclass lookup
1056
long complianceLevel = compilerOptions().complianceLevel;
1057        boolean isCompliant14 = complianceLevel >= ClassFileConstants.JDK1_4;
1058        boolean isCompliant15 = complianceLevel >= ClassFileConstants.JDK1_5;
1059        ReferenceBinding classHierarchyStart = currentType;
1060        MethodVerifier verifier = environment().methodVerifier();
1061        while (currentType != null) {
1062            unitScope.recordTypeReference(currentType);
1063            MethodBinding[] currentMethods = currentType.getMethods(selector);
1064            int currentLength = currentMethods.length;
1065            if (currentLength > 0) {
1066                if (isCompliant14 && (receiverTypeIsInterface || found.size > 0)) {
1067                    nextMethod: for (int i = 0, l = currentLength; i < l; i++) { // currentLength can be modified inside the loop
1068
MethodBinding currentMethod = currentMethods[i];
1069                        if (currentMethod == null) continue nextMethod;
1070                        if (receiverTypeIsInterface && !currentMethod.isPublic()) { // only public methods from Object are visible to interface receiverTypes
1071
currentLength--;
1072                            currentMethods[i] = null;
1073                            continue nextMethod;
1074                        }
1075
1076                        // if 1.4 compliant, must filter out redundant protected methods from superclasses
1077
// protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
1078
// when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
1079
// if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
1080
// BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
1081
for (int j = 0, max = found.size; j < max; j++) {
1082                            MethodBinding matchingMethod = (MethodBinding) found.elementAt(j);
1083                            if (verifier.doesMethodOverride(matchingMethod.original(), currentMethod.original())) {
1084                                if (isCompliant15) {
1085                                    if (matchingMethod.isBridge() && !currentMethod.isBridge())
1086                                        continue nextMethod; // keep inherited methods to find concrete method over a bridge method
1087
}
1088                                currentLength--;
1089                                currentMethods[i] = null;
1090                                continue nextMethod;
1091                            }
1092                        }
1093                    }
1094                }
1095
1096                if (currentLength > 0) {
1097                    // append currentMethods, filtering out null entries
1098
if (currentMethods.length == currentLength) {
1099                        found.addAll(currentMethods);
1100                    } else {
1101                        for (int i = 0, max = currentMethods.length; i < max; i++) {
1102                            MethodBinding currentMethod = currentMethods[i];
1103                            if (currentMethod != null)
1104                                found.add(currentMethod);
1105                        }
1106                    }
1107                }
1108            }
1109            currentType = currentType.superclass();
1110        }
1111
1112        // if found several candidates, then eliminate those not matching argument types
1113
int foundSize = found.size;
1114        MethodBinding[] candidates = null;
1115        int candidatesCount = 0;
1116        MethodBinding problemMethod = null;
1117        boolean searchForDefaultAbstractMethod = isCompliant14 && ! receiverTypeIsInterface && (receiverType.isAbstract() || receiverType.isTypeVariable());
1118        if (foundSize > 0) {
1119            // argument type compatibility check
1120
for (int i = 0; i < foundSize; i++) {
1121                MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
1122                MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1123                if (compatibleMethod != null) {
1124                    if (compatibleMethod.isValidBinding()) {
1125                        if (foundSize == 1 && compatibleMethod.canBeSeenBy(receiverType, invocationSite, this)) {
1126                            // return the single visible match now
1127
if (searchForDefaultAbstractMethod)
1128                                return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, compatibleMethod);
1129                            unitScope.recordTypeReferences(compatibleMethod.thrownExceptions);
1130                            return compatibleMethod;
1131                        }
1132                        if (candidatesCount == 0)
1133                            candidates = new MethodBinding[foundSize];
1134                        candidates[candidatesCount++] = compatibleMethod;
1135                    } else if (problemMethod == null) {
1136                        problemMethod = compatibleMethod;
1137                    }
1138                }
1139            }
1140        }
1141
1142        // no match was found
1143
if (candidatesCount == 0) {
1144            // abstract classes may get a match in interfaces; for non abstract
1145
// classes, reduces secondary errors since missing interface method
1146
// error is already reported
1147
MethodBinding interfaceMethod =
1148                findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null);
1149            if (interfaceMethod != null) return interfaceMethod;
1150            if (found.size == 0) return null;
1151            if (problemMethod != null) return problemMethod;
1152
1153            // still no match; try to find a close match when the parameter
1154
// order is wrong or missing some parameters
1155

1156            // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=69471
1157
// bad guesses are foo(), when argument types have been supplied
1158
// and foo(X, Y), when the argument types are (int, float, Y)
1159
// so answer the method with the most argType matches and least parameter type mismatches
1160
int bestArgMatches = -1;
1161            MethodBinding bestGuess = (MethodBinding) found.elementAt(0); // if no good match so just use the first one found
1162
int argLength = argumentTypes.length;
1163            foundSize = found.size;
1164            nextMethod : for (int i = 0; i < foundSize; i++) {
1165                MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
1166                TypeBinding[] params = methodBinding.parameters;
1167                int paramLength = params.length;
1168                int argMatches = 0;
1169                next: for (int a = 0; a < argLength; a++) {
1170                    TypeBinding arg = argumentTypes[a];
1171                    for (int p = a == 0 ? 0 : a - 1; p < paramLength && p < a + 1; p++) { // look one slot before & after to see if the type matches
1172
if (params[p] == arg) {
1173                            argMatches++;
1174                            continue next;
1175                        }
1176                    }
1177                }
1178                if (argMatches < bestArgMatches)
1179                    continue nextMethod;
1180                if (argMatches == bestArgMatches) {
1181                    int diff1 = paramLength < argLength ? 2 * (argLength - paramLength) : paramLength - argLength;
1182                    int bestLength = bestGuess.parameters.length;
1183                    int diff2 = bestLength < argLength ? 2 * (argLength - bestLength) : bestLength - argLength;
1184                    if (diff1 >= diff2)
1185                        continue nextMethod;
1186                }
1187                bestArgMatches = argMatches;
1188                bestGuess = methodBinding;
1189            }
1190            return new ProblemMethodBinding(bestGuess, bestGuess.selector, argumentTypes, ProblemReasons.NotFound);
1191        }
1192
1193        // tiebreak using visibility check
1194
int visiblesCount = 0;
1195        if (receiverTypeIsInterface) {
1196            if (candidatesCount == 1) {
1197                unitScope.recordTypeReferences(candidates[0].thrownExceptions);
1198                return candidates[0];
1199            }
1200            visiblesCount = candidatesCount;
1201        } else {
1202            for (int i = 0; i < candidatesCount; i++) {
1203                MethodBinding methodBinding = candidates[i];
1204                if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
1205                    if (visiblesCount != i) {
1206                        candidates[i] = null;
1207                        candidates[visiblesCount] = methodBinding;
1208                    }
1209                    visiblesCount++;
1210                }
1211            }
1212            if (visiblesCount == 1) {
1213                if (searchForDefaultAbstractMethod)
1214                    return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, candidates[0]);
1215                unitScope.recordTypeReferences(candidates[0].thrownExceptions);
1216                return candidates[0];
1217            }
1218            if (visiblesCount == 0) {
1219                MethodBinding interfaceMethod =
1220                    findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null);
1221                if (interfaceMethod != null) return interfaceMethod;
1222                return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, ProblemReasons.NotVisible);
1223            }
1224        }
1225
1226        if (complianceLevel <= ClassFileConstants.JDK1_3) {
1227            ReferenceBinding declaringClass = candidates[0].declaringClass;
1228            return !declaringClass.isInterface()
1229                ? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
1230                : mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
1231        }
1232
1233        // check for duplicate parameterized methods
1234
if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
1235            for (int i = 0; i < visiblesCount; i++) {
1236                MethodBinding current = candidates[i];
1237                if (current instanceof ParameterizedGenericMethodBinding)
1238                    current = ((ParameterizedGenericMethodBinding) current).originalMethod;
1239                if (current instanceof ParameterizedMethodBinding)
1240                    for (int j = i + 1; j < visiblesCount; j++)
1241                        if (current.declaringClass == candidates[j].declaringClass && current.areParametersEqual(candidates[j]))
1242                            return new ProblemMethodBinding(candidates[i], candidates[i].selector, candidates[i].parameters, ProblemReasons.Ambiguous);
1243            }
1244        }
1245
1246        MethodBinding mostSpecificMethod = mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite, receiverType);
1247        if (searchForDefaultAbstractMethod) { // search interfaces for a better match
1248
if (mostSpecificMethod.isValidBinding())
1249                // see if there is a better match in the interfaces - see AutoBoxingTest 99, LookupTest#81
1250
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, mostSpecificMethod);
1251            // see if there is a match in the interfaces - see LookupTest#84
1252
MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null);
1253            if (interfaceMethod != null && interfaceMethod.isValidBinding() /* else return the same error as before */)
1254                return interfaceMethod;
1255        }
1256        return mostSpecificMethod;
1257    }
1258
1259    // Internal use only
1260
public MethodBinding findMethodForArray(
1261        ArrayBinding receiverType,
1262        char[] selector,
1263        TypeBinding[] argumentTypes,
1264        InvocationSite invocationSite) {
1265
1266        TypeBinding leafType = receiverType.leafComponentType();
1267        if (leafType instanceof ReferenceBinding) {
1268            if (!((ReferenceBinding) leafType).canBeSeenBy(this))
1269                return new ProblemMethodBinding(selector, Binding.NO_PARAMETERS, (ReferenceBinding)leafType, ProblemReasons.ReceiverTypeNotVisible);
1270        }
1271
1272        ReferenceBinding object = getJavaLangObject();
1273        MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes, null);
1274        if (methodBinding != null) {
1275            // handle the method clone() specially... cannot be protected or throw exceptions
1276
if (argumentTypes == Binding.NO_PARAMETERS) {
1277                switch (selector[0]) {
1278                    case 'c':
1279                        if (CharOperation.equals(selector, CLONE)) {
1280                            return new UpdatedMethodBinding(
1281                                compilerOptions().targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
1282
(methodBinding.modifiers & ~ClassFileConstants.AccProtected) | ClassFileConstants.AccPublic,
1283                                CLONE,
1284                                methodBinding.returnType,
1285                                argumentTypes,
1286                                null,
1287                                object);
1288                        }
1289                        break;
1290                    case 'g':
1291                        if (CharOperation.equals(selector, GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) {
1292                            return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this);
1293                        }
1294                        break;
1295                }
1296            }
1297            if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
1298                return methodBinding;
1299        }
1300        methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
1301        if (methodBinding == null)
1302            return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
1303        return methodBinding;
1304    }
1305
1306    protected void findMethodInSuperInterfaces(ReferenceBinding currentType, char[] selector, ObjectVector found) {
1307        ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1308        if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
1309            ReferenceBinding[] interfacesToVisit = itsInterfaces;
1310            int nextPosition = interfacesToVisit.length;
1311            for (int i = 0; i < nextPosition; i++) {
1312                currentType = interfacesToVisit[i];
1313                compilationUnitScope().recordTypeReference(currentType);
1314                MethodBinding[] currentMethods = currentType.getMethods(selector);
1315                if (currentMethods.length > 0) {
1316                    int foundSize = found.size;
1317                    if (foundSize > 0) {
1318                        // its possible to walk the same superinterface from different classes in the hierarchy
1319
next : for (int c = 0, l = currentMethods.length; c < l; c++) {
1320                            MethodBinding current = currentMethods[c];
1321                            for (int f = 0; f < foundSize; f++)
1322                                if (current == found.elementAt(f)) continue next;
1323                            found.add(current);
1324                        }
1325                    } else {
1326                        found.addAll(currentMethods);
1327                    }
1328                }
1329                if ((itsInterfaces = currentType.superInterfaces()) != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
1330                    int itsLength = itsInterfaces.length;
1331                    if (nextPosition + itsLength >= interfacesToVisit.length)
1332                        System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
1333                    nextInterface : for (int a = 0; a < itsLength; a++) {
1334                        ReferenceBinding next = itsInterfaces[a];
1335                        for (int b = 0; b < nextPosition; b++)
1336                            if (next == interfacesToVisit[b]) continue nextInterface;
1337                        interfacesToVisit[nextPosition++] = next;
1338                    }
1339                }
1340            }
1341        }
1342    }
1343
1344    // Internal use only
1345
public ReferenceBinding findType(
1346        char[] typeName,
1347        PackageBinding declarationPackage,
1348        PackageBinding invocationPackage) {
1349
1350        compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
1351        ReferenceBinding typeBinding = declarationPackage.getType(typeName);
1352        if (typeBinding == null)
1353            return null;
1354
1355        if (typeBinding.isValidBinding()) {
1356            if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
1357                return new ProblemReferenceBinding(typeName, typeBinding, ProblemReasons.NotVisible);
1358        }
1359        return typeBinding;
1360    }
1361
1362    public LocalVariableBinding findVariable(char[] variable) {
1363
1364        return null;
1365    }
1366
1367    /* API
1368     *
1369     * Answer the binding that corresponds to the argument name.
1370     * flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
1371     * Only bindings corresponding to the mask can be answered.
1372     *
1373     * For example, getBinding("foo", VARIABLE, site) will answer
1374     * the binding for the field or local named "foo" (or an error binding if none exists).
1375     * If a type named "foo" exists, it will not be detected (and an error binding will be answered)
1376     *
1377     * The VARIABLE mask has precedence over the TYPE mask.
1378     *
1379     * If the VARIABLE mask is not set, neither fields nor locals will be looked for.
1380     *
1381     * InvocationSite implements:
1382     * isSuperAccess(); this is used to determine if the discovered field is visible.
1383     *
1384     * Limitations: cannot request FIELD independently of LOCAL, or vice versa
1385     */

1386    public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
1387        CompilationUnitScope unitScope = compilationUnitScope();
1388        LookupEnvironment env = unitScope.environment;
1389        try {
1390            env.missingClassFileLocation = invocationSite;
1391            Binding binding = null;
1392            FieldBinding problemField = null;
1393            if ((mask & Binding.VARIABLE) != 0) {
1394                boolean insideStaticContext = false;
1395                boolean insideConstructorCall = false;
1396                boolean insideTypeAnnotation = false;
1397                
1398                FieldBinding foundField = null;
1399                // can be a problem field which is answered if a valid field is not found
1400
ProblemFieldBinding foundInsideProblem = null;
1401                // inside Constructor call or inside static context
1402
Scope scope = this;
1403                int depth = 0;
1404                int foundDepth = 0;
1405                ReferenceBinding foundActualReceiverType = null;
1406                done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1407
switch (scope.kind) {
1408                        case METHOD_SCOPE :
1409                            MethodScope methodScope = (MethodScope) scope;
1410                            insideStaticContext |= methodScope.isStatic;
1411                            insideConstructorCall |= methodScope.isConstructorCall;
1412                            insideTypeAnnotation = methodScope.insideTypeAnnotation;
1413                            
1414                            // Fall through... could duplicate the code below to save a cast - questionable optimization
1415
case BLOCK_SCOPE :
1416                            LocalVariableBinding variableBinding = scope.findVariable(name);
1417                            // looks in this scope only
1418
if (variableBinding != null) {
1419                                if (foundField != null && foundField.isValidBinding())
1420                                    return new ProblemFieldBinding(
1421                                        foundField, // closest match
1422
foundField.declaringClass,
1423                                        name,
1424                                        ProblemReasons.InheritedNameHidesEnclosingName);
1425                                if (depth > 0)
1426                                    invocationSite.setDepth(depth);
1427                                return variableBinding;
1428                            }
1429                            break;
1430                        case CLASS_SCOPE :
1431                            ClassScope classScope = (ClassScope) scope;
1432                            ReferenceBinding receiverType = classScope.enclosingReceiverType();
1433                            if (!insideTypeAnnotation) {
1434                                FieldBinding fieldBinding = classScope.findField(receiverType, name, invocationSite, needResolve);
1435                                // Use next line instead if willing to enable protected access accross inner types
1436
// FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
1437

1438                                if (fieldBinding != null) { // skip it if we did not find anything
1439
if (fieldBinding.problemId() == ProblemReasons.Ambiguous) {
1440                                        if (foundField == null || foundField.problemId() == ProblemReasons.NotVisible)
1441                                            // supercedes any potential InheritedNameHidesEnclosingName problem
1442
return fieldBinding;
1443                                        // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
1444
return new ProblemFieldBinding(
1445                                            foundField, // closest match
1446
foundField.declaringClass,
1447                                            name,
1448                                            ProblemReasons.InheritedNameHidesEnclosingName);
1449                                    }
1450    
1451                                    ProblemFieldBinding insideProblem = null;
1452                                    if (fieldBinding.isValidBinding()) {
1453                                        if (!fieldBinding.isStatic()) {
1454                                            if (insideConstructorCall) {
1455                                                insideProblem =
1456                                                    new ProblemFieldBinding(
1457                                                        fieldBinding, // closest match
1458
fieldBinding.declaringClass,
1459                                                        name,
1460                                                        ProblemReasons.NonStaticReferenceInConstructorInvocation);
1461                                            } else if (insideStaticContext) {
1462                                                insideProblem =
1463                                                    new ProblemFieldBinding(
1464                                                        fieldBinding, // closest match
1465
fieldBinding.declaringClass,
1466                                                        name,
1467                                                        ProblemReasons.NonStaticReferenceInStaticContext);
1468                                            }
1469                                        }
1470                                        if (receiverType == fieldBinding.declaringClass || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
1471                                            // found a valid field in the 'immediate' scope (ie. not inherited)
1472
// OR in 1.4 mode (inherited shadows enclosing)
1473
if (foundField == null) {
1474                                                if (depth > 0){
1475                                                    invocationSite.setDepth(depth);
1476                                                    invocationSite.setActualReceiverType(receiverType);
1477                                                }
1478                                                // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
1479
return insideProblem == null ? fieldBinding : insideProblem;
1480                                            }
1481                                            if (foundField.isValidBinding())
1482                                                // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
1483
if (foundField.declaringClass != fieldBinding.declaringClass)
1484                                                    // ie. have we found the same field - do not trust field identity yet
1485
return new ProblemFieldBinding(
1486                                                        foundField, // closest match
1487
foundField.declaringClass,
1488                                                        name,
1489                                                        ProblemReasons.InheritedNameHidesEnclosingName);
1490                                        }
1491                                    }
1492    
1493                                    if (foundField == null || (foundField.problemId() == ProblemReasons.NotVisible && fieldBinding.problemId() != ProblemReasons.NotVisible)) {
1494                                        // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
1495
foundDepth = depth;
1496                                        foundActualReceiverType = receiverType;
1497                                        foundInsideProblem = insideProblem;
1498                                        foundField = fieldBinding;
1499                                    }
1500                                }
1501                            }
1502                            insideTypeAnnotation = false;
1503                            depth++;
1504                            insideStaticContext |= receiverType.isStatic();
1505                            // 1EX5I8Z - accessing outer fields within a constructor call is permitted
1506
// in order to do so, we change the flag as we exit from the type, not the method
1507
// itself, because the class scope is used to retrieve the fields.
1508
MethodScope enclosingMethodScope = scope.methodScope();
1509                            insideConstructorCall = enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
1510                            break;
1511                        case COMPILATION_UNIT_SCOPE :
1512                            break done;
1513                    }
1514                    scope = scope.parent;
1515                }
1516
1517                if (foundInsideProblem != null)
1518                    return foundInsideProblem;
1519                if (foundField != null) {
1520                    if (foundField.isValidBinding()) {
1521                        if (foundDepth > 0) {
1522                            invocationSite.setDepth(foundDepth);
1523                            invocationSite.setActualReceiverType(foundActualReceiverType);
1524                        }
1525                        return foundField;
1526                    }
1527                    problemField = foundField;
1528                    foundField = null;
1529                }
1530
1531                if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
1532                    // at this point the scope is a compilation unit scope & need to check for imported static fields
1533
unitScope.faultInImports(); // ensure static imports are resolved
1534
ImportBinding[] imports = unitScope.imports;
1535                    if (imports != null) {
1536                        // check single static imports
1537
for (int i = 0, length = imports.length; i < length; i++) {
1538                            ImportBinding importBinding = imports[i];
1539                            if (importBinding.isStatic() && !importBinding.onDemand) {
1540                                if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
1541                                    if (unitScope.resolveSingleImport(importBinding) != null && importBinding.resolvedImport instanceof FieldBinding) {
1542                                        foundField = (FieldBinding) importBinding.resolvedImport;
1543                                        ImportReference importReference = importBinding.reference;
1544                                        if (importReference != null && needResolve) {
1545                                            importReference.bits |= ASTNode.Used;
1546                                        }
1547                                        invocationSite.setActualReceiverType(foundField.declaringClass);
1548                                        if (foundField.isValidBinding()) {
1549                                            return foundField;
1550                                        }
1551                                        if (problemField == null)
1552                                            problemField = foundField;
1553                                    }
1554                                }
1555                            }
1556                        }
1557                        // check on demand imports
1558
boolean foundInImport = false;
1559                        for (int i = 0, length = imports.length; i < length; i++) {
1560                            ImportBinding importBinding = imports[i];
1561                            if (importBinding.isStatic() && importBinding.onDemand) {
1562                                Binding resolvedImport = importBinding.resolvedImport;
1563                                if (resolvedImport instanceof ReferenceBinding) {
1564                                    FieldBinding temp = findField((ReferenceBinding) resolvedImport, name, invocationSite, needResolve);
1565                                    if (temp != null) {
1566                                        if (!temp.isValidBinding()) {
1567                                            if (problemField == null)
1568                                                problemField = temp;
1569                                        } else if (temp.isStatic()) {
1570                                            if (foundField == temp) continue;
1571                                            ImportReference importReference = importBinding.reference;
1572                                            if (importReference != null && needResolve) {
1573                                                importReference.bits |= ASTNode.Used;
1574                                            }
1575                                            if (foundInImport)
1576                                                // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1577
return new ProblemReferenceBinding(name, null, ProblemReasons.Ambiguous);
1578                                            foundField = temp;
1579                                            foundInImport = true;
1580                                        }
1581                                    }
1582                                }
1583                            }
1584                        }
1585                        if (foundField != null) {
1586                            invocationSite.setActualReceiverType(foundField.declaringClass);
1587                            return foundField;
1588                        }
1589                    }
1590                }
1591            }
1592
1593            // We did not find a local or instance variable.
1594
if ((mask & Binding.TYPE) != 0) {
1595                if ((binding = getBaseType(name)) != null)
1596                    return binding;
1597                binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
1598                if (binding.isValidBinding() || mask == Binding.TYPE)
1599                    return binding;
1600                // answer the problem type binding if we are only looking for a type
1601
} else if ((mask & Binding.PACKAGE) != 0) {
1602                unitScope.recordSimpleReference(name);
1603                if ((binding = env.getTopLevelPackage(name)) != null)
1604                    return binding;
1605            }
1606            if (problemField != null) return problemField;
1607            if (binding != null && binding.problemId() != ProblemReasons.NotFound)
1608                return binding; // answer the better problem binding
1609
return new ProblemBinding(name, enclosingSourceType(), ProblemReasons.NotFound);
1610        } catch (AbortCompilation e) {
1611            e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1612            throw e;
1613        } finally {
1614            env.missingClassFileLocation = null;
1615        }
1616    }
1617
1618    public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1619        CompilationUnitScope unitScope = compilationUnitScope();
1620        LookupEnvironment env = unitScope.environment;
1621        try {
1622            env.missingClassFileLocation = invocationSite;
1623            unitScope.recordTypeReference(receiverType);
1624            unitScope.recordTypeReferences(argumentTypes);
1625            MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
1626            if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) {
1627                // targeting a non generic constructor with type arguments ?
1628
if (invocationSite.genericTypeArguments() != null)
1629                    methodBinding = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1630                return methodBinding;
1631            }
1632            MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
1633            if (methods == Binding.NO_METHODS)
1634                return new ProblemMethodBinding(
1635                    TypeConstants.INIT,
1636                    argumentTypes,
1637                    ProblemReasons.NotFound);
1638
1639            MethodBinding[] compatible = new MethodBinding[methods.length];
1640            int compatibleIndex = 0;
1641            MethodBinding problemMethod = null;
1642            for (int i = 0, length = methods.length; i < length; i++) {
1643                MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
1644                if (compatibleMethod != null) {
1645                    if (compatibleMethod.isValidBinding())
1646                        compatible[compatibleIndex++] = compatibleMethod;
1647                    else if (problemMethod == null)
1648                        problemMethod = compatibleMethod;
1649                }
1650            }
1651            if (compatibleIndex == 0) {
1652                if (problemMethod == null)
1653                    return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound);
1654                return problemMethod;
1655            }
1656            // need a more descriptive error... cannot convert from X to Y
1657

1658            MethodBinding[] visible = new MethodBinding[compatibleIndex];
1659            int visibleIndex = 0;
1660            for (int i = 0; i < compatibleIndex; i++) {
1661                MethodBinding method = compatible[i];
1662                if (method.canBeSeenBy(invocationSite, this))
1663                    visible[visibleIndex++] = method;
1664            }
1665            if (visibleIndex == 1) return visible[0];
1666            if (visibleIndex == 0)
1667                return new ProblemMethodBinding(
1668                    compatible[0],
1669                    TypeConstants.INIT,
1670                    compatible[0].parameters,
1671                    ProblemReasons.NotVisible);
1672            // all of visible are from the same declaringClass, even before 1.4 we can call this method instead of mostSpecificClassMethodBinding
1673
return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite, receiverType);
1674        } catch (AbortCompilation e) {
1675            e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1676            throw e;
1677        } finally {
1678            env.missingClassFileLocation = null;
1679        }
1680    }
1681
1682    public final PackageBinding getCurrentPackage() {
1683        Scope scope, unitScope = this;
1684        while ((scope = unitScope.parent) != null)
1685            unitScope = scope;
1686        return ((CompilationUnitScope) unitScope).fPackage;
1687    }
1688
1689    /**
1690     * Returns the modifiers of the innermost enclosing declaration.
1691     * @return modifiers
1692     */

1693    public int getDeclarationModifiers(){
1694        switch(this.kind){
1695            case Scope.BLOCK_SCOPE :
1696            case Scope.METHOD_SCOPE :
1697                MethodScope methodScope = methodScope();
1698                if (!methodScope.isInsideInitializer()){
1699                    // check method modifiers to see if deprecated
1700
MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1701                    if (context != null)
1702                        return context.modifiers;
1703                } else {
1704                    SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
1705
1706                    // inside field declaration ? check field modifier to see if deprecated
1707
if (methodScope.initializedField != null)
1708                        return methodScope.initializedField.modifiers;
1709                    if (type != null)
1710                        return type.modifiers;
1711                }
1712                break;
1713            case Scope.CLASS_SCOPE :
1714                ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1715                if (context != null)
1716                    return context.modifiers;
1717                break;
1718        }
1719        return -1;
1720    }
1721
1722    public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
1723        LookupEnvironment env = environment();
1724        try {
1725            env.missingClassFileLocation = invocationSite;
1726            FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/);
1727            if (field != null) return field;
1728    
1729            return new ProblemFieldBinding(
1730                receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
1731                fieldName,
1732                ProblemReasons.NotFound);
1733        } catch (AbortCompilation e) {
1734            e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1735            throw e;
1736        } finally {
1737            env.missingClassFileLocation = null;
1738        }
1739    }
1740    
1741    /* API
1742     *
1743     * Answer the method binding that corresponds to selector, argumentTypes.
1744     * Start the lookup at the enclosing type of the receiver.
1745     * InvocationSite implements
1746     * isSuperAccess(); this is used to determine if the discovered method is visible.
1747     * setDepth(int); this is used to record the depth of the discovered method
1748     * relative to the enclosing type of the receiver. (If the method is defined
1749     * in the enclosing type of the receiver, the depth is 0; in the next enclosing
1750     * type, the depth is 1; and so on
1751     *
1752     * If no visible method is discovered, an error binding is answered.
1753     */

1754    public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1755
1756        boolean insideStaticContext = false;
1757        boolean insideConstructorCall = false;
1758        boolean insideTypeAnnotation = false;
1759        MethodBinding foundMethod = null;
1760        MethodBinding foundProblem = null;
1761        boolean foundProblemVisible = false;
1762        Scope scope = this;
1763        int depth = 0;
1764        // in 1.4 mode (inherited visible shadows enclosing)
1765
CompilerOptions options;
1766        boolean inheritedHasPrecedence = (options = compilerOptions()).complianceLevel >= ClassFileConstants.JDK1_4;
1767        
1768        done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1769
switch (scope.kind) {
1770                case METHOD_SCOPE :
1771                    MethodScope methodScope = (MethodScope) scope;
1772                    insideStaticContext |= methodScope.isStatic;
1773                    insideConstructorCall |= methodScope.isConstructorCall;
1774                    insideTypeAnnotation = methodScope.insideTypeAnnotation;
1775                    break;
1776                case CLASS_SCOPE :
1777                    ClassScope classScope = (ClassScope) scope;
1778                    ReferenceBinding receiverType = classScope.enclosingReceiverType();
1779                    if (!insideTypeAnnotation) {
1780                        // retrieve an exact visible match (if possible)
1781
// compilationUnitScope().recordTypeReference(receiverType); not needed since receiver is the source type
1782
MethodBinding methodBinding = classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite);
1783                        if (methodBinding == null)
1784                            methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
1785                        if (methodBinding != null) { // skip it if we did not find anything
1786
if (foundMethod == null) {
1787                                if (methodBinding.isValidBinding()) {
1788                                    if (!methodBinding.isStatic() && (insideConstructorCall || insideStaticContext)) {
1789                                        if (foundProblem != null && foundProblem.problemId() != ProblemReasons.NotVisible)
1790                                            return foundProblem; // takes precedence
1791
return new ProblemMethodBinding(
1792                                            methodBinding, // closest match
1793
methodBinding.selector,
1794                                            methodBinding.parameters,
1795                                            insideConstructorCall
1796                                                ? ProblemReasons.NonStaticReferenceInConstructorInvocation
1797                                                : ProblemReasons.NonStaticReferenceInStaticContext);
1798                                    }
1799                                    if (inheritedHasPrecedence
1800                                            || receiverType == methodBinding.declaringClass
1801                                            || (receiverType.getMethods(selector)) != Binding.NO_METHODS) {
1802                                        // found a valid method in the 'immediate' scope (ie. not inherited)
1803
// OR in 1.4 mode (inherited visible shadows enclosing)
1804
// OR the receiverType implemented a method with the correct name
1805
// return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
1806
if (foundProblemVisible) {
1807                                            return foundProblem;
1808                                        }
1809                                        if (depth > 0) {
1810                                            invocationSite.setDepth(depth);
1811                                            invocationSite.setActualReceiverType(receiverType);
1812                                        }
1813                                        return methodBinding;
1814                                    }
1815
1816                                    if (foundProblem == null || foundProblem.problemId() == ProblemReasons.NotVisible) {
1817                                        if (foundProblem != null) foundProblem = null;
1818                                        // only remember the methodBinding if its the first one found
1819
// remember that private methods are visible if defined directly by an enclosing class
1820
if (depth > 0) {
1821                                            invocationSite.setDepth(depth);
1822                                            invocationSite.setActualReceiverType(receiverType);
1823                                        }
1824                                        foundMethod = methodBinding;
1825                                    }
1826                                } else { // methodBinding is a problem method
1827
if (methodBinding.problemId() != ProblemReasons.NotVisible && methodBinding.problemId() != ProblemReasons.NotFound)
1828                                        return methodBinding; // return the error now
1829
if (foundProblem == null) {
1830                                        foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible
1831
}
1832                                    if (! foundProblemVisible && methodBinding.problemId() == ProblemReasons.NotFound) {
1833                                        MethodBinding closestMatch = ((ProblemMethodBinding) methodBinding).closestMatch;
1834                                        if (closestMatch != null && closestMatch.canBeSeenBy(receiverType, invocationSite, this)) {
1835                                            foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible
1836
foundProblemVisible = true;
1837                                        }
1838                                    }
1839                                }
1840                            } else { // found a valid method so check to see if this is a hiding case
1841
if (methodBinding.problemId() == ProblemReasons.Ambiguous
1842                                    || (foundMethod.declaringClass != methodBinding.declaringClass
1843                                        && (receiverType == methodBinding.declaringClass || receiverType.getMethods(selector) != Binding.NO_METHODS)))
1844                                    // ambiguous case -> must qualify the method (javac generates an ambiguous error instead)
1845
// otherwise if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
1846
// NOTE: Unlike fields, a non visible method hides a visible method
1847
return new ProblemMethodBinding(
1848                                        methodBinding, // closest match
1849
selector,
1850                                        argumentTypes,
1851                                        ProblemReasons.InheritedNameHidesEnclosingName);
1852                            }
1853                        }
1854                    }
1855                    insideTypeAnnotation = false;
1856                    depth++;
1857                    insideStaticContext |= receiverType.isStatic();
1858                    // 1EX5I8Z - accessing outer fields within a constructor call is permitted
1859
// in order to do so, we change the flag as we exit from the type, not the method
1860
// itself, because the class scope is used to retrieve the fields.
1861
MethodScope enclosingMethodScope = scope.methodScope();
1862                    insideConstructorCall = enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
1863                    break;
1864                case COMPILATION_UNIT_SCOPE :
1865                    break done;
1866            }
1867            scope = scope.parent;
1868        }
1869
1870        if (insideStaticContext && options.sourceLevel >= ClassFileConstants.JDK1_5) {
1871            if (foundProblem != null) {
1872                if (foundProblem.declaringClass != null && foundProblem.declaringClass.id == TypeIds.T_JavaLangObject)
1873                    return foundProblem; // static imports lose to methods from Object
1874
if (foundProblem.problemId() == ProblemReasons.NotFound && foundProblemVisible) {
1875                    return foundProblem; // visible method selectors take precedence
1876
}
1877            }
1878
1879            // at this point the scope is a compilation unit scope & need to check for imported static methods
1880
CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1881            unitScope.faultInImports(); // field constants can cause static imports to be accessed before they're resolved
1882
ImportBinding[] imports = unitScope.imports;
1883            if (imports != null) {
1884                ObjectVector visible = null;
1885                boolean skipOnDemand = false; // set to true when matched static import of method name so stop looking for on demand methods
1886
for (int i = 0, length = imports.length; i < length; i++) {
1887                    ImportBinding importBinding = imports[i];
1888                    if (importBinding.isStatic()) {
1889                        Binding resolvedImport = importBinding.resolvedImport;
1890                        MethodBinding possible = null;
1891                        if (importBinding.onDemand) {
1892                            if (!skipOnDemand && resolvedImport instanceof ReferenceBinding)
1893                                // answers closest approximation, may not check argumentTypes or visibility
1894
possible = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite);
1895                        } else {
1896                            if (resolvedImport instanceof MethodBinding) {
1897                                MethodBinding staticMethod = (MethodBinding) resolvedImport;
1898                                if (CharOperation.equals(staticMethod.selector, selector))
1899                                    // answers closest approximation, may not check argumentTypes or visibility
1900
possible = findMethod(staticMethod.declaringClass, selector, argumentTypes, invocationSite);
1901                            } else if (resolvedImport instanceof FieldBinding) {
1902                                // check to see if there are also methods with the same name
1903
FieldBinding staticField = (FieldBinding) resolvedImport;
1904                                if (CharOperation.equals(staticField.name, selector)) {
1905                                    // must find the importRef's type again since the field can be from an inherited type
1906
char[][] importName = importBinding.reference.tokens;
1907                                    TypeBinding referencedType = getType(importName, importName.length - 1);
1908                                    if (referencedType != null)
1909                                        // answers closest approximation, may not check argumentTypes or visibility
1910
possible = findMethod((ReferenceBinding) referencedType, selector, argumentTypes, invocationSite);
1911                                }
1912                            }
1913                        }
1914                        if (possible != null && possible != foundProblem) {
1915                            if (!possible.isValidBinding()) {
1916                                if (foundProblem == null)
1917                                    foundProblem = possible; // answer as error case match
1918
} else if (possible.isStatic()) {
1919                                MethodBinding compatibleMethod = computeCompatibleMethod(possible, argumentTypes, invocationSite);
1920                                if (compatibleMethod != null) {
1921                                    if (compatibleMethod.isValidBinding()) {
1922                                        if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
1923                                            if (visible == null || !visible.contains(compatibleMethod)) {
1924                                                ImportReference importReference = importBinding.reference;
1925                                                if (importReference != null) {
1926                                                    importReference.bits |= ASTNode.Used;
1927                                                }
1928                                                if (!skipOnDemand && !importBinding.onDemand) {
1929                                                    visible = null; // forget previous matches from on demand imports
1930
skipOnDemand = true;
1931                                                }
1932                                                if (visible == null)
1933                                                    visible = new ObjectVector(3);
1934                                                visible.add(compatibleMethod);
1935                                            }
1936                                        } else if (foundProblem == null) {
1937                                            foundProblem = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, ProblemReasons.NotVisible);
1938                                        }
1939                                    } else if (foundProblem == null) {
1940                                        foundProblem = compatibleMethod;
1941                                    }
1942                                } else if (foundProblem == null) {
1943                                    foundProblem = new ProblemMethodBinding(possible, selector, argumentTypes, ProblemReasons.NotFound);
1944                                }
1945                            }
1946                        }
1947                    }
1948                }
1949                if (visible != null) {
1950                    MethodBinding[] temp = new MethodBinding[visible.size];
1951                    visible.copyInto(temp);
1952                    foundMethod = mostSpecificMethodBinding(temp, temp.length, argumentTypes, invocationSite, null);
1953                }
1954            }
1955        }
1956
1957        if (foundMethod != null) {
1958            invocationSite.setActualReceiverType(foundMethod.declaringClass);
1959            return foundMethod;
1960        }
1961        if (foundProblem != null)
1962            return foundProblem;
1963
1964        return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
1965    }
1966
1967    public final ReferenceBinding getJavaIoSerializable() {
1968        CompilationUnitScope unitScope = compilationUnitScope();
1969        unitScope.recordQualifiedReference(JAVA_IO_SERIALIZABLE);
1970        return unitScope.environment.getResolvedType(JAVA_IO_SERIALIZABLE, this);
1971    }
1972    
1973    public final ReferenceBinding getJavaLangAnnotationAnnotation() {
1974        CompilationUnitScope unitScope = compilationUnitScope();
1975        unitScope.recordQualifiedReference(JAVA_LANG_ANNOTATION_ANNOTATION);
1976        return unitScope.environment.getResolvedType(JAVA_LANG_ANNOTATION_ANNOTATION, this);
1977    }
1978    
1979    public final ReferenceBinding getJavaLangAssertionError() {
1980        CompilationUnitScope unitScope = compilationUnitScope();
1981        unitScope.recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
1982        return unitScope.environment.getResolvedType(JAVA_LANG_ASSERTIONERROR, this);
1983    }
1984
1985    public final ReferenceBinding getJavaLangClass() {
1986        CompilationUnitScope unitScope = compilationUnitScope();
1987        unitScope.recordQualifiedReference(JAVA_LANG_CLASS);
1988        return unitScope.environment.getResolvedType(JAVA_LANG_CLASS, this);
1989    }
1990
1991    public final ReferenceBinding getJavaLangCloneable() {
1992        CompilationUnitScope unitScope = compilationUnitScope();
1993        unitScope.recordQualifiedReference(JAVA_LANG_CLONEABLE);
1994        return unitScope.environment.getResolvedType(JAVA_LANG_CLONEABLE, this);
1995    }
1996    public final ReferenceBinding getJavaLangEnum() {
1997        CompilationUnitScope unitScope = compilationUnitScope();
1998        unitScope.recordQualifiedReference(JAVA_LANG_ENUM);
1999        return unitScope.environment.getResolvedType(JAVA_LANG_ENUM, this);
2000    }
2001
2002    public final ReferenceBinding getJavaLangIterable() {
2003        CompilationUnitScope unitScope = compilationUnitScope();
2004        unitScope.recordQualifiedReference(JAVA_LANG_ITERABLE);
2005        return unitScope.environment.getResolvedType(JAVA_LANG_ITERABLE, this);
2006    }
2007    public final ReferenceBinding getJavaLangObject() {
2008        CompilationUnitScope unitScope = compilationUnitScope();
2009        unitScope.recordQualifiedReference(JAVA_LANG_OBJECT);
2010        return unitScope.environment.getResolvedType(JAVA_LANG_OBJECT, this);
2011    }
2012
2013    public final ReferenceBinding getJavaLangString() {
2014        CompilationUnitScope unitScope = compilationUnitScope();
2015        unitScope.recordQualifiedReference(JAVA_LANG_STRING);
2016        return unitScope.environment.getResolvedType(JAVA_LANG_STRING, this);
2017    }
2018
2019    public final ReferenceBinding getJavaLangThrowable() {
2020        CompilationUnitScope unitScope = compilationUnitScope();
2021        unitScope.recordQualifiedReference(JAVA_LANG_THROWABLE);
2022        return unitScope.environment.getResolvedType(JAVA_LANG_THROWABLE, this);
2023    }
2024    public final ReferenceBinding getJavaUtilIterator() {
2025        CompilationUnitScope unitScope = compilationUnitScope();
2026        unitScope.recordQualifiedReference(JAVA_UTIL_ITERATOR);
2027        return unitScope.environment.getResolvedType(JAVA_UTIL_ITERATOR, this);
2028    }
2029
2030    /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
2031    */

2032    public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
2033        ReferenceBinding memberType = findMemberType(typeName, enclosingType);
2034        if (memberType != null) return memberType;
2035        return new ProblemReferenceBinding(typeName, null, ProblemReasons.NotFound);
2036    }
2037
2038    public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
2039        CompilationUnitScope unitScope = compilationUnitScope();
2040        LookupEnvironment env = unitScope.environment;
2041        try {
2042            env.missingClassFileLocation = invocationSite;
2043            switch (receiverType.kind()) {
2044                case Binding.BASE_TYPE :
2045                    return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
2046                case Binding.ARRAY_TYPE :
2047                    unitScope.recordTypeReference(receiverType);
2048                    return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
2049            }
2050            unitScope.recordTypeReference(receiverType);
2051
2052            ReferenceBinding currentType = (ReferenceBinding) receiverType;
2053            if (!currentType.canBeSeenBy(this))
2054                return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.ReceiverTypeNotVisible);
2055    
2056            // retrieve an exact visible match (if possible)
2057
MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
2058            if (methodBinding != null) return methodBinding;
2059    
2060            methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
2061            if (methodBinding == null)
2062                return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
2063            if (!methodBinding.isValidBinding())
2064                return methodBinding;
2065
2066            // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type)
2067
if (receiverType.id != T_JavaLangObject
2068                && argumentTypes == Binding.NO_PARAMETERS
2069                && CharOperation.equals(selector, GETCLASS)
2070                && methodBinding.returnType.isParameterizedType()/*1.5*/) {
2071                    return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this);
2072            }
2073            return methodBinding;
2074        } catch (AbortCompilation e) {
2075            e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
2076            throw e;
2077        } finally {
2078            env.missingClassFileLocation = null;
2079        }
2080    }
2081
2082    /* Answer the package from the compoundName or null if it begins with a type.
2083    * Intended to be used while resolving a qualified type name.
2084    *
2085    * NOTE: If a problem binding is returned, senders should extract the compound name
2086    * from the binding & not assume the problem applies to the entire compoundName.
2087    */

2088    public final Binding getPackage(char[][] compoundName) {
2089        compilationUnitScope().recordQualifiedReference(compoundName);
2090        Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
2091        if (binding == null)
2092            return new ProblemReferenceBinding(compoundName[0], null, ProblemReasons.NotFound);
2093        if (!binding.isValidBinding())
2094            return binding;
2095
2096        if (!(binding instanceof PackageBinding)) return null; // compoundName does not start with a package
2097

2098        int currentIndex = 1;
2099        PackageBinding packageBinding = (PackageBinding) binding;
2100        while (currentIndex < compoundName.length) {
2101            binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
2102            if (binding == null)
2103                return new ProblemReferenceBinding(
2104                    CharOperation.subarray(compoundName, 0, currentIndex),
2105                    null,
2106                    ProblemReasons.NotFound);
2107            if (!binding.isValidBinding())
2108                return new ProblemReferenceBinding(
2109                    CharOperation.subarray(compoundName, 0, currentIndex),
2110                    binding instanceof ReferenceBinding ? ((ReferenceBinding)binding).closestMatch() : null,
2111                    binding.problemId());
2112            if (!(binding instanceof PackageBinding))
2113                return packageBinding;
2114            packageBinding = (PackageBinding) binding;
2115        }
2116        return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound);
2117    }
2118
2119    /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
2120    * The name provided is a simple source name (e.g., "Object" , "Point", ...)
2121    */

2122    // The return type of this method could be ReferenceBinding if we did not answer base types.
2123
// NOTE: We could support looking for Base Types last in the search, however any code using
2124
// this feature would be extraordinarily slow. Therefore we don't do this
2125
public final TypeBinding getType(char[] name) {
2126        // Would like to remove this test and require senders to specially handle base types
2127
TypeBinding binding = getBaseType(name);
2128        if (binding != null) return binding;
2129        return (ReferenceBinding) getTypeOrPackage(name, Binding.TYPE);
2130    }
2131
2132    /* Answer the type binding that corresponds to the given name, starting the lookup in the receiver
2133    * or the packageBinding if provided.
2134    * The name provided is a simple source name (e.g., "Object" , "Point", ...)
2135    */

2136    public final TypeBinding getType(char[] name, PackageBinding packageBinding) {
2137        if (packageBinding == null)
2138            return getType(name);
2139
2140        Binding binding = packageBinding.getTypeOrPackage(name);
2141        if (binding == null)
2142            return new ProblemReferenceBinding(
2143                CharOperation.arrayConcat(packageBinding.compoundName, name),
2144                null,
2145                ProblemReasons.NotFound);
2146        if (!binding.isValidBinding())
2147            return new ProblemReferenceBinding(
2148                CharOperation.arrayConcat(packageBinding.compoundName, name),
2149                binding instanceof ReferenceBinding ? ((ReferenceBinding)binding).closestMatch() : null,
2150                binding.problemId());
2151
2152        ReferenceBinding typeBinding = (ReferenceBinding) binding;
2153        if (!typeBinding.canBeSeenBy(this))
2154            return new ProblemReferenceBinding(
2155                CharOperation.arrayConcat(packageBinding.compoundName, name),
2156                typeBinding,
2157                ProblemReasons.NotVisible);
2158        return typeBinding;
2159    }
2160
2161    /* Answer the type binding corresponding to the compoundName.
2162    *
2163    * NOTE: If a problem binding is returned, senders should extract the compound name
2164    * from the binding & not assume the problem applies to the entire compoundName.
2165    */

2166    public final TypeBinding getType(char[][] compoundName, int typeNameLength) {
2167        if (typeNameLength == 1) {
2168            // Would like to remove this test and require senders to specially handle base types
2169
TypeBinding binding = getBaseType(compoundName[0]);
2170            if (binding != null) return binding;
2171        }
2172
2173        CompilationUnitScope unitScope = compilationUnitScope();
2174        unitScope.recordQualifiedReference(compoundName);
2175        Binding binding =
2176            getTypeOrPackage(compoundName[0], typeNameLength == 1 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
2177        if (binding == null)
2178            return new ProblemReferenceBinding(compoundName[0], null, ProblemReasons.NotFound);
2179        if (!binding.isValidBinding())
2180            return (ReferenceBinding) binding;
2181
2182        int currentIndex = 1;
2183        boolean checkVisibility = false;
2184        if (binding instanceof PackageBinding) {
2185            PackageBinding packageBinding = (PackageBinding) binding;
2186            while (currentIndex < typeNameLength) {
2187                binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
2188
if (binding == null)
2189                    return new ProblemReferenceBinding(
2190                        CharOperation.subarray(compoundName, 0, currentIndex),
2191                        null,
2192                        ProblemReasons.NotFound);
2193                if (!binding.isValidBinding())
2194                    return new ProblemReferenceBinding(
2195                        CharOperation.subarray(compoundName, 0, currentIndex),
2196                        binding instanceof ReferenceBinding ? ((ReferenceBinding)binding).closestMatch() : null,
2197                        binding.problemId());
2198                if (!(binding instanceof PackageBinding))
2199                    break;
2200                packageBinding = (PackageBinding) binding;
2201            }
2202            if (binding instanceof PackageBinding)
2203                return new ProblemReferenceBinding(
2204                    CharOperation.subarray(compoundName, 0, currentIndex),
2205                    null,
2206                    ProblemReasons.NotFound);
2207            checkVisibility = true;
2208        }
2209
2210        // binding is now a ReferenceBinding
2211
ReferenceBinding typeBinding = (ReferenceBinding) binding;
2212        unitScope.recordTypeReference(typeBinding);
2213        if (checkVisibility) // handles the fall through case
2214
if (!typeBinding.canBeSeenBy(this))
2215                return new ProblemReferenceBinding(
2216                    CharOperation.subarray(compoundName, 0, currentIndex),
2217                    typeBinding,
2218                    ProblemReasons.NotVisible);
2219
2220        while (currentIndex < typeNameLength) {
2221            typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
2222            if (!typeBinding.isValidBinding()) {
2223                if (typeBinding instanceof ProblemReferenceBinding) {
2224                    ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding;
2225                    return new ProblemReferenceBinding(
2226                        CharOperation.subarray(compoundName, 0, currentIndex),
2227                        problemBinding.closestMatch(),
2228                        typeBinding.problemId());
2229                }
2230                return new ProblemReferenceBinding(
2231                    CharOperation.subarray(compoundName, 0, currentIndex),
2232                    ((ReferenceBinding)binding).closestMatch(),
2233                    typeBinding.problemId());
2234            }
2235        }
2236        return typeBinding;
2237    }
2238    
2239    /* Internal use only
2240    */

2241    final Binding getTypeOrPackage(char[] name, int mask) {
2242        Scope scope = this;
2243        ReferenceBinding foundType = null;
2244        boolean insideStaticContext = false;
2245        boolean insideTypeAnnotation = false;
2246        if ((mask & Binding.TYPE) == 0) {
2247            Scope next = scope;
2248            while ((next = scope.parent) != null)
2249                scope = next;
2250        } else {
2251            done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
2252
switch (scope.kind) {
2253                    case METHOD_SCOPE :
2254                        MethodScope methodScope = (MethodScope) scope;
2255                        AbstractMethodDeclaration methodDecl = methodScope.referenceMethod();
2256                        if (methodDecl != null && methodDecl.binding != null) {
2257                            TypeVariableBinding typeVariable = methodDecl.binding.getTypeVariable(name);
2258                            if (typeVariable != null) return typeVariable;
2259                        }
2260                        insideStaticContext |= methodScope.isStatic;
2261                        insideTypeAnnotation = methodScope.insideTypeAnnotation;
2262                    case BLOCK_SCOPE :
2263                        ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
2264
if (localType != null) {
2265                            if (foundType != null && foundType != localType)
2266                                return new ProblemReferenceBinding(name, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
2267                            return localType;
2268                        }
2269                        break;
2270                    case CLASS_SCOPE :
2271                        SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
2272                        if (scope == this && (sourceType.tagBits & TagBits.TypeVariablesAreConnected) == 0) {
2273                            // type variables take precedence over the source type, ex. class X <X> extends X == class X <Y> extends Y
2274
// but not when we step out to the enclosing type
2275
TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
2276                            if (typeVariable != null)
2277                                return typeVariable;
2278                            if (CharOperation.equals(name, sourceType.sourceName))
2279                                return sourceType;
2280                            insideStaticContext |= sourceType.isStatic();
2281                            break;
2282                        }
2283                        // member types take precedence over type variables
2284
if (!insideTypeAnnotation) {
2285                            // 6.5.5.1 - member types have precedence over top-level type in same unit
2286
ReferenceBinding memberType = findMemberType(name, sourceType);
2287                            if (memberType != null) { // skip it if we did not find anything
2288
if (memberType.problemId() == ProblemReasons.Ambiguous) {
2289                                    if (foundType == null || foundType.problemId() == ProblemReasons.NotVisible)
2290                                        // supercedes any potential InheritedNameHidesEnclosingName problem
2291
return memberType;
2292                                    // make the user qualify the type, likely wants the first inherited type
2293
return new ProblemReferenceBinding(name, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
2294                                }
2295                                if (memberType.isValidBinding()) {
2296                                    if (sourceType == memberType.enclosingType() || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
2297                                        if (insideStaticContext && !memberType.isStatic() && sourceType.isGenericType())
2298                                            return new ProblemReferenceBinding(name, memberType, ProblemReasons.NonStaticReferenceInStaticContext);
2299                                        // found a valid type in the 'immediate' scope (ie. not inherited)
2300
// OR in 1.4 mode (inherited shadows enclosing)
2301
if (foundType == null)
2302                                            return memberType;
2303                                        // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
2304
if (foundType.isValidBinding() && foundType != memberType)
2305                                            return new ProblemReferenceBinding(name, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
2306                                    }
2307                                }
2308                                if (foundType == null || (foundType.problemId() == ProblemReasons.NotVisible && memberType.problemId() != ProblemReasons.NotVisible))
2309                                    // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
2310
foundType = memberType;
2311                            }
2312                        }
2313                        TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
2314                        if (typeVariable != null) {
2315                            if (insideStaticContext) // do not consider this type modifiers: access is legite within same type
2316
return new ProblemReferenceBinding(name, typeVariable, ProblemReasons.NonStaticReferenceInStaticContext);
2317                            return typeVariable;
2318                        }
2319                        insideStaticContext |= sourceType.isStatic();
2320                        insideTypeAnnotation = false;
2321                        if (CharOperation.equals(sourceType.sourceName, name)) {
2322                            if (foundType != null && foundType != sourceType && foundType.problemId() != ProblemReasons.NotVisible)
2323                                return new ProblemReferenceBinding(name, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
2324                            return sourceType;
2325                        }
2326                        break;
2327                    case COMPILATION_UNIT_SCOPE :
2328                        break done;
2329                }
2330                scope = scope.parent;
2331            }
2332            if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible)
2333                return foundType;
2334        }
2335
2336        // at this point the scope is a compilation unit scope
2337
CompilationUnitScope unitScope = (CompilationUnitScope) scope;
2338        HashtableOfObject typeOrPackageCache = unitScope.typeOrPackageCache;
2339        if (typeOrPackageCache != null) {
2340            Binding binding = (Binding) typeOrPackageCache.get(name);
2341            if (binding != null) { // can also include NotFound ProblemReferenceBindings if we already know this name is not found
2342
if (binding instanceof ImportBinding) { // single type import cached in faultInImports(), replace it in the cache with the type
2343
ImportReference importReference = ((ImportBinding) binding).reference;
2344                    if (importReference != null) {
2345                        importReference.bits |= ASTNode.Used;
2346                    }
2347                    if (binding instanceof ImportConflictBinding)
2348                        typeOrPackageCache.put(name, binding = ((ImportConflictBinding) binding).conflictingTypeBinding); // already know its visible
2349
else
2350                        typeOrPackageCache.put(name, binding = ((ImportBinding) binding).resolvedImport); // already know its visible
2351
}
2352                if ((mask & Binding.TYPE) != 0) {
2353                    if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible && binding.problemId() != ProblemReasons.Ambiguous)
2354                        return foundType; // problem type from above supercedes NotFound type but not Ambiguous import case
2355
if (binding instanceof ReferenceBinding)
2356                        return binding; // cached type found in previous walk below
2357
}
2358                if ((mask & Binding.PACKAGE) != 0 && binding instanceof PackageBinding)
2359                    return binding; // cached package found in previous walk below
2360
}
2361        }
2362
2363        // ask for the imports + name
2364
if ((mask & Binding.TYPE) != 0) {
2365            ImportBinding[] imports = unitScope.imports;
2366            if (imports != null && typeOrPackageCache == null) { // walk single type imports since faultInImports() has not run yet
2367
nextImport : for (int i = 0, length = imports.length; i < length; i++) {
2368                    ImportBinding importBinding = imports[i];
2369                    if (!importBinding.onDemand) {
2370                        if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
2371                            Binding resolvedImport = unitScope.resolveSingleImport(importBinding);
2372                            if (resolvedImport == null) continue nextImport;
2373                            if (resolvedImport instanceof MethodBinding) {
2374                                resolvedImport = getType(importBinding.compoundName, importBinding.compoundName.length);
2375                                if (!resolvedImport.isValidBinding()) continue nextImport;
2376                            }
2377                            if (resolvedImport instanceof TypeBinding) {
2378                                ImportReference importReference = importBinding.reference;
2379                                if (importReference != null)
2380                                    importReference.bits |= ASTNode.Used;
2381                                return resolvedImport; // already know its visible
2382
}
2383                        }
2384                    }
2385                }
2386            }
2387
2388            // check if the name is in the current package, skip it if its a sub-package
2389
PackageBinding currentPackage = unitScope.fPackage;
2390            unitScope.recordReference(currentPackage.compoundName, name);
2391            Binding binding = currentPackage.getTypeOrPackage(name);
2392            if (binding instanceof ReferenceBinding) {
2393                if (typeOrPackageCache != null)
2394                    typeOrPackageCache.put(name, binding);
2395                return binding; // type is always visible to its own package
2396
}
2397
2398            // check on demand imports
2399
if (imports != null) {
2400                boolean foundInImport = false;
2401                ReferenceBinding type = null;
2402                for (int i = 0, length = imports.length; i < length; i++) {
2403                    ImportBinding someImport = imports[i];
2404                    if (someImport.onDemand) {
2405                        Binding resolvedImport = someImport.resolvedImport;
2406                        ReferenceBinding temp = null;
2407                        if (resolvedImport instanceof PackageBinding) {
2408                            temp = findType(name, (PackageBinding) resolvedImport, currentPackage);
2409                        } else if (someImport.isStatic()) {
2410                            temp = findMemberType(name, (ReferenceBinding) resolvedImport); // static imports are allowed to see inherited member types
2411
if (temp != null && !temp.isStatic())
2412                                temp = null;
2413                        } else {
2414                            temp = findDirectMemberType(name, (ReferenceBinding) resolvedImport);
2415                        }
2416                        if (temp != type && temp != null) {
2417                            if (temp.isValidBinding()) {
2418                                ImportReference importReference = someImport.reference;
2419                                if (importReference != null) {
2420                                    importReference.bits |= ASTNode.Used;
2421                                }
2422                                if (foundInImport) {
2423                                    // Answer error binding -- import on demand conflict; name found in two import on demand packages.
2424
temp = new ProblemReferenceBinding(name, type, ProblemReasons.Ambiguous);
2425                                    if (typeOrPackageCache != null)
2426                                        typeOrPackageCache.put(name, temp);
2427                                    return temp;
2428                                }
2429                                type = temp;
2430                                foundInImport = true;
2431                            } else if (foundType == null) {
2432                                foundType = temp;
2433                            }
2434                        }
2435                    }
2436                }
2437                if (type != null) {
2438                    if (typeOrPackageCache != null)
2439                        typeOrPackageCache.put(name, type);
2440                    return type;
2441                }
2442            }
2443        }
2444
2445        unitScope.recordSimpleReference(name);
2446        if ((mask & Binding.PACKAGE) != 0) {
2447            PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
2448            if (packageBinding != null) {
2449                if (typeOrPackageCache != null)
2450                    typeOrPackageCache.put(name, packageBinding);
2451                return packageBinding;
2452            }
2453        }
2454
2455        // Answer error binding -- could not find name
2456
if (foundType == null) {
2457            foundType = new ProblemReferenceBinding(name, null, ProblemReasons.NotFound);
2458            if (typeOrPackageCache != null && (mask & Binding.PACKAGE) != 0) // only put NotFound type in cache if you know its not a package
2459
typeOrPackageCache.put(name, foundType);
2460        }
2461        return foundType;
2462    }
2463    
2464    // Added for code assist... NOT Public API
2465
// DO NOT USE to resolve import references since this method assumes 'A.B' is relative to a single type import of 'p1.A'
2466
// when it may actually mean the type B in the package A
2467
// use CompilationUnitScope.getImport(char[][]) instead
2468
public final Binding getTypeOrPackage(char[][] compoundName) {
2469        int nameLength = compoundName.length;
2470        if (nameLength == 1) {
2471            TypeBinding binding = getBaseType(compoundName[0]);
2472            if (binding != null) return binding;
2473        }
2474        Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
2475        if (!binding.isValidBinding()) return binding;
2476
2477        int currentIndex = 1;
2478        boolean checkVisibility = false;
2479        if (binding instanceof PackageBinding) {
2480            PackageBinding packageBinding = (PackageBinding) binding;
2481
2482            while (currentIndex < nameLength) {
2483                binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
2484                if (binding == null)
2485                    return new ProblemReferenceBinding(
2486                        CharOperation.subarray(compoundName, 0, currentIndex),
2487                        null,
2488                        ProblemReasons.NotFound);
2489                if (!binding.isValidBinding())
2490                    return new ProblemReferenceBinding(
2491                        CharOperation.subarray(compoundName, 0, currentIndex),
2492                        binding instanceof ReferenceBinding ? ((ReferenceBinding)binding).closestMatch() : null,
2493                        binding.problemId());
2494                if (!(binding instanceof PackageBinding))
2495                    break;
2496                packageBinding = (PackageBinding) binding;
2497            }
2498            if (binding instanceof PackageBinding) return binding;
2499            checkVisibility = true;
2500        }
2501        // binding is now a ReferenceBinding
2502
ReferenceBinding typeBinding = (ReferenceBinding) binding;
2503        ReferenceBinding qualifiedType = (ReferenceBinding) this.environment().convertToRawType(typeBinding);
2504
2505        if (checkVisibility) // handles the fall through case
2506
if (!typeBinding.canBeSeenBy(this))
2507                return new ProblemReferenceBinding(
2508                    CharOperation.subarray(compoundName, 0, currentIndex),
2509                    typeBinding,
2510                    ProblemReasons.NotVisible);
2511
2512        while (currentIndex < nameLength) {
2513            typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
2514            // checks visibility
2515
if (!typeBinding.isValidBinding())
2516                return new ProblemReferenceBinding(
2517                    CharOperation.subarray(compoundName, 0, currentIndex),
2518                    ((ReferenceBinding)binding).closestMatch(),
2519                    typeBinding.problemId());
2520            
2521            if (typeBinding.isGenericType()) {
2522                qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
2523            } else {
2524                qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
2525                    ? this.environment().createParameterizedType(typeBinding, null, qualifiedType)
2526                    : typeBinding;
2527            }
2528        }
2529        return qualifiedType;
2530    }
2531
2532    protected boolean hasErasedCandidatesCollisions(TypeBinding one, TypeBinding two, Map invocations, ReferenceBinding type, ASTNode typeRef) {
2533        invocations.clear();
2534        TypeBinding[] mecs = minimalErasedCandidates(new TypeBinding[] {one, two}, invocations);
2535        if (mecs != null) {
2536            nextCandidate: for (int k = 0, max = mecs.length; k < max; k++) {
2537                TypeBinding mec = mecs[k];
2538                if (mec == null) continue nextCandidate;
2539                Object JavaDoc value = invocations.get(mec);
2540                if (value instanceof TypeBinding[]) {
2541                    TypeBinding[] invalidInvocations = (TypeBinding[]) value;
2542                    problemReporter().superinterfacesCollide(invalidInvocations[0].erasure(), typeRef, invalidInvocations[0], invalidInvocations[1]);
2543                    type.tagBits |= TagBits.HierarchyHasProblems;
2544                    return true;
2545                }
2546            }
2547        }
2548        return false;
2549    }
2550
2551    /**
2552     * Returns the immediately enclosing switchCase statement (carried by closest blockScope),
2553     */

2554    public CaseStatement innermostSwitchCase() {
2555        Scope scope = this;
2556        do {
2557            if (scope instanceof BlockScope)
2558                return ((BlockScope) scope).enclosingCase;
2559            scope = scope.parent;
2560        } while (scope != null);
2561        return null;
2562    }
2563
2564    protected boolean isAcceptableMethod(MethodBinding one, MethodBinding two) {
2565        TypeBinding[] oneParams = one.parameters;
2566        TypeBinding[] twoParams = two.parameters;
2567        int oneParamsLength = oneParams.length;
2568        int twoParamsLength = twoParams.length;
2569        if (oneParamsLength == twoParamsLength) {
2570            for (int i = 0; i < oneParamsLength; i++) {
2571                TypeBinding oneParam = oneParams[i];
2572                TypeBinding twoParam = twoParams[i];
2573                if (oneParam == twoParam) {
2574                    if (oneParam.leafComponentType().isRawType()) {
2575                        // A#RAW is not more specific than a rawified A<T>
2576
if (oneParam == one.original().parameters[i] && oneParam != two.original().parameters[i])
2577                            return false;
2578                    }
2579                    continue;
2580                }
2581                if (oneParam.isCompatibleWith(twoParam)) {
2582                    if (oneParam.leafComponentType().isRawType()) {
2583                        // A#RAW is not more specific than a rawified A<T>
2584
if (oneParam.needsUncheckedConversion(two.declaringClass.isRawType() ? twoParam : two.original().parameters[i]))
2585                            return false;
2586                    }
2587                } else {
2588                    if (i == oneParamsLength - 1 && one.isVarargs() && two.isVarargs()) {
2589                        TypeBinding eType = ((ArrayBinding) twoParam).elementsType();
2590                        if (oneParam == eType || oneParam.isCompatibleWith(eType))
2591                            return true; // special case to choose between 2 varargs methods when the last arg is Object[]
2592
}
2593                    return false;
2594                }
2595            }
2596            return true;
2597        }
2598
2599        if (one.isVarargs() && two.isVarargs()) {
2600            if (oneParamsLength > twoParamsLength) {
2601                // special case when autoboxing makes (int, int...) better than (Object...) but not (int...) or (Integer, int...)
2602
if (((ArrayBinding) twoParams[twoParamsLength - 1]).elementsType().id != TypeIds.T_JavaLangObject)
2603                    return false;
2604            }
2605            // check that each parameter before the vararg parameters are compatible (no autoboxing allowed here)
2606
for (int i = (oneParamsLength > twoParamsLength ? twoParamsLength : oneParamsLength) - 2; i >= 0; i--)
2607                if (oneParams[i] != twoParams[i] && !oneParams[i].isCompatibleWith(twoParams[i]))
2608                    return false;
2609            if (parameterCompatibilityLevel(one, twoParams) == NOT_COMPATIBLE
2610                && parameterCompatibilityLevel(two, oneParams) == VARARGS_COMPATIBLE)
2611                    return true;
2612        }
2613        return false;
2614    }
2615
2616    public boolean isBoxingCompatibleWith(TypeBinding expressionType, TypeBinding targetType) {
2617        LookupEnvironment environment = environment();
2618        if (environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5 || expressionType.isBaseType() == targetType.isBaseType())
2619            return false;
2620    
2621        // check if autoboxed type is compatible
2622
TypeBinding convertedType = environment.computeBoxingType(expressionType);
2623        return convertedType == targetType || convertedType.isCompatibleWith(targetType);
2624    }
2625
2626    /* Answer true if the scope is nested inside a given field declaration.
2627     * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed
2628     * e.g. during name resolution.
2629    */

2630    public final boolean isDefinedInField(FieldBinding field) {
2631        Scope scope = this;
2632        do {
2633            if (scope instanceof MethodScope) {
2634                MethodScope methodScope = (MethodScope) scope;
2635                if (methodScope.initializedField == field) return true;
2636            }
2637            scope = scope.parent;
2638        } while (scope != null);
2639        return false;
2640    }
2641
2642    /* Answer true if the scope is nested inside a given method declaration
2643    */

2644    public final boolean isDefinedInMethod(MethodBinding method) {
2645        Scope scope = this;
2646        do {
2647            if (scope instanceof MethodScope) {
2648                ReferenceContext refContext = ((MethodScope) scope).referenceContext;
2649                if (refContext instanceof AbstractMethodDeclaration)
2650                    if (((AbstractMethodDeclaration) refContext).binding == method)
2651                        return true;
2652            }
2653            scope = scope.parent;
2654        } while (scope != null);
2655        return false;
2656    }
2657
2658    /* Answer whether the type is defined in the same compilation unit as the receiver
2659    */

2660    public final boolean isDefinedInSameUnit(ReferenceBinding type) {
2661        // find the outer most enclosing type
2662
ReferenceBinding enclosingType = type;
2663        while ((type = enclosingType.enclosingType()) != null)
2664            enclosingType = type;
2665
2666        // find the compilation unit scope
2667
Scope scope, unitScope = this;
2668        while ((scope = unitScope.parent) != null)
2669            unitScope = scope;
2670
2671        // test that the enclosingType is not part of the compilation unit
2672
SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
2673        for (int i = topLevelTypes.length; --i >= 0;)
2674            if (topLevelTypes[i] == enclosingType)
2675                return true;
2676        return false;
2677    }
2678        
2679    /* Answer true if the scope is nested inside a given type declaration
2680    */

2681    public final boolean isDefinedInType(ReferenceBinding type) {
2682        Scope scope = this;
2683        do {
2684            if (scope instanceof ClassScope)
2685                if (((ClassScope) scope).referenceContext.binding == type)
2686                    return true;
2687            scope = scope.parent;
2688        } while (scope != null);
2689        return false;
2690    }
2691
2692    /**
2693     * Returns true if the scope or one of its parent is associated to a given caseStatement, denoting
2694     * being part of a given switch case statement.
2695     */

2696    public boolean isInsideCase(CaseStatement caseStatement) {
2697        Scope scope = this;
2698        do {
2699            switch (scope.kind) {
2700                case Scope.BLOCK_SCOPE :
2701                    if (((BlockScope) scope).enclosingCase == caseStatement) {
2702                        return true;
2703                    }
2704            }
2705            scope = scope.parent;
2706        } while (scope != null);
2707        return false;
2708    }
2709    
2710    public boolean isInsideDeprecatedCode(){
2711        switch(this.kind){
2712            case Scope.BLOCK_SCOPE :
2713            case Scope.METHOD_SCOPE :
2714                MethodScope methodScope = methodScope();
2715                if (!methodScope.isInsideInitializer()){
2716                    // check method modifiers to see if deprecated
2717
MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
2718                    if (context != null && context.isViewedAsDeprecated())
2719                        return true;
2720                } else {
2721                    SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
2722                    // inside field declaration ? check field modifier to see if deprecated
2723
if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated())
2724                        return true;
2725                    if (type != null) {
2726                        type.initializeDeprecatedAnnotationTagBits(); // may not have been resolved until then
2727
if (type.isViewedAsDeprecated())
2728                            return true;
2729                    }
2730                }
2731                break;
2732            case Scope.CLASS_SCOPE :
2733                ReferenceBinding context = ((ClassScope)this).referenceType().binding;
2734                if (context != null) {
2735                    context.initializeDeprecatedAnnotationTagBits(); // may not have been resolved until then
2736
if (context.isViewedAsDeprecated())
2737                        return true;
2738                }
2739                break;
2740            case Scope.COMPILATION_UNIT_SCOPE :
2741                // consider import as being deprecated if first type is itself deprecated (123522)
2742
CompilationUnitDeclaration unit = referenceCompilationUnit();
2743                if (unit.types != null && unit.types.length > 0) {
2744                    SourceTypeBinding type = unit.types[0].binding;
2745                    if (type != null) {
2746                        type.initializeDeprecatedAnnotationTagBits(); // may not have been resolved until then
2747
if (type.isViewedAsDeprecated())
2748                            return true;
2749                    }
2750                }
2751        }
2752        return false;
2753    }
2754
2755    private TypeBinding leastContainingInvocation(TypeBinding mec, Object JavaDoc invocationData, List lubStack) {
2756        if (invocationData == null) return mec; // no alternate invocation
2757
if (invocationData instanceof TypeBinding) { // only one invocation, simply return it (array only allocated if more than one)
2758
return (TypeBinding) invocationData;
2759        }
2760        TypeBinding[] invocations = (TypeBinding[]) invocationData;
2761
2762        // if mec is an array type, intersect invocation leaf component types, then promote back to array
2763
int dim = mec.dimensions();
2764        mec = mec.leafComponentType();
2765        
2766        int argLength = mec.typeVariables().length;
2767        if (argLength == 0) return mec; // should be caught by no invocation check
2768

2769        // infer proper parameterized type from invocations
2770
TypeBinding[] bestArguments = new TypeBinding[argLength];
2771        for (int i = 0, length = invocations.length; i < length; i++) {
2772            TypeBinding invocation = invocations[i].leafComponentType();
2773            switch (invocation.kind()) {
2774                case Binding.GENERIC_TYPE :
2775                    TypeVariableBinding[] invocationVariables = invocation.typeVariables();
2776                    for (int j = 0; j < argLength; j++) {
2777                        TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], invocationVariables[j], (ReferenceBinding) mec, j, lubStack);
2778                        if (bestArgument == null) return null;
2779                        bestArguments[j] = bestArgument;
2780                    }
2781                    break;
2782                case Binding.PARAMETERIZED_TYPE :
2783                    ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)invocation;
2784                    for (int j = 0; j < argLength; j++) {
2785                        TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], parameterizedType.arguments[j], (ReferenceBinding) mec, j, lubStack);
2786                        if (bestArgument == null) return null;
2787                        bestArguments[j] = bestArgument;
2788                    }
2789                    break;
2790                case Binding.RAW_TYPE :
2791                    return dim == 0 ? invocation : environment().createArrayType(invocation, dim); // raw type is taking precedence
2792
}
2793        }
2794        TypeBinding least = environment().createParameterizedType((ReferenceBinding) mec.erasure(), bestArguments, mec.enclosingType());
2795        return dim == 0 ? least : environment().createArrayType(least, dim);
2796    }
2797    
2798    // JLS 15.12.2
2799
private TypeBinding leastContainingTypeArgument(TypeBinding u, TypeBinding v, ReferenceBinding genericType, int rank, List lubStack) {
2800        if (u == null) return v;
2801        if (u == v) return u;
2802        if (v.isWildcard()) {
2803            WildcardBinding wildV = (WildcardBinding) v;
2804            if (u.isWildcard()) {
2805                WildcardBinding wildU = (WildcardBinding) u;
2806                switch (wildU.boundKind) {
2807                    // ? extends U
2808
case Wildcard.EXTENDS :
2809                        switch(wildV.boundKind) {
2810                            // ? extends U, ? extends V
2811
case Wildcard.EXTENDS :
2812                                TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound,wildV.bound}, lubStack);
2813                                if (lub == null) return null;
2814                                // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard
2815
if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND);
2816                                return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS);
2817                            // ? extends U, ? SUPER V
2818
case Wildcard.SUPER :
2819                                if (wildU.bound == wildV.bound) return wildU.bound;
2820                                return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND);
2821                        }
2822                        break;
2823                        // ? super U
2824
case Wildcard.SUPER :
2825                        // ? super U, ? super V
2826
if (wildU.boundKind == Wildcard.SUPER) {
2827                            TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound});
2828                            if (glb == null) return null;
2829                            return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2830
}
2831                }
2832            } else {
2833                switch (wildV.boundKind) {
2834                    // U, ? extends V
2835
case Wildcard.EXTENDS :
2836                        TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,wildV.bound}, lubStack);
2837                        if (lub == null) return null;
2838                        // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard
2839
if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND);
2840                        return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS);
2841                    // U, ? super V
2842
case Wildcard.SUPER :
2843                        TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound});
2844                        if (glb == null) return null;
2845                        return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2846
case Wildcard.UNBOUND :
2847                }
2848            }
2849        } else if (u.isWildcard()) {
2850            WildcardBinding wildU = (WildcardBinding) u;
2851            switch (wildU.boundKind) {
2852                // U, ? extends V
2853
case Wildcard.EXTENDS :
2854                    TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound, v}, lubStack);
2855                    if (lub == null) return null;
2856                    // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard
2857
if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND);
2858                    return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS);
2859                // U, ? super V
2860
case Wildcard.SUPER :
2861                    TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v});
2862                    if (glb == null) return null;
2863                    return environment().createWildcard(genericType, rank, glb[0], null /*no extra bound*/, Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2864
case Wildcard.UNBOUND :
2865            }
2866        }
2867        TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,v}, lubStack);
2868        if (lub == null) return null;
2869        // int is returned to denote cycle detected in lub computation - stop recursion by answering unbound wildcard
2870
if (lub == TypeBinding.INT) return environment().createWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND);
2871        return environment().createWildcard(genericType, rank, lub, null /*no extra bound*/, Wildcard.EXTENDS);
2872    }
2873
2874    // 15.12.2
2875
/**
2876     * Returns VoidBinding if types have no intersection (e.g. 2 unrelated interfaces), or null if
2877     * no common supertype (e.g. List<String> and List<Exception>), or the intersection type if possible
2878     */

2879    public TypeBinding lowerUpperBound(TypeBinding[] types) {
2880        int typeLength = types.length;
2881        if (typeLength == 1) {
2882            TypeBinding type = types[0];
2883            return type == null ? TypeBinding.VOID : type;
2884        }
2885        return lowerUpperBound(types, new ArrayList(1));
2886    }
2887    
2888    // 15.12.2
2889
private TypeBinding lowerUpperBound(TypeBinding[] types, List lubStack) {
2890        
2891        int typeLength = types.length;
2892        if (typeLength == 1) {
2893            TypeBinding type = types[0];
2894            return type == null ? TypeBinding.VOID : type;
2895        }
2896        // cycle detection
2897
int stackLength = lubStack.size();
2898        nextLubCheck: for (int i = 0; i < stackLength; i++) {
2899            TypeBinding[] lubTypes = (TypeBinding[])lubStack.get(i);
2900            int lubTypeLength = lubTypes.length;
2901            if (lubTypeLength < typeLength) continue nextLubCheck;
2902            nextTypeCheck: for (int j = 0; j < typeLength; j++) {
2903                TypeBinding type = types[j];
2904                if (type == null) continue nextTypeCheck; // ignore
2905
for (int k = 0; k < lubTypeLength; k++) {
2906                    TypeBinding lubType = lubTypes[k];
2907                    if (lubType == null) continue; // ignore
2908
if (lubType == type || lubType.isEquivalentTo(type)) continue nextTypeCheck; // type found, jump to next one
2909
}
2910                continue nextLubCheck; // type not found in current lubTypes
2911
}
2912            // all types are included in some lub, cycle detected - stop recursion by answering special value (int)
2913
return TypeBinding.INT;
2914        }
2915
2916        lubStack.add(types);
2917        Map invocations = new HashMap(1);
2918        TypeBinding[] mecs = minimalErasedCandidates(types, invocations);
2919        if (mecs == null) return null;
2920        int length = mecs.length;
2921        if (length == 0) return TypeBinding.VOID;
2922        int count = 0;
2923        TypeBinding firstBound = null;
2924        int commonDim = -1;
2925        for (int i = 0; i < length; i++) {
2926            TypeBinding mec = mecs[i];
2927            if (mec == null) continue;
2928            mec = leastContainingInvocation(mec, invocations.get(mec), lubStack);
2929            if (mec == null) return null;
2930            int dim = mec.dimensions();
2931            if (commonDim == -1) {
2932                commonDim = dim;
2933            } else if (dim != commonDim) { // not all types have same dimension
2934
return null;
2935            }
2936            if (firstBound == null && !mec.leafComponentType().isInterface()) firstBound = mec.leafComponentType();
2937            mecs[count++] = mec; // recompact them to the front
2938
}
2939        switch (count) {
2940            case 0 : return TypeBinding.VOID;
2941            case 1 : return mecs[0];
2942            case 2 :
2943                if ((commonDim == 0 ? mecs[1].id : mecs[1].leafComponentType().id) == T_JavaLangObject) return mecs[0];
2944                if ((commonDim == 0 ? mecs[0].id : mecs[0].leafComponentType().id) == T_JavaLangObject) return mecs[1];
2945        }
2946        TypeBinding[] otherBounds = new TypeBinding[count - 1];
2947        int rank = 0;
2948        for (int i = 0; i < count; i++) {
2949            TypeBinding mec = commonDim == 0 ? mecs[i] : mecs[i].leafComponentType();
2950            if (mec.isInterface()) {
2951                otherBounds[rank++] = mec;
2952            }
2953        }
2954        TypeBinding intersectionType = environment().createWildcard(null, 0, firstBound, otherBounds, Wildcard.EXTENDS);
2955        return commonDim == 0 ? intersectionType : environment().createArrayType(intersectionType, commonDim);
2956    }
2957    
2958    public final MethodScope methodScope() {
2959        Scope scope = this;
2960        do {
2961            if (scope instanceof MethodScope)
2962                return (MethodScope) scope;
2963            scope = scope.parent;
2964        } while (scope != null);
2965        return null;
2966    }
2967
2968    /**
2969     * Returns the most specific set of types compatible with all given types.
2970     * (i.e. most specific common super types)
2971     * If no types is given, will return an empty array. If not compatible
2972     * reference type is found, returns null. In other cases, will return an array
2973     * of minimal erased types, where some nulls may appear (and must simply be
2974     * ignored).
2975     */

2976    protected TypeBinding[] minimalErasedCandidates(TypeBinding[] types, Map allInvocations) {
2977        int length = types.length;
2978        int indexOfFirst = -1, actualLength = 0;
2979        for (int i = 0; i < length; i++) {
2980            TypeBinding type = types[i];
2981            if (type == null) continue;
2982            if (type.isBaseType()) return null;
2983            if (indexOfFirst < 0) indexOfFirst = i;
2984            actualLength ++;
2985        }
2986        switch (actualLength) {
2987            case 0: return Binding.NO_TYPES;
2988            case 1: return types;
2989        }
2990        TypeBinding firstType = types[indexOfFirst];
2991        if (firstType.isBaseType()) return null;
2992
2993        // record all supertypes of type
2994
// intersect with all supertypes of otherType
2995
ArrayList typesToVisit = new ArrayList(5);
2996        
2997        int dim = firstType.dimensions();
2998        TypeBinding leafType = firstType.leafComponentType();
2999        TypeBinding firstErasure = (leafType.isTypeVariable() || leafType.isWildcard()/*&& !leafType.isCapture()*/) ? firstType : firstType.erasure();
3000        if (firstErasure != firstType) {
3001            allInvocations.put(firstErasure, firstType);
3002        }
3003        typesToVisit.add(firstType);
3004        int max = 1;
3005        ReferenceBinding currentType;
3006        for (int i = 0; i < max; i++) {
3007            TypeBinding typeToVisit = (TypeBinding) typesToVisit.get(i);
3008            dim = typeToVisit.dimensions();
3009            if (dim > 0) {
3010                leafType = typeToVisit.leafComponentType();
3011                switch(leafType.id) {
3012                    case T_JavaLangObject:
3013                        if (dim > 1) { // Object[][] supertype is Object[]
3014
TypeBinding elementType = ((ArrayBinding)typeToVisit).elementsType();
3015                            if (!typesToVisit.contains(elementType)) {
3016                                typesToVisit.add(elementType);
3017                                max++;
3018                            }
3019                            continue;
3020                        }
3021                        // fallthrough
3022
case T_byte:
3023                    case T_short:
3024                    case T_char:
3025                    case T_boolean:
3026                    case T_int:
3027                    case T_long:
3028                    case T_float:
3029                    case T_double:
3030                        TypeBinding superType = getJavaIoSerializable();
3031                        if (!typesToVisit.contains(superType)) {
3032                            typesToVisit.add(superType);
3033                            max++;
3034                        }
3035                        superType = getJavaLangCloneable();
3036                        if (!typesToVisit.contains(superType)) {
3037                            typesToVisit.add(superType);
3038                            max++;
3039                        }
3040                        superType = getJavaLangObject();
3041                        if (!typesToVisit.contains(superType)) {
3042                            typesToVisit.add(superType);
3043                            max++;
3044                        }
3045                        continue;
3046                    
3047                    default:
3048                }
3049                typeToVisit = leafType;
3050            }
3051            currentType = (ReferenceBinding) typeToVisit;
3052            if (currentType.isCapture()) {
3053                TypeBinding firstBound = ((CaptureBinding) currentType).firstBound;
3054                if (firstBound != null && firstBound.isArrayType()) {
3055                    TypeBinding superType = dim == 0 ? firstBound : (TypeBinding)environment().createArrayType(firstBound, dim); // recreate array if needed
3056
if (!typesToVisit.contains(superType)) {
3057                        typesToVisit.add(superType);
3058                        max++;
3059                        TypeBinding superTypeErasure = (firstBound.isTypeVariable() || firstBound.isWildcard() /*&& !itsInterface.isCapture()*/) ? superType : superType.erasure();
3060                        if (superTypeErasure != superType) {
3061                            allInvocations.put(superTypeErasure, superType);
3062                        }
3063                    }
3064                    continue;
3065                }
3066            }
3067            // inject super interfaces prior to superclass
3068
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
3069            if (itsInterfaces != null) { // can be null during code assist operations that use LookupEnvironment.completeTypeBindings(parsedUnit, buildFieldsAndMethods)
3070
for (int j = 0, count = itsInterfaces.length; j < count; j++) {
3071                    TypeBinding itsInterface = itsInterfaces[j];
3072                    TypeBinding superType = dim == 0 ? itsInterface : (TypeBinding)environment().createArrayType(itsInterface, dim); // recreate array if needed
3073
if (!typesToVisit.contains(superType)) {
3074                        typesToVisit.add(superType);
3075                        max++;
3076                        TypeBinding superTypeErasure = (itsInterface.isTypeVariable() || itsInterface.isWildcard() /*&& !itsInterface.isCapture()*/) ? superType : superType.erasure();
3077                        if (superTypeErasure != superType) {
3078                            allInvocations.put(superTypeErasure, superType);
3079                        }
3080                    }
3081                }
3082            }
3083            TypeBinding itsSuperclass = currentType.superclass();
3084            if (itsSuperclass != null) {
3085                TypeBinding superType = dim == 0 ? itsSuperclass : (TypeBinding)environment().createArrayType(itsSuperclass, dim); // recreate array if needed
3086
if (!typesToVisit.contains(superType)) {
3087                    typesToVisit.add(superType);
3088                    max++;
3089                    TypeBinding superTypeErasure = (itsSuperclass.isTypeVariable() || itsSuperclass.isWildcard() /*&& !itsSuperclass.isCapture()*/) ? superType : superType.erasure();
3090                    if (superTypeErasure != superType) {
3091                        allInvocations.put(superTypeErasure, superType);
3092                    }
3093                }
3094            }
3095        }
3096        int superLength = typesToVisit.size();
3097        TypeBinding[] erasedSuperTypes = new TypeBinding[superLength];
3098        int rank = 0;
3099        for (Iterator iter = typesToVisit.iterator(); iter.hasNext();) {
3100            TypeBinding type = (TypeBinding)iter.next();
3101            leafType = type.leafComponentType();
3102            erasedSuperTypes[rank++] = (leafType.isTypeVariable() || leafType.isWildcard() /*&& !leafType.isCapture()*/) ? type : type.erasure();
3103        }
3104        // intersecting first type supertypes with other types' ones, nullifying non matching supertypes
3105
int remaining = superLength;
3106        nextOtherType: for (int i = indexOfFirst+1; i < length; i++) {
3107            TypeBinding otherType = types[i];
3108            if (otherType == null) continue nextOtherType;
3109            if (otherType.isArrayType()) {
3110                nextSuperType: for (int j = 0; j < superLength; j++) {
3111                    TypeBinding erasedSuperType = erasedSuperTypes[j];
3112                    if (erasedSuperType == null || erasedSuperType == otherType) continue nextSuperType;
3113                    TypeBinding match;
3114                    if ((match = otherType.findSuperTypeWithSameErasure(erasedSuperType)) == null) {
3115                        erasedSuperTypes[j] = null;
3116                        if (--remaining == 0) return null;
3117                        continue nextSuperType;
3118                    }
3119                    // record invocation
3120
Object JavaDoc invocationData = allInvocations.get(erasedSuperType);
3121                    if (invocationData == null) {
3122                        allInvocations.put(erasedSuperType, match); // no array for singleton
3123
} else if (invocationData instanceof TypeBinding) {
3124                        if (match != invocationData) {
3125                            // using an array to record invocations in order (188103)
3126
TypeBinding[] someInvocations = { (TypeBinding) invocationData, match, };
3127                            allInvocations.put(erasedSuperType, someInvocations);
3128                        }
3129                    } else { // using an array to record invocations in order (188103)
3130
TypeBinding[] someInvocations = (TypeBinding[]) invocationData;
3131                        checkExisting: {
3132                            int invocLength = someInvocations.length;
3133                            for (int k = 0; k < invocLength; k++) {
3134                                if (someInvocations[k] == match) break checkExisting;
3135                            }
3136                            System.arraycopy(someInvocations, 0, someInvocations = new TypeBinding[invocLength+1], 0, invocLength);
3137                            allInvocations.put(erasedSuperType, someInvocations);
3138                            someInvocations[invocLength] = match;
3139                        }
3140                    }
3141                }
3142                continue nextOtherType;
3143            }
3144            nextSuperType: for (int j = 0; j < superLength; j++) {
3145                TypeBinding erasedSuperType = erasedSuperTypes[j];
3146                if (erasedSuperType == null) continue nextSuperType;
3147                TypeBinding match;
3148                if (erasedSuperType == otherType || erasedSuperType.id == T_JavaLangObject && otherType.isInterface()) {
3149                    match = erasedSuperType;
3150                } else {
3151                    if (erasedSuperType.isArrayType()) {
3152                        match = null;
3153                    } else {
3154                        match = otherType.findSuperTypeWithSameErasure(erasedSuperType);
3155                    }
3156                    if (match == null) { // incompatible super type
3157
erasedSuperTypes[j] = null;
3158                        if (--remaining == 0) return null;
3159                        continue nextSuperType;
3160                    }
3161                }
3162                // record invocation
3163
Object JavaDoc invocationData = allInvocations.get(erasedSuperType);
3164                if (invocationData == null) {
3165                    allInvocations.put(erasedSuperType, match); // no array for singleton
3166
} else if (invocationData instanceof TypeBinding) {
3167                    if (match != invocationData) {
3168                        // using an array to record invocations in order (188103)
3169
TypeBinding[] someInvocations = { (TypeBinding) invocationData, match, };
3170                        allInvocations.put(erasedSuperType, someInvocations);
3171                    }
3172                } else { // using an array to record invocations in order (188103)
3173
TypeBinding[] someInvocations = (TypeBinding[]) invocationData;
3174                    checkExisting: {
3175                        int invocLength = someInvocations.length;
3176                        for (int k = 0; k < invocLength; k++) {
3177                            if (someInvocations[k] == match) break checkExisting;
3178                        }
3179                        System.arraycopy(someInvocations, 0, someInvocations = new TypeBinding[invocLength+1], 0, invocLength);
3180                        allInvocations.put(erasedSuperType, someInvocations);
3181                        someInvocations[invocLength] = match;
3182                    }
3183                }
3184            }
3185        }
3186        // eliminate non minimal super types
3187
if (remaining > 1) {
3188            nextType: for (int i = 0; i < superLength; i++) {
3189                TypeBinding erasedSuperType = erasedSuperTypes[i];
3190                if (erasedSuperType == null) continue nextType;
3191                nextOtherType: for (int j = 0; j < superLength; j++) {
3192                    if (i == j) continue nextOtherType;
3193                    TypeBinding otherType = erasedSuperTypes[j];
3194                    if (otherType == null) continue nextOtherType;
3195                    if (erasedSuperType instanceof ReferenceBinding) {
3196                        if (otherType.id == T_JavaLangObject && erasedSuperType.isInterface()) continue nextOtherType; // keep Object for an interface
3197
if (erasedSuperType.findSuperTypeWithSameErasure(otherType) != null) {
3198                            erasedSuperTypes[j] = null; // discard non minimal supertype
3199
remaining--;
3200                        }
3201                    } else if (erasedSuperType.isArrayType()) {
3202                    if (otherType.isArrayType() // keep Object[...] for an interface array (same dimensions)
3203
&& otherType.leafComponentType().id == T_JavaLangObject
3204                            && otherType.dimensions() == erasedSuperType.dimensions()
3205                            && erasedSuperType.leafComponentType().isInterface()) continue nextOtherType;
3206                        if (erasedSuperType.findSuperTypeWithSameErasure(otherType) != null) {
3207                            erasedSuperTypes[j] = null; // discard non minimal supertype
3208
remaining--;
3209                        }
3210                    }
3211                }
3212            }
3213        }
3214        return erasedSuperTypes;
3215    }
3216    
3217    // Internal use only
3218
/* All methods in visible are acceptable matches for the method in question...
3219    * The methods defined by the receiver type appear before those defined by its
3220    * superclass and so on. We want to find the one which matches best.
3221    *
3222    * Since the receiver type is a class, we know each method's declaring class is
3223    * either the receiver type or one of its superclasses. It is an error if the best match
3224    * is defined by a superclass, when a lesser match is defined by the receiver type
3225    * or a closer superclass.
3226    */

3227    protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
3228        MethodBinding previous = null;
3229        nextVisible : for (int i = 0; i < visibleSize; i++) {
3230            MethodBinding method = visible[i];
3231            if (previous != null && method.declaringClass != previous.declaringClass)
3232                break; // cannot answer a method farther up the hierarchy than the first method found
3233

3234            if (!method.isStatic()) previous = method; // no ambiguity for static methods
3235
for (int j = 0; j < visibleSize; j++) {
3236                if (i == j) continue;
3237                if (!visible[j].areParametersCompatibleWith(method.parameters))
3238                    continue nextVisible;
3239            }
3240            compilationUnitScope().recordTypeReferences(method.thrownExceptions);
3241            return method;
3242        }
3243        return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
3244    }
3245    
3246    // Internal use only
3247
/* All methods in visible are acceptable matches for the method in question...
3248    * Since the receiver type is an interface, we ignore the possibility that 2 inherited
3249    * but unrelated superinterfaces may define the same method in acceptable but
3250    * not identical ways... we just take the best match that we find since any class which
3251    * implements the receiver interface MUST implement all signatures for the method...
3252    * in which case the best match is correct.
3253    *
3254    * NOTE: This is different than javac... in the following example, the message send of
3255    * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
3256    * interface I MUST implement both signatures for bar. If this class was the receiver of
3257    * the message send instead of the interface I, then no problem would be reported.
3258    *
3259    interface I1 {
3260        void bar(J j);
3261    }
3262    interface I2 {
3263    // void bar(J j);
3264        void bar(Object o);
3265    }
3266    interface I extends I1, I2 {}
3267    interface J {}
3268    
3269    class X implements J {}
3270    
3271    class Y extends X {
3272        public void foo(I i, X x) { i.bar(x); }
3273    }
3274    */

3275    protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
3276        nextVisible : for (int i = 0; i < visibleSize; i++) {
3277            MethodBinding method = visible[i];
3278            for (int j = 0; j < visibleSize; j++) {
3279                if (i == j) continue;
3280                if (!visible[j].areParametersCompatibleWith(method.parameters))
3281                    continue nextVisible;
3282            }
3283            compilationUnitScope().recordTypeReferences(method.thrownExceptions);
3284            return method;
3285        }
3286        return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
3287    }
3288
3289    // caveat: this is not a direct implementation of JLS
3290
protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, InvocationSite invocationSite, ReferenceBinding receiverType) {
3291        int[] compatibilityLevels = new int[visibleSize];
3292        for (int i = 0; i < visibleSize; i++)
3293            compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes);
3294
3295        boolean useTiebreakMethod = invocationSite.genericTypeArguments() == null;
3296        MethodBinding[] moreSpecific = new MethodBinding[visibleSize];
3297        int count = 0;
3298        for (int level = 0, max = VARARGS_COMPATIBLE; level <= max; level++) {
3299            nextVisible : for (int i = 0; i < visibleSize; i++) {
3300                if (compatibilityLevels[i] != level) continue nextVisible;
3301                max = level; // do not examine further categories, will either return mostSpecific or report ambiguous case
3302
MethodBinding current = visible[i];
3303                MethodBinding original = current.original();
3304                MethodBinding tiebreakMethod = useTiebreakMethod ? current.tiebreakMethod() : current;
3305                for (int j = 0; j < visibleSize; j++) {
3306                    if (i == j || compatibilityLevels[j] != level) continue;
3307                    MethodBinding next = visible[j];
3308                    if (original == next.original()) {
3309                        // parameterized superclasses & interfaces may be walked twice from different paths so skip next from now on
3310
compatibilityLevels[j] = -1;
3311                        continue;
3312                    }
3313
3314                    MethodBinding methodToTest = next;
3315                    if (next instanceof ParameterizedGenericMethodBinding) {
3316                        ParameterizedGenericMethodBinding pNext = (ParameterizedGenericMethodBinding) next;
3317                        if (pNext.isRaw && !pNext.isStatic()) {
3318                            // hold onto the raw substituted method
3319
} else {
3320                            methodToTest = pNext.originalMethod;
3321                        }
3322                    }
3323                    MethodBinding acceptable = computeCompatibleMethod(methodToTest, tiebreakMethod.parameters, invocationSite);
3324                    /* There are 4 choices to consider with current & next :
3325                     foo(B) & foo(A) where B extends A
3326                     1. the 2 methods are equal (both accept each others parameters) -> want to continue
3327                     2. current has more specific parameters than next (so acceptable is a valid method) -> want to continue
3328                     3. current has less specific parameters than next (so acceptable is null) -> go on to next
3329                     4. current and next are not compatible with each other (so acceptable is null) -> go on to next
3330                     */

3331                    if (acceptable == null || !acceptable.isValidBinding())
3332                        continue nextVisible;
3333                    if (!isAcceptableMethod(tiebreakMethod, acceptable))
3334                        continue nextVisible;
3335                    // pick a concrete method over a bridge method when parameters are equal since the return type of the concrete method is more specific
3336
if (current.isBridge() && !next.isBridge())
3337                        if (tiebreakMethod.areParametersEqual(acceptable))
3338                            continue nextVisible; // skip current so acceptable wins over this bridge method
3339
}
3340                moreSpecific[i] = current;
3341                count++;
3342            }
3343        }
3344        if (count == 1) {
3345            for (int i = 0; i < visibleSize; i++) {
3346                if (moreSpecific[i] != null) {
3347                    compilationUnitScope().recordTypeReferences(visible[i].thrownExceptions);
3348                    return visible[i];
3349                }
3350            }
3351        } else if (count == 0) {
3352            return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
3353        }
3354
3355        // found several methods that are mutually acceptable -> must be equal
3356
// so now with the first acceptable method, find the 'correct' inherited method for each other acceptable method AND
3357
// see if they are equal after substitution of type variables (do the type variables have to be equal to be considered an override???)
3358
if (receiverType != null)
3359            receiverType = receiverType instanceof CaptureBinding ? receiverType : (ReferenceBinding) receiverType.erasure();
3360        nextSpecific : for (int i = 0; i < visibleSize; i++) {
3361            MethodBinding current = moreSpecific[i];
3362            if (current != null) {
3363                ReferenceBinding[] mostSpecificExceptions = null;
3364                SimpleSet possibleMethods = null;
3365                MethodBinding original = current.original();
3366                for (int j = 0; j < visibleSize; j++) {
3367                    MethodBinding next = moreSpecific[j];
3368                    if (next == null || i == j) continue;
3369                    MethodBinding original2 = next.original();
3370                    if (original.declaringClass == original2.declaringClass)
3371                        break nextSpecific; // duplicates thru substitution
3372

3373                    if (!original.isAbstract()) {
3374                        if (original2.isAbstract())
3375                            continue; // only compare current against other concrete methods
3376
TypeBinding superType = original.declaringClass.findSuperTypeWithSameErasure(original2.declaringClass.erasure());
3377                        if (superType == null)
3378                            continue nextSpecific; // current's declaringClass is not a subtype of next's declaringClass
3379
if (current.hasSubstitutedParameters() || original.typeVariables != Binding.NO_TYPE_VARIABLES) {
3380                            if (original2.declaringClass != superType) {
3381                                // must find inherited method with the same substituted variables
3382
MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(original2.selector);
3383                                for (int m = 0, l = superMethods.length; m < l; m++) {
3384                                    if (superMethods[m].original() == original2) {
3385                                        original2 = superMethods[m];
3386                                        break;
3387                                    }
3388                                }
3389                            }
3390                            if (!environment().methodVerifier().doesMethodOverride(original, original2))
3391                                continue nextSpecific; // current does not override next
3392
}
3393                    } else if (receiverType != null) { // should not be null if original isAbstract, but be safe
3394
TypeBinding superType = receiverType.findSuperTypeWithSameErasure(original.declaringClass.erasure());
3395                        if (original.declaringClass == superType || !(superType instanceof ReferenceBinding)) {
3396                            // keep original
3397
} else {
3398                            // must find inherited method with the same substituted variables
3399
MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(original.selector);
3400                            for (int m = 0, l = superMethods.length; m < l; m++) {
3401                                if (superMethods[m].original() == original) {
3402                                    original = superMethods[m];
3403                                    break;
3404                                }
3405                            }
3406                        }
3407                        superType = receiverType.findSuperTypeWithSameErasure(original2.declaringClass.erasure());
3408                        if (original2.declaringClass == superType || !(superType instanceof ReferenceBinding)) {
3409                            // keep original2
3410
} else {
3411                            // must find inherited method with the same substituted variables
3412
MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(original2.selector);
3413                            for (int m = 0, l = superMethods.length; m < l; m++) {
3414                                if (superMethods[m].original() == original2) {
3415                                    original2 = superMethods[m];
3416                                    break;
3417                                }
3418                            }
3419                        }
3420                        if (original.typeVariables != Binding.NO_TYPE_VARIABLES)
3421                            original2 = original.computeSubstitutedMethod(original2, environment());
3422                        if (original2 == null || !original.areParameterErasuresEqual(original2))
3423                            continue nextSpecific; // current does not override next
3424
if (!original.returnType.isCompatibleWith(original2.returnType) &&
3425                                !original.returnType.erasure().isCompatibleWith(original2.returnType.erasure())) {
3426                            // 15.12.2
3427
continue nextSpecific; // choose original2 instead
3428
}
3429                        if (original.thrownExceptions != original2.thrownExceptions) {
3430                            if (mostSpecificExceptions == null)
3431                                mostSpecificExceptions = original.thrownExceptions;
3432                            if (possibleMethods == null)
3433                                possibleMethods = new SimpleSet(3);
3434                            int mostSpecificLength = mostSpecificExceptions.length;
3435                            int original2Length = original2.thrownExceptions.length;
3436                            SimpleSet temp = new SimpleSet(mostSpecificLength);
3437                            nextException : for (int t = 0; t < mostSpecificLength; t++) {
3438                                ReferenceBinding exception = mostSpecificExceptions[t];
3439                                for (int s = 0; s < original2Length; s++) {
3440                                    if (exception.isCompatibleWith(original2.thrownExceptions[s])) {
3441                                        possibleMethods.add(current);
3442                                        temp.add(exception);
3443                                        continue nextException;
3444                                    } else if (original2.thrownExceptions[s].isCompatibleWith(exception)) {
3445                                        possibleMethods.add(next);
3446                                        temp.add(original2.thrownExceptions[s]);
3447                                        continue nextException;
3448                                    }
3449                                }
3450                            }
3451                            mostSpecificExceptions = temp.elementSize == 0 ? Binding.NO_EXCEPTIONS : new ReferenceBinding[temp.elementSize];
3452                            temp.asArray(mostSpecificExceptions);
3453                        }
3454                    }
3455                }
3456                if (mostSpecificExceptions != null) {
3457                    Object JavaDoc[] values = possibleMethods.values;
3458                    int exceptionLength = mostSpecificExceptions.length;
3459                    nextMethod : for (int p = 0, vLength = values.length; p < vLength; p++) {
3460                        MethodBinding possible = (MethodBinding) values[p];
3461                        if (possible == null) continue nextMethod;
3462                        ReferenceBinding[] itsExceptions = possible.thrownExceptions;
3463                        if (itsExceptions.length == exceptionLength) {
3464                            nextException : for (int e = 0; e < exceptionLength; e++) {
3465                                ReferenceBinding exception = itsExceptions[e];
3466                                for (int f = 0; f < exceptionLength; f++)
3467                                    if (exception == mostSpecificExceptions[f]) continue nextException;
3468                                continue nextMethod;
3469                            }
3470                            return possible;
3471                        }
3472                    }
3473// do not return a new methodBinding until we know that it does not cause problems
3474
// return new MethodBinding(
3475
// current.modifiers,
3476
// current.selector,
3477
// current.returnType,
3478
// current.parameters,
3479
// mostSpecificExceptions,
3480
// current.declaringClass
3481
// );
3482
}
3483                return current;
3484            }
3485        }
3486
3487        // if all moreSpecific methods are equal then see if duplicates exist because of substitution
3488
return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
3489    }
3490
3491    public final ClassScope outerMostClassScope() {
3492        ClassScope lastClassScope = null;
3493        Scope scope = this;
3494        do {
3495            if (scope instanceof ClassScope)
3496                lastClassScope = (ClassScope) scope;
3497            scope = scope.parent;
3498        } while (scope != null);
3499        return lastClassScope; // may answer null if no class around
3500
}
3501
3502    public final MethodScope outerMostMethodScope() {
3503        MethodScope lastMethodScope = null;
3504        Scope scope = this;
3505        do {
3506            if (scope instanceof MethodScope)
3507                lastMethodScope = (MethodScope) scope;
3508            scope = scope.parent;
3509        } while (scope != null);
3510        return lastMethodScope; // may answer null if no method around
3511
}
3512
3513    public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
3514        TypeBinding[] parameters = method.parameters;
3515        int paramLength = parameters.length;
3516        int argLength = arguments.length;
3517
3518        if (compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) {
3519            if (paramLength != argLength)
3520                return NOT_COMPATIBLE;
3521            for (int i = 0; i < argLength; i++) {
3522                TypeBinding param = parameters[i];
3523                TypeBinding arg = arguments[i];
3524                if (arg != param && !arg.isCompatibleWith(param))
3525                    return NOT_COMPATIBLE;
3526            }
3527            return COMPATIBLE;
3528        }
3529
3530        int level = COMPATIBLE; // no autoboxing or varargs support needed
3531
int lastIndex = argLength;
3532        LookupEnvironment env = environment();
3533        if (method.isVarargs()) {
3534            lastIndex = paramLength - 1;
3535            if (paramLength == argLength) { // accept X or X[] but not X[][]
3536
TypeBinding param = parameters[lastIndex]; // is an ArrayBinding by definition
3537
TypeBinding arg = arguments[lastIndex];
3538                if (param != arg) {
3539                    level = parameterCompatibilityLevel(arg, param, env);
3540                    if (level == NOT_COMPATIBLE) {
3541                        // expect X[], is it called with X
3542
param = ((ArrayBinding) param).elementsType();
3543                        if (parameterCompatibilityLevel(arg, param, env) == NOT_COMPATIBLE)
3544                            return NOT_COMPATIBLE;
3545                        level = VARARGS_COMPATIBLE; // varargs support needed
3546
}
3547                }
3548            } else {
3549                if (paramLength < argLength) { // all remaining argument types must be compatible with the elementsType of varArgType
3550
TypeBinding param = ((ArrayBinding) parameters[lastIndex]).elementsType();
3551                    for (int i = lastIndex; i < argLength; i++) {
3552                        TypeBinding arg = arguments[i];
3553                        if (param != arg && parameterCompatibilityLevel(arg, param, env) == NOT_COMPATIBLE)
3554                            return NOT_COMPATIBLE;
3555                    }
3556                } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
3557
return NOT_COMPATIBLE;
3558                }
3559                level = VARARGS_COMPATIBLE; // varargs support needed
3560
}
3561        } else if (paramLength != argLength) {
3562            return NOT_COMPATIBLE;
3563        }
3564        // now compare standard arguments from 0 to lastIndex
3565
for (int i = 0; i < lastIndex; i++) {
3566            TypeBinding param = parameters[i];
3567            TypeBinding arg = arguments[i];
3568            if (arg != param) {
3569                int newLevel = parameterCompatibilityLevel(arg, param, env);
3570                if (newLevel == NOT_COMPATIBLE)
3571                    return NOT_COMPATIBLE;
3572                if (newLevel > level)
3573                    level = newLevel;
3574            }
3575        }
3576        return level;
3577    }
3578
3579    private int parameterCompatibilityLevel(TypeBinding arg, TypeBinding param, LookupEnvironment env) {
3580        // only called if env.options.sourceLevel >= ClassFileConstants.JDK1_5
3581
if (arg.isCompatibleWith(param))
3582            return COMPATIBLE;
3583        if (arg.isBaseType() != param.isBaseType()) {
3584            TypeBinding convertedType = env.computeBoxingType(arg);
3585            if (convertedType == param || convertedType.isCompatibleWith(param))
3586                return AUTOBOX_COMPATIBLE;
3587        }
3588        return NOT_COMPATIBLE;
3589    }
3590
3591    public abstract ProblemReporter problemReporter();
3592
3593    public final CompilationUnitDeclaration referenceCompilationUnit() {
3594        Scope scope, unitScope = this;
3595        while ((scope = unitScope.parent) != null)
3596            unitScope = scope;
3597        return ((CompilationUnitScope) unitScope).referenceContext;
3598    }
3599    
3600    /**
3601     * Returns the nearest reference context, starting from current scope.
3602     * If starting on a class, it will return current class. If starting on unitScope, returns unit.
3603     */

3604    public ReferenceContext referenceContext() {
3605        Scope current = this;
3606        do {
3607            switch(current.kind) {
3608                case METHOD_SCOPE :
3609                    return ((MethodScope) current).referenceContext;
3610                case CLASS_SCOPE :
3611                    return ((ClassScope) current).referenceContext;
3612                case COMPILATION_UNIT_SCOPE :
3613                    return ((CompilationUnitScope) current).referenceContext;
3614            }
3615        } while ((current = current.parent) != null);
3616        return null;
3617    }
3618    
3619    // start position in this scope - for ordering scopes vs. variables
3620
int startIndex() {
3621        return 0;
3622    }
3623}
3624
Popular Tags