Fix nasty bug #706. See trac.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / Scope.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
12
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
15 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
16 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
17 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
18 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
20 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
21
22 public abstract class Scope implements BaseTypes, BindingIds,
23                 CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
24
25         public Scope parent;
26
27         public int kind;
28
29         public final static int BLOCK_SCOPE = 1;
30
31         public final static int METHOD_SCOPE = 2;
32
33         public final static int CLASS_SCOPE = 3;
34
35         public final static int COMPILATION_UNIT_SCOPE = 4;
36
37         protected Scope(int kind, Scope parent) {
38                 this.kind = kind;
39                 this.parent = parent;
40         }
41
42         public abstract ProblemReporter problemReporter();
43
44         // Internal use only
45         protected final boolean areParametersAssignable(TypeBinding[] parameters,
46                         TypeBinding[] arguments) {
47                 if (parameters == arguments)
48                         return true;
49
50                 int length = parameters.length;
51                 if (length != arguments.length)
52                         return false;
53
54                 for (int i = 0; i < length; i++)
55                         if (parameters[i] != arguments[i])
56                                 if (!arguments[i].isCompatibleWith(parameters[i]))
57                                         return false;
58                 return true;
59         }
60
61         /*
62          * Answer an int describing the relationship between the given types.
63          * 
64          * NotRelated EqualOrMoreSpecific : left is compatible with right
65          * MoreGeneric : right is compatible with left
66          */
67         public static int compareTypes(TypeBinding left, TypeBinding right) {
68                 if (left.isCompatibleWith(right))
69                         return EqualOrMoreSpecific;
70                 if (right.isCompatibleWith(left))
71                         return MoreGeneric;
72                 return NotRelated;
73         }
74
75         /*
76          * Answer an int describing the relationship between the given type and
77          * unchecked exceptions.
78          * 
79          * NotRelated EqualOrMoreSpecific : type is known for sure to be an
80          * unchecked exception type MoreGeneric : type is a supertype of an actual
81          * unchecked exception type
82          */
83         public int compareUncheckedException(ReferenceBinding type) {
84                 int comparison = compareTypes(type, getJavaLangRuntimeException());
85                 if (comparison != 0)
86                         return comparison;
87                 return compareTypes(type, getJavaLangError());
88         }
89
90         public final CompilationUnitScope compilationUnitScope() {
91                 Scope lastScope = null;
92                 Scope scope = this;
93                 do {
94                         lastScope = scope;
95                         scope = scope.parent;
96                 } while (scope != null);
97                 return (CompilationUnitScope) lastScope;
98         }
99
100         public ArrayBinding createArray(TypeBinding type, int dimension) {
101                 if (type.isValidBinding())
102                         return environment().createArrayType(type, dimension);
103                 else
104                         return new ArrayBinding(type, dimension);
105         }
106
107         public final ClassScope enclosingClassScope() {
108                 Scope scope = this;
109                 while ((scope = scope.parent) != null) {
110                         if (scope instanceof ClassScope)
111                                 return (ClassScope) scope;
112                 }
113                 return null; // may answer null if no type around
114         }
115
116         public final MethodScope enclosingMethodScope() {
117                 Scope scope = this;
118                 while ((scope = scope.parent) != null) {
119                         if (scope instanceof MethodScope)
120                                 return (MethodScope) scope;
121                 }
122                 return null; // may answer null if no method around
123         }
124
125         /*
126          * Answer the receiver's enclosing source type.
127          */
128         public final SourceTypeBinding enclosingSourceType() {
129                 Scope scope = this;
130                 do {
131                         if (scope instanceof ClassScope)
132                                 return ((ClassScope) scope).referenceContext.binding;
133                         scope = scope.parent;
134                 } while (scope != null);
135                 return null;
136         }
137
138         public final LookupEnvironment environment() {
139                 Scope scope, unitScope = this;
140                 while ((scope = unitScope.parent) != null)
141                         unitScope = scope;
142                 return ((CompilationUnitScope) unitScope).environment;
143         }
144
145         // Internal use only
146         public ReferenceBinding findDirectMemberType(char[] typeName,
147                         ReferenceBinding enclosingType) {
148                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
149                         return null; // know it has no member types (nor inherited member
150                                                         // types)
151
152                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
153                 compilationUnitScope().recordReference(enclosingType.compoundName,
154                                 typeName);
155                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
156                 if (memberType != null) {
157                         compilationUnitScope().recordTypeReference(memberType); // to record
158                                                                                                                                         // supertypes
159                         if (enclosingSourceType == null ? memberType
160                                         .canBeSeenBy(getCurrentPackage()) : memberType.canBeSeenBy(
161                                         enclosingType, enclosingSourceType))
162                                 return memberType;
163                         else
164                                 return new ProblemReferenceBinding(typeName, memberType,
165                                                 NotVisible);
166                 }
167                 return null;
168         }
169
170         // Internal use only
171         public MethodBinding findExactMethod(ReferenceBinding receiverType,
172                         char[] selector, TypeBinding[] argumentTypes,
173                         InvocationSite invocationSite) {
174
175                 compilationUnitScope().recordTypeReference(receiverType);
176                 compilationUnitScope().recordTypeReferences(argumentTypes);
177                 MethodBinding exactMethod = receiverType.getExactMethod(selector,
178                                 argumentTypes);
179                 if (exactMethod != null) {
180                         compilationUnitScope().recordTypeReferences(
181                                         exactMethod.thrownExceptions);
182                         if (receiverType.isInterface()
183                                         || exactMethod.canBeSeenBy(receiverType, invocationSite,
184                                                         this))
185                                 return exactMethod;
186                 }
187                 return null;
188         }
189
190         // Internal use only
191         /*
192          * Answer the field binding that corresponds to fieldName. Start the lookup
193          * at the receiverType. InvocationSite implements isSuperAccess(); this is
194          * used to determine if the discovered field is visible. Only fields defined
195          * by the receiverType or its supertypes are answered; a field of an
196          * enclosing type will not be found using this API.
197          * 
198          * If no visible field is discovered, null is answered.
199          */
200         public FieldBinding findField(TypeBinding receiverType, char[] fieldName,
201                         InvocationSite invocationSite) {
202                 if (receiverType.isBaseType())
203                         return null;
204                 if (receiverType.isArrayType()) {
205                         TypeBinding leafType = receiverType.leafComponentType();
206                         if (leafType instanceof ReferenceBinding) {
207                                 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
208                                         return new ProblemFieldBinding((ReferenceBinding) leafType,
209                                                         fieldName, ReceiverTypeNotVisible);
210                         }
211                         if (CharOperation.equals(fieldName, LENGTH))
212                                 return ArrayBinding.LengthField;
213                         return null;
214                 }
215
216                 compilationUnitScope().recordTypeReference(receiverType);
217
218                 ReferenceBinding currentType = (ReferenceBinding) receiverType;
219                 if (!currentType.canBeSeenBy(this))
220                         return new ProblemFieldBinding(currentType, fieldName,
221                                         ReceiverTypeNotVisible);
222
223                 FieldBinding field = currentType.getField(fieldName);
224                 if (field != null) {
225                         if (field.canBeSeenBy(currentType, invocationSite, this))
226                                 return field;
227                         else
228                                 return new ProblemFieldBinding(field.declaringClass, fieldName,
229                                                 NotVisible);
230                 }
231                 // collect all superinterfaces of receiverType until the field is found
232                 // in a supertype
233                 ReferenceBinding[][] interfacesToVisit = null;
234                 int lastPosition = -1;
235                 FieldBinding visibleField = null;
236                 boolean keepLooking = true;
237                 boolean notVisible = false;
238                 // we could hold onto the not visible field for extra error reporting
239                 while (keepLooking) {
240                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
241                         if (itsInterfaces != NoSuperInterfaces) {
242                                 if (interfacesToVisit == null)
243                                         interfacesToVisit = new ReferenceBinding[5][];
244                                 if (++lastPosition == interfacesToVisit.length)
245                                         System
246                                                         .arraycopy(
247                                                                         interfacesToVisit,
248                                                                         0,
249                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
250                                                                         0, lastPosition);
251                                 interfacesToVisit[lastPosition] = itsInterfaces;
252                         }
253                         if ((currentType = currentType.superclass()) == null)
254                                 break;
255
256                         if ((field = currentType.getField(fieldName)) != null) {
257                                 keepLooking = false;
258                                 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
259                                         if (visibleField == null)
260                                                 visibleField = field;
261                                         else
262                                                 return new ProblemFieldBinding(
263                                                                 visibleField.declaringClass, fieldName,
264                                                                 Ambiguous);
265                                 } else {
266                                         notVisible = true;
267                                 }
268                         }
269                 }
270
271                 // walk all visible interfaces to find ambiguous references
272                 if (interfacesToVisit != null) {
273                         ProblemFieldBinding ambiguous = null;
274                         done: for (int i = 0; i <= lastPosition; i++) {
275                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
276                                 for (int j = 0, length = interfaces.length; j < length; j++) {
277                                         ReferenceBinding anInterface = interfaces[j];
278                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
279                                                 // if interface as not already been visited
280                                                 anInterface.tagBits |= InterfaceVisited;
281                                                 if ((field = anInterface.getField(fieldName)) != null) {
282                                                         if (visibleField == null) {
283                                                                 visibleField = field;
284                                                         } else {
285                                                                 ambiguous = new ProblemFieldBinding(
286                                                                                 visibleField.declaringClass, fieldName,
287                                                                                 Ambiguous);
288                                                                 break done;
289                                                         }
290                                                 } else {
291                                                         ReferenceBinding[] itsInterfaces = anInterface
292                                                                         .superInterfaces();
293                                                         if (itsInterfaces != NoSuperInterfaces) {
294                                                                 if (++lastPosition == interfacesToVisit.length)
295                                                                         System
296                                                                                         .arraycopy(
297                                                                                                         interfacesToVisit,
298                                                                                                         0,
299                                                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
300                                                                                                         0, lastPosition);
301                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
302                                                         }
303                                                 }
304                                         }
305                                 }
306                         }
307
308                         // bit reinitialization
309                         for (int i = 0; i <= lastPosition; i++) {
310                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
311                                 for (int j = 0, length = interfaces.length; j < length; j++)
312                                         interfaces[j].tagBits &= ~InterfaceVisited;
313                         }
314                         if (ambiguous != null)
315                                 return ambiguous;
316                 }
317
318                 if (visibleField != null)
319                         return visibleField;
320                 if (notVisible)
321                         return new ProblemFieldBinding(currentType, fieldName, NotVisible);
322                 return null;
323         }
324
325         // Internal use only
326         public ReferenceBinding findMemberType(char[] typeName,
327                         ReferenceBinding enclosingType) {
328                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
329                         return null; // know it has no member types (nor inherited member
330                                                         // types)
331
332                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
333                 PackageBinding currentPackage = getCurrentPackage();
334                 compilationUnitScope().recordReference(enclosingType.compoundName,
335                                 typeName);
336                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
337                 if (memberType != null) {
338                         compilationUnitScope().recordTypeReference(memberType); // to record
339                                                                                                                                         // supertypes
340                         if (enclosingSourceType == null ? memberType
341                                         .canBeSeenBy(currentPackage) : memberType.canBeSeenBy(
342                                         enclosingType, enclosingSourceType))
343                                 return memberType;
344                         else
345                                 return new ProblemReferenceBinding(typeName, memberType,
346                                                 NotVisible);
347                 }
348
349                 // collect all superinterfaces of receiverType until the memberType is
350                 // found in a supertype
351                 ReferenceBinding currentType = enclosingType;
352                 ReferenceBinding[][] interfacesToVisit = null;
353                 int lastPosition = -1;
354                 ReferenceBinding visibleMemberType = null;
355                 boolean keepLooking = true;
356                 ReferenceBinding notVisible = null;
357                 // we could hold onto the not visible field for extra error reporting
358                 while (keepLooking) {
359                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
360                         if (itsInterfaces != NoSuperInterfaces) {
361                                 if (interfacesToVisit == null)
362                                         interfacesToVisit = new ReferenceBinding[5][];
363                                 if (++lastPosition == interfacesToVisit.length)
364                                         System
365                                                         .arraycopy(
366                                                                         interfacesToVisit,
367                                                                         0,
368                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
369                                                                         0, lastPosition);
370                                 interfacesToVisit[lastPosition] = itsInterfaces;
371                         }
372                         if ((currentType = currentType.superclass()) == null)
373                                 break;
374
375                         compilationUnitScope().recordReference(currentType.compoundName,
376                                         typeName);
377                         if ((memberType = currentType.getMemberType(typeName)) != null) {
378                                 compilationUnitScope().recordTypeReference(memberType); // to
379                                                                                                                                                 // record
380                                                                                                                                                 // supertypes
381                                 keepLooking = false;
382                                 if (enclosingSourceType == null ? memberType
383                                                 .canBeSeenBy(currentPackage) : memberType.canBeSeenBy(
384                                                 enclosingType, enclosingSourceType)) {
385                                         if (visibleMemberType == null)
386                                                 visibleMemberType = memberType;
387                                         else
388                                                 return new ProblemReferenceBinding(typeName, Ambiguous);
389                                 } else {
390                                         notVisible = memberType;
391                                 }
392                         }
393                 }
394                 // walk all visible interfaces to find ambiguous references
395                 if (interfacesToVisit != null) {
396                         ProblemReferenceBinding ambiguous = null;
397                         done: for (int i = 0; i <= lastPosition; i++) {
398                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
399                                 for (int j = 0, length = interfaces.length; j < length; j++) {
400                                         ReferenceBinding anInterface = interfaces[j];
401                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
402                                                 // if interface as not already been visited
403                                                 anInterface.tagBits |= InterfaceVisited;
404                                                 compilationUnitScope().recordReference(
405                                                                 anInterface.compoundName, typeName);
406                                                 if ((memberType = anInterface.getMemberType(typeName)) != null) {
407                                                         compilationUnitScope().recordTypeReference(
408                                                                         memberType); // to record supertypes
409                                                         if (visibleMemberType == null) {
410                                                                 visibleMemberType = memberType;
411                                                         } else {
412                                                                 ambiguous = new ProblemReferenceBinding(
413                                                                                 typeName, Ambiguous);
414                                                                 break done;
415                                                         }
416                                                 } else {
417                                                         ReferenceBinding[] itsInterfaces = anInterface
418                                                                         .superInterfaces();
419                                                         if (itsInterfaces != NoSuperInterfaces) {
420                                                                 if (++lastPosition == interfacesToVisit.length)
421                                                                         System
422                                                                                         .arraycopy(
423                                                                                                         interfacesToVisit,
424                                                                                                         0,
425                                                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
426                                                                                                         0, lastPosition);
427                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
428                                                         }
429                                                 }
430                                         }
431                                 }
432                         }
433
434                         // bit reinitialization
435                         for (int i = 0; i <= lastPosition; i++) {
436                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
437                                 for (int j = 0, length = interfaces.length; j < length; j++)
438                                         interfaces[j].tagBits &= ~InterfaceVisited;
439                         }
440                         if (ambiguous != null)
441                                 return ambiguous;
442                 }
443                 if (visibleMemberType != null)
444                         return visibleMemberType;
445                 if (notVisible != null)
446                         return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
447                 return null;
448         }
449
450         // Internal use only
451         public MethodBinding findMethod(ReferenceBinding receiverType,
452                         char[] selector, TypeBinding[] argumentTypes,
453                         InvocationSite invocationSite) {
454
455                 ReferenceBinding currentType = receiverType;
456                 MethodBinding matchingMethod = null;
457                 ObjectVector found = new ObjectVector();
458
459                 compilationUnitScope().recordTypeReference(receiverType);
460                 compilationUnitScope().recordTypeReferences(argumentTypes);
461
462                 if (currentType.isInterface()) {
463                         MethodBinding[] currentMethods = currentType.getMethods(selector);
464                         int currentLength = currentMethods.length;
465                         if (currentLength == 1) {
466                                 matchingMethod = currentMethods[0];
467                         } else if (currentLength > 1) {
468                                 found.addAll(currentMethods);
469                         }
470                         matchingMethod = findMethodInSuperInterfaces(currentType, selector,
471                                         found, matchingMethod);
472                         currentType = getJavaLangObject();
473                 }
474
475                 // boolean isCompliant14 =
476                 // compilationUnitScope().environment.options.complianceLevel >=
477                 // CompilerOptions.JDK1_4;
478                 // superclass lookup
479                 ReferenceBinding classHierarchyStart = currentType;
480                 while (currentType != null) {
481                         MethodBinding[] currentMethods = currentType.getMethods(selector);
482                         int currentLength = currentMethods.length;
483
484                         /*
485                          * if 1.4 compliant, must filter out redundant protected methods
486                          * from superclasses
487                          */
488                         // if (isCompliant14){
489                         // nextMethod: for (int i = 0; i < currentLength; i++){
490                         // MethodBinding currentMethod = currentMethods[i];
491                         // // protected method need to be checked only - default access is
492                         // already dealt with in #canBeSeen implementation
493                         // // when checking that p.C -> q.B -> p.A cannot see default access
494                         // members from A through B.
495                         // if ((currentMethod.modifiers & AccProtected) == 0) continue
496                         // nextMethod;
497                         // if (matchingMethod != null){
498                         // if (currentMethod.areParametersEqual(matchingMethod)){
499                         // currentLength--;
500                         // currentMethods[i] = null; // discard this match
501                         // continue nextMethod;
502                         // }
503                         // } else {
504                         // for (int j = 0, max = found.size; j < max; j++) {
505                         // if
506                         // (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
507                         // currentLength--;
508                         // currentMethods[i] = null;
509                         // continue nextMethod;
510                         // }
511                         // }
512                         // }
513                         // }
514                         // }
515                         if (currentLength == 1 && matchingMethod == null && found.size == 0) {
516                                 matchingMethod = currentMethods[0];
517                         } else if (currentLength > 0) {
518                                 if (matchingMethod != null) {
519                                         found.add(matchingMethod);
520                                         matchingMethod = null;
521                                 }
522                                 // append currentMethods, filtering out null entries
523                                 int maxMethod = currentMethods.length;
524                                 if (maxMethod == currentLength) { // no method was eliminated
525                                                                                                         // for 1.4 compliance (see
526                                                                                                         // above)
527                                         found.addAll(currentMethods);
528                                 } else {
529                                         for (int i = 0, max = currentMethods.length; i < max; i++) {
530                                                 MethodBinding currentMethod = currentMethods[i];
531                                                 if (currentMethod != null)
532                                                         found.add(currentMethod);
533                                         }
534                                 }
535                         }
536                         currentType = currentType.superclass();
537                 }
538
539                 int foundSize = found.size;
540                 if (foundSize == 0) {
541                         if (matchingMethod != null
542                                         && areParametersAssignable(matchingMethod.parameters,
543                                                         argumentTypes)) {
544                                 // (if no default abstract) must explicitly look for one
545                                 // instead, which could be a better match
546                                 if (!matchingMethod.canBeSeenBy(receiverType, invocationSite,
547                                                 this)) {
548                                         // ignore matching method (to be consistent with multiple
549                                         // matches, none visible (matching method is then null)
550                                         MethodBinding interfaceMethod = findDefaultAbstractMethod(
551                                                         receiverType, selector, argumentTypes,
552                                                         invocationSite, classHierarchyStart, null, found);
553                                         if (interfaceMethod != null)
554                                                 return interfaceMethod;
555                                 }
556                                 return matchingMethod;
557                         }
558                         return findDefaultAbstractMethod(receiverType, selector,
559                                         argumentTypes, invocationSite, classHierarchyStart,
560                                         matchingMethod, found);
561                 }
562
563                 MethodBinding[] candidates = new MethodBinding[foundSize];
564                 int candidatesCount = 0;
565                 // argument type compatibility check
566                 for (int i = 0; i < foundSize; i++) {
567                         MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
568                         if (areParametersAssignable(methodBinding.parameters, argumentTypes))
569                                 candidates[candidatesCount++] = methodBinding;
570                 }
571                 if (candidatesCount == 1) {
572                         compilationUnitScope().recordTypeReferences(
573                                         candidates[0].thrownExceptions);
574                         return candidates[0]; // have not checked visibility
575                 }
576                 if (candidatesCount == 0) { // try to find a close match when the
577                                                                         // parameter order is wrong or missing some
578                                                                         // parameters
579                         MethodBinding interfaceMethod = findDefaultAbstractMethod(
580                                         receiverType, selector, argumentTypes, invocationSite,
581                                         classHierarchyStart, matchingMethod, found);
582                         if (interfaceMethod != null)
583                                 return interfaceMethod;
584
585                         int argLength = argumentTypes.length;
586                         foundSize = found.size;
587                         nextMethod: for (int i = 0; i < foundSize; i++) {
588                                 MethodBinding methodBinding = (MethodBinding) found
589                                                 .elementAt(i);
590                                 TypeBinding[] params = methodBinding.parameters;
591                                 int paramLength = params.length;
592                                 nextArg: for (int a = 0; a < argLength; a++) {
593                                         TypeBinding arg = argumentTypes[a];
594                                         for (int p = 0; p < paramLength; p++)
595                                                 if (params[p] == arg)
596                                                         continue nextArg;
597                                         continue nextMethod;
598                                 }
599                                 return methodBinding;
600                         }
601                         return (MethodBinding) found.elementAt(0); // no good match so just
602                                                                                                                 // use the first one
603                                                                                                                 // found
604                 }
605
606                 // visibility check
607                 int visiblesCount = 0;
608                 for (int i = 0; i < candidatesCount; i++) {
609                         MethodBinding methodBinding = candidates[i];
610                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
611                                 if (visiblesCount != i) {
612                                         candidates[i] = null;
613                                         candidates[visiblesCount] = methodBinding;
614                                 }
615                                 visiblesCount++;
616                         }
617                 }
618                 if (visiblesCount == 1) {
619                         compilationUnitScope().recordTypeReferences(
620                                         candidates[0].thrownExceptions);
621                         return candidates[0];
622                 }
623                 if (visiblesCount == 0) {
624                         MethodBinding interfaceMethod = findDefaultAbstractMethod(
625                                         receiverType, selector, argumentTypes, invocationSite,
626                                         classHierarchyStart, matchingMethod, found);
627                         if (interfaceMethod != null)
628                                 return interfaceMethod;
629                         return new ProblemMethodBinding(candidates[0],
630                                         candidates[0].selector, candidates[0].parameters,
631                                         NotVisible);
632                 }
633                 if (candidates[0].declaringClass.isClass()) {
634                         return mostSpecificClassMethodBinding(candidates, visiblesCount);
635                 } else {
636                         return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
637                 }
638         }
639
640         // abstract method lookup lookup (since maybe missing default abstract
641         // methods)
642         public MethodBinding findDefaultAbstractMethod(
643                         ReferenceBinding receiverType, char[] selector,
644                         TypeBinding[] argumentTypes, InvocationSite invocationSite,
645                         ReferenceBinding classHierarchyStart, MethodBinding matchingMethod,
646                         ObjectVector found) {
647
648                 int startFoundSize = found.size;
649                 ReferenceBinding currentType = classHierarchyStart;
650                 while (currentType != null) {
651                         matchingMethod = findMethodInSuperInterfaces(currentType, selector,
652                                         found, matchingMethod);
653                         currentType = currentType.superclass();
654                 }
655                 int foundSize = found.size;
656                 if (foundSize == startFoundSize)
657                         return matchingMethod; // maybe null
658
659                 MethodBinding[] candidates = new MethodBinding[foundSize
660                                 - startFoundSize];
661                 int candidatesCount = 0;
662                 // argument type compatibility check
663                 for (int i = startFoundSize; i < foundSize; i++) {
664                         MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
665                         if (areParametersAssignable(methodBinding.parameters, argumentTypes))
666                                 candidates[candidatesCount++] = methodBinding;
667                 }
668                 if (candidatesCount == 1) {
669                         compilationUnitScope().recordTypeReferences(
670                                         candidates[0].thrownExceptions);
671                         return candidates[0];
672                 }
673                 if (candidatesCount == 0) { // try to find a close match when the
674                                                                         // parameter order is wrong or missing some
675                                                                         // parameters
676                         int argLength = argumentTypes.length;
677                         nextMethod: for (int i = 0; i < foundSize; i++) {
678                                 MethodBinding methodBinding = (MethodBinding) found
679                                                 .elementAt(i);
680                                 TypeBinding[] params = methodBinding.parameters;
681                                 int paramLength = params.length;
682                                 nextArg: for (int a = 0; a < argLength; a++) {
683                                         TypeBinding arg = argumentTypes[a];
684                                         for (int p = 0; p < paramLength; p++)
685                                                 if (params[p] == arg)
686                                                         continue nextArg;
687                                         continue nextMethod;
688                                 }
689                                 return methodBinding;
690                         }
691                         return (MethodBinding) found.elementAt(0); // no good match so just
692                                                                                                                 // use the first one
693                                                                                                                 // found
694                 }
695                 // no need to check for visibility - interface methods are public
696                 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
697         }
698
699         public MethodBinding findMethodInSuperInterfaces(
700                         ReferenceBinding currentType, char[] selector, ObjectVector found,
701                         MethodBinding matchingMethod) {
702
703                 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
704                 if (itsInterfaces != NoSuperInterfaces) {
705                         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
706                         int lastPosition = -1;
707                         if (++lastPosition == interfacesToVisit.length)
708                                 System
709                                                 .arraycopy(
710                                                                 interfacesToVisit,
711                                                                 0,
712                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
713                                                                 0, lastPosition);
714                         interfacesToVisit[lastPosition] = itsInterfaces;
715
716                         for (int i = 0; i <= lastPosition; i++) {
717                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
718                                 for (int j = 0, length = interfaces.length; j < length; j++) {
719                                         currentType = interfaces[j];
720                                         if ((currentType.tagBits & InterfaceVisited) == 0) {
721                                                 // if interface as not already been visited
722                                                 currentType.tagBits |= InterfaceVisited;
723
724                                                 MethodBinding[] currentMethods = currentType
725                                                                 .getMethods(selector);
726                                                 int currentLength = currentMethods.length;
727                                                 if (currentLength == 1 && matchingMethod == null
728                                                                 && found.size == 0) {
729                                                         matchingMethod = currentMethods[0];
730                                                 } else if (currentLength > 0) {
731                                                         if (matchingMethod != null) {
732                                                                 found.add(matchingMethod);
733                                                                 matchingMethod = null;
734                                                         }
735                                                         found.addAll(currentMethods);
736                                                 }
737                                                 itsInterfaces = currentType.superInterfaces();
738                                                 if (itsInterfaces != NoSuperInterfaces) {
739                                                         if (++lastPosition == interfacesToVisit.length)
740                                                                 System
741                                                                                 .arraycopy(
742                                                                                                 interfacesToVisit,
743                                                                                                 0,
744                                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
745                                                                                                 0, lastPosition);
746                                                         interfacesToVisit[lastPosition] = itsInterfaces;
747                                                 }
748                                         }
749                                 }
750                         }
751
752                         // bit reinitialization
753                         for (int i = 0; i <= lastPosition; i++) {
754                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
755                                 for (int j = 0, length = interfaces.length; j < length; j++)
756                                         interfaces[j].tagBits &= ~InterfaceVisited;
757                         }
758                 }
759                 return matchingMethod;
760         }
761
762         // Internal use only
763         public MethodBinding findMethodForArray(ArrayBinding receiverType,
764                         char[] selector, TypeBinding[] argumentTypes,
765                         InvocationSite invocationSite) {
766
767                 TypeBinding leafType = receiverType.leafComponentType();
768                 if (leafType instanceof ReferenceBinding) {
769                         if (!((ReferenceBinding) leafType).canBeSeenBy(this))
770                                 return new ProblemMethodBinding(selector,
771                                                 MethodBinding.NoParameters,
772                                                 (ReferenceBinding) leafType, ReceiverTypeNotVisible);
773                 }
774
775                 ReferenceBinding object = getJavaLangObject();
776                 MethodBinding methodBinding = object.getExactMethod(selector,
777                                 argumentTypes);
778                 if (methodBinding != null) {
779                         // handle the method clone() specially... cannot be protected or
780                         // throw exceptions
781                         if (argumentTypes == NoParameters
782                                         && CharOperation.equals(selector, CLONE))
783                                 return new MethodBinding(
784                                                 (methodBinding.modifiers ^ AccProtected) | AccPublic,
785                                                 CLONE, methodBinding.returnType, argumentTypes, null,
786                                                 object);
787                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
788                                 return methodBinding;
789                 }
790                 // answers closest approximation, may not check argumentTypes or
791                 // visibility
792                 methodBinding = findMethod(object, selector, argumentTypes,
793                                 invocationSite);
794                 if (methodBinding == null)
795                         return new ProblemMethodBinding(selector, argumentTypes, NotFound);
796                 if (methodBinding.isValidBinding()) {
797                         if (!areParametersAssignable(methodBinding.parameters,
798                                         argumentTypes))
799                                 return new ProblemMethodBinding(methodBinding, selector,
800                                                 argumentTypes, NotFound);
801                         if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
802                                 return new ProblemMethodBinding(methodBinding, selector,
803                                                 methodBinding.parameters, NotVisible);
804                 }
805                 return methodBinding;
806         }
807
808         // Internal use only
809         public ReferenceBinding findType(char[] typeName,
810                         PackageBinding declarationPackage, PackageBinding invocationPackage) {
811
812                 compilationUnitScope().recordReference(declarationPackage.compoundName,
813                                 typeName);
814                 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
815                 if (typeBinding == null)
816                         return null;
817
818                 if (typeBinding.isValidBinding()) {
819                         if (declarationPackage != invocationPackage
820                                         && !typeBinding.canBeSeenBy(invocationPackage))
821                                 return new ProblemReferenceBinding(typeName, typeBinding,
822                                                 NotVisible);
823                 }
824                 return typeBinding;
825         }
826
827         public TypeBinding getBaseType(char[] name) {
828                 // list should be optimized (with most often used first)
829                 int length = name.length;
830                 if (length > 2 && length < 8) {
831                         switch (name[0]) {
832                         case 'i':
833                                 if (length == 3 && name[1] == 'n' && name[2] == 't')
834                                         return IntBinding;
835                                 break;
836                         case 'v':
837                                 if (length == 4 && name[1] == 'o' && name[2] == 'i'
838                                                 && name[3] == 'd')
839                                         return VoidBinding;
840                                 break;
841                         case 'b':
842                                 if (length == 7 && name[1] == 'o' && name[2] == 'o'
843                                                 && name[3] == 'l' && name[4] == 'e' && name[5] == 'a'
844                                                 && name[6] == 'n')
845                                         return BooleanBinding;
846                                 if (length == 4 && name[1] == 'y' && name[2] == 't'
847                                                 && name[3] == 'e')
848                                         return ByteBinding;
849                                 break;
850                         case 'c':
851                                 if (length == 4 && name[1] == 'h' && name[2] == 'a'
852                                                 && name[3] == 'r')
853                                         return CharBinding;
854                                 break;
855                         case 'd':
856                                 if (length == 6 && name[1] == 'o' && name[2] == 'u'
857                                                 && name[3] == 'b' && name[4] == 'l' && name[5] == 'e')
858                                         return DoubleBinding;
859                                 break;
860                         case 'f':
861                                 if (length == 5 && name[1] == 'l' && name[2] == 'o'
862                                                 && name[3] == 'a' && name[4] == 't')
863                                         return FloatBinding;
864                                 break;
865                         case 'l':
866                                 if (length == 4 && name[1] == 'o' && name[2] == 'n'
867                                                 && name[3] == 'g')
868                                         return LongBinding;
869                                 break;
870                         case 's':
871                                 if (length == 5 && name[1] == 'h' && name[2] == 'o'
872                                                 && name[3] == 'r' && name[4] == 't')
873                                         return ShortBinding;
874                         }
875                 }
876                 return null;
877         }
878
879         public final PackageBinding getCurrentPackage() {
880                 Scope scope, unitScope = this;
881                 while ((scope = unitScope.parent) != null)
882                         unitScope = scope;
883                 return ((CompilationUnitScope) unitScope).fPackage;
884         }
885
886         /**
887          * Returns the modifiers of the innermost enclosing declaration.
888          * 
889          * @return modifiers
890          */
891         public int getDeclarationModifiers() {
892                 switch (this.kind) {
893                 case Scope.BLOCK_SCOPE:
894                 case Scope.METHOD_SCOPE:
895                         MethodScope methodScope = methodScope();
896                         if (!methodScope.isInsideInitializer()) {
897                                 // check method modifiers to see if deprecated
898                                 MethodBinding context = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
899                                 if (context != null) {
900                                         return context.modifiers;
901                                 }
902                         } else {
903                                 SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
904
905                                 // inside field declaration ? check field modifier to see if
906                                 // deprecated
907                                 if (methodScope.initializedField != null) {
908                                         return methodScope.initializedField.modifiers;
909                                 }
910                                 if (type != null) {
911                                         return type.modifiers;
912                                 }
913                         }
914                         break;
915                 case Scope.CLASS_SCOPE:
916                         ReferenceBinding context = ((ClassScope) this).referenceType().binding;
917                         if (context != null) {
918                                 return context.modifiers;
919                         }
920                         break;
921                 }
922                 return -1;
923         }
924
925         public final ReferenceBinding getJavaIoSerializable() {
926                 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
927                 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
928                 if (type != null)
929                         return type;
930
931                 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE,
932                                 referenceCompilationUnit());
933                 return null; // will not get here since the above error aborts the
934                                                 // compilation
935         }
936
937         public final ReferenceBinding getJavaLangClass() {
938                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
939                 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
940                 if (type != null)
941                         return type;
942
943                 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS,
944                                 referenceCompilationUnit());
945                 return null; // will not get here since the above error aborts the
946                                                 // compilation
947         }
948
949         public final ReferenceBinding getJavaLangCloneable() {
950                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
951                 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
952                 if (type != null)
953                         return type;
954
955                 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE,
956                                 referenceCompilationUnit());
957                 return null; // will not get here since the above error aborts the
958                                                 // compilation
959         }
960
961         public final ReferenceBinding getJavaLangError() {
962                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
963                 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
964                 if (type != null)
965                         return type;
966
967                 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR,
968                                 referenceCompilationUnit());
969                 return null; // will not get here since the above error aborts the
970                                                 // compilation
971         }
972
973         public final ReferenceBinding getJavaLangAssertionError() {
974                 compilationUnitScope().recordQualifiedReference(
975                                 JAVA_LANG_ASSERTIONERROR);
976                 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
977                 if (type != null)
978                         return type;
979                 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR,
980                                 referenceCompilationUnit());
981                 return null; // will not get here since the above error aborts the
982                                                 // compilation
983         }
984
985         public final ReferenceBinding getJavaLangObject() {
986                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
987                 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
988                 if (type != null)
989                         return type;
990
991                 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT,
992                                 referenceCompilationUnit());
993                 return null; // will not get here since the above error aborts the
994                                                 // compilation
995         }
996
997         public final ReferenceBinding getJavaLangRuntimeException() {
998                 compilationUnitScope().recordQualifiedReference(
999                                 JAVA_LANG_RUNTIMEEXCEPTION);
1000                 ReferenceBinding type = environment().getType(
1001                                 JAVA_LANG_RUNTIMEEXCEPTION);
1002                 if (type != null)
1003                         return type;
1004
1005                 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION,
1006                                 referenceCompilationUnit());
1007                 return null; // will not get here since the above error aborts the
1008                                                 // compilation
1009         }
1010
1011         public final ReferenceBinding getJavaLangString() {
1012                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
1013                 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
1014                 if (type != null)
1015                         return type;
1016
1017                 problemReporter().isClassPathCorrect(JAVA_LANG_STRING,
1018                                 referenceCompilationUnit());
1019                 return null; // will not get here since the above error aborts the
1020                                                 // compilation
1021         }
1022
1023         public final ReferenceBinding getJavaLangThrowable() {
1024                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
1025                 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
1026                 if (type != null)
1027                         return type;
1028
1029                 // problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE,
1030                 // referenceCompilationUnit());
1031                 return null; // will not get here since the above error aborts the
1032                                                 // compilation
1033         }
1034
1035         /*
1036          * Answer the type binding corresponding to the typeName argument, relative
1037          * to the enclosingType.
1038          */
1039         public final ReferenceBinding getMemberType(char[] typeName,
1040                         ReferenceBinding enclosingType) {
1041                 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
1042                 if (memberType != null)
1043                         return memberType;
1044                 return new ProblemReferenceBinding(typeName, NotFound);
1045         }
1046
1047         /*
1048          * Answer the type binding corresponding to the compoundName.
1049          * 
1050          * NOTE: If a problem binding is returned, senders should extract the
1051          * compound name from the binding & not assume the problem applies to the
1052          * entire compoundName.
1053          */
1054         public final TypeBinding getType(char[][] compoundName) {
1055                 int typeNameLength = compoundName.length;
1056                 if (typeNameLength == 1) {
1057                         // Would like to remove this test and require senders to specially
1058                         // handle base types
1059                         TypeBinding binding = getBaseType(compoundName[0]);
1060                         if (binding != null)
1061                                 return binding;
1062                 }
1063
1064                 compilationUnitScope().recordQualifiedReference(compoundName);
1065                 Binding binding = getTypeOrPackage(compoundName[0],
1066                                 typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
1067                 if (binding == null)
1068                         return new ProblemReferenceBinding(compoundName[0], NotFound);
1069                 if (!binding.isValidBinding())
1070                         return (ReferenceBinding) binding;
1071
1072                 int currentIndex = 1;
1073                 boolean checkVisibility = false;
1074                 if (binding instanceof PackageBinding) {
1075                         PackageBinding packageBinding = (PackageBinding) binding;
1076                         while (currentIndex < typeNameLength) {
1077                                 binding = packageBinding
1078                                                 .getTypeOrPackage(compoundName[currentIndex++]); // does
1079                                                                                                                                                         // not
1080                                                                                                                                                         // check
1081                                                                                                                                                         // visibility
1082                                 if (binding == null)
1083                                         return new ProblemReferenceBinding(CharOperation.subarray(
1084                                                         compoundName, 0, currentIndex), NotFound);
1085                                 if (!binding.isValidBinding())
1086                                         return new ProblemReferenceBinding(CharOperation.subarray(
1087                                                         compoundName, 0, currentIndex), binding.problemId());
1088                                 if (!(binding instanceof PackageBinding))
1089                                         break;
1090                                 packageBinding = (PackageBinding) binding;
1091                         }
1092                         if (binding instanceof PackageBinding)
1093                                 return new ProblemReferenceBinding(CharOperation.subarray(
1094                                                 compoundName, 0, currentIndex), NotFound);
1095                         checkVisibility = true;
1096                 }
1097
1098                 // binding is now a ReferenceBinding
1099                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1100                 compilationUnitScope().recordTypeReference(typeBinding); // to record
1101                                                                                                                                         // supertypes
1102                 if (checkVisibility) // handles the fall through case
1103                         if (!typeBinding.canBeSeenBy(this))
1104                                 return new ProblemReferenceBinding(CharOperation.subarray(
1105                                                 compoundName, 0, currentIndex), typeBinding, NotVisible);
1106
1107                 while (currentIndex < typeNameLength) {
1108                         typeBinding = getMemberType(compoundName[currentIndex++],
1109                                         typeBinding);
1110                         if (!typeBinding.isValidBinding())
1111                                 return new ProblemReferenceBinding(CharOperation.subarray(
1112                                                 compoundName, 0, currentIndex), typeBinding.problemId());
1113                 }
1114                 return typeBinding;
1115         }
1116
1117         /*
1118          * Answer the type binding that corresponds the given name, starting the
1119          * lookup in the receiver. The name provided is a simple source name (e.g.,
1120          * "Object" , "Point", ...)
1121          */
1122         // The return type of this method could be ReferenceBinding if we did not
1123         // answer base types.
1124         // NOTE: We could support looking for Base Types last in the search, however
1125         // any code using
1126         // this feature would be extraordinarily slow. Therefore we don't do this
1127         public final TypeBinding getType(char[] name) {
1128                 // Would like to remove this test and require senders to specially
1129                 // handle base types
1130                 TypeBinding binding = getBaseType(name);
1131                 if (binding != null)
1132                         return binding;
1133                 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
1134         }
1135
1136         // Added for code assist... NOT Public API
1137         public final Binding getTypeOrPackage(char[][] compoundName) {
1138                 int nameLength = compoundName.length;
1139                 if (nameLength == 1) {
1140                         TypeBinding binding = getBaseType(compoundName[0]);
1141                         if (binding != null)
1142                                 return binding;
1143                 }
1144                 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
1145                 if (!binding.isValidBinding())
1146                         return binding;
1147
1148                 int currentIndex = 1;
1149                 boolean checkVisibility = false;
1150                 if (binding instanceof PackageBinding) {
1151                         PackageBinding packageBinding = (PackageBinding) binding;
1152
1153                         while (currentIndex < nameLength) {
1154                                 binding = packageBinding
1155                                                 .getTypeOrPackage(compoundName[currentIndex++]);
1156                                 if (binding == null)
1157                                         return new ProblemReferenceBinding(CharOperation.subarray(
1158                                                         compoundName, 0, currentIndex), NotFound);
1159                                 if (!binding.isValidBinding())
1160                                         return new ProblemReferenceBinding(CharOperation.subarray(
1161                                                         compoundName, 0, currentIndex), binding.problemId());
1162                                 if (!(binding instanceof PackageBinding))
1163                                         break;
1164                                 packageBinding = (PackageBinding) binding;
1165                         }
1166                         if (binding instanceof PackageBinding)
1167                                 return binding;
1168                         checkVisibility = true;
1169                 }
1170                 // binding is now a ReferenceBinding
1171                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1172                 if (checkVisibility) // handles the fall through case
1173                         if (!typeBinding.canBeSeenBy(this))
1174                                 return new ProblemReferenceBinding(CharOperation.subarray(
1175                                                 compoundName, 0, currentIndex), typeBinding, NotVisible);
1176
1177                 while (currentIndex < nameLength) {
1178                         typeBinding = getMemberType(compoundName[currentIndex++],
1179                                         typeBinding);
1180                         // checks visibility
1181                         if (!typeBinding.isValidBinding())
1182                                 return new ProblemReferenceBinding(CharOperation.subarray(
1183                                                 compoundName, 0, currentIndex), typeBinding.problemId());
1184                 }
1185                 return typeBinding;
1186         }
1187
1188         /*
1189          * Internal use only
1190          */
1191         final Binding getTypeOrPackage(char[] name, int mask) {
1192                 Scope scope = this;
1193                 ReferenceBinding foundType = null;
1194                 if ((mask & TYPE) == 0) {
1195                         Scope next = scope;
1196                         while ((next = scope.parent) != null)
1197                                 scope = next;
1198                 } else {
1199                         done: while (true) { // done when a COMPILATION_UNIT_SCOPE is
1200                                                                         // found
1201                                 switch (scope.kind) {
1202                                 case METHOD_SCOPE:
1203                                 case BLOCK_SCOPE:
1204                                         ReferenceBinding localType = ((BlockScope) scope)
1205                                                         .findLocalType(name); // looks in this scope only
1206                                         if (localType != null) {
1207                                                 if (foundType != null && foundType != localType)
1208                                                         return new ProblemReferenceBinding(name,
1209                                                                         InheritedNameHidesEnclosingName);
1210                                                 return localType;
1211                                         }
1212                                         break;
1213                                 case CLASS_SCOPE:
1214                                         SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
1215                                         // 6.5.5.1 - simple name favors member type over top-level
1216                                         // type in same unit
1217                                         ReferenceBinding memberType = findMemberType(name,
1218                                                         sourceType);
1219                                         if (memberType != null) { // skip it if we did not find
1220                                                                                                 // anything
1221                                                 if (memberType.problemId() == Ambiguous) {
1222                                                         if (foundType == null
1223                                                                         || foundType.problemId() == NotVisible)
1224                                                                 // supercedes any potential
1225                                                                 // InheritedNameHidesEnclosingName problem
1226                                                                 return memberType;
1227                                                         else
1228                                                                 // make the user qualify the type, likely wants
1229                                                                 // the first inherited type
1230                                                                 return new ProblemReferenceBinding(name,
1231                                                                                 InheritedNameHidesEnclosingName);
1232                                                 }
1233                                                 // if (memberType.isValidBinding()) {
1234                                                 // if (sourceType == memberType.enclosingType()
1235                                                 // || environment().options.complianceLevel >=
1236                                                 // CompilerOptions.JDK1_4) {
1237                                                 // // found a valid type in the 'immediate' scope (ie.
1238                                                 // not inherited)
1239                                                 // // OR in 1.4 mode (inherited shadows enclosing)
1240                                                 // if (foundType == null)
1241                                                 // return memberType;
1242                                                 // if (foundType.isValidBinding())
1243                                                 // // if a valid type was found, complain when another
1244                                                 // is found in an 'immediate' enclosing type (ie. not
1245                                                 // inherited)
1246                                                 // if (foundType != memberType)
1247                                                 // return new ProblemReferenceBinding(name,
1248                                                 // InheritedNameHidesEnclosingName);
1249                                                 // }
1250                                                 // }
1251                                                 if (foundType == null
1252                                                                 || (foundType.problemId() == NotVisible && memberType
1253                                                                                 .problemId() != NotVisible))
1254                                                         // only remember the memberType if its the first one
1255                                                         // found or the previous one was not visible &
1256                                                         // memberType is...
1257                                                         foundType = memberType;
1258                                         }
1259                                         if (CharOperation.equals(sourceType.sourceName, name)) {
1260                                                 if (foundType != null && foundType != sourceType
1261                                                                 && foundType.problemId() != NotVisible)
1262                                                         return new ProblemReferenceBinding(name,
1263                                                                         InheritedNameHidesEnclosingName);
1264                                                 return sourceType;
1265                                         }
1266                                         break;
1267                                 case COMPILATION_UNIT_SCOPE:
1268                                         break done;
1269                                 }
1270                                 scope = scope.parent;
1271                         }
1272                         if (foundType != null && foundType.problemId() != NotVisible)
1273                                 return foundType;
1274                 }
1275
1276                 // at this point the scope is a compilation unit scope
1277                 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1278                 PackageBinding currentPackage = unitScope.fPackage;
1279                 // ask for the imports + name
1280                 if ((mask & TYPE) != 0) {
1281                         // check single type imports.
1282                         ImportBinding[] imports = unitScope.imports;
1283                         if (imports != null) {
1284                                 // copy the list, since single type imports are removed if they
1285                                 // cannot be resolved
1286                                 for (int i = 0, length = imports.length; i < length; i++) {
1287                                         ImportBinding typeImport = imports[i];
1288                                         if (!typeImport.onDemand) {
1289                                                 if (CharOperation
1290                                                                 .equals(
1291                                                                                 typeImport.compoundName[typeImport.compoundName.length - 1],
1292                                                                                 name)) {
1293                                                         if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1294                                                                 ImportReference importReference = typeImport.reference;
1295                                                                 if (importReference != null)
1296                                                                         importReference.used = true;
1297                                                                 return typeImport.resolvedImport; // already
1298                                                                                                                                         // know its
1299                                                                                                                                         // visible
1300                                                         }
1301                                                 }
1302                                         }
1303                                 }
1304                         }
1305                         // check if the name is in the current package, skip it if its a
1306                         // sub-package
1307                         unitScope.recordReference(currentPackage.compoundName, name);
1308                         Binding binding = currentPackage.getTypeOrPackage(name);
1309                         if (binding instanceof ReferenceBinding)
1310                                 return binding; // type is always visible to its own package
1311
1312                         // check on demand imports
1313                         boolean foundInImport = false;
1314                         ReferenceBinding type = null;
1315                         if (imports != null) {
1316                                 for (int i = 0, length = imports.length; i < length; i++) {
1317                                         ImportBinding someImport = imports[i];
1318                                         if (someImport.onDemand) {
1319                                                 Binding resolvedImport = someImport.resolvedImport;
1320                                                 ReferenceBinding temp = resolvedImport instanceof PackageBinding ? findType(
1321                                                                 name, (PackageBinding) resolvedImport,
1322                                                                 currentPackage)
1323                                                                 : findDirectMemberType(name,
1324                                                                                 (ReferenceBinding) resolvedImport);
1325                                                 if (temp != null && temp.isValidBinding()) {
1326                                                         // ImportReference importReference =
1327                                                         // someImport.reference;
1328                                                         // if (importReference != null) importReference.used
1329                                                         // = true;
1330                                                         if (foundInImport)
1331                                                                 // Answer error binding -- import on demand
1332                                                                 // conflict; name found in two import on demand
1333                                                                 // packages.
1334                                                                 return new ProblemReferenceBinding(name,
1335                                                                                 Ambiguous);
1336                                                         type = temp;
1337                                                         foundInImport = true;
1338                                                 }
1339                                         }
1340                                 }
1341                         }
1342                         if (type != null)
1343                                 return type;
1344                 }
1345
1346                 unitScope.recordSimpleReference(name);
1347                 if ((mask & PACKAGE) != 0) {
1348                         PackageBinding packageBinding = unitScope.environment
1349                                         .getTopLevelPackage(name);
1350                         if (packageBinding != null)
1351                                 return packageBinding;
1352                 }
1353
1354                 // Answer error binding -- could not find name
1355                 if (foundType != null)
1356                         return foundType; // problem type from above
1357                 return new ProblemReferenceBinding(name, NotFound);
1358         }
1359
1360         /*
1361          * Answer whether the type is defined in the same compilation unit as the
1362          * receiver
1363          */
1364         public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1365                 // find the outer most enclosing type
1366                 ReferenceBinding enclosingType = type;
1367                 while ((type = enclosingType.enclosingType()) != null)
1368                         enclosingType = type;
1369
1370                 // find the compilation unit scope
1371                 Scope scope, unitScope = this;
1372                 while ((scope = unitScope.parent) != null)
1373                         unitScope = scope;
1374
1375                 // test that the enclosingType is not part of the compilation unit
1376                 SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
1377                 for (int i = topLevelTypes.length; --i >= 0;)
1378                         if (topLevelTypes[i] == enclosingType)
1379                                 return true;
1380                 return false;
1381         }
1382
1383         /*
1384          * Answer true if the scope is nested inside a given field declaration.
1385          * Note: it works as long as the scope.fieldDeclarationIndex is reflecting
1386          * the field being traversed e.g. during name resolution.
1387          */
1388         public final boolean isDefinedInField(FieldBinding field) {
1389                 Scope scope = this;
1390                 do {
1391                         if (scope instanceof MethodScope) {
1392                                 MethodScope methodScope = (MethodScope) scope;
1393                                 ReferenceContext refContext = methodScope.referenceContext;
1394                                 if (refContext instanceof TypeDeclaration
1395                                                 && ((TypeDeclaration) refContext).binding == field.declaringClass
1396                                                 && methodScope.fieldDeclarationIndex == field.id) {
1397                                         return true;
1398                                 }
1399                         }
1400                         scope = scope.parent;
1401                 } while (scope != null);
1402                 return false;
1403         }
1404
1405         /*
1406          * Answer true if the scope is nested inside a given method declaration
1407          */
1408         public final boolean isDefinedInMethod(MethodBinding method) {
1409                 Scope scope = this;
1410                 do {
1411                         if (scope instanceof MethodScope) {
1412                                 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
1413                                 if (refContext instanceof AbstractMethodDeclaration
1414                                                 && ((AbstractMethodDeclaration) refContext).binding == method) {
1415                                         return true;
1416                                 }
1417                         }
1418                         scope = scope.parent;
1419                 } while (scope != null);
1420                 return false;
1421         }
1422
1423         /*
1424          * Answer true if the scope is nested inside a given type declaration
1425          */
1426         public final boolean isDefinedInType(ReferenceBinding type) {
1427                 Scope scope = this;
1428                 do {
1429                         if (scope instanceof ClassScope)
1430                                 if (((ClassScope) scope).referenceContext.binding == type) {
1431                                         return true;
1432                                 }
1433                         scope = scope.parent;
1434                 } while (scope != null);
1435                 return false;
1436         }
1437
1438         public boolean isInsideDeprecatedCode() {
1439                 switch (kind) {
1440                 case Scope.BLOCK_SCOPE:
1441                 case Scope.METHOD_SCOPE:
1442                         MethodScope methodScope = methodScope();
1443                         if (!methodScope.isInsideInitializer()) {
1444                                 // check method modifiers to see if deprecated
1445                                 MethodBinding context = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
1446                                 if (context != null && context.isViewedAsDeprecated()) {
1447                                         return true;
1448                                 }
1449                         } else {
1450                                 SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
1451
1452                                 // inside field declaration ? check field modifier to see if
1453                                 // deprecated
1454                                 if (methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl) {
1455                                         for (int i = 0; i < type.fields.length; i++) {
1456                                                 if (type.fields[i].id == methodScope.fieldDeclarationIndex) {
1457                                                         // currently inside this field initialization
1458                                                         if (type.fields[i].isViewedAsDeprecated()) {
1459                                                                 return true;
1460                                                         }
1461                                                         break;
1462                                                 }
1463                                         }
1464                                 }
1465                                 if (type != null && type.isViewedAsDeprecated()) {
1466                                         return true;
1467                                 }
1468                         }
1469                         break;
1470                 case Scope.CLASS_SCOPE:
1471                         ReferenceBinding context = ((ClassScope) this).referenceType().binding;
1472                         if (context != null && context.isViewedAsDeprecated()) {
1473                                 return true;
1474                         }
1475                         break;
1476                 }
1477                 return false;
1478         }
1479
1480         public final boolean isJavaIoSerializable(TypeBinding tb) {
1481                 return tb == getJavaIoSerializable();
1482         }
1483
1484         public final boolean isJavaLangCloneable(TypeBinding tb) {
1485                 return tb == getJavaLangCloneable();
1486         }
1487
1488         public final boolean isJavaLangObject(TypeBinding type) {
1489                 return type.id == T_JavaLangObject;
1490         }
1491
1492         public final MethodScope methodScope() {
1493                 Scope scope = this;
1494                 do {
1495                         if (scope instanceof MethodScope)
1496                                 return (MethodScope) scope;
1497                         scope = scope.parent;
1498                 } while (scope != null);
1499                 return null;
1500         }
1501
1502         // Internal use only
1503         /*
1504          * All methods in visible are acceptable matches for the method in
1505          * question... The methods defined by the receiver type appear before those
1506          * defined by its superclass and so on. We want to find the one which
1507          * matches best.
1508          * 
1509          * Since the receiver type is a class, we know each method's declaring class
1510          * is either the receiver type or one of its superclasses. It is an error if
1511          * the best match is defined by a superclass, when a lesser match is defined
1512          * by the receiver type or a closer superclass.
1513          */
1514         protected final MethodBinding mostSpecificClassMethodBinding(
1515                         MethodBinding[] visible, int visibleSize) {
1516
1517                 MethodBinding method = null;
1518                 MethodBinding previous = null;
1519
1520                 nextVisible: for (int i = 0; i < visibleSize; i++) {
1521                         method = visible[i];
1522
1523                         if (previous != null
1524                                         && method.declaringClass != previous.declaringClass)
1525                                 break; // cannot answer a method farther up the hierarchy than
1526                                                 // the first method found
1527                         previous = method;
1528                         for (int j = 0; j < visibleSize; j++) {
1529                                 if (i == j)
1530                                         continue;
1531                                 MethodBinding next = visible[j];
1532                                 if (!areParametersAssignable(next.parameters, method.parameters))
1533                                         continue nextVisible;
1534                         }
1535                         compilationUnitScope()
1536                                         .recordTypeReferences(method.thrownExceptions);
1537                         return method;
1538                 }
1539                 return new ProblemMethodBinding(visible[0].selector,
1540                                 visible[0].parameters, Ambiguous);
1541         }
1542
1543         // Internal use only
1544         /*
1545          * All methods in visible are acceptable matches for the method in
1546          * question... Since the receiver type is an interface, we ignore the
1547          * possibility that 2 inherited but unrelated superinterfaces may define the
1548          * same method in acceptable but not identical ways... we just take the best
1549          * match that we find since any class which implements the receiver
1550          * interface MUST implement all signatures for the method... in which case
1551          * the best match is correct.
1552          * 
1553          * NOTE: This is different than javac... in the following example, the
1554          * message send of bar(X) in class Y is supposed to be ambiguous. But any
1555          * class which implements the interface I MUST implement both signatures for
1556          * bar. If this class was the receiver of the message send instead of the
1557          * interface I, then no problem would be reported.
1558          * 
1559          * interface I1 { void bar(J j); } interface I2 { // void bar(J j); void
1560          * bar(Object o); } interface I extends I1, I2 {} interface J {}
1561          * 
1562          * class X implements J {}
1563          * 
1564          * class Y extends X { public void foo(I i, X x) { i.bar(x); } }
1565          */
1566         protected final MethodBinding mostSpecificInterfaceMethodBinding(
1567                         MethodBinding[] visible, int visibleSize) {
1568                 MethodBinding method = null;
1569                 nextVisible: for (int i = 0; i < visibleSize; i++) {
1570                         method = visible[i];
1571                         for (int j = 0; j < visibleSize; j++) {
1572                                 if (i == j)
1573                                         continue;
1574                                 MethodBinding next = visible[j];
1575                                 if (!areParametersAssignable(next.parameters, method.parameters))
1576                                         continue nextVisible;
1577                         }
1578                         compilationUnitScope()
1579                                         .recordTypeReferences(method.thrownExceptions);
1580                         return method;
1581                 }
1582                 return new ProblemMethodBinding(visible[0].selector,
1583                                 visible[0].parameters, Ambiguous);
1584         }
1585
1586         public final ClassScope outerMostClassScope() {
1587                 ClassScope lastClassScope = null;
1588                 Scope scope = this;
1589                 do {
1590                         if (scope instanceof ClassScope)
1591                                 lastClassScope = (ClassScope) scope;
1592                         scope = scope.parent;
1593                 } while (scope != null);
1594                 return lastClassScope; // may answer null if no class around
1595         }
1596
1597         public final MethodScope outerMostMethodScope() {
1598                 MethodScope lastMethodScope = null;
1599                 Scope scope = this;
1600                 do {
1601                         if (scope instanceof MethodScope)
1602                                 lastMethodScope = (MethodScope) scope;
1603                         scope = scope.parent;
1604                 } while (scope != null);
1605                 return lastMethodScope; // may answer null if no method around
1606         }
1607
1608         public final CompilationUnitDeclaration referenceCompilationUnit() {
1609                 Scope scope, unitScope = this;
1610                 while ((scope = unitScope.parent) != null)
1611                         unitScope = scope;
1612                 return ((CompilationUnitScope) unitScope).referenceContext;
1613         }
1614
1615         // start position in this scope - for ordering scopes vs. variables
1616         int startIndex() {
1617                 return 0;
1618         }
1619 }