1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
13 import net.sourceforge.phpdt.core.compiler.CharOperation;
14 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
15 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
16 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
17 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
18 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
19 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
20 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
22 public abstract class Scope
35 public final static int BLOCK_SCOPE = 1;
36 public final static int METHOD_SCOPE = 2;
37 public final static int CLASS_SCOPE = 3;
38 public final static int COMPILATION_UNIT_SCOPE = 4;
39 protected Scope(int kind, Scope parent) {
44 public abstract ProblemReporter problemReporter();
47 protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
48 if (parameters == arguments)
51 int length = parameters.length;
52 if (length != arguments.length)
55 for (int i = 0; i < length; i++)
56 if (parameters[i] != arguments[i])
57 if (!arguments[i].isCompatibleWith(parameters[i]))
62 /* Answer an int describing the relationship between the given types.
65 * EqualOrMoreSpecific : left is compatible with right
66 * MoreGeneric : right is compatible with left
68 public static int compareTypes(TypeBinding left, TypeBinding right) {
69 if (left.isCompatibleWith(right))
70 return EqualOrMoreSpecific;
71 if (right.isCompatibleWith(left))
76 /* Answer an int describing the relationship between the given type and unchecked exceptions.
79 * EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
80 * MoreGeneric : type is a supertype of an actual unchecked exception type
82 public int compareUncheckedException(ReferenceBinding type) {
83 int comparison = compareTypes(type, getJavaLangRuntimeException());
84 if (comparison != 0) return comparison;
85 return compareTypes(type, getJavaLangError());
88 public final CompilationUnitScope compilationUnitScope() {
89 Scope lastScope = null;
94 } while (scope != null);
95 return (CompilationUnitScope) lastScope;
98 public ArrayBinding createArray(TypeBinding type, int dimension) {
99 if (type.isValidBinding())
100 return environment().createArrayType(type, dimension);
102 return new ArrayBinding(type, dimension);
105 public final ClassScope enclosingClassScope() {
107 while ((scope = scope.parent) != null) {
108 if (scope instanceof ClassScope) return (ClassScope)scope;
110 return null; // may answer null if no type around
113 public final MethodScope enclosingMethodScope() {
115 while ((scope = scope.parent) != null) {
116 if (scope instanceof MethodScope) return (MethodScope)scope;
118 return null; // may answer null if no method around
121 /* Answer the receiver's enclosing source type.
123 public final SourceTypeBinding enclosingSourceType() {
126 if (scope instanceof ClassScope)
127 return ((ClassScope) scope).referenceContext.binding;
128 scope = scope.parent;
129 } while (scope != null);
132 public final LookupEnvironment environment() {
133 Scope scope, unitScope = this;
134 while ((scope = unitScope.parent) != null)
136 return ((CompilationUnitScope) unitScope).environment;
140 public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
141 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
142 return null; // know it has no member types (nor inherited member types)
144 SourceTypeBinding enclosingSourceType = enclosingSourceType();
145 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
146 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
147 if (memberType != null) {
148 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
149 if (enclosingSourceType == null
150 ? memberType.canBeSeenBy(getCurrentPackage())
151 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
154 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
160 public MethodBinding findExactMethod(
161 ReferenceBinding receiverType,
163 TypeBinding[] argumentTypes,
164 InvocationSite invocationSite) {
166 compilationUnitScope().recordTypeReference(receiverType);
167 compilationUnitScope().recordTypeReferences(argumentTypes);
168 MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
169 if (exactMethod != null) {
170 compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
171 if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
178 /* Answer the field binding that corresponds to fieldName.
179 Start the lookup at the receiverType.
180 InvocationSite implements
181 isSuperAccess(); this is used to determine if the discovered field is visible.
182 Only fields defined by the receiverType or its supertypes are answered;
183 a field of an enclosing type will not be found using this API.
185 If no visible field is discovered, null is answered.
187 public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
188 if (receiverType.isBaseType()) return null;
189 if (receiverType.isArrayType()) {
190 TypeBinding leafType = receiverType.leafComponentType();
191 if (leafType instanceof ReferenceBinding) {
192 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
193 return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
195 if (CharOperation.equals(fieldName, LENGTH))
196 return ArrayBinding.LengthField;
200 compilationUnitScope().recordTypeReference(receiverType);
202 ReferenceBinding currentType = (ReferenceBinding) receiverType;
203 if (!currentType.canBeSeenBy(this))
204 return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
206 FieldBinding field = currentType.getField(fieldName);
208 if (field.canBeSeenBy(currentType, invocationSite, this))
211 return new ProblemFieldBinding(field.declaringClass, fieldName, NotVisible);
213 // collect all superinterfaces of receiverType until the field is found in a supertype
214 ReferenceBinding[][] interfacesToVisit = null;
215 int lastPosition = -1;
216 FieldBinding visibleField = null;
217 boolean keepLooking = true;
218 boolean notVisible = false;
219 // we could hold onto the not visible field for extra error reporting
220 while (keepLooking) {
221 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
222 if (itsInterfaces != NoSuperInterfaces) {
223 if (interfacesToVisit == null)
224 interfacesToVisit = new ReferenceBinding[5][];
225 if (++lastPosition == interfacesToVisit.length)
229 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
232 interfacesToVisit[lastPosition] = itsInterfaces;
234 if ((currentType = currentType.superclass()) == null)
237 if ((field = currentType.getField(fieldName)) != null) {
239 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
240 if (visibleField == null)
241 visibleField = field;
243 return new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
250 // walk all visible interfaces to find ambiguous references
251 if (interfacesToVisit != null) {
252 ProblemFieldBinding ambiguous = null;
253 done : for (int i = 0; i <= lastPosition; i++) {
254 ReferenceBinding[] interfaces = interfacesToVisit[i];
255 for (int j = 0, length = interfaces.length; j < length; j++) {
256 ReferenceBinding anInterface = interfaces[j];
257 if ((anInterface.tagBits & InterfaceVisited) == 0) {
258 // if interface as not already been visited
259 anInterface.tagBits |= InterfaceVisited;
260 if ((field = anInterface.getField(fieldName)) != null) {
261 if (visibleField == null) {
262 visibleField = field;
264 ambiguous = new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
268 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
269 if (itsInterfaces != NoSuperInterfaces) {
270 if (++lastPosition == interfacesToVisit.length)
274 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
277 interfacesToVisit[lastPosition] = itsInterfaces;
284 // bit reinitialization
285 for (int i = 0; i <= lastPosition; i++) {
286 ReferenceBinding[] interfaces = interfacesToVisit[i];
287 for (int j = 0, length = interfaces.length; j < length; j++)
288 interfaces[j].tagBits &= ~InterfaceVisited;
290 if (ambiguous != null)
294 if (visibleField != null)
297 return new ProblemFieldBinding(currentType, fieldName, NotVisible);
302 public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
303 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
304 return null; // know it has no member types (nor inherited member types)
306 SourceTypeBinding enclosingSourceType = enclosingSourceType();
307 PackageBinding currentPackage = getCurrentPackage();
308 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
309 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
310 if (memberType != null) {
311 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
312 if (enclosingSourceType == null
313 ? memberType.canBeSeenBy(currentPackage)
314 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
317 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
320 // collect all superinterfaces of receiverType until the memberType is found in a supertype
321 ReferenceBinding currentType = enclosingType;
322 ReferenceBinding[][] interfacesToVisit = null;
323 int lastPosition = -1;
324 ReferenceBinding visibleMemberType = null;
325 boolean keepLooking = true;
326 ReferenceBinding notVisible = null;
327 // we could hold onto the not visible field for extra error reporting
328 while (keepLooking) {
329 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
330 if (itsInterfaces != NoSuperInterfaces) {
331 if (interfacesToVisit == null)
332 interfacesToVisit = new ReferenceBinding[5][];
333 if (++lastPosition == interfacesToVisit.length)
337 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
340 interfacesToVisit[lastPosition] = itsInterfaces;
342 if ((currentType = currentType.superclass()) == null)
345 compilationUnitScope().recordReference(currentType.compoundName, typeName);
346 if ((memberType = currentType.getMemberType(typeName)) != null) {
347 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
349 if (enclosingSourceType == null
350 ? memberType.canBeSeenBy(currentPackage)
351 : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
352 if (visibleMemberType == null)
353 visibleMemberType = memberType;
355 return new ProblemReferenceBinding(typeName, Ambiguous);
357 notVisible = memberType;
361 // walk all visible interfaces to find ambiguous references
362 if (interfacesToVisit != null) {
363 ProblemReferenceBinding ambiguous = null;
364 done : for (int i = 0; i <= lastPosition; i++) {
365 ReferenceBinding[] interfaces = interfacesToVisit[i];
366 for (int j = 0, length = interfaces.length; j < length; j++) {
367 ReferenceBinding anInterface = interfaces[j];
368 if ((anInterface.tagBits & InterfaceVisited) == 0) {
369 // if interface as not already been visited
370 anInterface.tagBits |= InterfaceVisited;
371 compilationUnitScope().recordReference(anInterface.compoundName, typeName);
372 if ((memberType = anInterface.getMemberType(typeName)) != null) {
373 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
374 if (visibleMemberType == null) {
375 visibleMemberType = memberType;
377 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
381 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
382 if (itsInterfaces != NoSuperInterfaces) {
383 if (++lastPosition == interfacesToVisit.length)
387 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
390 interfacesToVisit[lastPosition] = itsInterfaces;
397 // bit reinitialization
398 for (int i = 0; i <= lastPosition; i++) {
399 ReferenceBinding[] interfaces = interfacesToVisit[i];
400 for (int j = 0, length = interfaces.length; j < length; j++)
401 interfaces[j].tagBits &= ~InterfaceVisited;
403 if (ambiguous != null)
406 if (visibleMemberType != null)
407 return visibleMemberType;
408 if (notVisible != null)
409 return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
414 public MethodBinding findMethod(
415 ReferenceBinding receiverType,
417 TypeBinding[] argumentTypes,
418 InvocationSite invocationSite) {
420 ReferenceBinding currentType = receiverType;
421 MethodBinding matchingMethod = null;
422 ObjectVector found = new ObjectVector();
424 compilationUnitScope().recordTypeReference(receiverType);
425 compilationUnitScope().recordTypeReferences(argumentTypes);
427 if (currentType.isInterface()) {
428 MethodBinding[] currentMethods = currentType.getMethods(selector);
429 int currentLength = currentMethods.length;
430 if (currentLength == 1) {
431 matchingMethod = currentMethods[0];
432 } else if (currentLength > 1) {
433 found.addAll(currentMethods);
435 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
436 currentType = getJavaLangObject();
439 // boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= CompilerOptions.JDK1_4;
441 ReferenceBinding classHierarchyStart = currentType;
442 while (currentType != null) {
443 MethodBinding[] currentMethods = currentType.getMethods(selector);
444 int currentLength = currentMethods.length;
447 * if 1.4 compliant, must filter out redundant protected methods from superclasses
449 // if (isCompliant14){
450 // nextMethod: for (int i = 0; i < currentLength; i++){
451 // MethodBinding currentMethod = currentMethods[i];
452 // // protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
453 // // when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
454 // if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
455 // if (matchingMethod != null){
456 // if (currentMethod.areParametersEqual(matchingMethod)){
458 // currentMethods[i] = null; // discard this match
459 // continue nextMethod;
462 // for (int j = 0, max = found.size; j < max; j++) {
463 // if (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
465 // currentMethods[i] = null;
466 // continue nextMethod;
473 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
474 matchingMethod = currentMethods[0];
475 } else if (currentLength > 0) {
476 if (matchingMethod != null) {
477 found.add(matchingMethod);
478 matchingMethod = null;
480 // append currentMethods, filtering out null entries
481 int maxMethod = currentMethods.length;
482 if (maxMethod == currentLength) { // no method was eliminated for 1.4 compliance (see above)
483 found.addAll(currentMethods);
485 for (int i = 0, max = currentMethods.length; i < max; i++) {
486 MethodBinding currentMethod = currentMethods[i];
487 if (currentMethod != null) found.add(currentMethod);
491 currentType = currentType.superclass();
494 int foundSize = found.size;
495 if (foundSize == 0) {
496 if (matchingMethod != null && areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
497 // (if no default abstract) must explicitly look for one instead, which could be a better match
498 if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
499 // ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
500 MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);
501 if (interfaceMethod != null) return interfaceMethod;
503 return matchingMethod;
505 return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
508 MethodBinding[] candidates = new MethodBinding[foundSize];
509 int candidatesCount = 0;
510 // argument type compatibility check
511 for (int i = 0; i < foundSize; i++) {
512 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
513 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
514 candidates[candidatesCount++] = methodBinding;
516 if (candidatesCount == 1) {
517 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
518 return candidates[0]; // have not checked visibility
520 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
521 MethodBinding interfaceMethod =
522 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
523 if (interfaceMethod != null) return interfaceMethod;
525 int argLength = argumentTypes.length;
526 foundSize = found.size;
527 nextMethod : for (int i = 0; i < foundSize; i++) {
528 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
529 TypeBinding[] params = methodBinding.parameters;
530 int paramLength = params.length;
531 nextArg: for (int a = 0; a < argLength; a++) {
532 TypeBinding arg = argumentTypes[a];
533 for (int p = 0; p < paramLength; p++)
534 if (params[p] == arg)
538 return methodBinding;
540 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
544 int visiblesCount = 0;
545 for (int i = 0; i < candidatesCount; i++) {
546 MethodBinding methodBinding = candidates[i];
547 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
548 if (visiblesCount != i) {
549 candidates[i] = null;
550 candidates[visiblesCount] = methodBinding;
555 if (visiblesCount == 1) {
556 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
557 return candidates[0];
559 if (visiblesCount == 0) {
560 MethodBinding interfaceMethod =
561 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
562 if (interfaceMethod != null) return interfaceMethod;
563 return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
565 if (candidates[0].declaringClass.isClass()) {
566 return mostSpecificClassMethodBinding(candidates, visiblesCount);
568 return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
572 // abstract method lookup lookup (since maybe missing default abstract methods)
573 public MethodBinding findDefaultAbstractMethod(
574 ReferenceBinding receiverType,
576 TypeBinding[] argumentTypes,
577 InvocationSite invocationSite,
578 ReferenceBinding classHierarchyStart,
579 MethodBinding matchingMethod,
580 ObjectVector found) {
582 int startFoundSize = found.size;
583 ReferenceBinding currentType = classHierarchyStart;
584 while (currentType != null) {
585 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
586 currentType = currentType.superclass();
588 int foundSize = found.size;
589 if (foundSize == startFoundSize) return matchingMethod; // maybe null
591 MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
592 int candidatesCount = 0;
593 // argument type compatibility check
594 for (int i = startFoundSize; i < foundSize; i++) {
595 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
596 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
597 candidates[candidatesCount++] = methodBinding;
599 if (candidatesCount == 1) {
600 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
601 return candidates[0];
603 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
604 int argLength = argumentTypes.length;
605 nextMethod : for (int i = 0; i < foundSize; i++) {
606 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
607 TypeBinding[] params = methodBinding.parameters;
608 int paramLength = params.length;
609 nextArg: for (int a = 0; a < argLength; a++) {
610 TypeBinding arg = argumentTypes[a];
611 for (int p = 0; p < paramLength; p++)
612 if (params[p] == arg)
616 return methodBinding;
618 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
620 // no need to check for visibility - interface methods are public
621 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
624 public MethodBinding findMethodInSuperInterfaces(
625 ReferenceBinding currentType,
628 MethodBinding matchingMethod) {
630 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
631 if (itsInterfaces != NoSuperInterfaces) {
632 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
633 int lastPosition = -1;
634 if (++lastPosition == interfacesToVisit.length)
636 interfacesToVisit, 0,
637 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
639 interfacesToVisit[lastPosition] = itsInterfaces;
641 for (int i = 0; i <= lastPosition; i++) {
642 ReferenceBinding[] interfaces = interfacesToVisit[i];
643 for (int j = 0, length = interfaces.length; j < length; j++) {
644 currentType = interfaces[j];
645 if ((currentType.tagBits & InterfaceVisited) == 0) {
646 // if interface as not already been visited
647 currentType.tagBits |= InterfaceVisited;
649 MethodBinding[] currentMethods = currentType.getMethods(selector);
650 int currentLength = currentMethods.length;
651 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
652 matchingMethod = currentMethods[0];
653 } else if (currentLength > 0) {
654 if (matchingMethod != null) {
655 found.add(matchingMethod);
656 matchingMethod = null;
658 found.addAll(currentMethods);
660 itsInterfaces = currentType.superInterfaces();
661 if (itsInterfaces != NoSuperInterfaces) {
662 if (++lastPosition == interfacesToVisit.length)
664 interfacesToVisit, 0,
665 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
667 interfacesToVisit[lastPosition] = itsInterfaces;
673 // bit reinitialization
674 for (int i = 0; i <= lastPosition; i++) {
675 ReferenceBinding[] interfaces = interfacesToVisit[i];
676 for (int j = 0, length = interfaces.length; j < length; j++)
677 interfaces[j].tagBits &= ~InterfaceVisited;
680 return matchingMethod;
684 public MethodBinding findMethodForArray(
685 ArrayBinding receiverType,
687 TypeBinding[] argumentTypes,
688 InvocationSite invocationSite) {
690 TypeBinding leafType = receiverType.leafComponentType();
691 if (leafType instanceof ReferenceBinding) {
692 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
693 return new ProblemMethodBinding(selector, MethodBinding.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
696 ReferenceBinding object = getJavaLangObject();
697 MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
698 if (methodBinding != null) {
699 // handle the method clone() specially... cannot be protected or throw exceptions
700 if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
701 return new MethodBinding(
702 (methodBinding.modifiers ^ AccProtected) | AccPublic,
704 methodBinding.returnType,
708 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
709 return methodBinding;
711 // answers closest approximation, may not check argumentTypes or visibility
712 methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
713 if (methodBinding == null)
714 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
715 if (methodBinding.isValidBinding()) {
716 if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
717 return new ProblemMethodBinding(
722 if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
723 return new ProblemMethodBinding(
726 methodBinding.parameters,
729 return methodBinding;
733 public ReferenceBinding findType(
735 PackageBinding declarationPackage,
736 PackageBinding invocationPackage) {
738 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
739 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
740 if (typeBinding == null)
743 if (typeBinding.isValidBinding()) {
744 if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
745 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
750 public TypeBinding getBaseType(char[] name) {
751 // list should be optimized (with most often used first)
752 int length = name.length;
753 if (length > 2 && length < 8) {
756 if (length == 3 && name[1] == 'n' && name[2] == 't')
760 if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
771 return BooleanBinding;
772 if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
776 if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
786 return DoubleBinding;
797 if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
812 public final PackageBinding getCurrentPackage() {
813 Scope scope, unitScope = this;
814 while ((scope = unitScope.parent) != null)
816 return ((CompilationUnitScope) unitScope).fPackage;
819 * Returns the modifiers of the innermost enclosing declaration.
822 public int getDeclarationModifiers(){
824 case Scope.BLOCK_SCOPE :
825 case Scope.METHOD_SCOPE :
826 MethodScope methodScope = methodScope();
827 if (!methodScope.isInsideInitializer()){
828 // check method modifiers to see if deprecated
829 MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
830 if (context != null) {
831 return context.modifiers;
834 SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
836 // inside field declaration ? check field modifier to see if deprecated
837 if (methodScope.initializedField != null) {
838 return methodScope.initializedField.modifiers;
841 return type.modifiers;
845 case Scope.CLASS_SCOPE :
846 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
847 if (context != null) {
848 return context.modifiers;
855 public final ReferenceBinding getJavaIoSerializable() {
856 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
857 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
858 if (type != null) return type;
860 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
861 return null; // will not get here since the above error aborts the compilation
864 public final ReferenceBinding getJavaLangClass() {
865 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
866 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
867 if (type != null) return type;
869 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
870 return null; // will not get here since the above error aborts the compilation
873 public final ReferenceBinding getJavaLangCloneable() {
874 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
875 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
876 if (type != null) return type;
878 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
879 return null; // will not get here since the above error aborts the compilation
882 public final ReferenceBinding getJavaLangError() {
883 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
884 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
885 if (type != null) return type;
887 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
888 return null; // will not get here since the above error aborts the compilation
891 public final ReferenceBinding getJavaLangAssertionError() {
892 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
893 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
894 if (type != null) return type;
895 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
896 return null; // will not get here since the above error aborts the compilation
899 public final ReferenceBinding getJavaLangObject() {
900 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
901 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
902 if (type != null) return type;
904 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
905 return null; // will not get here since the above error aborts the compilation
908 public final ReferenceBinding getJavaLangRuntimeException() {
909 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
910 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
911 if (type != null) return type;
913 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
914 return null; // will not get here since the above error aborts the compilation
917 public final ReferenceBinding getJavaLangString() {
918 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
919 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
920 if (type != null) return type;
922 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
923 return null; // will not get here since the above error aborts the compilation
926 public final ReferenceBinding getJavaLangThrowable() {
927 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
928 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
929 if (type != null) return type;
931 // problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
932 return null; // will not get here since the above error aborts the compilation
935 /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
937 public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
938 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
939 if (memberType != null) return memberType;
940 return new ProblemReferenceBinding(typeName, NotFound);
943 /* Answer the type binding corresponding to the compoundName.
945 * NOTE: If a problem binding is returned, senders should extract the compound name
946 * from the binding & not assume the problem applies to the entire compoundName.
948 public final TypeBinding getType(char[][] compoundName) {
949 int typeNameLength = compoundName.length;
950 if (typeNameLength == 1) {
951 // Would like to remove this test and require senders to specially handle base types
952 TypeBinding binding = getBaseType(compoundName[0]);
953 if (binding != null) return binding;
956 compilationUnitScope().recordQualifiedReference(compoundName);
958 getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
960 return new ProblemReferenceBinding(compoundName[0], NotFound);
961 if (!binding.isValidBinding())
962 return (ReferenceBinding) binding;
964 int currentIndex = 1;
965 boolean checkVisibility = false;
966 if (binding instanceof PackageBinding) {
967 PackageBinding packageBinding = (PackageBinding) binding;
968 while (currentIndex < typeNameLength) {
969 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
971 return new ProblemReferenceBinding(
972 CharOperation.subarray(compoundName, 0, currentIndex),
974 if (!binding.isValidBinding())
975 return new ProblemReferenceBinding(
976 CharOperation.subarray(compoundName, 0, currentIndex),
977 binding.problemId());
978 if (!(binding instanceof PackageBinding))
980 packageBinding = (PackageBinding) binding;
982 if (binding instanceof PackageBinding)
983 return new ProblemReferenceBinding(
984 CharOperation.subarray(compoundName, 0, currentIndex),
986 checkVisibility = true;
989 // binding is now a ReferenceBinding
990 ReferenceBinding typeBinding = (ReferenceBinding) binding;
991 compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
992 if (checkVisibility) // handles the fall through case
993 if (!typeBinding.canBeSeenBy(this))
994 return new ProblemReferenceBinding(
995 CharOperation.subarray(compoundName, 0, currentIndex),
999 while (currentIndex < typeNameLength) {
1000 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
1001 if (!typeBinding.isValidBinding())
1002 return new ProblemReferenceBinding(
1003 CharOperation.subarray(compoundName, 0, currentIndex),
1004 typeBinding.problemId());
1009 /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
1010 * The name provided is a simple source name (e.g., "Object" , "Point", ...)
1012 // The return type of this method could be ReferenceBinding if we did not answer base types.
1013 // NOTE: We could support looking for Base Types last in the search, however any code using
1014 // this feature would be extraordinarily slow. Therefore we don't do this
1015 public final TypeBinding getType(char[] name) {
1016 // Would like to remove this test and require senders to specially handle base types
1017 TypeBinding binding = getBaseType(name);
1018 if (binding != null) return binding;
1019 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
1022 // Added for code assist... NOT Public API
1023 public final Binding getTypeOrPackage(char[][] compoundName) {
1024 int nameLength = compoundName.length;
1025 if (nameLength == 1) {
1026 TypeBinding binding = getBaseType(compoundName[0]);
1027 if (binding != null) return binding;
1029 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
1030 if (!binding.isValidBinding()) return binding;
1032 int currentIndex = 1;
1033 boolean checkVisibility = false;
1034 if (binding instanceof PackageBinding) {
1035 PackageBinding packageBinding = (PackageBinding) binding;
1037 while (currentIndex < nameLength) {
1038 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
1039 if (binding == null)
1040 return new ProblemReferenceBinding(
1041 CharOperation.subarray(compoundName, 0, currentIndex),
1043 if (!binding.isValidBinding())
1044 return new ProblemReferenceBinding(
1045 CharOperation.subarray(compoundName, 0, currentIndex),
1046 binding.problemId());
1047 if (!(binding instanceof PackageBinding))
1049 packageBinding = (PackageBinding) binding;
1051 if (binding instanceof PackageBinding) return binding;
1052 checkVisibility = true;
1054 // binding is now a ReferenceBinding
1055 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1056 if (checkVisibility) // handles the fall through case
1057 if (!typeBinding.canBeSeenBy(this))
1058 return new ProblemReferenceBinding(
1059 CharOperation.subarray(compoundName, 0, currentIndex),
1063 while (currentIndex < nameLength) {
1064 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
1065 // checks visibility
1066 if (!typeBinding.isValidBinding())
1067 return new ProblemReferenceBinding(
1068 CharOperation.subarray(compoundName, 0, currentIndex),
1069 typeBinding.problemId());
1074 /* Internal use only
1076 final Binding getTypeOrPackage(char[] name, int mask) {
1078 ReferenceBinding foundType = null;
1079 if ((mask & TYPE) == 0) {
1081 while ((next = scope.parent) != null)
1084 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1085 switch (scope.kind) {
1088 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
1089 if (localType != null) {
1090 if (foundType != null && foundType != localType)
1091 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1096 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
1097 // 6.5.5.1 - simple name favors member type over top-level type in same unit
1098 ReferenceBinding memberType = findMemberType(name, sourceType);
1099 if (memberType != null) { // skip it if we did not find anything
1100 if (memberType.problemId() == Ambiguous) {
1101 if (foundType == null || foundType.problemId() == NotVisible)
1102 // supercedes any potential InheritedNameHidesEnclosingName problem
1105 // make the user qualify the type, likely wants the first inherited type
1106 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1108 // if (memberType.isValidBinding()) {
1109 // if (sourceType == memberType.enclosingType()
1110 // || environment().options.complianceLevel >= CompilerOptions.JDK1_4) {
1111 // // found a valid type in the 'immediate' scope (ie. not inherited)
1112 // // OR in 1.4 mode (inherited shadows enclosing)
1113 // if (foundType == null)
1114 // return memberType;
1115 // if (foundType.isValidBinding())
1116 // // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
1117 // if (foundType != memberType)
1118 // return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1121 if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
1122 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
1123 foundType = memberType;
1125 if (CharOperation.equals(sourceType.sourceName, name)) {
1126 if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
1127 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1131 case COMPILATION_UNIT_SCOPE :
1134 scope = scope.parent;
1136 if (foundType != null && foundType.problemId() != NotVisible)
1140 // at this point the scope is a compilation unit scope
1141 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1142 PackageBinding currentPackage = unitScope.fPackage;
1143 // ask for the imports + name
1144 if ((mask & TYPE) != 0) {
1145 // check single type imports.
1146 ImportBinding[] imports = unitScope.imports;
1147 if (imports != null) {
1148 // copy the list, since single type imports are removed if they cannot be resolved
1149 for (int i = 0, length = imports.length; i < length; i++) {
1150 ImportBinding typeImport = imports[i];
1151 if (!typeImport.onDemand) {
1152 if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
1153 if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1154 ImportReference importReference = typeImport.reference;
1155 if (importReference != null) importReference.used = true;
1156 return typeImport.resolvedImport; // already know its visible
1162 // check if the name is in the current package, skip it if its a sub-package
1163 unitScope.recordReference(currentPackage.compoundName, name);
1164 Binding binding = currentPackage.getTypeOrPackage(name);
1165 if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
1167 // check on demand imports
1168 boolean foundInImport = false;
1169 ReferenceBinding type = null;
1170 if (imports != null) {
1171 for (int i = 0, length = imports.length; i < length; i++) {
1172 ImportBinding someImport = imports[i];
1173 if (someImport.onDemand) {
1174 Binding resolvedImport = someImport.resolvedImport;
1175 ReferenceBinding temp = resolvedImport instanceof PackageBinding
1176 ? findType(name, (PackageBinding) resolvedImport, currentPackage)
1177 : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
1178 if (temp != null && temp.isValidBinding()) {
1179 // ImportReference importReference = someImport.reference;
1180 // if (importReference != null) importReference.used = true;
1182 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1183 return new ProblemReferenceBinding(name, Ambiguous);
1185 foundInImport = true;
1190 if (type != null) return type;
1193 unitScope.recordSimpleReference(name);
1194 if ((mask & PACKAGE) != 0) {
1195 PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
1196 if (packageBinding != null) return packageBinding;
1199 // Answer error binding -- could not find name
1200 if (foundType != null) return foundType; // problem type from above
1201 return new ProblemReferenceBinding(name, NotFound);
1204 /* Answer whether the type is defined in the same compilation unit as the receiver
1206 public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1207 // find the outer most enclosing type
1208 ReferenceBinding enclosingType = type;
1209 while ((type = enclosingType.enclosingType()) != null)
1210 enclosingType = type;
1212 // find the compilation unit scope
1213 Scope scope, unitScope = this;
1214 while ((scope = unitScope.parent) != null)
1217 // test that the enclosingType is not part of the compilation unit
1218 SourceTypeBinding[] topLevelTypes =
1219 ((CompilationUnitScope) unitScope).topLevelTypes;
1220 for (int i = topLevelTypes.length; --i >= 0;)
1221 if (topLevelTypes[i] == enclosingType)
1226 /* Answer true if the scope is nested inside a given field declaration.
1227 * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed
1228 * e.g. during name resolution.
1230 public final boolean isDefinedInField(FieldBinding field) {
1233 if (scope instanceof MethodScope) {
1234 MethodScope methodScope = (MethodScope) scope;
1235 ReferenceContext refContext = methodScope.referenceContext;
1236 if (refContext instanceof TypeDeclaration
1237 && ((TypeDeclaration)refContext).binding == field.declaringClass
1238 && methodScope.fieldDeclarationIndex == field.id) {
1242 scope = scope.parent;
1243 } while (scope != null);
1247 /* Answer true if the scope is nested inside a given method declaration
1249 public final boolean isDefinedInMethod(MethodBinding method) {
1252 if (scope instanceof MethodScope) {
1253 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
1254 if (refContext instanceof AbstractMethodDeclaration
1255 && ((AbstractMethodDeclaration)refContext).binding == method) {
1259 scope = scope.parent;
1260 } while (scope != null);
1264 /* Answer true if the scope is nested inside a given type declaration
1266 public final boolean isDefinedInType(ReferenceBinding type) {
1269 if (scope instanceof ClassScope)
1270 if (((ClassScope) scope).referenceContext.binding == type){
1273 scope = scope.parent;
1274 } while (scope != null);
1278 public boolean isInsideDeprecatedCode(){
1280 case Scope.BLOCK_SCOPE :
1281 case Scope.METHOD_SCOPE :
1282 MethodScope methodScope = methodScope();
1283 if (!methodScope.isInsideInitializer()){
1284 // check method modifiers to see if deprecated
1285 MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1286 if (context != null && context.isViewedAsDeprecated()) {
1290 SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
1292 // inside field declaration ? check field modifier to see if deprecated
1293 if (methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl) {
1294 for (int i = 0; i < type.fields.length; i++){
1295 if (type.fields[i].id == methodScope.fieldDeclarationIndex) {
1296 // currently inside this field initialization
1297 if (type.fields[i].isViewedAsDeprecated()){
1304 if (type != null && type.isViewedAsDeprecated()) {
1309 case Scope.CLASS_SCOPE :
1310 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1311 if (context != null && context.isViewedAsDeprecated()) {
1319 public final boolean isJavaIoSerializable(TypeBinding tb) {
1320 return tb == getJavaIoSerializable();
1323 public final boolean isJavaLangCloneable(TypeBinding tb) {
1324 return tb == getJavaLangCloneable();
1327 public final boolean isJavaLangObject(TypeBinding type) {
1328 return type.id == T_JavaLangObject;
1331 public final MethodScope methodScope() {
1334 if (scope instanceof MethodScope)
1335 return (MethodScope) scope;
1336 scope = scope.parent;
1337 } while (scope != null);
1341 // Internal use only
1342 /* All methods in visible are acceptable matches for the method in question...
1343 * The methods defined by the receiver type appear before those defined by its
1344 * superclass and so on. We want to find the one which matches best.
1346 * Since the receiver type is a class, we know each method's declaring class is
1347 * either the receiver type or one of its superclasses. It is an error if the best match
1348 * is defined by a superclass, when a lesser match is defined by the receiver type
1349 * or a closer superclass.
1351 protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
1353 MethodBinding method = null;
1354 MethodBinding previous = null;
1356 nextVisible : for (int i = 0; i < visibleSize; i++) {
1357 method = visible[i];
1359 if (previous != null && method.declaringClass != previous.declaringClass)
1360 break; // cannot answer a method farther up the hierarchy than the first method found
1362 for (int j = 0; j < visibleSize; j++) {
1363 if (i == j) continue;
1364 MethodBinding next = visible[j];
1365 if (!areParametersAssignable(next.parameters, method.parameters))
1366 continue nextVisible;
1368 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1371 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1374 // Internal use only
1375 /* All methods in visible are acceptable matches for the method in question...
1376 * Since the receiver type is an interface, we ignore the possibility that 2 inherited
1377 * but unrelated superinterfaces may define the same method in acceptable but
1378 * not identical ways... we just take the best match that we find since any class which
1379 * implements the receiver interface MUST implement all signatures for the method...
1380 * in which case the best match is correct.
1382 * NOTE: This is different than javac... in the following example, the message send of
1383 * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
1384 * interface I MUST implement both signatures for bar. If this class was the receiver of
1385 * the message send instead of the interface I, then no problem would be reported.
1394 interface I extends I1, I2 {}
1397 class X implements J {}
1400 public void foo(I i, X x) { i.bar(x); }
1403 protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
1404 MethodBinding method = null;
1405 nextVisible : for (int i = 0; i < visibleSize; i++) {
1406 method = visible[i];
1407 for (int j = 0; j < visibleSize; j++) {
1408 if (i == j) continue;
1409 MethodBinding next = visible[j];
1410 if (!areParametersAssignable(next.parameters, method.parameters))
1411 continue nextVisible;
1413 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1416 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1419 public final ClassScope outerMostClassScope() {
1420 ClassScope lastClassScope = null;
1423 if (scope instanceof ClassScope)
1424 lastClassScope = (ClassScope) scope;
1425 scope = scope.parent;
1426 } while (scope != null);
1427 return lastClassScope; // may answer null if no class around
1430 public final MethodScope outerMostMethodScope() {
1431 MethodScope lastMethodScope = null;
1434 if (scope instanceof MethodScope)
1435 lastMethodScope = (MethodScope) scope;
1436 scope = scope.parent;
1437 } while (scope != null);
1438 return lastMethodScope; // may answer null if no method around
1441 public final CompilationUnitDeclaration referenceCompilationUnit() {
1442 Scope scope, unitScope = this;
1443 while ((scope = unitScope.parent) != null)
1445 return ((CompilationUnitScope) unitScope).referenceContext;
1447 // start position in this scope - for ordering scopes vs. variables