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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.compiler.lookup;
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;
22 public abstract class Scope
23 implements BaseTypes, BindingIds, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
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;
33 protected Scope(int kind, Scope parent) {
38 /* Answer an int describing the relationship between the given types.
41 * EqualOrMoreSpecific : left is compatible with right
42 * MoreGeneric : right is compatible with left
44 public static int compareTypes(TypeBinding left, TypeBinding right) {
45 if (left.isCompatibleWith(right))
46 return EqualOrMoreSpecific;
47 if (right.isCompatibleWith(left))
53 protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
54 if (parameters == arguments)
57 int length = parameters.length;
58 if (length != arguments.length)
61 for (int i = 0; i < length; i++)
62 if (parameters[i] != arguments[i])
63 if (!arguments[i].isCompatibleWith(parameters[i]))
68 public final ClassScope classScope() {
71 if (scope instanceof ClassScope)
72 return (ClassScope) scope;
74 } while (scope != null);
78 /* Answer an int describing the relationship between the given type and unchecked exceptions.
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
84 public int compareUncheckedException(ReferenceBinding type) {
85 int comparison = compareTypes(type, getJavaLangRuntimeException());
86 if (comparison != 0) return comparison;
87 return compareTypes(type, getJavaLangError());
90 public final CompilationUnitScope compilationUnitScope() {
91 Scope lastScope = null;
96 } while (scope != null);
97 return (CompilationUnitScope) lastScope;
100 public ArrayBinding createArray(TypeBinding type, int dimension) {
101 if (!type.isValidBinding())
102 return new ArrayBinding(type, dimension);
103 return environment().createArrayType(type, dimension);
106 public final ClassScope enclosingClassScope() {
108 while ((scope = scope.parent) != null) {
109 if (scope instanceof ClassScope) return (ClassScope)scope;
111 return null; // may answer null if no type around
114 public final MethodScope enclosingMethodScope() {
116 while ((scope = scope.parent) != null) {
117 if (scope instanceof MethodScope) return (MethodScope)scope;
119 return null; // may answer null if no method around
122 /* Answer the receiver's enclosing source type.
124 public final SourceTypeBinding enclosingSourceType() {
127 if (scope instanceof ClassScope)
128 return ((ClassScope) scope).referenceContext.binding;
129 scope = scope.parent;
130 } while (scope != null);
133 public final LookupEnvironment environment() {
134 Scope scope, unitScope = this;
135 while ((scope = unitScope.parent) != null)
137 return ((CompilationUnitScope) unitScope).environment;
140 protected void faultInReceiverType(TypeBinding type) {
141 if (type.isArrayType())
142 type = ((ArrayBinding) type).leafComponentType;
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;
162 // abstract method lookup lookup (since maybe missing default abstract methods)
163 public MethodBinding findDefaultAbstractMethod(
164 ReferenceBinding receiverType,
166 TypeBinding[] argumentTypes,
167 InvocationSite invocationSite,
168 ReferenceBinding classHierarchyStart,
169 MethodBinding matchingMethod,
170 ObjectVector found) {
172 int startFoundSize = found.size;
173 ReferenceBinding currentType = classHierarchyStart;
174 while (currentType != null) {
175 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
176 currentType = currentType.superclass();
178 int foundSize = found.size;
179 if (foundSize == startFoundSize) {
180 if (matchingMethod != null) compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
181 return matchingMethod; // maybe null
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;
191 if (candidatesCount == 1) {
192 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
193 return candidates[0];
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)
208 return methodBinding;
210 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
212 // no need to check for visibility - interface methods are public
213 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
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)
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))
230 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
236 public MethodBinding findExactMethod(
237 ReferenceBinding receiverType,
239 TypeBinding[] argumentTypes,
240 InvocationSite invocationSite) {
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))
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.
262 If no visible field is discovered, null is answered.
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);
272 if (CharOperation.equals(fieldName, LENGTH))
273 return ArrayBinding.ArrayLength;
277 faultInReceiverType(receiverType);
278 compilationUnitScope().recordTypeReference(receiverType);
280 ReferenceBinding currentType = (ReferenceBinding) receiverType;
281 if (!currentType.canBeSeenBy(this))
282 return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
284 FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
286 if (field.canBeSeenBy(currentType, invocationSite, this))
288 return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible);
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)
306 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
309 interfacesToVisit[lastPosition] = itsInterfaces;
311 if ((currentType = currentType.superclass()) == null)
314 if ((field = currentType.getField(fieldName, needResolve)) != null) {
316 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
317 if (visibleField == null)
318 visibleField = field;
320 return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
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;
341 ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
345 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
346 if (itsInterfaces != NoSuperInterfaces) {
347 if (++lastPosition == interfacesToVisit.length)
351 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
354 interfacesToVisit[lastPosition] = itsInterfaces;
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;
367 if (ambiguous != null)
371 if (visibleField != null)
374 return new ProblemFieldBinding(currentType, fieldName, NotVisible);
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)
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))
393 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
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)
413 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
416 interfacesToVisit[lastPosition] = itsInterfaces;
418 if ((currentType = currentType.superclass()) == null)
421 compilationUnitScope().recordReference(currentType.compoundName, typeName);
422 if ((memberType = currentType.getMemberType(typeName)) != null) {
423 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
425 if (enclosingSourceType == null
426 ? memberType.canBeSeenBy(currentPackage)
427 : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
428 if (visibleMemberType == null)
429 visibleMemberType = memberType;
431 return new ProblemReferenceBinding(typeName, Ambiguous);
433 notVisible = memberType;
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;
453 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
457 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
458 if (itsInterfaces != NoSuperInterfaces) {
459 if (++lastPosition == interfacesToVisit.length)
463 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
466 interfacesToVisit[lastPosition] = itsInterfaces;
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;
479 if (ambiguous != null)
482 if (visibleMemberType != null)
483 return visibleMemberType;
484 if (notVisible != null)
485 return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
490 public MethodBinding findMethod(
491 ReferenceBinding receiverType,
493 TypeBinding[] argumentTypes,
494 InvocationSite invocationSite) {
496 ReferenceBinding currentType = receiverType;
497 MethodBinding matchingMethod = null;
498 ObjectVector found = new ObjectVector(); //TODO should rewrite to remove #matchingMethod since found is allocated anyway
500 faultInReceiverType(receiverType);
501 compilationUnitScope().recordTypeReference(receiverType);
502 compilationUnitScope().recordTypeReferences(argumentTypes);
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);
512 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
513 currentType = getJavaLangObject();
516 boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
518 ReferenceBinding classHierarchyStart = currentType;
519 while (currentType != null) {
520 MethodBinding[] currentMethods = currentType.getMethods(selector);
521 int currentLength = currentMethods.length;
524 * if 1.4 compliant, must filter out redundant protected methods from superclasses
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)){
535 currentMethods[i] = null; // discard this match
539 for (int j = 0, max = found.size; j < max; j++) {
540 if (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
542 currentMethods[i] = null;
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;
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);
562 for (int i = 0, max = currentMethods.length; i < max; i++) {
563 MethodBinding currentMethod = currentMethods[i];
564 if (currentMethod != null) found.add(currentMethod);
568 currentType = currentType.superclass();
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 ?
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) {
583 matchingMethod = methodBinding; // if only one match, reuse matchingMethod
584 checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
587 candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
588 candidates[0] = matchingMethod; // copy back
589 matchingMethod = null;
592 candidates[candidatesCount] = methodBinding;
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;
610 return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
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;
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)
632 return methodBinding;
634 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
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;
649 if (visiblesCount == 1) {
650 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
651 return candidates[0];
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);
660 return mostSpecificMethodBinding(candidates, visiblesCount);
661 return candidates[0].declaringClass.isClass()
662 ? mostSpecificClassMethodBinding(candidates, visiblesCount)
663 : mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
667 public MethodBinding findMethodForArray(
668 ArrayBinding receiverType,
670 TypeBinding[] argumentTypes,
671 InvocationSite invocationSite) {
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);
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,
688 methodBinding.returnType,
692 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
693 return methodBinding;
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(
706 if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
707 return new ProblemMethodBinding(
710 methodBinding.parameters,
713 return methodBinding;
716 public MethodBinding findMethodInSuperInterfaces(
717 ReferenceBinding currentType,
720 MethodBinding matchingMethod) {
722 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
723 if (itsInterfaces != NoSuperInterfaces) {
724 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
725 int lastPosition = -1;
726 if (++lastPosition == interfacesToVisit.length)
728 interfacesToVisit, 0,
729 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
731 interfacesToVisit[lastPosition] = itsInterfaces;
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;
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;
750 found.addAll(currentMethods);
752 itsInterfaces = currentType.superInterfaces();
753 if (itsInterfaces != NoSuperInterfaces) {
754 if (++lastPosition == interfacesToVisit.length)
756 interfacesToVisit, 0,
757 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
759 interfacesToVisit[lastPosition] = itsInterfaces;
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;
772 return matchingMethod;
776 public ReferenceBinding findType(
778 PackageBinding declarationPackage,
779 PackageBinding invocationPackage) {
781 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
782 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
783 if (typeBinding == null)
786 if (typeBinding.isValidBinding()) {
787 if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
788 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
793 public LocalVariableBinding findVariable(char[] variable) {
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) {
804 if (length == 3 && name[1] == 'n' && name[2] == 't')
808 if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
819 return BooleanBinding;
820 if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
824 if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
834 return DoubleBinding;
845 if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
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.
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)
870 * The VARIABLE mask has precedence over the TYPE mask.
872 * If the VARIABLE mask is not set, neither fields nor locals will be looked for.
874 * InvocationSite implements:
875 * isSuperAccess(); this is used to determine if the discovered field is visible.
877 * Limitations: cannot request FIELD independently of LOCAL, or vice versa
879 public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
882 Binding binding = null;
883 FieldBinding problemField = null;
884 if ((mask & VARIABLE) != 0) {
885 boolean insideStaticContext = false;
886 boolean insideConstructorCall = false;
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
895 ReferenceBinding foundActualReceiverType = null;
896 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
897 switch (scope.kind) {
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
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,
912 InheritedNameHidesEnclosingName);
914 invocationSite.setDepth(depth);
915 return variableBinding;
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
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,
935 InheritedNameHidesEnclosingName);
938 ProblemFieldBinding insideProblem = null;
939 if (fieldBinding.isValidBinding()) {
940 if (!fieldBinding.isStatic()) {
941 if (insideConstructorCall) {
943 new ProblemFieldBinding(
944 fieldBinding, // closest match
945 fieldBinding.declaringClass,
947 NonStaticReferenceInConstructorInvocation);
948 } else if (insideStaticContext) {
950 new ProblemFieldBinding(
951 fieldBinding, // closest match
952 fieldBinding.declaringClass,
954 NonStaticReferenceInStaticContext);
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) {
963 invocationSite.setDepth(depth);
964 invocationSite.setActualReceiverType(enclosingType);
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;
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,
977 InheritedNameHidesEnclosingName);
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...
986 foundActualReceiverType = enclosingType;
987 foundInsideProblem = insideProblem;
988 foundField = fieldBinding;
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;
1000 case COMPILATION_UNIT_SCOPE :
1003 scope = scope.parent;
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);
1016 problemField = foundField;
1020 // We did not find a local or instance variable.
1021 if ((mask & TYPE) != 0) {
1022 if ((binding = getBaseType(name)) != null)
1024 binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
1025 if (binding.isValidBinding() || mask == TYPE)
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)
1033 if (problemField != null) return problemField;
1034 return new ProblemBinding(name, enclosingSourceType(), NotFound);
1036 } catch (AbortCompilation e) {
1037 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1042 public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
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,
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,
1067 // need a more descriptive error... cannot convert from X to Y
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;
1076 if (visibleIndex == 1) return visible[0];
1077 if (visibleIndex == 0)
1078 return new ProblemMethodBinding(
1080 ConstructorDeclaration.ConstantPoolName,
1081 compatible[0].parameters,
1083 return mostSpecificClassMethodBinding(visible, visibleIndex);
1084 } catch (AbortCompilation e) {
1085 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1090 public final PackageBinding getCurrentPackage() {
1091 Scope scope, unitScope = this;
1092 while ((scope = unitScope.parent) != null)
1094 return ((CompilationUnitScope) unitScope).fPackage;
1098 * Returns the modifiers of the innermost enclosing declaration.
1101 public int getDeclarationModifiers(){
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;
1113 SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
1115 // inside field declaration ? check field modifier to see if deprecated
1116 if (methodScope.initializedField != null) {
1117 return methodScope.initializedField.modifiers;
1120 return type.modifiers;
1124 case Scope.CLASS_SCOPE :
1125 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1126 if (context != null) {
1127 return context.modifiers;
1134 public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
1136 FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/);
1137 if (field != null) return field;
1139 return new ProblemFieldBinding(
1140 receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
1143 } catch (AbortCompilation e) {
1144 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
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
1160 * If no visible method is discovered, an error binding is answered.
1162 public MethodBinding getImplicitMethod(
1164 TypeBinding[] argumentTypes,
1165 InvocationSite invocationSite) {
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
1176 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1177 switch (scope.kind) {
1179 MethodScope methodScope = (MethodScope) scope;
1180 insideStaticContext |= methodScope.isStatic;
1181 insideConstructorCall |= methodScope.isConstructorCall;
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(
1195 : classScope.findExactMethod(
1197 foundMethod.selector,
1198 foundMethod.parameters,
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;
1206 classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
1207 // methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
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;
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
1220 InheritedNameHidesEnclosingName);
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);
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);
1234 } else if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
1235 // using <classScope> instead of <this> for visibility check does grant all access to innerclass
1237 new ProblemMethodBinding(
1240 methodBinding.parameters,
1244 if (fuzzyProblem == null && !methodBinding.isStatic()) {
1245 if (insideConstructorCall) {
1247 new ProblemMethodBinding(
1248 methodBinding, // closest match
1249 methodBinding.selector,
1250 methodBinding.parameters,
1251 NonStaticReferenceInConstructorInvocation);
1252 } else if (insideStaticContext) {
1254 new ProblemMethodBinding(
1255 methodBinding, // closest match
1256 methodBinding.selector,
1257 methodBinding.parameters,
1258 NonStaticReferenceInStaticContext);
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) {
1270 invocationSite.setDepth(depth);
1271 invocationSite.setActualReceiverType(receiverType);
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;
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);
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
1298 invocationSite.setDepth(depth);
1299 invocationSite.setActualReceiverType(receiverType);
1301 foundFuzzyProblem = fuzzyProblem;
1302 foundInsideProblem = insideProblem;
1303 if (fuzzyProblem == null)
1304 foundMethod = methodBinding; // only keep it if no error was found
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;
1316 case COMPILATION_UNIT_SCOPE :
1319 scope = scope.parent;
1322 if (foundFuzzyProblem != null)
1323 return foundFuzzyProblem;
1324 if (foundInsideProblem != null)
1325 return foundInsideProblem;
1326 if (foundMethod != null)
1328 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
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;
1336 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
1337 return null; // will not get here since the above error aborts the compilation
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
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;
1353 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
1354 return null; // will not get here since the above error aborts the compilation
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;
1362 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
1363 return null; // will not get here since the above error aborts the compilation
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;
1371 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
1372 return null; // will not get here since the above error aborts the compilation
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;
1380 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
1381 return null; // will not get here since the above error aborts the compilation
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;
1389 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
1390 return null; // will not get here since the above error aborts the compilation
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;
1398 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
1399 return null; // will not get here since the above error aborts the compilation
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;
1407 problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
1408 return null; // will not get here since the above error aborts the compilation
1411 /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
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);
1419 public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1421 if (receiverType.isArrayType())
1422 return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
1423 if (receiverType.isBaseType())
1424 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1426 ReferenceBinding currentType = (ReferenceBinding) receiverType;
1427 if (!currentType.canBeSeenBy(this))
1428 return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
1430 // retrieve an exact visible match (if possible)
1431 MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
1432 if (methodBinding != null) return methodBinding;
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(
1445 if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
1446 return new ProblemMethodBinding(
1449 methodBinding.parameters,
1452 return methodBinding;
1454 } catch (AbortCompilation e) {
1455 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
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", ...)
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);
1473 /* Answer the type binding corresponding to the compoundName.
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.
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;
1486 compilationUnitScope().recordQualifiedReference(compoundName);
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;
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),
1504 if (!binding.isValidBinding())
1505 return new ProblemReferenceBinding(
1506 CharOperation.subarray(compoundName, 0, currentIndex),
1507 binding.problemId());
1508 if (!(binding instanceof PackageBinding))
1510 packageBinding = (PackageBinding) binding;
1512 if (binding instanceof PackageBinding)
1513 return new ProblemReferenceBinding(
1514 CharOperation.subarray(compoundName, 0, currentIndex),
1516 checkVisibility = true;
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),
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());
1539 return new ProblemReferenceBinding(
1540 CharOperation.subarray(compoundName, 0, currentIndex),
1541 typeBinding.problemId());
1547 /* Internal use only
1549 final Binding getTypeOrPackage(char[] name, int mask) {
1551 ReferenceBinding foundType = null;
1552 if ((mask & TYPE) == 0) {
1554 while ((next = scope.parent) != null)
1557 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1558 switch (scope.kind) {
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);
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
1577 // make the user qualify the type, likely wants the first inherited type
1578 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
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)
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);
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;
1597 if (CharOperation.equals(sourceType.sourceName, name)) {
1598 if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
1599 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1603 case COMPILATION_UNIT_SCOPE :
1606 scope = scope.parent;
1608 if (foundType != null && foundType.problemId() != NotVisible)
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.
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
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
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
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);
1662 if (temp.isValidBinding()) {
1663 ImportReference importReference = someImport.reference;
1664 if (importReference != null) importReference.used = true;
1666 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1667 return new ProblemReferenceBinding(name, Ambiguous);
1669 foundInImport = true;
1670 } else if (foundType == null) {
1676 if (type != null) return type;
1680 unitScope.recordSimpleReference(name);
1681 if ((mask & PACKAGE) != 0) {
1682 PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
1683 if (packageBinding != null) return packageBinding;
1686 // Answer error binding -- could not find name
1687 if (foundType != null) return foundType; // problem type from above
1688 return new ProblemReferenceBinding(name, NotFound);
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;
1698 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
1699 if (!binding.isValidBinding()) return binding;
1701 int currentIndex = 1;
1702 boolean checkVisibility = false;
1703 if (binding instanceof PackageBinding) {
1704 PackageBinding packageBinding = (PackageBinding) binding;
1706 while (currentIndex < nameLength) {
1707 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
1708 if (binding == null)
1709 return new ProblemReferenceBinding(
1710 CharOperation.subarray(compoundName, 0, currentIndex),
1712 if (!binding.isValidBinding())
1713 return new ProblemReferenceBinding(
1714 CharOperation.subarray(compoundName, 0, currentIndex),
1715 binding.problemId());
1716 if (!(binding instanceof PackageBinding))
1718 packageBinding = (PackageBinding) binding;
1720 if (binding instanceof PackageBinding) return binding;
1721 checkVisibility = true;
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),
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());
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.
1747 public final boolean isDefinedInField(FieldBinding field) {
1750 if (scope instanceof MethodScope) {
1751 MethodScope methodScope = (MethodScope) scope;
1752 if (methodScope.initializedField == field) return true;
1754 scope = scope.parent;
1755 } while (scope != null);
1759 /* Answer true if the scope is nested inside a given method declaration
1761 public final boolean isDefinedInMethod(MethodBinding method) {
1764 if (scope instanceof MethodScope) {
1765 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
1766 if (refContext instanceof AbstractMethodDeclaration
1767 && ((AbstractMethodDeclaration)refContext).binding == method) {
1771 scope = scope.parent;
1772 } while (scope != null);
1776 /* Answer whether the type is defined in the same compilation unit as the receiver
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;
1784 // find the compilation unit scope
1785 Scope scope, unitScope = this;
1786 while ((scope = unitScope.parent) != null)
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)
1798 /* Answer true if the scope is nested inside a given type declaration
1800 public final boolean isDefinedInType(ReferenceBinding type) {
1803 if (scope instanceof ClassScope)
1804 if (((ClassScope) scope).referenceContext.binding == type){
1807 scope = scope.parent;
1808 } while (scope != null);
1812 public boolean isInsideDeprecatedCode(){
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()) {
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()) {
1829 if (type != null && type.isViewedAsDeprecated()) {
1834 case Scope.CLASS_SCOPE :
1835 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1836 if (context != null && context.isViewedAsDeprecated()) {
1844 public final MethodScope methodScope() {
1847 if (scope instanceof MethodScope)
1848 return (MethodScope) scope;
1849 scope = scope.parent;
1850 } while (scope != null);
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.
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.
1864 protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
1866 MethodBinding method = null;
1867 MethodBinding previous = null;
1869 nextVisible : for (int i = 0; i < visibleSize; i++) {
1870 method = visible[i];
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;
1881 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1884 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
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.
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.
1907 interface I extends I1, I2 {}
1910 class X implements J {}
1913 public void foo(I i, X x) { i.bar(x); }
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;
1926 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1929 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
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
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;
1947 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1950 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1953 public final ClassScope outerMostClassScope() {
1954 ClassScope lastClassScope = null;
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
1964 public final MethodScope outerMostMethodScope() {
1965 MethodScope lastMethodScope = null;
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
1975 public abstract ProblemReporter problemReporter();
1977 public final CompilationUnitDeclaration referenceCompilationUnit() {
1978 Scope scope, unitScope = this;
1979 while ((scope = unitScope.parent) != null)
1981 return ((CompilationUnitScope) unitScope).referenceContext;
1983 // start position in this scope - for ordering scopes vs. variables
1989 * Returns the immediately enclosing switchCase statement (carried by closest blockScope),
1991 public CaseStatement switchCase() {
1994 if (scope instanceof BlockScope)
1995 return ((BlockScope) scope).switchCase;
1996 scope = scope.parent;
1997 } while (scope != null);