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