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