858d48022c7dc53b1ddae674152ee14b64f3eeee
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / lookup / Scope.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.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.internal.compiler.ast.CompilationUnitDeclaration;
14 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
15 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
16 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
17 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
18
19 public abstract class Scope
20         implements
21                 BaseTypes,
22                 BindingIds,
23                 CompilerModifiers,
24                 ProblemReasons,
25                 TagBits,
26                 TypeConstants,
27                 TypeIds {
28
29         public Scope parent;
30         public int kind;
31
32         public final static int BLOCK_SCOPE = 1;
33         public final static int METHOD_SCOPE = 2;
34         public final static int CLASS_SCOPE = 3;
35         public final static int COMPILATION_UNIT_SCOPE = 4;
36         protected Scope(int kind, Scope parent) {
37                 this.kind = kind;
38                 this.parent = parent;
39         }
40
41         public abstract ProblemReporter problemReporter();
42
43         // Internal use only
44         protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
45                 if (parameters == arguments)
46                         return true;
47
48                 int length = parameters.length;
49                 if (length != arguments.length)
50                         return false;
51
52                 for (int i = 0; i < length; i++)
53                         if (parameters[i] != arguments[i])
54                                 if (!arguments[i].isCompatibleWith(parameters[i]))
55                                         return false;
56                 return true;
57         }
58
59         /* Answer true if the left type can be assigned to right
60         */
61         public static boolean areTypesCompatible(TypeBinding left, TypeBinding right) {
62                 return left.isCompatibleWith(right);
63         }
64
65         /* Answer an int describing the relationship between the given types.
66         *
67         *               NotRelated 
68         *               EqualOrMoreSpecific : left is compatible with right
69         *               MoreGeneric : right is compatible with left
70         */
71         public static int compareTypes(TypeBinding left, TypeBinding right) {
72                 if (areTypesCompatible(left, right))
73                         return EqualOrMoreSpecific;
74                 if (areTypesCompatible(right, left))
75                         return MoreGeneric;
76                 return NotRelated;
77         }
78
79         /* Answer an int describing the relationship between the given type and unchecked exceptions.
80         *
81         *       NotRelated 
82         *       EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
83         *       MoreGeneric : type is a supertype of an actual unchecked exception type
84         */
85         public int compareUncheckedException(ReferenceBinding type) {
86                 int comparison = compareTypes(type, getJavaLangRuntimeException());
87                 if (comparison != 0) return comparison;
88                 return compareTypes(type, getJavaLangError());
89         }
90
91         public final CompilationUnitScope compilationUnitScope() {
92                 Scope lastScope = null;
93                 Scope scope = this;
94                 do {
95                         lastScope = scope;
96                         scope = scope.parent;
97                 } while (scope != null);
98                 return (CompilationUnitScope) lastScope;
99         }
100
101         public ArrayBinding createArray(TypeBinding type, int dimension) {
102                 if (type.isValidBinding())
103                         return environment().createArrayType(type, dimension);
104                 else
105                         return new ArrayBinding(type, dimension);
106         }
107
108         /* Answer the receiver's enclosing source type.
109         */
110         public final SourceTypeBinding enclosingSourceType() {
111                 Scope scope = this;
112                 do {
113                         if (scope instanceof ClassScope)
114                                 return ((ClassScope) scope).referenceContext.binding;
115                         scope = scope.parent;
116                 } while (scope != null);
117                 return null;
118         }
119         public final LookupEnvironment environment() {
120                 Scope scope, unitScope = this;
121                 while ((scope = unitScope.parent) != null)
122                         unitScope = scope;
123                 return ((CompilationUnitScope) unitScope).environment;
124         }
125
126         // Internal use only
127         public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
128                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
129                         return null; // know it has no member types (nor inherited member types)
130
131                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
132                 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
133                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
134                 if (memberType != null) {
135                         compilationUnitScope().recordTypeReference(memberType); // to record supertypes
136                         if (enclosingSourceType == null
137                                 ? memberType.canBeSeenBy(getCurrentPackage())
138                                 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
139                                 return memberType;
140                         else
141                                 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
142                 }
143                 return null;
144         }
145
146         // Internal use only
147         public MethodBinding findExactMethod(
148                 ReferenceBinding receiverType,
149                 char[] selector,
150                 TypeBinding[] argumentTypes,
151                 InvocationSite invocationSite) {
152
153                 compilationUnitScope().recordTypeReference(receiverType);
154                 compilationUnitScope().recordTypeReferences(argumentTypes);
155                 MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
156                 if (exactMethod != null) {
157                         compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
158                         if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
159                                 return exactMethod;
160                 }
161                 return null;
162         }
163
164         // Internal use only
165         /*      Answer the field binding that corresponds to fieldName.
166                 Start the lookup at the receiverType.
167                 InvocationSite implements
168                         isSuperAccess(); this is used to determine if the discovered field is visible.
169                 Only fields defined by the receiverType or its supertypes are answered;
170                 a field of an enclosing type will not be found using this API.
171         
172                 If no visible field is discovered, null is answered.
173         */
174         public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
175                 if (receiverType.isBaseType()) return null;
176                 if (receiverType.isArrayType()) {
177                         if (CharOperation.equals(fieldName, LENGTH))
178                                 return ArrayBinding.LengthField;
179                         return null;
180                 }
181
182                 compilationUnitScope().recordTypeReference(receiverType);
183
184                 ReferenceBinding currentType = (ReferenceBinding) receiverType;
185                 if (!currentType.canBeSeenBy(this))
186                         return new ProblemFieldBinding(currentType, fieldName, NotVisible);
187                 // *** Need a new problem id - TypeNotVisible?
188
189                 FieldBinding field = currentType.getField(fieldName);
190                 if (field != null) {
191                         if (field.canBeSeenBy(currentType, invocationSite, this))
192                                 return field;
193                         else
194                                 return new ProblemFieldBinding(field.declaringClass, fieldName, NotVisible);
195                 }
196                 // collect all superinterfaces of receiverType until the field is found in a supertype
197                 ReferenceBinding[][] interfacesToVisit = null;
198                 int lastPosition = -1;
199                 FieldBinding visibleField = null;
200                 boolean keepLooking = true;
201                 boolean notVisible = false;
202                 // we could hold onto the not visible field for extra error reporting
203                 while (keepLooking) {
204                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
205                         if (itsInterfaces != NoSuperInterfaces) {
206                                 if (interfacesToVisit == null)
207                                         interfacesToVisit = new ReferenceBinding[5][];
208                                 if (++lastPosition == interfacesToVisit.length)
209                                         System.arraycopy(
210                                                 interfacesToVisit,
211                                                 0,
212                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
213                                                 0,
214                                                 lastPosition);
215                                 interfacesToVisit[lastPosition] = itsInterfaces;
216                         }
217                         if ((currentType = currentType.superclass()) == null)
218                                 break;
219
220                         if ((field = currentType.getField(fieldName)) != null) {
221                                 keepLooking = false;
222                                 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
223                                         if (visibleField == null)
224                                                 visibleField = field;
225                                         else
226                                                 return new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
227                                 } else {
228                                         notVisible = true;
229                                 }
230                         }
231                 }
232
233                 // walk all visible interfaces to find ambiguous references
234                 if (interfacesToVisit != null) {
235                         ProblemFieldBinding ambiguous = null;
236                         done : for (int i = 0; i <= lastPosition; i++) {
237                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
238                                 for (int j = 0, length = interfaces.length; j < length; j++) {
239                                         ReferenceBinding anInterface = interfaces[j];
240                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
241                                                 // if interface as not already been visited
242                                                 anInterface.tagBits |= InterfaceVisited;
243                                                 if ((field = anInterface.getField(fieldName)) != null) {
244                                                         if (visibleField == null) {
245                                                                 visibleField = field;
246                                                         } else {
247                                                                 ambiguous = new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
248                                                                 break done;
249                                                         }
250                                                 } else {
251                                                         ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
252                                                         if (itsInterfaces != NoSuperInterfaces) {
253                                                                 if (++lastPosition == interfacesToVisit.length)
254                                                                         System.arraycopy(
255                                                                                 interfacesToVisit,
256                                                                                 0,
257                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
258                                                                                 0,
259                                                                                 lastPosition);
260                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
261                                                         }
262                                                 }
263                                         }
264                                 }
265                         }
266
267                         // bit reinitialization
268                         for (int i = 0; i <= lastPosition; i++) {
269                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
270                                 for (int j = 0, length = interfaces.length; j < length; j++)
271                                         interfaces[j].tagBits &= ~InterfaceVisited;
272                         }
273                         if (ambiguous != null)
274                                 return ambiguous;
275                 }
276
277                 if (visibleField != null)
278                         return visibleField;
279                 if (notVisible)
280                         return new ProblemFieldBinding(currentType, fieldName, NotVisible);
281                 return null;
282         }
283
284         // Internal use only
285         public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
286                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
287                         return null; // know it has no member types (nor inherited member types)
288
289                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
290                 PackageBinding currentPackage = getCurrentPackage();
291                 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
292                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
293                 if (memberType != null) {
294                         compilationUnitScope().recordTypeReference(memberType); // to record supertypes
295                         if (enclosingSourceType == null
296                                 ? memberType.canBeSeenBy(currentPackage)
297                                 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
298                                 return memberType;
299                         else
300                                 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
301                 }
302
303                 // collect all superinterfaces of receiverType until the memberType is found in a supertype
304                 ReferenceBinding currentType = enclosingType;
305                 ReferenceBinding[][] interfacesToVisit = null;
306                 int lastPosition = -1;
307                 ReferenceBinding visibleMemberType = null;
308                 boolean keepLooking = true;
309                 ReferenceBinding notVisible = null;
310                 // we could hold onto the not visible field for extra error reporting
311                 while (keepLooking) {
312                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
313                         if (itsInterfaces != NoSuperInterfaces) {
314                                 if (interfacesToVisit == null)
315                                         interfacesToVisit = new ReferenceBinding[5][];
316                                 if (++lastPosition == interfacesToVisit.length)
317                                         System.arraycopy(
318                                                 interfacesToVisit,
319                                                 0,
320                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
321                                                 0,
322                                                 lastPosition);
323                                 interfacesToVisit[lastPosition] = itsInterfaces;
324                         }
325                         if ((currentType = currentType.superclass()) == null)
326                                 break;
327
328                         compilationUnitScope().recordReference(currentType.compoundName, typeName);
329                         if ((memberType = currentType.getMemberType(typeName)) != null) {
330                                 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
331                                 keepLooking = false;
332                                 if (enclosingSourceType == null
333                                         ? memberType.canBeSeenBy(currentPackage)
334                                         : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
335                                                 if (visibleMemberType == null)
336                                                         visibleMemberType = memberType;
337                                                 else
338                                                         return new ProblemReferenceBinding(typeName, Ambiguous);
339                                 } else {
340                                         notVisible = memberType;
341                                 }
342                         }
343                 }
344                 // walk all visible interfaces to find ambiguous references
345                 if (interfacesToVisit != null) {
346                         ProblemReferenceBinding ambiguous = null;
347                         done : for (int i = 0; i <= lastPosition; i++) {
348                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
349                                 for (int j = 0, length = interfaces.length; j < length; j++) {
350                                         ReferenceBinding anInterface = interfaces[j];
351                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
352                                                 // if interface as not already been visited
353                                                 anInterface.tagBits |= InterfaceVisited;
354                                                 compilationUnitScope().recordReference(anInterface.compoundName, typeName);
355                                                 if ((memberType = anInterface.getMemberType(typeName)) != null) {
356                                                         compilationUnitScope().recordTypeReference(memberType); // to record supertypes
357                                                         if (visibleMemberType == null) {
358                                                                 visibleMemberType = memberType;
359                                                         } else {
360                                                                 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
361                                                                 break done;
362                                                         }
363                                                 } else {
364                                                         ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
365                                                         if (itsInterfaces != NoSuperInterfaces) {
366                                                                 if (++lastPosition == interfacesToVisit.length)
367                                                                         System.arraycopy(
368                                                                                 interfacesToVisit,
369                                                                                 0,
370                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
371                                                                                 0,
372                                                                                 lastPosition);
373                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
374                                                         }
375                                                 }
376                                         }
377                                 }
378                         }
379
380                         // bit reinitialization
381                         for (int i = 0; i <= lastPosition; i++) {
382                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
383                                 for (int j = 0, length = interfaces.length; j < length; j++)
384                                         interfaces[j].tagBits &= ~InterfaceVisited;
385                         }
386                         if (ambiguous != null)
387                                 return ambiguous;
388                 }
389                 if (visibleMemberType != null)
390                         return visibleMemberType;
391                 if (notVisible != null)
392                         return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
393                 return null;
394         }
395
396         // Internal use only
397         public MethodBinding findMethod(
398                 ReferenceBinding receiverType,
399                 char[] selector,
400                 TypeBinding[] argumentTypes,
401                 InvocationSite invocationSite) {
402
403                 ReferenceBinding currentType = receiverType;
404                 MethodBinding matchingMethod = null;
405                 ObjectVector found = new ObjectVector();
406
407                 compilationUnitScope().recordTypeReference(receiverType);
408                 compilationUnitScope().recordTypeReferences(argumentTypes);
409
410                 if (currentType.isInterface()) {
411                         MethodBinding[] currentMethods = currentType.getMethods(selector);
412                         int currentLength = currentMethods.length;
413                         if (currentLength == 1) {
414                                 matchingMethod = currentMethods[0];
415                         } else if (currentLength > 1) {
416                                 found.addAll(currentMethods);
417                         }
418                         matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
419                         currentType = getJavaLangObject();
420                 }
421
422                 // superclass lookup
423                 ReferenceBinding classHierarchyStart = currentType;
424                 while (currentType != null) {
425                         MethodBinding[] currentMethods = currentType.getMethods(selector);
426                         int currentLength = currentMethods.length;
427                         if (currentLength == 1 && matchingMethod == null && found.size == 0) {
428                                 matchingMethod = currentMethods[0];
429                         } else if (currentLength > 0) {
430                                 if (matchingMethod != null) {
431                                         found.add(matchingMethod);
432                                         matchingMethod = null;
433                                 }
434                                 found.addAll(currentMethods);
435                         }
436                         currentType = currentType.superclass();
437                 }
438
439                 int foundSize = found.size;
440                 if (foundSize == 0) {
441                         if (matchingMethod != null && areParametersAssignable(matchingMethod.parameters, argumentTypes))
442                                 return matchingMethod;
443                         return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
444                 }
445
446                 MethodBinding[] candidates = new MethodBinding[foundSize];
447                 int candidatesCount = 0;
448                 // argument type compatibility check
449                 for (int i = 0; i < foundSize; i++) {
450                         MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
451                         if (areParametersAssignable(methodBinding.parameters, argumentTypes))
452                                 candidates[candidatesCount++] = methodBinding;
453                 }
454                 if (candidatesCount == 1) {
455                         compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
456                         return candidates[0]; // have not checked visibility
457                 }
458                 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
459                         MethodBinding interfaceMethod =
460                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
461                         if (interfaceMethod != null) return interfaceMethod;
462
463                         int argLength = argumentTypes.length;
464                         foundSize = found.size;
465                         nextMethod : for (int i = 0; i < foundSize; i++) {
466                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
467                                 TypeBinding[] params = methodBinding.parameters;
468                                 int paramLength = params.length;
469                                 nextArg: for (int a = 0; a < argLength; a++) {
470                                         TypeBinding arg = argumentTypes[a];
471                                         for (int p = 0; p < paramLength; p++)
472                                                 if (params[p] == arg)
473                                                         continue nextArg;
474                                         continue nextMethod;
475                                 }
476                                 return methodBinding;
477                         }
478                         return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
479                 }
480
481                 // visibility check
482                 int visiblesCount = 0;
483                 for (int i = 0; i < candidatesCount; i++) {
484                         MethodBinding methodBinding = candidates[i];
485                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
486                                 if (visiblesCount != i) {
487                                         candidates[i] = null;
488                                         candidates[visiblesCount] = methodBinding;
489                                 }
490                                 visiblesCount++;
491                         }
492                 }
493                 if (visiblesCount == 1) {
494                         compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
495                         return candidates[0];
496                 }
497                 if (visiblesCount == 0) {
498                         MethodBinding interfaceMethod =
499                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
500                         if (interfaceMethod != null) return interfaceMethod;
501                         return new ProblemMethodBinding(candidates[0].selector, argumentTypes, candidates[0].declaringClass, NotVisible);
502                 }       
503                 if (candidates[0].declaringClass.isClass()) {
504                         return mostSpecificClassMethodBinding(candidates, visiblesCount);
505                 } else {
506                         return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
507                 }
508         }
509
510         // abstract method lookup lookup (since maybe missing default abstract methods)
511         public MethodBinding findDefaultAbstractMethod(
512                 ReferenceBinding receiverType, 
513                 char[] selector,
514                 TypeBinding[] argumentTypes,
515                 InvocationSite invocationSite,
516                 ReferenceBinding classHierarchyStart,
517                 MethodBinding matchingMethod,
518                 ObjectVector found) {
519
520                 int startFoundSize = found.size;
521                 ReferenceBinding currentType = classHierarchyStart;
522                 while (currentType != null) {
523                         matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
524                         currentType = currentType.superclass();
525                 }
526                 int foundSize = found.size;
527                 if (foundSize == startFoundSize) return matchingMethod; // maybe null
528
529                 MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
530                 int candidatesCount = 0;
531                 // argument type compatibility check
532                 for (int i = startFoundSize; i < foundSize; i++) {
533                         MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
534                         if (areParametersAssignable(methodBinding.parameters, argumentTypes))
535                                 candidates[candidatesCount++] = methodBinding;
536                 }
537                 if (candidatesCount == 1) {
538                         compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
539                         return candidates[0]; 
540                 }
541                 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
542                         int argLength = argumentTypes.length;
543                         nextMethod : for (int i = 0; i < foundSize; i++) {
544                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
545                                 TypeBinding[] params = methodBinding.parameters;
546                                 int paramLength = params.length;
547                                 nextArg: for (int a = 0; a < argLength; a++) {
548                                         TypeBinding arg = argumentTypes[a];
549                                         for (int p = 0; p < paramLength; p++)
550                                                 if (params[p] == arg)
551                                                         continue nextArg;
552                                         continue nextMethod;
553                                 }
554                                 return methodBinding;
555                         }
556                         return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
557                 }
558                 // no need to check for visibility - interface methods are public
559                 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
560         }
561
562         public MethodBinding findMethodInSuperInterfaces(
563                 ReferenceBinding currentType,
564                 char[] selector,
565                 ObjectVector found,
566                 MethodBinding matchingMethod) {
567
568                 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
569                 if (itsInterfaces != NoSuperInterfaces) {
570                         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
571                         int lastPosition = -1;
572                         if (++lastPosition == interfacesToVisit.length)
573                                 System.arraycopy(
574                                         interfacesToVisit, 0,
575                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
576                                         lastPosition);
577                         interfacesToVisit[lastPosition] = itsInterfaces;
578
579                         for (int i = 0; i <= lastPosition; i++) {
580                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
581                                 for (int j = 0, length = interfaces.length; j < length; j++) {
582                                         currentType = interfaces[j];
583                                         if ((currentType.tagBits & InterfaceVisited) == 0) {
584                                                 // if interface as not already been visited
585                                                 currentType.tagBits |= InterfaceVisited;
586
587                                                 MethodBinding[] currentMethods = currentType.getMethods(selector);
588                                                 int currentLength = currentMethods.length;
589                                                 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
590                                                         matchingMethod = currentMethods[0];
591                                                 } else if (currentLength > 0) {
592                                                         if (matchingMethod != null) {
593                                                                 found.add(matchingMethod);
594                                                                 matchingMethod = null;
595                                                         }
596                                                         found.addAll(currentMethods);
597                                                 }
598                                                 itsInterfaces = currentType.superInterfaces();
599                                                 if (itsInterfaces != NoSuperInterfaces) {
600                                                         if (++lastPosition == interfacesToVisit.length)
601                                                                 System.arraycopy(
602                                                                         interfacesToVisit, 0,
603                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
604                                                                         lastPosition);
605                                                         interfacesToVisit[lastPosition] = itsInterfaces;
606                                                 }
607                                         }
608                                 }
609                         }
610
611                         // bit reinitialization
612                         for (int i = 0; i <= lastPosition; i++) {
613                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
614                                 for (int j = 0, length = interfaces.length; j < length; j++)
615                                         interfaces[j].tagBits &= ~InterfaceVisited;
616                         }
617                 }
618                 return matchingMethod;
619         }
620         
621         // Internal use only
622         public MethodBinding findMethodForArray(
623                 ArrayBinding receiverType,
624                 char[] selector,
625                 TypeBinding[] argumentTypes,
626                 InvocationSite invocationSite) {
627
628                 ReferenceBinding object = getJavaLangObject();
629                 MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
630                 if (methodBinding != null) {
631                         // handle the method clone() specially... cannot be protected or throw exceptions
632                         if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
633                                 return new MethodBinding(
634                                         (methodBinding.modifiers ^ AccProtected) | AccPublic,
635                                         CLONE,
636                                         methodBinding.returnType,
637                                         argumentTypes,
638                                         null,
639                                         object);
640                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
641                                 return methodBinding;
642                 }
643                 // answers closest approximation, may not check argumentTypes or visibility
644                 methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
645                 if (methodBinding == null)
646                         return new ProblemMethodBinding(selector, argumentTypes, NotFound);
647                 if (methodBinding.isValidBinding()) {
648                         if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
649                                 return new ProblemMethodBinding(
650                                         methodBinding,
651                                         selector,
652                                         argumentTypes,
653                                         NotFound);
654                         if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
655                                 return new ProblemMethodBinding(
656                                         selector,
657                                         argumentTypes,
658                                         methodBinding.declaringClass,
659                                         NotVisible);
660                 }
661                 return methodBinding;
662         }
663
664         // Internal use only
665         public ReferenceBinding findType(
666                 char[] typeName,
667                 PackageBinding declarationPackage,
668                 PackageBinding invocationPackage) {
669
670                 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
671                 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
672                 if (typeBinding == null)
673                         return null;
674
675                 if (typeBinding.isValidBinding()) {
676 // Not convinced that this is necessary
677 //                      compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
678                         if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
679                                 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
680                 }
681                 return typeBinding;
682         }
683
684         public TypeBinding getBaseType(char[] name) {
685                 // list should be optimized (with most often used first)
686                 int length = name.length;
687                 if (length > 2 && length < 8) {
688                         switch (name[0]) {
689                                 case 'i' :
690                                         if (length == 3 && name[1] == 'n' && name[2] == 't')
691                                                 return IntBinding;
692                                         break;
693                                 case 'v' :
694                                         if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
695                                                 return VoidBinding;
696                                         break;
697                                 case 'b' :
698                                         if (length == 7
699                                                 && name[1] == 'o'
700                                                 && name[2] == 'o'
701                                                 && name[3] == 'l'
702                                                 && name[4] == 'e'
703                                                 && name[5] == 'a'
704                                                 && name[6] == 'n')
705                                                 return BooleanBinding;
706                                         if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
707                                                 return ByteBinding;
708                                         break;
709                                 case 'c' :
710                                         if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
711                                                 return CharBinding;
712                                         break;
713                                 case 'd' :
714                                         if (length == 6
715                                                 && name[1] == 'o'
716                                                 && name[2] == 'u'
717                                                 && name[3] == 'b'
718                                                 && name[4] == 'l'
719                                                 && name[5] == 'e')
720                                                 return DoubleBinding;
721                                         break;
722                                 case 'f' :
723                                         if (length == 5
724                                                 && name[1] == 'l'
725                                                 && name[2] == 'o'
726                                                 && name[3] == 'a'
727                                                 && name[4] == 't')
728                                                 return FloatBinding;
729                                         break;
730                                 case 'l' :
731                                         if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
732                                                 return LongBinding;
733                                         break;
734                                 case 's' :
735                                         if (length == 5
736                                                 && name[1] == 'h'
737                                                 && name[2] == 'o'
738                                                 && name[3] == 'r'
739                                                 && name[4] == 't')
740                                                 return ShortBinding;
741                         }
742                 }
743                 return null;
744         }
745
746         public final PackageBinding getCurrentPackage() {
747                 Scope scope, unitScope = this;
748                 while ((scope = unitScope.parent) != null)
749                         unitScope = scope;
750                 return ((CompilationUnitScope) unitScope).fPackage;
751         }
752
753         public final ReferenceBinding getJavaIoSerializable() {
754                 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
755                 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
756                 if (type != null) return type;
757         
758                 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
759                 return null; // will not get here since the above error aborts the compilation
760         }
761
762         public final ReferenceBinding getJavaLangClass() {
763                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
764                 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
765                 if (type != null) return type;
766         
767                 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
768                 return null; // will not get here since the above error aborts the compilation
769         }
770
771         public final ReferenceBinding getJavaLangCloneable() {
772                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
773                 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
774                 if (type != null) return type;
775         
776                 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
777                 return null; // will not get here since the above error aborts the compilation
778         }
779
780         public final ReferenceBinding getJavaLangError() {
781                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
782                 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
783                 if (type != null) return type;
784         
785                 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
786                 return null; // will not get here since the above error aborts the compilation
787         }
788
789         public final ReferenceBinding getJavaLangAssertionError() {
790                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
791                 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
792                 if (type != null) return type;
793                 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
794                 return null; // will not get here since the above error aborts the compilation
795         }
796
797         public final ReferenceBinding getJavaLangObject() {
798                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
799                 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
800                 if (type != null) return type;
801         
802                 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
803                 return null; // will not get here since the above error aborts the compilation
804         }
805
806         public final ReferenceBinding getJavaLangRuntimeException() {
807                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
808                 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
809                 if (type != null) return type;
810         
811                 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
812                 return null; // will not get here since the above error aborts the compilation
813         }
814
815         public final ReferenceBinding getJavaLangString() {
816                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
817                 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
818                 if (type != null) return type;
819         
820                 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
821                 return null; // will not get here since the above error aborts the compilation
822         }
823
824         public final ReferenceBinding getJavaLangThrowable() {
825                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
826                 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
827                 if (type != null) return type;
828         
829                 problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
830                 return null; // will not get here since the above error aborts the compilation
831         }
832
833         /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
834         */
835         public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
836                 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
837                 if (memberType != null) return memberType;
838                 return new ProblemReferenceBinding(typeName, NotFound);
839         }
840
841         /* Answer the type binding corresponding to the compoundName.
842         *
843         * NOTE: If a problem binding is returned, senders should extract the compound name
844         * from the binding & not assume the problem applies to the entire compoundName.
845         */
846         public final TypeBinding getType(char[][] compoundName) {
847                 int typeNameLength = compoundName.length;
848                 if (typeNameLength == 1) {
849                         // Would like to remove this test and require senders to specially handle base types
850                         TypeBinding binding = getBaseType(compoundName[0]);
851                         if (binding != null) return binding;
852                 }
853
854                 compilationUnitScope().recordQualifiedReference(compoundName);
855                 Binding binding =
856                         getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
857                 if (binding == null)
858                         return new ProblemReferenceBinding(compoundName[0], NotFound);
859                 if (!binding.isValidBinding())
860                         return (ReferenceBinding) binding;
861
862                 int currentIndex = 1;
863                 boolean checkVisibility = false;
864                 if (binding instanceof PackageBinding) {
865                         PackageBinding packageBinding = (PackageBinding) binding;
866                         while (currentIndex < typeNameLength) {
867                                 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
868                                 if (binding == null)
869                                         return new ProblemReferenceBinding(
870                                                 CharOperation.subarray(compoundName, 0, currentIndex),
871                                                 NotFound);
872                                 if (!binding.isValidBinding())
873                                         return new ProblemReferenceBinding(
874                                                 CharOperation.subarray(compoundName, 0, currentIndex),
875                                                 binding.problemId());
876                                 if (!(binding instanceof PackageBinding))
877                                         break;
878                                 packageBinding = (PackageBinding) binding;
879                         }
880                         if (binding instanceof PackageBinding)
881                                 return new ProblemReferenceBinding(
882                                         CharOperation.subarray(compoundName, 0, currentIndex),
883                                         NotFound);
884                         checkVisibility = true;
885                 }
886
887                 // binding is now a ReferenceBinding
888                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
889                 compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
890                 if (checkVisibility) // handles the fall through case
891                         if (!typeBinding.canBeSeenBy(this))
892                                 return new ProblemReferenceBinding(
893                                         CharOperation.subarray(compoundName, 0, currentIndex),
894                                         typeBinding,
895                                         NotVisible);
896
897                 while (currentIndex < typeNameLength) {
898                         typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
899                         if (!typeBinding.isValidBinding())
900                                 return new ProblemReferenceBinding(
901                                         CharOperation.subarray(compoundName, 0, currentIndex),
902                                         typeBinding.problemId());
903                 }
904                 return typeBinding;
905         }
906
907         /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
908         * The name provided is a simple source name (e.g., "Object" , "Point", ...)
909         */
910         // The return type of this method could be ReferenceBinding if we did not answer base types.
911         // NOTE: We could support looking for Base Types last in the search, however any code using
912         // this feature would be extraordinarily slow.  Therefore we don't do this
913         public final TypeBinding getType(char[] name) {
914                 // Would like to remove this test and require senders to specially handle base types
915                 TypeBinding binding = getBaseType(name);
916                 if (binding != null) return binding;
917                 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
918         }
919
920         // Added for code assist... NOT Public API
921         public final Binding getTypeOrPackage(char[][] compoundName) {
922                 int nameLength = compoundName.length;
923                 if (nameLength == 1) {
924                         TypeBinding binding = getBaseType(compoundName[0]);
925                         if (binding != null) return binding;
926                 }
927                 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
928                 if (!binding.isValidBinding()) return binding;
929
930                 int currentIndex = 1;
931                 boolean checkVisibility = false;
932                 if (binding instanceof PackageBinding) {
933                         PackageBinding packageBinding = (PackageBinding) binding;
934
935                         while (currentIndex < nameLength) {
936                                 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
937                                 if (binding == null)
938                                         return new ProblemReferenceBinding(
939                                                 CharOperation.subarray(compoundName, 0, currentIndex),
940                                                 NotFound);
941                                 if (!binding.isValidBinding())
942                                         return new ProblemReferenceBinding(
943                                                 CharOperation.subarray(compoundName, 0, currentIndex),
944                                                 binding.problemId());
945                                 if (!(binding instanceof PackageBinding))
946                                         break;
947                                 packageBinding = (PackageBinding) binding;
948                         }
949                         if (binding instanceof PackageBinding) return binding;
950                         checkVisibility = true;
951                 }
952                 // binding is now a ReferenceBinding
953                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
954                 if (checkVisibility) // handles the fall through case
955                         if (!typeBinding.canBeSeenBy(this))
956                                 return new ProblemReferenceBinding(
957                                         CharOperation.subarray(compoundName, 0, currentIndex),
958                                         typeBinding,
959                                         NotVisible);
960
961                 while (currentIndex < nameLength) {
962                         typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
963                         // checks visibility
964                         if (!typeBinding.isValidBinding())
965                                 return new ProblemReferenceBinding(
966                                         CharOperation.subarray(compoundName, 0, currentIndex),
967                                         typeBinding.problemId());
968                 }
969                 return typeBinding;
970         }
971
972         /* Internal use only 
973         */
974         final Binding getTypeOrPackage(char[] name, int mask) {
975                 
976                 Scope scope = this;
977                 ReferenceBinding foundType = null;
978                 if ((mask & TYPE) == 0) {
979                         Scope next = scope;
980                         while ((next = scope.parent) != null)
981                                 scope = next;
982                 } else {
983                         done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
984                                 switch (scope.kind) {
985                                         case METHOD_SCOPE :
986                                         case BLOCK_SCOPE :
987                                                 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
988                                                 if (localType != null) {
989                                                         if (foundType != null && foundType != localType)
990                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
991                                                         return localType;
992                                                 }
993                                                 break;
994                                         case CLASS_SCOPE :
995                                                 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
996                                                 if (CharOperation.equals(sourceType.sourceName, name)) {
997                                                         if (foundType != null && foundType != sourceType)
998                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
999                                                         return sourceType;
1000                                                 }
1001
1002                                                 ReferenceBinding memberType = findMemberType(name, sourceType);
1003                                                 if (memberType != null) { // skip it if we did not find anything
1004                                                         if (memberType.problemId() == Ambiguous) {
1005                                                                 if (foundType == null || foundType.problemId() == NotVisible)
1006                                                                         // supercedes any potential InheritedNameHidesEnclosingName problem
1007                                                                         return memberType;
1008                                                                 else
1009                                                                         // make the user qualify the type, likely wants the first inherited type
1010                                                                         return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1011                                                         }
1012                                                         if (memberType.isValidBinding()) {
1013                                                                 if (sourceType == memberType.enclosingType()
1014                                                                         || environment().options.complianceLevel >= CompilerOptions.JDK1_4) {
1015                                                                         // found a valid type in the 'immediate' scope (ie. not inherited)
1016                                                                         // OR in 1.4 mode (inherited shadows enclosing)
1017                                                                         if (foundType == null)
1018                                                                                 return memberType;
1019                                                                         if (foundType.isValidBinding())
1020                                                                                 // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
1021                                                                                 if (foundType != memberType)
1022                                                                                         return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1023                                                                 }
1024                                                         }
1025                                                         if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
1026                                                                 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
1027                                                                 foundType = memberType;
1028                                                 }
1029                                                 break;
1030                                         case COMPILATION_UNIT_SCOPE :
1031                                                 break done;
1032                                 }
1033                                 scope = scope.parent;
1034                         }
1035                         if (foundType != null && foundType.problemId() != NotVisible)
1036                                 return foundType;
1037                 }
1038
1039                 // at this point the scope is a compilation unit scope
1040                 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1041                 // ask for the imports + name
1042                 if ((mask & TYPE) != 0) {
1043                         // check single type imports.
1044                         ImportBinding[] imports = unitScope.imports;
1045                         if (imports != null){
1046                                 // copy the list, since single type imports are removed if they cannot be resolved
1047                                 for (int i = 0, length = imports.length; i < length; i++) {
1048                                         ImportBinding typeImport = imports[i];
1049                                         if (!typeImport.onDemand)
1050                                                 if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name))
1051                                                         if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1052                                                                 if (typeImport.reference != null) typeImport.reference.used = true;
1053                                                                 return typeImport.resolvedImport; // already know its visible
1054                                                         }
1055                                 }
1056                         }
1057                         // check if the name is in the current package (answer the problem binding unless its not found in which case continue to look)
1058                         ReferenceBinding type = findType(name, unitScope.fPackage, unitScope.fPackage); // is always visible
1059                         if (type != null) return type;
1060
1061                         // check on demand imports
1062                         boolean foundInImport = false;
1063                         if (imports != null){
1064                                 for (int i = 0, length = imports.length; i < length; i++) {
1065                                         ImportBinding someImport = imports[i];
1066                                         if (someImport.onDemand) {
1067                                                 Binding resolvedImport = someImport.resolvedImport;
1068                                                 ReferenceBinding temp =
1069                                                         (resolvedImport instanceof PackageBinding)
1070                                                                 ? findType(name, (PackageBinding) resolvedImport, unitScope.fPackage)
1071                                                                 : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
1072                                                 if (temp != null && temp.isValidBinding()) {
1073                                                         if (someImport.reference != null) someImport.reference.used = true;
1074                                                         if (foundInImport)
1075                                                                 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1076                                                                 return new ProblemReferenceBinding(name, Ambiguous);
1077                                                         type = temp;
1078                                                         foundInImport = true;
1079                                                 }
1080                                         }
1081                                 }
1082                         }
1083                         if (type != null)
1084                                 return type;
1085                 }
1086                 // see if the name is a package
1087                 if ((mask & PACKAGE) != 0) {
1088                         compilationUnitScope().recordSimpleReference(name);
1089                         PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
1090                         if (packageBinding != null)
1091                                 return packageBinding;
1092                 }
1093
1094                 compilationUnitScope().recordSimpleReference(name);
1095                 // Answer error binding -- could not find name
1096                 if (foundType != null){
1097                         return foundType;
1098                 }
1099                 return new ProblemReferenceBinding(name, NotFound);
1100         }
1101
1102         /* Answer whether the type is defined in the same compilation unit as the receiver
1103         */
1104         public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1105                 // find the outer most enclosing type
1106                 ReferenceBinding enclosingType = type;
1107                 while ((type = enclosingType.enclosingType()) != null)
1108                         enclosingType = type;
1109
1110                 // find the compilation unit scope
1111                 Scope scope, unitScope = this;
1112                 while ((scope = unitScope.parent) != null)
1113                         unitScope = scope;
1114
1115                 // test that the enclosingType is not part of the compilation unit
1116                 SourceTypeBinding[] topLevelTypes =
1117                         ((CompilationUnitScope) unitScope).topLevelTypes;
1118                 for (int i = topLevelTypes.length; --i >= 0;)
1119                         if (topLevelTypes[i] == enclosingType)
1120                                 return true;
1121                 return false;
1122         }
1123
1124         public final boolean isJavaIoSerializable(TypeBinding tb) {
1125                 //a first -none optimized version-...:-)....
1126                 //please modify as needed
1127
1128                 return tb == getJavaIoSerializable();
1129         }
1130
1131         public final boolean isJavaLangCloneable(TypeBinding tb) {
1132                 //a first -none optimized version-...:-)....
1133                 //please modify as needed
1134
1135                 return tb == getJavaLangCloneable();
1136         }
1137
1138         public final boolean isJavaLangObject(TypeBinding type) {
1139                 return type.id == T_JavaLangObject;
1140         }
1141
1142         public final MethodScope methodScope() {
1143                 Scope scope = this;
1144                 do {
1145                         if (scope instanceof MethodScope)
1146                                 return (MethodScope) scope;
1147                         scope = scope.parent;
1148                 } while (scope != null);
1149                 return null;
1150         }
1151
1152         // Internal use only
1153         /* All methods in visible are acceptable matches for the method in question...
1154         * The methods defined by the receiver type appear before those defined by its
1155         * superclass and so on. We want to find the one which matches best.
1156         *
1157         * Since the receiver type is a class, we know each method's declaring class is
1158         * either the receiver type or one of its superclasses. It is an error if the best match
1159         * is defined by a superclass, when a lesser match is defined by the receiver type
1160         * or a closer superclass.
1161         */
1162         protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
1163
1164                 MethodBinding method = null;
1165                 MethodBinding previous = null;
1166
1167                 nextVisible : for (int i = 0; i < visibleSize; i++) {
1168                         method = visible[i];
1169                                                 
1170                         if (previous != null && method.declaringClass != previous.declaringClass)
1171                                 break; // cannot answer a method farther up the hierarchy than the first method found
1172                         previous = method;
1173                         for (int j = 0; j < visibleSize; j++) {
1174                                 if (i == j) continue;
1175                                 MethodBinding next = visible[j];
1176                                 if (!areParametersAssignable(next.parameters, method.parameters))
1177                                         continue nextVisible;
1178                         }
1179                         compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1180                         return method;
1181                 }
1182                 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1183         }
1184
1185         // Internal use only
1186         /* All methods in visible are acceptable matches for the method in question...
1187         * Since the receiver type is an interface, we ignore the possibility that 2 inherited
1188         * but unrelated superinterfaces may define the same method in acceptable but
1189         * not identical ways... we just take the best match that we find since any class which
1190         * implements the receiver interface MUST implement all signatures for the method...
1191         * in which case the best match is correct.
1192         *
1193         * NOTE: This is different than javac... in the following example, the message send of
1194         * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
1195         * interface I MUST implement both signatures for bar. If this class was the receiver of
1196         * the message send instead of the interface I, then no problem would be reported.
1197         *
1198         interface I1 {
1199                 void bar(J j);
1200         }
1201         interface I2 {
1202         //      void bar(J j);
1203                 void bar(Object o);
1204         }
1205         interface I extends I1, I2 {}
1206         interface J {}
1207         
1208         class X implements J {}
1209         
1210         class Y extends X {
1211                 public void foo(I i, X x) { i.bar(x); }
1212         }
1213         */
1214         protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
1215                 MethodBinding method = null;
1216                 nextVisible : for (int i = 0; i < visibleSize; i++) {
1217                         method = visible[i];
1218                         for (int j = 0; j < visibleSize; j++) {
1219                                 if (i == j) continue;
1220                                 MethodBinding next = visible[j];
1221                                 if (!areParametersAssignable(next.parameters, method.parameters))
1222                                         continue nextVisible;
1223                         }
1224                         compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1225                         return method;
1226                 }
1227                 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1228         }
1229
1230         public final ClassScope outerMostClassScope() {
1231                 ClassScope lastClassScope = null;
1232                 Scope scope = this;
1233                 do {
1234                         if (scope instanceof ClassScope)
1235                                 lastClassScope = (ClassScope) scope;
1236                         scope = scope.parent;
1237                 } while (scope != null);
1238                 return lastClassScope; // may answer null if no class around
1239         }
1240
1241         public final MethodScope outerMostMethodScope() {
1242                 MethodScope lastMethodScope = null;
1243                 Scope scope = this;
1244                 do {
1245                         if (scope instanceof MethodScope)
1246                                 lastMethodScope = (MethodScope) scope;
1247                         scope = scope.parent;
1248                 } while (scope != null);
1249                 return lastMethodScope; // may answer null if no method around
1250         }
1251
1252         public final CompilationUnitDeclaration referenceCompilationUnit() {
1253                 Scope scope, unitScope = this;
1254                 while ((scope = unitScope.parent) != null)
1255                         unitScope = scope;
1256                 return ((CompilationUnitScope) unitScope).referenceContext;
1257         }
1258         // start position in this scope - for ordering scopes vs. variables
1259         int startIndex() {
1260                 return 0;
1261         }
1262 }