Makefile fixup
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / lookup / Scope.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 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 org.eclipse.jdt.internal.compiler.lookup;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ast.*;
15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
16 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
17 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
18 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
19 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
20 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
21
22 public abstract class Scope
23         implements BaseTypes, BindingIds, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
24
25         public final static int BLOCK_SCOPE = 1;
26         public final static int METHOD_SCOPE = 2;
27         public final static int CLASS_SCOPE = 3;
28         public final static int COMPILATION_UNIT_SCOPE = 4;
29
30         public int kind;
31         public Scope parent;
32
33         protected Scope(int kind, Scope parent) {
34                 this.kind = kind;
35                 this.parent = parent;
36         }
37
38         /* Answer an int describing the relationship between the given types.
39         *
40         *               NotRelated 
41         *               EqualOrMoreSpecific : left is compatible with right
42         *               MoreGeneric : right is compatible with left
43         */
44         public static int compareTypes(TypeBinding left, TypeBinding right) {
45                 if (left.isCompatibleWith(right))
46                         return EqualOrMoreSpecific;
47                 if (right.isCompatibleWith(left))
48                         return MoreGeneric;
49                 return NotRelated;
50         }
51
52         // Internal use only
53         protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
54                 if (parameters == arguments)
55                         return true;
56
57                 int length = parameters.length;
58                 if (length != arguments.length)
59                         return false;
60
61                 for (int i = 0; i < length; i++)
62                         if (parameters[i] != arguments[i])
63                                 if (!arguments[i].isCompatibleWith(parameters[i]))
64                                         return false;
65                 return true;
66         }
67         
68         public final ClassScope classScope() {
69                 Scope scope = this;
70                 do {
71                         if (scope instanceof ClassScope)
72                                 return (ClassScope) scope;
73                         scope = scope.parent;
74                 } while (scope != null);
75                 return null;
76         }       
77
78         /* Answer an int describing the relationship between the given type and unchecked exceptions.
79         *
80         *       NotRelated 
81         *       EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
82         *       MoreGeneric : type is a supertype of an actual unchecked exception type
83         */
84         public int compareUncheckedException(ReferenceBinding type) {
85                 int comparison = compareTypes(type, getJavaLangRuntimeException());
86                 if (comparison != 0) return comparison;
87                 return compareTypes(type, getJavaLangError());
88         }
89
90         public final CompilationUnitScope compilationUnitScope() {
91                 Scope lastScope = null;
92                 Scope scope = this;
93                 do {
94                         lastScope = scope;
95                         scope = scope.parent;
96                 } while (scope != null);
97                 return (CompilationUnitScope) lastScope;
98         }
99
100         public ArrayBinding createArray(TypeBinding type, int dimension) {
101                 if (!type.isValidBinding())
102                         return new ArrayBinding(type, dimension);
103                 return environment().createArrayType(type, dimension);
104         }
105
106         public final ClassScope enclosingClassScope() {
107                 Scope scope = this;
108                 while ((scope = scope.parent) != null) {
109                         if (scope instanceof ClassScope) return (ClassScope)scope;
110                 }
111                 return null; // may answer null if no type around
112         }
113
114         public final MethodScope enclosingMethodScope() {
115                 Scope scope = this;
116                 while ((scope = scope.parent) != null) {
117                         if (scope instanceof MethodScope) return (MethodScope)scope;
118                 }
119                 return null; // may answer null if no method around
120         }
121
122         /* Answer the receiver's enclosing source type.
123         */
124         public final SourceTypeBinding enclosingSourceType() {
125                 Scope scope = this;
126                 do {
127                         if (scope instanceof ClassScope)
128                                 return ((ClassScope) scope).referenceContext.binding;
129                         scope = scope.parent;
130                 } while (scope != null);
131                 return null;
132         }
133         public final LookupEnvironment environment() {
134                 Scope scope, unitScope = this;
135                 while ((scope = unitScope.parent) != null)
136                         unitScope = scope;
137                 return ((CompilationUnitScope) unitScope).environment;
138         }
139
140         protected void faultInReceiverType(TypeBinding type) {
141                 if (type.isArrayType())
142                         type = ((ArrayBinding) type).leafComponentType;
143
144         // check on Begin bit, so as to be resilient with potential illformed binaries containing cycles (67769)
145                 if (type instanceof BinaryTypeBinding && (type.tagBits & BeginHierarchyCheck) == 0) {
146                     type.tagBits |= BeginHierarchyCheck;
147                         // fault in the hierarchy of the type now so we can detect missing types instead of in storeDependencyInfo
148                         BinaryTypeBinding binaryType = (BinaryTypeBinding) type;
149                         ReferenceBinding enclosingType = binaryType.enclosingType();
150                         if (enclosingType != null)
151                                 faultInReceiverType(enclosingType);
152                         ReferenceBinding superclass = binaryType.superclass();
153                         if (superclass != null)
154                                 faultInReceiverType(superclass);
155                         ReferenceBinding[] interfaces = binaryType.superInterfaces();
156                         for (int i = 0, l = interfaces.length; i < l; i++)
157                                 faultInReceiverType(interfaces[i]);
158                         type.tagBits |= EndHierarchyCheck;
159                 }
160         }
161
162         // abstract method lookup lookup (since maybe missing default abstract methods)
163         public MethodBinding findDefaultAbstractMethod(
164                 ReferenceBinding receiverType, 
165                 char[] selector,
166                 TypeBinding[] argumentTypes,
167                 InvocationSite invocationSite,
168                 ReferenceBinding classHierarchyStart,
169                 MethodBinding matchingMethod,
170                 ObjectVector found) {
171
172                 int startFoundSize = found.size;
173                 ReferenceBinding currentType = classHierarchyStart;
174                 while (currentType != null) {
175                         matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
176                         currentType = currentType.superclass();
177                 }
178                 int foundSize = found.size;
179                 if (foundSize == startFoundSize) {
180                         if (matchingMethod != null) compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
181                         return matchingMethod; // maybe null
182                 }
183                 MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
184                 int candidatesCount = 0;
185                 // argument type compatibility check
186                 for (int i = startFoundSize; i < foundSize; i++) {
187                         MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
188                         if (areParametersAssignable(methodBinding.parameters, argumentTypes))
189                                 candidates[candidatesCount++] = methodBinding;
190                 }
191                 if (candidatesCount == 1) {
192                         compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
193                         return candidates[0]; 
194                 }
195                 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
196                         int argLength = argumentTypes.length;
197                         nextMethod : for (int i = 0; i < foundSize; i++) {
198                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
199                                 TypeBinding[] params = methodBinding.parameters;
200                                 int paramLength = params.length;
201                                 nextArg: for (int a = 0; a < argLength; a++) {
202                                         TypeBinding arg = argumentTypes[a];
203                                         for (int p = 0; p < paramLength; p++)
204                                                 if (params[p] == arg)
205                                                         continue nextArg;
206                                         continue nextMethod;
207                                 }
208                                 return methodBinding;
209                         }
210                         return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
211                 }
212                 // no need to check for visibility - interface methods are public
213                 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
214         }
215
216         // Internal use only
217         public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
218                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
219                         return null; // know it has no member types (nor inherited member types)
220
221                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
222                 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
223                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
224                 if (memberType != null) {
225                         compilationUnitScope().recordTypeReference(memberType); // to record supertypes
226                         if (enclosingSourceType == null
227                                         ? memberType.canBeSeenBy(getCurrentPackage())
228                                         : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
229                                 return memberType;
230                         return new ProblemReferenceBinding(typeName, memberType, NotVisible);
231                 }
232                 return null;
233         }
234
235         // Internal use only
236         public MethodBinding findExactMethod(
237                 ReferenceBinding receiverType,
238                 char[] selector,
239                 TypeBinding[] argumentTypes,
240                 InvocationSite invocationSite) {
241
242                 faultInReceiverType(receiverType);
243                 compilationUnitScope().recordTypeReference(receiverType);
244                 compilationUnitScope().recordTypeReferences(argumentTypes);
245                 MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
246                 if (exactMethod != null) {
247                         compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
248                         if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
249                                 return exactMethod;
250                 }
251                 return null;
252         }
253
254         // Internal use only
255         /*      Answer the field binding that corresponds to fieldName.
256                 Start the lookup at the receiverType.
257                 InvocationSite implements
258                         isSuperAccess(); this is used to determine if the discovered field is visible.
259                 Only fields defined by the receiverType or its supertypes are answered;
260                 a field of an enclosing type will not be found using this API.
261         
262                 If no visible field is discovered, null is answered.
263         */
264         public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
265                 if (receiverType.isBaseType()) return null;
266                 if (receiverType.isArrayType()) {
267                         TypeBinding leafType = receiverType.leafComponentType();
268                         if (leafType instanceof ReferenceBinding) {
269                                 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
270                                         return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
271                         }
272                         if (CharOperation.equals(fieldName, LENGTH))
273                                 return ArrayBinding.ArrayLength;
274                         return null;
275                 }
276
277                 faultInReceiverType(receiverType);
278                 compilationUnitScope().recordTypeReference(receiverType);
279
280                 ReferenceBinding currentType = (ReferenceBinding) receiverType;
281                 if (!currentType.canBeSeenBy(this))
282                         return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
283
284                 FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
285                 if (field != null) {
286                         if (field.canBeSeenBy(currentType, invocationSite, this))
287                                 return field;
288                         return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible);
289                 }
290                 // collect all superinterfaces of receiverType until the field is found in a supertype
291                 ReferenceBinding[][] interfacesToVisit = null;
292                 int lastPosition = -1;
293                 FieldBinding visibleField = null;
294                 boolean keepLooking = true;
295                 boolean notVisible = false;
296                 // we could hold onto the not visible field for extra error reporting
297                 while (keepLooking) {
298                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
299                         if (itsInterfaces != NoSuperInterfaces) {
300                                 if (interfacesToVisit == null)
301                                         interfacesToVisit = new ReferenceBinding[5][];
302                                 if (++lastPosition == interfacesToVisit.length)
303                                         System.arraycopy(
304                                                 interfacesToVisit,
305                                                 0,
306                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
307                                                 0,
308                                                 lastPosition);
309                                 interfacesToVisit[lastPosition] = itsInterfaces;
310                         }
311                         if ((currentType = currentType.superclass()) == null)
312                                 break;
313
314                         if ((field = currentType.getField(fieldName, needResolve)) != null) {
315                                 keepLooking = false;
316                                 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
317                                         if (visibleField == null)
318                                                 visibleField = field;
319                                         else
320                                                 return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
321                                 } else {
322                                         notVisible = true;
323                                 }
324                         }
325                 }
326
327                 // walk all visible interfaces to find ambiguous references
328                 if (interfacesToVisit != null) {
329                         ProblemFieldBinding ambiguous = null;
330                         done : for (int i = 0; i <= lastPosition; i++) {
331                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
332                                 for (int j = 0, length = interfaces.length; j < length; j++) {
333                                         ReferenceBinding anInterface = interfaces[j];
334                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
335                                                 // if interface as not already been visited
336                                                 anInterface.tagBits |= InterfaceVisited;
337                                                 if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
338                                                         if (visibleField == null) {
339                                                                 visibleField = field;
340                                                         } else {
341                                                                 ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
342                                                                 break done;
343                                                         }
344                                                 } else {
345                                                         ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
346                                                         if (itsInterfaces != NoSuperInterfaces) {
347                                                                 if (++lastPosition == interfacesToVisit.length)
348                                                                         System.arraycopy(
349                                                                                 interfacesToVisit,
350                                                                                 0,
351                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
352                                                                                 0,
353                                                                                 lastPosition);
354                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
355                                                         }
356                                                 }
357                                         }
358                                 }
359                         }
360
361                         // bit reinitialization
362                         for (int i = 0; i <= lastPosition; i++) {
363                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
364                                 for (int j = 0, length = interfaces.length; j < length; j++)
365                                         interfaces[j].tagBits &= ~InterfaceVisited;
366                         }
367                         if (ambiguous != null)
368                                 return ambiguous;
369                 }
370
371                 if (visibleField != null)
372                         return visibleField;
373                 if (notVisible)
374                         return new ProblemFieldBinding(currentType, fieldName, NotVisible);
375                 return null;
376         }
377
378         // Internal use only
379         public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
380                 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
381                         return null; // know it has no member types (nor inherited member types)
382
383                 SourceTypeBinding enclosingSourceType = enclosingSourceType();
384                 PackageBinding currentPackage = getCurrentPackage();
385                 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
386                 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
387                 if (memberType != null) {
388                         compilationUnitScope().recordTypeReference(memberType); // to record supertypes
389                         if (enclosingSourceType == null
390                                         ? memberType.canBeSeenBy(currentPackage)
391                                         : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
392                                 return memberType;
393                         return new ProblemReferenceBinding(typeName, memberType, NotVisible);
394                 }
395
396                 // collect all superinterfaces of receiverType until the memberType is found in a supertype
397                 ReferenceBinding currentType = enclosingType;
398                 ReferenceBinding[][] interfacesToVisit = null;
399                 int lastPosition = -1;
400                 ReferenceBinding visibleMemberType = null;
401                 boolean keepLooking = true;
402                 ReferenceBinding notVisible = null;
403                 // we could hold onto the not visible field for extra error reporting
404                 while (keepLooking) {
405                         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
406                         if (itsInterfaces != NoSuperInterfaces) {
407                                 if (interfacesToVisit == null)
408                                         interfacesToVisit = new ReferenceBinding[5][];
409                                 if (++lastPosition == interfacesToVisit.length)
410                                         System.arraycopy(
411                                                 interfacesToVisit,
412                                                 0,
413                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
414                                                 0,
415                                                 lastPosition);
416                                 interfacesToVisit[lastPosition] = itsInterfaces;
417                         }
418                         if ((currentType = currentType.superclass()) == null)
419                                 break;
420
421                         compilationUnitScope().recordReference(currentType.compoundName, typeName);
422                         if ((memberType = currentType.getMemberType(typeName)) != null) {
423                                 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
424                                 keepLooking = false;
425                                 if (enclosingSourceType == null
426                                         ? memberType.canBeSeenBy(currentPackage)
427                                         : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
428                                                 if (visibleMemberType == null)
429                                                         visibleMemberType = memberType;
430                                                 else
431                                                         return new ProblemReferenceBinding(typeName, Ambiguous);
432                                 } else {
433                                         notVisible = memberType;
434                                 }
435                         }
436                 }
437                 // walk all visible interfaces to find ambiguous references
438                 if (interfacesToVisit != null) {
439                         ProblemReferenceBinding ambiguous = null;
440                         done : for (int i = 0; i <= lastPosition; i++) {
441                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
442                                 for (int j = 0, length = interfaces.length; j < length; j++) {
443                                         ReferenceBinding anInterface = interfaces[j];
444                                         if ((anInterface.tagBits & InterfaceVisited) == 0) {
445                                                 // if interface as not already been visited
446                                                 anInterface.tagBits |= InterfaceVisited;
447                                                 compilationUnitScope().recordReference(anInterface.compoundName, typeName);
448                                                 if ((memberType = anInterface.getMemberType(typeName)) != null) {
449                                                         compilationUnitScope().recordTypeReference(memberType); // to record supertypes
450                                                         if (visibleMemberType == null) {
451                                                                 visibleMemberType = memberType;
452                                                         } else {
453                                                                 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
454                                                                 break done;
455                                                         }
456                                                 } else {
457                                                         ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
458                                                         if (itsInterfaces != NoSuperInterfaces) {
459                                                                 if (++lastPosition == interfacesToVisit.length)
460                                                                         System.arraycopy(
461                                                                                 interfacesToVisit,
462                                                                                 0,
463                                                                                 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
464                                                                                 0,
465                                                                                 lastPosition);
466                                                                 interfacesToVisit[lastPosition] = itsInterfaces;
467                                                         }
468                                                 }
469                                         }
470                                 }
471                         }
472
473                         // bit reinitialization
474                         for (int i = 0; i <= lastPosition; i++) {
475                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
476                                 for (int j = 0, length = interfaces.length; j < length; j++)
477                                         interfaces[j].tagBits &= ~InterfaceVisited;
478                         }
479                         if (ambiguous != null)
480                                 return ambiguous;
481                 }
482                 if (visibleMemberType != null)
483                         return visibleMemberType;
484                 if (notVisible != null)
485                         return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
486                 return null;
487         }
488
489         // Internal use only
490         public MethodBinding findMethod(
491                 ReferenceBinding receiverType,
492                 char[] selector,
493                 TypeBinding[] argumentTypes,
494                 InvocationSite invocationSite) {
495
496                 ReferenceBinding currentType = receiverType;
497                 MethodBinding matchingMethod = null;
498                 ObjectVector found = new ObjectVector(); //TODO should rewrite to remove #matchingMethod since found is allocated anyway
499
500                 faultInReceiverType(receiverType);
501                 compilationUnitScope().recordTypeReference(receiverType);
502                 compilationUnitScope().recordTypeReferences(argumentTypes);
503
504                 if (currentType.isInterface()) {
505                         MethodBinding[] currentMethods = currentType.getMethods(selector);
506                         int currentLength = currentMethods.length;
507                         if (currentLength == 1) {
508                                 matchingMethod = currentMethods[0];
509                         } else if (currentLength > 1) {
510                                 found.addAll(currentMethods);
511                         }
512                         matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
513                         currentType = getJavaLangObject();
514                 }
515
516                 boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
517                 // superclass lookup
518                 ReferenceBinding classHierarchyStart = currentType;
519                 while (currentType != null) {
520                         MethodBinding[] currentMethods = currentType.getMethods(selector);
521                         int currentLength = currentMethods.length;
522                         
523                         /*
524                          * if 1.4 compliant, must filter out redundant protected methods from superclasses
525                          */
526                         if (isCompliant14){                      
527                                 nextMethod: for (int i = 0; i < currentLength; i++){
528                                         MethodBinding currentMethod = currentMethods[i];
529                                         // protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
530                                         // when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
531                                         if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
532                                         if (matchingMethod != null){
533                                                 if (currentMethod.areParametersEqual(matchingMethod)){
534                                                         currentLength--;
535                                                         currentMethods[i] = null; // discard this match
536                                                         continue nextMethod;
537                                                 }
538                                         } else {
539                                                 for (int j = 0, max = found.size; j < max; j++) {
540                                                         if (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
541                                                                 currentLength--;
542                                                                 currentMethods[i] = null;
543                                                                 continue nextMethod;
544                                                         }
545                                                 }
546                                         }
547                                 }
548                         }
549                         
550                         if (currentLength == 1 && matchingMethod == null && found.size == 0) {
551                                 matchingMethod = currentMethods[0];
552                         } else if (currentLength > 0) {
553                                 if (matchingMethod != null) {
554                                         found.add(matchingMethod);
555                                         matchingMethod = null;
556                                 }
557                                 // append currentMethods, filtering out null entries
558                                 int maxMethod = currentMethods.length;
559                                 if (maxMethod == currentLength) { // no method was eliminated for 1.4 compliance (see above)
560                                         found.addAll(currentMethods);
561                                 } else {
562                                         for (int i = 0, max = currentMethods.length; i < max; i++) {
563                                                 MethodBinding currentMethod = currentMethods[i];
564                                                 if (currentMethod != null) found.add(currentMethod);
565                                         }
566                                 }
567                         }
568                         currentType = currentType.superclass();
569                 }
570
571                 // if found several candidates, then eliminate those not matching argument types
572                 int foundSize = found.size;
573                 MethodBinding[] candidates = null;
574                 int candidatesCount = 0;
575                 boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ?
576                 if (foundSize > 0) {
577                         // argument type compatibility check
578                         for (int i = 0; i < foundSize; i++) {
579                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
580                                 if (areParametersAssignable(methodBinding.parameters, argumentTypes)) {
581                                         switch (candidatesCount) {
582                                                 case 0: 
583                                                         matchingMethod = methodBinding; // if only one match, reuse matchingMethod
584                                                         checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
585                                                         break;
586                                                 case 1:
587                                                         candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
588                                                         candidates[0] = matchingMethod; // copy back
589                                                         matchingMethod = null;
590                                                         // fall through
591                                                 default:
592                                                         candidates[candidatesCount] = methodBinding;
593                                         }
594                                         candidatesCount++;
595                                 }
596                         }
597                 }
598                 // if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod
599                 if (matchingMethod != null) {
600                         if (checkedMatchingMethod || areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
601                                 // (if no default abstract) must explicitly look for one instead, which could be a better match
602                                 if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
603                                         // ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
604                                         MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);                                             
605                                         if (interfaceMethod != null) return interfaceMethod;
606                                         compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
607                                         return matchingMethod;
608                                 }
609                         } 
610                         return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
611                 }
612
613                 // no match was found, try to find a close match when the parameter order is wrong or missing some parameters
614                 if (candidatesCount == 0) {
615                         MethodBinding interfaceMethod =
616                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
617                         if (interfaceMethod != null) return interfaceMethod;
618
619                         int argLength = argumentTypes.length;
620                         foundSize = found.size;
621                         nextMethod : for (int i = 0; i < foundSize; i++) {
622                                 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
623                                 TypeBinding[] params = methodBinding.parameters;
624                                 int paramLength = params.length;
625                                 nextArg: for (int a = 0; a < argLength; a++) {
626                                         TypeBinding arg = argumentTypes[a];
627                                         for (int p = 0; p < paramLength; p++)
628                                                 if (params[p] == arg)
629                                                         continue nextArg;
630                                         continue nextMethod;
631                                 }
632                                 return methodBinding;
633                         }
634                         return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
635                 }
636
637                 // tiebreak using visibility check
638                 int visiblesCount = 0;
639                 for (int i = 0; i < candidatesCount; i++) {
640                         MethodBinding methodBinding = candidates[i];
641                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
642                                 if (visiblesCount != i) {
643                                         candidates[i] = null;
644                                         candidates[visiblesCount] = methodBinding;
645                                 }
646                                 visiblesCount++;
647                         }
648                 }
649                 if (visiblesCount == 1) {
650                         compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
651                         return candidates[0];
652                 }
653                 if (visiblesCount == 0) {
654                         MethodBinding interfaceMethod =
655                                 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
656                         if (interfaceMethod != null) return interfaceMethod;
657                         return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
658                 }
659                 if (isCompliant14)
660                         return mostSpecificMethodBinding(candidates, visiblesCount);
661                 return candidates[0].declaringClass.isClass()
662                         ? mostSpecificClassMethodBinding(candidates, visiblesCount)
663                         : mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
664         }
665         
666         // Internal use only
667         public MethodBinding findMethodForArray(
668                 ArrayBinding receiverType,
669                 char[] selector,
670                 TypeBinding[] argumentTypes,
671                 InvocationSite invocationSite) {
672
673                 TypeBinding leafType = receiverType.leafComponentType();
674                 if (leafType instanceof ReferenceBinding) {
675                         if (!((ReferenceBinding) leafType).canBeSeenBy(this))
676                                 return new ProblemMethodBinding(selector, TypeConstants.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
677                 }
678
679                 ReferenceBinding object = getJavaLangObject();
680                 MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
681                 if (methodBinding != null) {
682                         // handle the method clone() specially... cannot be protected or throw exceptions
683                         if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
684                                 return new UpdatedMethodBinding(
685                                         environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
686                                         (methodBinding.modifiers ^ AccProtected) | AccPublic,
687                                         CLONE,
688                                         methodBinding.returnType,
689                                         argumentTypes,
690                                         null,
691                                         object);
692                         if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
693                                 return methodBinding;
694                 }
695                 // answers closest approximation, may not check argumentTypes or visibility
696                 methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
697                 if (methodBinding == null)
698                         return new ProblemMethodBinding(selector, argumentTypes, NotFound);
699                 if (methodBinding.isValidBinding()) {
700                         if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
701                                 return new ProblemMethodBinding(
702                                         methodBinding,
703                                         selector,
704                                         argumentTypes,
705                                         NotFound);
706                         if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
707                                 return new ProblemMethodBinding(
708                                         methodBinding,
709                                         selector,
710                                         methodBinding.parameters,
711                                         NotVisible);
712                 }
713                 return methodBinding;
714         }
715
716         public MethodBinding findMethodInSuperInterfaces(
717                 ReferenceBinding currentType,
718                 char[] selector,
719                 ObjectVector found,
720                 MethodBinding matchingMethod) {
721
722                 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
723                 if (itsInterfaces != NoSuperInterfaces) {
724                         ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
725                         int lastPosition = -1;
726                         if (++lastPosition == interfacesToVisit.length)
727                                 System.arraycopy(
728                                         interfacesToVisit, 0,
729                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
730                                         lastPosition);
731                         interfacesToVisit[lastPosition] = itsInterfaces;
732
733                         for (int i = 0; i <= lastPosition; i++) {
734                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
735                                 for (int j = 0, length = interfaces.length; j < length; j++) {
736                                         currentType = interfaces[j];
737                                         if ((currentType.tagBits & InterfaceVisited) == 0) {
738                                                 // if interface as not already been visited
739                                                 currentType.tagBits |= InterfaceVisited;
740
741                                                 MethodBinding[] currentMethods = currentType.getMethods(selector);
742                                                 int currentLength = currentMethods.length;
743                                                 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
744                                                         matchingMethod = currentMethods[0];
745                                                 } else if (currentLength > 0) {
746                                                         if (matchingMethod != null) {
747                                                                 found.add(matchingMethod);
748                                                                 matchingMethod = null;
749                                                         }
750                                                         found.addAll(currentMethods);
751                                                 }
752                                                 itsInterfaces = currentType.superInterfaces();
753                                                 if (itsInterfaces != NoSuperInterfaces) {
754                                                         if (++lastPosition == interfacesToVisit.length)
755                                                                 System.arraycopy(
756                                                                         interfacesToVisit, 0,
757                                                                         interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
758                                                                         lastPosition);
759                                                         interfacesToVisit[lastPosition] = itsInterfaces;
760                                                 }
761                                         }
762                                 }
763                         }
764
765                         // bit reinitialization
766                         for (int i = 0; i <= lastPosition; i++) {
767                                 ReferenceBinding[] interfaces = interfacesToVisit[i];
768                                 for (int j = 0, length = interfaces.length; j < length; j++)
769                                         interfaces[j].tagBits &= ~InterfaceVisited;
770                         }
771                 }
772                 return matchingMethod;
773         }
774
775         // Internal use only
776         public ReferenceBinding findType(
777                 char[] typeName,
778                 PackageBinding declarationPackage,
779                 PackageBinding invocationPackage) {
780
781                 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
782                 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
783                 if (typeBinding == null)
784                         return null;
785
786                 if (typeBinding.isValidBinding()) {
787                         if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
788                                 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
789                 }
790                 return typeBinding;
791         }
792
793         public LocalVariableBinding findVariable(char[] variable) {
794
795                 return null;
796         }
797         
798         public TypeBinding getBaseType(char[] name) {
799                 // list should be optimized (with most often used first)
800                 int length = name.length;
801                 if (length > 2 && length < 8) {
802                         switch (name[0]) {
803                                 case 'i' :
804                                         if (length == 3 && name[1] == 'n' && name[2] == 't')
805                                                 return IntBinding;
806                                         break;
807                                 case 'v' :
808                                         if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
809                                                 return VoidBinding;
810                                         break;
811                                 case 'b' :
812                                         if (length == 7
813                                                 && name[1] == 'o'
814                                                 && name[2] == 'o'
815                                                 && name[3] == 'l'
816                                                 && name[4] == 'e'
817                                                 && name[5] == 'a'
818                                                 && name[6] == 'n')
819                                                 return BooleanBinding;
820                                         if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
821                                                 return ByteBinding;
822                                         break;
823                                 case 'c' :
824                                         if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
825                                                 return CharBinding;
826                                         break;
827                                 case 'd' :
828                                         if (length == 6
829                                                 && name[1] == 'o'
830                                                 && name[2] == 'u'
831                                                 && name[3] == 'b'
832                                                 && name[4] == 'l'
833                                                 && name[5] == 'e')
834                                                 return DoubleBinding;
835                                         break;
836                                 case 'f' :
837                                         if (length == 5
838                                                 && name[1] == 'l'
839                                                 && name[2] == 'o'
840                                                 && name[3] == 'a'
841                                                 && name[4] == 't')
842                                                 return FloatBinding;
843                                         break;
844                                 case 'l' :
845                                         if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
846                                                 return LongBinding;
847                                         break;
848                                 case 's' :
849                                         if (length == 5
850                                                 && name[1] == 'h'
851                                                 && name[2] == 'o'
852                                                 && name[3] == 'r'
853                                                 && name[4] == 't')
854                                                 return ShortBinding;
855                         }
856                 }
857                 return null;
858         }
859
860         /* API
861      *  
862          *      Answer the binding that corresponds to the argument name.
863          *      flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
864          *      Only bindings corresponding to the mask can be answered.
865          *
866          *      For example, getBinding("foo", VARIABLE, site) will answer
867          *      the binding for the field or local named "foo" (or an error binding if none exists).
868          *      If a type named "foo" exists, it will not be detected (and an error binding will be answered)
869          *
870          *      The VARIABLE mask has precedence over the TYPE mask.
871          *
872          *      If the VARIABLE mask is not set, neither fields nor locals will be looked for.
873          *
874          *      InvocationSite implements:
875          *              isSuperAccess(); this is used to determine if the discovered field is visible.
876          *
877          *      Limitations: cannot request FIELD independently of LOCAL, or vice versa
878          */
879         public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
880
881                 try {
882                         Binding binding = null;
883                         FieldBinding problemField = null;
884                         if ((mask & VARIABLE) != 0) {
885                                 boolean insideStaticContext = false;
886                                 boolean insideConstructorCall = false;
887         
888                                 FieldBinding foundField = null;
889                                 // can be a problem field which is answered if a valid field is not found
890                                 ProblemFieldBinding foundInsideProblem = null;
891                                 // inside Constructor call or inside static context
892                                 Scope scope = this;
893                                 int depth = 0;
894                                 int foundDepth = 0;
895                                 ReferenceBinding foundActualReceiverType = null;
896                                 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
897                                         switch (scope.kind) {
898                                                 case METHOD_SCOPE :
899                                                         MethodScope methodScope = (MethodScope) scope;
900                                                         insideStaticContext |= methodScope.isStatic;
901                                                         insideConstructorCall |= methodScope.isConstructorCall;
902                                                         // Fall through... could duplicate the code below to save a cast - questionable optimization
903                                                 case BLOCK_SCOPE :
904                                                         LocalVariableBinding variableBinding = scope.findVariable(name);
905                                                         // looks in this scope only
906                                                         if (variableBinding != null) {
907                                                                 if (foundField != null && foundField.isValidBinding())
908                                                                         return new ProblemFieldBinding(
909                                                                                 foundField, // closest match
910                                                                                 foundField.declaringClass,
911                                                                                 name,
912                                                                                 InheritedNameHidesEnclosingName);
913                                                                 if (depth > 0)
914                                                                         invocationSite.setDepth(depth);
915                                                                 return variableBinding;
916                                                         }
917                                                         break;
918                                                 case CLASS_SCOPE :
919                                                         ClassScope classScope = (ClassScope) scope;
920                                                         SourceTypeBinding enclosingType = classScope.referenceContext.binding;
921                                                         FieldBinding fieldBinding =
922                                                                 classScope.findField(enclosingType, name, invocationSite, needResolve);
923                                                         // Use next line instead if willing to enable protected access accross inner types
924                                                         // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
925                                                         if (fieldBinding != null) { // skip it if we did not find anything
926                                                                 if (fieldBinding.problemId() == Ambiguous) {
927                                                                         if (foundField == null || foundField.problemId() == NotVisible)
928                                                                                 // supercedes any potential InheritedNameHidesEnclosingName problem
929                                                                                 return fieldBinding;
930                                                                         // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
931                                                                         return new ProblemFieldBinding(
932                                                                                 foundField, // closest match
933                                                                                 foundField.declaringClass,
934                                                                                 name,
935                                                                                 InheritedNameHidesEnclosingName);
936                                                                 }
937         
938                                                                 ProblemFieldBinding insideProblem = null;
939                                                                 if (fieldBinding.isValidBinding()) {
940                                                                         if (!fieldBinding.isStatic()) {
941                                                                                 if (insideConstructorCall) {
942                                                                                         insideProblem =
943                                                                                                 new ProblemFieldBinding(
944                                                                                                         fieldBinding, // closest match
945                                                                                                         fieldBinding.declaringClass,
946                                                                                                         name,
947                                                                                                         NonStaticReferenceInConstructorInvocation);
948                                                                                 } else if (insideStaticContext) {
949                                                                                         insideProblem =
950                                                                                                 new ProblemFieldBinding(
951                                                                                                         fieldBinding, // closest match
952                                                                                                         fieldBinding.declaringClass,
953                                                                                                         name,
954                                                                                                         NonStaticReferenceInStaticContext);
955                                                                                 }
956                                                                         }
957                                                                         if (enclosingType == fieldBinding.declaringClass
958                                                                                 || environment().options.complianceLevel >= ClassFileConstants.JDK1_4){
959                                                                                 // found a valid field in the 'immediate' scope (ie. not inherited)
960                                                                                 // OR in 1.4 mode (inherited shadows enclosing)
961                                                                                 if (foundField == null) {
962                                                                                         if (depth > 0){
963                                                                                                 invocationSite.setDepth(depth);
964                                                                                                 invocationSite.setActualReceiverType(enclosingType);
965                                                                                         }
966                                                                                         // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
967                                                                                         return insideProblem == null ? fieldBinding : insideProblem;
968                                                                                 }
969                                                                                 if (foundField.isValidBinding())
970                                                                                         // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
971                                                                                         if (foundField.declaringClass != fieldBinding.declaringClass)
972                                                                                                 // ie. have we found the same field - do not trust field identity yet
973                                                                                                 return new ProblemFieldBinding(
974                                                                                                         foundField, // closest match
975                                                                                                         foundField.declaringClass,
976                                                                                                         name,
977                                                                                                         InheritedNameHidesEnclosingName);
978                                                                         }
979                                                                 }
980         
981                                                                 if (foundField == null
982                                                                         || (foundField.problemId() == NotVisible
983                                                                                 && fieldBinding.problemId() != NotVisible)) {
984                                                                         // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
985                                                                         foundDepth = depth;
986                                                                         foundActualReceiverType = enclosingType;
987                                                                         foundInsideProblem = insideProblem;
988                                                                         foundField = fieldBinding;
989                                                                 }
990                                                         }
991                                                         depth++;
992                                                         insideStaticContext |= enclosingType.isStatic();
993                                                         // 1EX5I8Z - accessing outer fields within a constructor call is permitted
994                                                         // in order to do so, we change the flag as we exit from the type, not the method
995                                                         // itself, because the class scope is used to retrieve the fields.
996                                                         MethodScope enclosingMethodScope = scope.methodScope();
997                                                         insideConstructorCall =
998                                                                 enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
999                                                         break;
1000                                                 case COMPILATION_UNIT_SCOPE :
1001                                                         break done;
1002                                         }
1003                                         scope = scope.parent;
1004                                 }
1005         
1006                                 if (foundInsideProblem != null)
1007                                         return foundInsideProblem;
1008                                 if (foundField != null) {
1009                                         if (foundField.isValidBinding()){
1010                                                 if (foundDepth > 0){
1011                                                         invocationSite.setDepth(foundDepth);
1012                                                         invocationSite.setActualReceiverType(foundActualReceiverType);
1013                                                 }
1014                                                 return foundField;
1015                                         }
1016                                         problemField = foundField;
1017                                 }
1018                         }
1019         
1020                         // We did not find a local or instance variable.
1021                         if ((mask & TYPE) != 0) {
1022                                 if ((binding = getBaseType(name)) != null)
1023                                         return binding;
1024                                 binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
1025                                 if (binding.isValidBinding() || mask == TYPE)
1026                                         return binding;
1027                                 // answer the problem type binding if we are only looking for a type
1028                         } else if ((mask & PACKAGE) != 0) {
1029                                 compilationUnitScope().recordSimpleReference(name);
1030                                 if ((binding = environment().getTopLevelPackage(name)) != null)
1031                                         return binding;
1032                         }
1033                         if (problemField != null) return problemField;
1034                         return new ProblemBinding(name, enclosingSourceType(), NotFound);
1035
1036                 } catch (AbortCompilation e) {
1037                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1038                         throw e;
1039                 }
1040         }
1041
1042         public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1043                 try {
1044                         faultInReceiverType(receiverType);
1045                         compilationUnitScope().recordTypeReference(receiverType);
1046                         compilationUnitScope().recordTypeReferences(argumentTypes);
1047                         MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
1048                         if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this))
1049                                 return methodBinding;
1050                         MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
1051                         if (methods == NoMethods)
1052                                 return new ProblemMethodBinding(
1053                                         ConstructorDeclaration.ConstantPoolName,
1054                                         argumentTypes,
1055                                         NotFound);
1056         
1057                         MethodBinding[] compatible = new MethodBinding[methods.length];
1058                         int compatibleIndex = 0;
1059                         for (int i = 0, length = methods.length; i < length; i++)
1060                                 if (areParametersAssignable(methods[i].parameters, argumentTypes))
1061                                         compatible[compatibleIndex++] = methods[i];
1062                         if (compatibleIndex == 0)
1063                                 return new ProblemMethodBinding(
1064                                         ConstructorDeclaration.ConstantPoolName,
1065                                         argumentTypes,
1066                                         NotFound);
1067                         // need a more descriptive error... cannot convert from X to Y
1068         
1069                         MethodBinding[] visible = new MethodBinding[compatibleIndex];
1070                         int visibleIndex = 0;
1071                         for (int i = 0; i < compatibleIndex; i++) {
1072                                 MethodBinding method = compatible[i];
1073                                 if (method.canBeSeenBy(invocationSite, this))
1074                                         visible[visibleIndex++] = method;
1075                         }
1076                         if (visibleIndex == 1) return visible[0];
1077                         if (visibleIndex == 0)
1078                                 return new ProblemMethodBinding(
1079                                         compatible[0],
1080                                         ConstructorDeclaration.ConstantPoolName,
1081                                         compatible[0].parameters,
1082                                         NotVisible);
1083                         return mostSpecificClassMethodBinding(visible, visibleIndex);
1084                 } catch (AbortCompilation e) {
1085                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1086                         throw e;
1087                 }
1088         }
1089
1090         public final PackageBinding getCurrentPackage() {
1091                 Scope scope, unitScope = this;
1092                 while ((scope = unitScope.parent) != null)
1093                         unitScope = scope;
1094                 return ((CompilationUnitScope) unitScope).fPackage;
1095         }
1096
1097         /**
1098          * Returns the modifiers of the innermost enclosing declaration.
1099          * @return modifiers
1100          */
1101         public int getDeclarationModifiers(){
1102                 switch(this.kind){
1103                         case Scope.BLOCK_SCOPE :
1104                         case Scope.METHOD_SCOPE :
1105                                 MethodScope methodScope = methodScope();
1106                                 if (!methodScope.isInsideInitializer()){
1107                                         // check method modifiers to see if deprecated
1108                                         MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1109                                         if (context != null) {
1110                                                 return context.modifiers;
1111                                         }
1112                                 } else {
1113                                         SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
1114
1115                                         // inside field declaration ? check field modifier to see if deprecated
1116                                         if (methodScope.initializedField != null) {
1117                                                 return methodScope.initializedField.modifiers;
1118                                         }
1119                                         if (type != null) {
1120                                                 return type.modifiers;
1121                                         }
1122                                 }
1123                                 break;
1124                         case Scope.CLASS_SCOPE :
1125                                 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1126                                 if (context != null) {
1127                                         return context.modifiers;
1128                                 }
1129                                 break;
1130                 }
1131                 return -1;
1132         }
1133
1134         public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
1135                 try {
1136                         FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/);
1137                         if (field != null) return field;
1138         
1139                         return new ProblemFieldBinding(
1140                                 receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
1141                                 fieldName,
1142                                 NotFound);
1143                 } catch (AbortCompilation e) {
1144                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1145                         throw e;
1146                 }
1147         }
1148
1149         /* API
1150          *      
1151          *      Answer the method binding that corresponds to selector, argumentTypes.
1152          *      Start the lookup at the enclosing type of the receiver.
1153          *      InvocationSite implements 
1154          *              isSuperAccess(); this is used to determine if the discovered method is visible.
1155          *              setDepth(int); this is used to record the depth of the discovered method
1156          *                      relative to the enclosing type of the receiver. (If the method is defined
1157          *                      in the enclosing type of the receiver, the depth is 0; in the next enclosing
1158          *                      type, the depth is 1; and so on
1159          * 
1160          *      If no visible method is discovered, an error binding is answered.
1161          */
1162         public MethodBinding getImplicitMethod(
1163                 char[] selector,
1164                 TypeBinding[] argumentTypes,
1165                 InvocationSite invocationSite) {
1166
1167                 boolean insideStaticContext = false;
1168                 boolean insideConstructorCall = false;
1169                 MethodBinding foundMethod = null;
1170                 ProblemMethodBinding foundFuzzyProblem = null;
1171                 // the weird method lookup case (matches method name in scope, then arg types, then visibility)
1172                 ProblemMethodBinding foundInsideProblem = null;
1173                 // inside Constructor call or inside static context
1174                 Scope scope = this;
1175                 int depth = 0;
1176                 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1177                         switch (scope.kind) {
1178                                 case METHOD_SCOPE :
1179                                         MethodScope methodScope = (MethodScope) scope;
1180                                         insideStaticContext |= methodScope.isStatic;
1181                                         insideConstructorCall |= methodScope.isConstructorCall;
1182                                         break;
1183                                 case CLASS_SCOPE :
1184                                         ClassScope classScope = (ClassScope) scope;
1185                                         SourceTypeBinding receiverType = classScope.referenceContext.binding;
1186                                         boolean isExactMatch = true;
1187                                         // retrieve an exact visible match (if possible)
1188                                         MethodBinding methodBinding =
1189                                                 (foundMethod == null)
1190                                                         ? classScope.findExactMethod(
1191                                                                 receiverType,
1192                                                                 selector,
1193                                                                 argumentTypes,
1194                                                                 invocationSite)
1195                                                         : classScope.findExactMethod(
1196                                                                 receiverType,
1197                                                                 foundMethod.selector,
1198                                                                 foundMethod.parameters,
1199                                                                 invocationSite);
1200                                         //                                              ? findExactMethod(receiverType, selector, argumentTypes, invocationSite)
1201                                         //                                              : findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite);
1202                                         if (methodBinding == null) {
1203                                                 // answers closest approximation, may not check argumentTypes or visibility
1204                                                 isExactMatch = false;
1205                                                 methodBinding =
1206                                                         classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
1207                                                 //                                      methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
1208                                         }
1209                                         if (methodBinding != null) { // skip it if we did not find anything
1210                                                 if (methodBinding.problemId() == Ambiguous) {
1211                                                         if (foundMethod == null || foundMethod.problemId() == NotVisible) {
1212                                                                 // supercedes any potential InheritedNameHidesEnclosingName problem
1213                                                                 return methodBinding;
1214                                                         }
1215                                                         // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
1216                                                         return new ProblemMethodBinding(
1217                                                                 methodBinding, // closest match
1218                                                                 selector,
1219                                                                 argumentTypes,
1220                                                                 InheritedNameHidesEnclosingName);
1221                                                 }
1222                                                 ProblemMethodBinding fuzzyProblem = null;
1223                                                 ProblemMethodBinding insideProblem = null;
1224                                                 if (methodBinding.isValidBinding()) {
1225                                                         if (!isExactMatch) {
1226                                                                 if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) {
1227                                                                         if (foundMethod == null || foundMethod.problemId() == NotVisible){
1228                                                                                 // inherited mismatch is reported directly, not looking at enclosing matches
1229                                                                                 return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
1230                                                                         }
1231                                                                         // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
1232                                                                         fuzzyProblem = new ProblemMethodBinding(selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
1233
1234                                                                 } else if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
1235                                                                         // using <classScope> instead of <this> for visibility check does grant all access to innerclass
1236                                                                         fuzzyProblem =
1237                                                                                 new ProblemMethodBinding(
1238                                                                                         methodBinding,
1239                                                                                         selector,
1240                                                                                         methodBinding.parameters,
1241                                                                                         NotVisible);
1242                                                                 }
1243                                                         }
1244                                                         if (fuzzyProblem == null && !methodBinding.isStatic()) {
1245                                                                 if (insideConstructorCall) {
1246                                                                         insideProblem =
1247                                                                                 new ProblemMethodBinding(
1248                                                                                         methodBinding, // closest match
1249                                                                                         methodBinding.selector,
1250                                                                                         methodBinding.parameters,
1251                                                                                         NonStaticReferenceInConstructorInvocation);
1252                                                                 } else if (insideStaticContext) {
1253                                                                         insideProblem =
1254                                                                                 new ProblemMethodBinding(
1255                                                                                         methodBinding, // closest match
1256                                                                                         methodBinding.selector,
1257                                                                                         methodBinding.parameters,
1258                                                                                         NonStaticReferenceInStaticContext);
1259                                                                 }
1260                                                         }
1261                                                         
1262                                                         if (receiverType == methodBinding.declaringClass
1263                                                                 || (receiverType.getMethods(selector)) != NoMethods
1264                                                                 || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)){
1265                                                                 // found a valid method in the 'immediate' scope (ie. not inherited)
1266                                                                 // OR the receiverType implemented a method with the correct name
1267                                                                 // OR in 1.4 mode (inherited visible shadows enclosing)
1268                                                                 if (foundMethod == null) {
1269                                                                         if (depth > 0){
1270                                                                                 invocationSite.setDepth(depth);
1271                                                                                 invocationSite.setActualReceiverType(receiverType);
1272                                                                         }
1273                                                                         // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
1274                                                                         if (fuzzyProblem != null)
1275                                                                                 return fuzzyProblem;
1276                                                                         if (insideProblem != null)
1277                                                                                 return insideProblem;
1278                                                                         return methodBinding;
1279                                                                 }
1280                                                                 // if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
1281                                                                 // NOTE: Unlike fields, a non visible method hides a visible method
1282                                                                 if (foundMethod.declaringClass != methodBinding.declaringClass)
1283                                                                         // ie. have we found the same method - do not trust field identity yet
1284                                                                         return new ProblemMethodBinding(
1285                                                                                 methodBinding, // closest match
1286                                                                                 methodBinding.selector,
1287                                                                                 methodBinding.parameters,
1288                                                                                 InheritedNameHidesEnclosingName);
1289                                                         }
1290                                                 }
1291
1292                                                 if (foundMethod == null
1293                                                         || (foundMethod.problemId() == NotVisible
1294                                                                 && methodBinding.problemId() != NotVisible)) {
1295                                                         // only remember the methodBinding if its the first one found or the previous one was not visible & methodBinding is...
1296                                                         // remember that private methods are visible if defined directly by an enclosing class
1297                                                         if (depth > 0){
1298                                                                 invocationSite.setDepth(depth);
1299                                                                 invocationSite.setActualReceiverType(receiverType);
1300                                                         }
1301                                                         foundFuzzyProblem = fuzzyProblem;
1302                                                         foundInsideProblem = insideProblem;
1303                                                         if (fuzzyProblem == null)
1304                                                                 foundMethod = methodBinding; // only keep it if no error was found
1305                                                 }
1306                                         }
1307                                         depth++;
1308                                         insideStaticContext |= receiverType.isStatic();
1309                                         // 1EX5I8Z - accessing outer fields within a constructor call is permitted
1310                                         // in order to do so, we change the flag as we exit from the type, not the method
1311                                         // itself, because the class scope is used to retrieve the fields.
1312                                         MethodScope enclosingMethodScope = scope.methodScope();
1313                                         insideConstructorCall =
1314                                                 enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
1315                                         break;
1316                                 case COMPILATION_UNIT_SCOPE :
1317                                         break done;
1318                         }
1319                         scope = scope.parent;
1320                 }
1321
1322                 if (foundFuzzyProblem != null)
1323                         return foundFuzzyProblem;
1324                 if (foundInsideProblem != null)
1325                         return foundInsideProblem;
1326                 if (foundMethod != null)
1327                         return foundMethod;
1328                 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1329         }
1330
1331         public final ReferenceBinding getJavaIoSerializable() {
1332                 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
1333                 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
1334                 if (type != null) return type;
1335         
1336                 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
1337                 return null; // will not get here since the above error aborts the compilation
1338         }
1339
1340         public final ReferenceBinding getJavaLangAssertionError() {
1341                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
1342                 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
1343                 if (type != null) return type;
1344                 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
1345                 return null; // will not get here since the above error aborts the compilation
1346         }
1347
1348         public final ReferenceBinding getJavaLangClass() {
1349                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
1350                 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
1351                 if (type != null) return type;
1352         
1353                 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
1354                 return null; // will not get here since the above error aborts the compilation
1355         }
1356
1357         public final ReferenceBinding getJavaLangCloneable() {
1358                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
1359                 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
1360                 if (type != null) return type;
1361         
1362                 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
1363                 return null; // will not get here since the above error aborts the compilation
1364         }
1365
1366         public final ReferenceBinding getJavaLangError() {
1367                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
1368                 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
1369                 if (type != null) return type;
1370         
1371                 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
1372                 return null; // will not get here since the above error aborts the compilation
1373         }
1374
1375         public final ReferenceBinding getJavaLangObject() {
1376                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
1377                 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
1378                 if (type != null) return type;
1379         
1380                 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
1381                 return null; // will not get here since the above error aborts the compilation
1382         }
1383
1384         public final ReferenceBinding getJavaLangRuntimeException() {
1385                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
1386                 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
1387                 if (type != null) return type;
1388         
1389                 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
1390                 return null; // will not get here since the above error aborts the compilation
1391         }
1392
1393         public final ReferenceBinding getJavaLangString() {
1394                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
1395                 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
1396                 if (type != null) return type;
1397         
1398                 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
1399                 return null; // will not get here since the above error aborts the compilation
1400         }
1401
1402         public final ReferenceBinding getJavaLangThrowable() {
1403                 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
1404                 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
1405                 if (type != null) return type;
1406         
1407                 problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
1408                 return null; // will not get here since the above error aborts the compilation
1409         }
1410
1411         /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
1412         */
1413         public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
1414                 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
1415                 if (memberType != null) return memberType;
1416                 return new ProblemReferenceBinding(typeName, NotFound);
1417         }
1418
1419         public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1420                 try {
1421                         if (receiverType.isArrayType())
1422                                 return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
1423                         if (receiverType.isBaseType())
1424                                 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1425         
1426                         ReferenceBinding currentType = (ReferenceBinding) receiverType;
1427                         if (!currentType.canBeSeenBy(this))
1428                                 return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
1429         
1430                         // retrieve an exact visible match (if possible)
1431                         MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
1432                         if (methodBinding != null) return methodBinding;
1433         
1434                         // answers closest approximation, may not check argumentTypes or visibility
1435                         methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
1436                         if (methodBinding == null)
1437                                 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1438                         if (methodBinding.isValidBinding()) {
1439                                 if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
1440                                         return new ProblemMethodBinding(
1441                                                 methodBinding,
1442                                                 selector,
1443                                                 argumentTypes,
1444                                                 NotFound);
1445                                 if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
1446                                         return new ProblemMethodBinding(
1447                                                 methodBinding,
1448                                                 selector,
1449                                                 methodBinding.parameters,
1450                                                 NotVisible);
1451                         }
1452                         return methodBinding;
1453                         
1454                 } catch (AbortCompilation e) {
1455                         e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1456                         throw e;
1457                 }
1458         }
1459
1460         /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
1461         * The name provided is a simple source name (e.g., "Object" , "Point", ...)
1462         */
1463         // The return type of this method could be ReferenceBinding if we did not answer base types.
1464         // NOTE: We could support looking for Base Types last in the search, however any code using
1465         // this feature would be extraordinarily slow.  Therefore we don't do this
1466         public final TypeBinding getType(char[] name) {
1467                 // Would like to remove this test and require senders to specially handle base types
1468                 TypeBinding binding = getBaseType(name);
1469                 if (binding != null) return binding;
1470                 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
1471         }
1472
1473         /* Answer the type binding corresponding to the compoundName.
1474         *
1475         * NOTE: If a problem binding is returned, senders should extract the compound name
1476         * from the binding & not assume the problem applies to the entire compoundName.
1477         */
1478         public final TypeBinding getType(char[][] compoundName) {
1479                 int typeNameLength = compoundName.length;
1480                 if (typeNameLength == 1) {
1481                         // Would like to remove this test and require senders to specially handle base types
1482                         TypeBinding binding = getBaseType(compoundName[0]);
1483                         if (binding != null) return binding;
1484                 }
1485
1486                 compilationUnitScope().recordQualifiedReference(compoundName);
1487                 Binding binding =
1488                         getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
1489                 if (binding == null)
1490                         return new ProblemReferenceBinding(compoundName[0], NotFound);
1491                 if (!binding.isValidBinding())
1492                         return (ReferenceBinding) binding;
1493
1494                 int currentIndex = 1;
1495                 boolean checkVisibility = false;
1496                 if (binding instanceof PackageBinding) {
1497                         PackageBinding packageBinding = (PackageBinding) binding;
1498                         while (currentIndex < typeNameLength) {
1499                                 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
1500                                 if (binding == null)
1501                                         return new ProblemReferenceBinding(
1502                                                 CharOperation.subarray(compoundName, 0, currentIndex),
1503                                                 NotFound);
1504                                 if (!binding.isValidBinding())
1505                                         return new ProblemReferenceBinding(
1506                                                 CharOperation.subarray(compoundName, 0, currentIndex),
1507                                                 binding.problemId());
1508                                 if (!(binding instanceof PackageBinding))
1509                                         break;
1510                                 packageBinding = (PackageBinding) binding;
1511                         }
1512                         if (binding instanceof PackageBinding)
1513                                 return new ProblemReferenceBinding(
1514                                         CharOperation.subarray(compoundName, 0, currentIndex),
1515                                         NotFound);
1516                         checkVisibility = true;
1517                 }
1518
1519                 // binding is now a ReferenceBinding
1520                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1521                 compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
1522                 if (checkVisibility) // handles the fall through case
1523                         if (!typeBinding.canBeSeenBy(this))
1524                                 return new ProblemReferenceBinding(
1525                                         CharOperation.subarray(compoundName, 0, currentIndex),
1526                                         typeBinding,
1527                                         NotVisible);
1528
1529                 while (currentIndex < typeNameLength) {
1530                         typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
1531                         if (!typeBinding.isValidBinding()) {
1532                                 if (typeBinding instanceof ProblemReferenceBinding) {
1533                                         ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding;
1534                                         return new ProblemReferenceBinding(
1535                                                 CharOperation.subarray(compoundName, 0, currentIndex),
1536                                                 problemBinding.original,
1537                                                 typeBinding.problemId());
1538                                 }
1539                                 return new ProblemReferenceBinding(
1540                                         CharOperation.subarray(compoundName, 0, currentIndex),
1541                                         typeBinding.problemId());
1542                         }
1543                 }
1544                 return typeBinding;
1545         }
1546
1547         /* Internal use only 
1548         */
1549         final Binding getTypeOrPackage(char[] name, int mask) {
1550                 Scope scope = this;
1551                 ReferenceBinding foundType = null;
1552                 if ((mask & TYPE) == 0) {
1553                         Scope next = scope;
1554                         while ((next = scope.parent) != null)
1555                                 scope = next;
1556                 } else {
1557                         done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1558                                 switch (scope.kind) {
1559                                         case METHOD_SCOPE :
1560                                         case BLOCK_SCOPE :
1561                                                 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
1562                                                 if (localType != null) {
1563                                                         if (foundType != null && foundType != localType)
1564                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1565                                                         return localType;
1566                                                 }
1567                                                 break;
1568                                         case CLASS_SCOPE :
1569                                                 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
1570                                                 // 6.5.5.1 - simple name favors member type over top-level type in same unit
1571                                                 ReferenceBinding memberType = findMemberType(name, sourceType);
1572                                                 if (memberType != null) { // skip it if we did not find anything
1573                                                         if (memberType.problemId() == Ambiguous) {
1574                                                                 if (foundType == null || foundType.problemId() == NotVisible)
1575                                                                         // supercedes any potential InheritedNameHidesEnclosingName problem
1576                                                                         return memberType;
1577                                                                 // make the user qualify the type, likely wants the first inherited type
1578                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1579                                                         }
1580                                                         if (memberType.isValidBinding()) {
1581                                                                 if (sourceType == memberType.enclosingType()
1582                                                                                 || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
1583                                                                         // found a valid type in the 'immediate' scope (ie. not inherited)
1584                                                                         // OR in 1.4 mode (inherited shadows enclosing)
1585                                                                         if (foundType == null)
1586                                                                                 return memberType; 
1587                                                                         if (foundType.isValidBinding())
1588                                                                                 // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
1589                                                                                 if (foundType != memberType)
1590                                                                                         return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1591                                                                 }
1592                                                         }
1593                                                         if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
1594                                                                 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
1595                                                                 foundType = memberType;
1596                                                 }
1597                                                 if (CharOperation.equals(sourceType.sourceName, name)) {
1598                                                         if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
1599                                                                 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1600                                                         return sourceType;
1601                                                 }
1602                                                 break;
1603                                         case COMPILATION_UNIT_SCOPE :
1604                                                 break done;
1605                                 }
1606                                 scope = scope.parent;
1607                         }
1608                         if (foundType != null && foundType.problemId() != NotVisible)
1609                                 return foundType;
1610                 }
1611
1612                 // at this point the scope is a compilation unit scope
1613                 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1614                 PackageBinding currentPackage = unitScope.fPackage; 
1615                 // ask for the imports + name
1616                 if ((mask & TYPE) != 0) {
1617                         // check single type imports.
1618
1619                         ImportBinding[] imports = unitScope.imports;
1620                         if (imports != null) {
1621                                 HashtableOfObject typeImports = unitScope.resolvedSingeTypeImports;
1622                                 if (typeImports != null) {
1623                                         ImportBinding typeImport = (ImportBinding) typeImports.get(name);
1624                                         if (typeImport != null) {
1625                                                 ImportReference importReference = typeImport.reference;
1626                                                 if (importReference != null) importReference.used = true;
1627                                                 return typeImport.resolvedImport; // already know its visible
1628                                         }
1629                                 } else {
1630                                         // walk all the imports since resolvedSingeTypeImports is not yet initialized
1631                                         for (int i = 0, length = imports.length; i < length; i++) {
1632                                                 ImportBinding typeImport = imports[i];
1633                                                 if (!typeImport.onDemand) {
1634                                                         if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
1635                                                                 if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1636                                                                         ImportReference importReference = typeImport.reference;
1637                                                                         if (importReference != null) importReference.used = true;
1638                                                                         return typeImport.resolvedImport; // already know its visible
1639                                                                 }
1640                                                         }
1641                                                 }
1642                                         }
1643                                 }
1644                         }
1645                         // check if the name is in the current package, skip it if its a sub-package
1646                         unitScope.recordReference(currentPackage.compoundName, name);
1647                         Binding binding = currentPackage.getTypeOrPackage(name);
1648                         if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
1649
1650                         // check on demand imports
1651                         if (imports != null) {
1652                                 boolean foundInImport = false;
1653                                 ReferenceBinding type = null;
1654                                 for (int i = 0, length = imports.length; i < length; i++) {
1655                                         ImportBinding someImport = imports[i];
1656                                         if (someImport.onDemand) {
1657                                                 Binding resolvedImport = someImport.resolvedImport;
1658                                                 ReferenceBinding temp = resolvedImport instanceof PackageBinding
1659                                                         ? findType(name, (PackageBinding) resolvedImport, currentPackage)
1660                                                         : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
1661                                                 if (temp != null) {
1662                                                         if (temp.isValidBinding()) {
1663                                                                 ImportReference importReference = someImport.reference;
1664                                                                 if (importReference != null) importReference.used = true;
1665                                                                 if (foundInImport)
1666                                                                         // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1667                                                                         return new ProblemReferenceBinding(name, Ambiguous);
1668                                                                 type = temp;
1669                                                                 foundInImport = true;
1670                                                         } else if (foundType == null) {
1671                                                                 foundType = temp;
1672                                                         }
1673                                                 }
1674                                         }
1675                                 }
1676                                 if (type != null) return type;
1677                         }
1678                 }
1679
1680                 unitScope.recordSimpleReference(name);
1681                 if ((mask & PACKAGE) != 0) {
1682                         PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
1683                         if (packageBinding != null) return packageBinding;
1684                 }
1685
1686                 // Answer error binding -- could not find name
1687                 if (foundType != null) return foundType; // problem type from above
1688                 return new ProblemReferenceBinding(name, NotFound);
1689         }
1690
1691         // Added for code assist... NOT Public API
1692         public final Binding getTypeOrPackage(char[][] compoundName) {
1693                 int nameLength = compoundName.length;
1694                 if (nameLength == 1) {
1695                         TypeBinding binding = getBaseType(compoundName[0]);
1696                         if (binding != null) return binding;
1697                 }
1698                 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
1699                 if (!binding.isValidBinding()) return binding;
1700
1701                 int currentIndex = 1;
1702                 boolean checkVisibility = false;
1703                 if (binding instanceof PackageBinding) {
1704                         PackageBinding packageBinding = (PackageBinding) binding;
1705
1706                         while (currentIndex < nameLength) {
1707                                 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
1708                                 if (binding == null)
1709                                         return new ProblemReferenceBinding(
1710                                                 CharOperation.subarray(compoundName, 0, currentIndex),
1711                                                 NotFound);
1712                                 if (!binding.isValidBinding())
1713                                         return new ProblemReferenceBinding(
1714                                                 CharOperation.subarray(compoundName, 0, currentIndex),
1715                                                 binding.problemId());
1716                                 if (!(binding instanceof PackageBinding))
1717                                         break;
1718                                 packageBinding = (PackageBinding) binding;
1719                         }
1720                         if (binding instanceof PackageBinding) return binding;
1721                         checkVisibility = true;
1722                 }
1723                 // binding is now a ReferenceBinding
1724                 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1725                 if (checkVisibility) // handles the fall through case
1726                         if (!typeBinding.canBeSeenBy(this))
1727                                 return new ProblemReferenceBinding(
1728                                         CharOperation.subarray(compoundName, 0, currentIndex),
1729                                         typeBinding,
1730                                         NotVisible);
1731
1732                 while (currentIndex < nameLength) {
1733                         typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
1734                         // checks visibility
1735                         if (!typeBinding.isValidBinding())
1736                                 return new ProblemReferenceBinding(
1737                                         CharOperation.subarray(compoundName, 0, currentIndex),
1738                                         typeBinding.problemId());
1739                 }
1740                 return typeBinding;
1741         }
1742
1743         /* Answer true if the scope is nested inside a given field declaration.
1744      * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed 
1745      * e.g. during name resolution.
1746         */
1747         public final boolean isDefinedInField(FieldBinding field) {
1748                 Scope scope = this;
1749                 do {
1750                         if (scope instanceof MethodScope) {
1751                                 MethodScope methodScope = (MethodScope) scope;
1752                                 if (methodScope.initializedField == field) return true;
1753                         }
1754                         scope = scope.parent;
1755                 } while (scope != null);
1756                 return false;
1757         }
1758
1759         /* Answer true if the scope is nested inside a given method declaration
1760         */
1761         public final boolean isDefinedInMethod(MethodBinding method) {
1762                 Scope scope = this;
1763                 do {
1764                         if (scope instanceof MethodScope) {
1765                                 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
1766                                 if (refContext instanceof AbstractMethodDeclaration
1767                                                 && ((AbstractMethodDeclaration)refContext).binding == method) {
1768                                         return true;
1769                                 }
1770                         }
1771                         scope = scope.parent;
1772                 } while (scope != null);
1773                 return false;
1774         }
1775
1776         /* Answer whether the type is defined in the same compilation unit as the receiver
1777         */
1778         public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1779                 // find the outer most enclosing type
1780                 ReferenceBinding enclosingType = type;
1781                 while ((type = enclosingType.enclosingType()) != null)
1782                         enclosingType = type;
1783
1784                 // find the compilation unit scope
1785                 Scope scope, unitScope = this;
1786                 while ((scope = unitScope.parent) != null)
1787                         unitScope = scope;
1788
1789                 // test that the enclosingType is not part of the compilation unit
1790                 SourceTypeBinding[] topLevelTypes =
1791                         ((CompilationUnitScope) unitScope).topLevelTypes;
1792                 for (int i = topLevelTypes.length; --i >= 0;)
1793                         if (topLevelTypes[i] == enclosingType)
1794                                 return true;
1795                 return false;
1796         }
1797                 
1798         /* Answer true if the scope is nested inside a given type declaration
1799         */
1800         public final boolean isDefinedInType(ReferenceBinding type) {
1801                 Scope scope = this;
1802                 do {
1803                         if (scope instanceof ClassScope)
1804                                 if (((ClassScope) scope).referenceContext.binding == type){
1805                                         return true;
1806                                 }
1807                         scope = scope.parent;
1808                 } while (scope != null);
1809                 return false;
1810         }
1811
1812         public boolean isInsideDeprecatedCode(){
1813                 switch(this.kind){
1814                         case Scope.BLOCK_SCOPE :
1815                         case Scope.METHOD_SCOPE :
1816                                 MethodScope methodScope = methodScope();
1817                                 if (!methodScope.isInsideInitializer()){
1818                                         // check method modifiers to see if deprecated
1819                                         MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1820                                         if (context != null && context.isViewedAsDeprecated()) {
1821                                                 return true;
1822                                         }
1823                                 } else {
1824                                         SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
1825                                         // inside field declaration ? check field modifier to see if deprecated
1826                                         if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated()) {
1827                                                 return true;
1828                                         }
1829                                         if (type != null && type.isViewedAsDeprecated()) {
1830                                                 return true;
1831                                         }
1832                                 }
1833                                 break;
1834                         case Scope.CLASS_SCOPE :
1835                                 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1836                                 if (context != null && context.isViewedAsDeprecated()) {
1837                                         return true;
1838                                 }
1839                                 break;
1840                 }
1841                 return false;
1842         }
1843         
1844         public final MethodScope methodScope() {
1845                 Scope scope = this;
1846                 do {
1847                         if (scope instanceof MethodScope)
1848                                 return (MethodScope) scope;
1849                         scope = scope.parent;
1850                 } while (scope != null);
1851                 return null;
1852         }
1853
1854         // Internal use only
1855         /* All methods in visible are acceptable matches for the method in question...
1856         * The methods defined by the receiver type appear before those defined by its
1857         * superclass and so on. We want to find the one which matches best.
1858         *
1859         * Since the receiver type is a class, we know each method's declaring class is
1860         * either the receiver type or one of its superclasses. It is an error if the best match
1861         * is defined by a superclass, when a lesser match is defined by the receiver type
1862         * or a closer superclass.
1863         */
1864         protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
1865
1866                 MethodBinding method = null;
1867                 MethodBinding previous = null;
1868
1869                 nextVisible : for (int i = 0; i < visibleSize; i++) {
1870                         method = visible[i];
1871                                                 
1872                         if (previous != null && method.declaringClass != previous.declaringClass)
1873                                 break; // cannot answer a method farther up the hierarchy than the first method found
1874                         if (!method.isStatic()) previous = method;  // no ambiguity for static methods
1875                         for (int j = 0; j < visibleSize; j++) {
1876                                 if (i == j) continue;
1877                                 MethodBinding next = visible[j];
1878                                 if (!areParametersAssignable(next.parameters, method.parameters))
1879                                         continue nextVisible;
1880                         }
1881                         compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1882                         return method;
1883                 }
1884                 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1885         }
1886
1887         // Internal use only
1888         /* All methods in visible are acceptable matches for the method in question...
1889         * Since the receiver type is an interface, we ignore the possibility that 2 inherited
1890         * but unrelated superinterfaces may define the same method in acceptable but
1891         * not identical ways... we just take the best match that we find since any class which
1892         * implements the receiver interface MUST implement all signatures for the method...
1893         * in which case the best match is correct.
1894         *
1895         * NOTE: This is different than javac... in the following example, the message send of
1896         * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
1897         * interface I MUST implement both signatures for bar. If this class was the receiver of
1898         * the message send instead of the interface I, then no problem would be reported.
1899         *
1900         interface I1 {
1901                 void bar(J j);
1902         }
1903         interface I2 {
1904         //      void bar(J j);
1905                 void bar(Object o);
1906         }
1907         interface I extends I1, I2 {}
1908         interface J {}
1909         
1910         class X implements J {}
1911         
1912         class Y extends X {
1913                 public void foo(I i, X x) { i.bar(x); }
1914         }
1915         */
1916         protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
1917                 MethodBinding method = null;
1918                 nextVisible : for (int i = 0; i < visibleSize; i++) {
1919                         method = visible[i];
1920                         for (int j = 0; j < visibleSize; j++) {
1921                                 if (i == j) continue;
1922                                 MethodBinding next = visible[j];
1923                                 if (!areParametersAssignable(next.parameters, method.parameters))
1924                                         continue nextVisible;
1925                         }
1926                         compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1927                         return method;
1928                 }
1929                 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1930         }
1931
1932         
1933         // Internal use only
1934         /* All methods in visible are acceptable matches for the method in question...
1935         * Since 1.4, the inherited ambiguous case has been removed from mostSpecificClassMethodBinding
1936         */
1937         protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize) {
1938                 MethodBinding method = null;
1939                 nextVisible : for (int i = 0; i < visibleSize; i++) {
1940                         method = visible[i];
1941                         for (int j = 0; j < visibleSize; j++) {
1942                                 if (i == j) continue;
1943                                 MethodBinding next = visible[j];
1944                                 if (!areParametersAssignable(next.parameters, method.parameters))
1945                                         continue nextVisible;
1946                         }
1947                         compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1948                         return method;
1949                 }
1950                 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1951         }
1952
1953         public final ClassScope outerMostClassScope() {
1954                 ClassScope lastClassScope = null;
1955                 Scope scope = this;
1956                 do {
1957                         if (scope instanceof ClassScope)
1958                                 lastClassScope = (ClassScope) scope;
1959                         scope = scope.parent;
1960                 } while (scope != null);
1961                 return lastClassScope; // may answer null if no class around
1962         }
1963
1964         public final MethodScope outerMostMethodScope() {
1965                 MethodScope lastMethodScope = null;
1966                 Scope scope = this;
1967                 do {
1968                         if (scope instanceof MethodScope)
1969                                 lastMethodScope = (MethodScope) scope;
1970                         scope = scope.parent;
1971                 } while (scope != null);
1972                 return lastMethodScope; // may answer null if no method around
1973         }
1974
1975         public abstract ProblemReporter problemReporter();
1976
1977         public final CompilationUnitDeclaration referenceCompilationUnit() {
1978                 Scope scope, unitScope = this;
1979                 while ((scope = unitScope.parent) != null)
1980                         unitScope = scope;
1981                 return ((CompilationUnitScope) unitScope).referenceContext;
1982         }
1983         // start position in this scope - for ordering scopes vs. variables
1984         int startIndex() {
1985                 return 0;
1986         }
1987         
1988         /**
1989          * Returns the immediately enclosing switchCase statement (carried by closest blockScope),
1990          */
1991         public CaseStatement switchCase() {
1992                 Scope scope = this;
1993                 do {
1994                         if (scope instanceof BlockScope)
1995                                 return ((BlockScope) scope).switchCase;
1996                         scope = scope.parent;
1997                 } while (scope != null);
1998                 return null;
1999         }
2000 }