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 public final ReferenceBinding getJavaIoSerializable() {
820 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
821 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
822 if (type != null) return type;
824 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
825 return null; // will not get here since the above error aborts the compilation
828 public final ReferenceBinding getJavaLangClass() {
829 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
830 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
831 if (type != null) return type;
833 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
834 return null; // will not get here since the above error aborts the compilation
837 public final ReferenceBinding getJavaLangCloneable() {
838 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
839 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
840 if (type != null) return type;
842 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
843 return null; // will not get here since the above error aborts the compilation
846 public final ReferenceBinding getJavaLangError() {
847 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
848 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
849 if (type != null) return type;
851 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
852 return null; // will not get here since the above error aborts the compilation
855 public final ReferenceBinding getJavaLangAssertionError() {
856 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
857 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
858 if (type != null) return type;
859 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
860 return null; // will not get here since the above error aborts the compilation
863 public final ReferenceBinding getJavaLangObject() {
864 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
865 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
866 if (type != null) return type;
868 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
869 return null; // will not get here since the above error aborts the compilation
872 public final ReferenceBinding getJavaLangRuntimeException() {
873 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
874 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
875 if (type != null) return type;
877 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
878 return null; // will not get here since the above error aborts the compilation
881 public final ReferenceBinding getJavaLangString() {
882 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
883 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
884 if (type != null) return type;
886 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
887 return null; // will not get here since the above error aborts the compilation
890 public final ReferenceBinding getJavaLangThrowable() {
891 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
892 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
893 if (type != null) return type;
895 problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
896 return null; // will not get here since the above error aborts the compilation
899 /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
901 public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
902 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
903 if (memberType != null) return memberType;
904 return new ProblemReferenceBinding(typeName, NotFound);
907 /* Answer the type binding corresponding to the compoundName.
909 * NOTE: If a problem binding is returned, senders should extract the compound name
910 * from the binding & not assume the problem applies to the entire compoundName.
912 public final TypeBinding getType(char[][] compoundName) {
913 int typeNameLength = compoundName.length;
914 if (typeNameLength == 1) {
915 // Would like to remove this test and require senders to specially handle base types
916 TypeBinding binding = getBaseType(compoundName[0]);
917 if (binding != null) return binding;
920 compilationUnitScope().recordQualifiedReference(compoundName);
922 getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
924 return new ProblemReferenceBinding(compoundName[0], NotFound);
925 if (!binding.isValidBinding())
926 return (ReferenceBinding) binding;
928 int currentIndex = 1;
929 boolean checkVisibility = false;
930 if (binding instanceof PackageBinding) {
931 PackageBinding packageBinding = (PackageBinding) binding;
932 while (currentIndex < typeNameLength) {
933 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
935 return new ProblemReferenceBinding(
936 CharOperation.subarray(compoundName, 0, currentIndex),
938 if (!binding.isValidBinding())
939 return new ProblemReferenceBinding(
940 CharOperation.subarray(compoundName, 0, currentIndex),
941 binding.problemId());
942 if (!(binding instanceof PackageBinding))
944 packageBinding = (PackageBinding) binding;
946 if (binding instanceof PackageBinding)
947 return new ProblemReferenceBinding(
948 CharOperation.subarray(compoundName, 0, currentIndex),
950 checkVisibility = true;
953 // binding is now a ReferenceBinding
954 ReferenceBinding typeBinding = (ReferenceBinding) binding;
955 compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
956 if (checkVisibility) // handles the fall through case
957 if (!typeBinding.canBeSeenBy(this))
958 return new ProblemReferenceBinding(
959 CharOperation.subarray(compoundName, 0, currentIndex),
963 while (currentIndex < typeNameLength) {
964 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
965 if (!typeBinding.isValidBinding())
966 return new ProblemReferenceBinding(
967 CharOperation.subarray(compoundName, 0, currentIndex),
968 typeBinding.problemId());
973 /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
974 * The name provided is a simple source name (e.g., "Object" , "Point", ...)
976 // The return type of this method could be ReferenceBinding if we did not answer base types.
977 // NOTE: We could support looking for Base Types last in the search, however any code using
978 // this feature would be extraordinarily slow. Therefore we don't do this
979 public final TypeBinding getType(char[] name) {
980 // Would like to remove this test and require senders to specially handle base types
981 TypeBinding binding = getBaseType(name);
982 if (binding != null) return binding;
983 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
986 // Added for code assist... NOT Public API
987 public final Binding getTypeOrPackage(char[][] compoundName) {
988 int nameLength = compoundName.length;
989 if (nameLength == 1) {
990 TypeBinding binding = getBaseType(compoundName[0]);
991 if (binding != null) return binding;
993 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
994 if (!binding.isValidBinding()) return binding;
996 int currentIndex = 1;
997 boolean checkVisibility = false;
998 if (binding instanceof PackageBinding) {
999 PackageBinding packageBinding = (PackageBinding) binding;
1001 while (currentIndex < nameLength) {
1002 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
1003 if (binding == null)
1004 return new ProblemReferenceBinding(
1005 CharOperation.subarray(compoundName, 0, currentIndex),
1007 if (!binding.isValidBinding())
1008 return new ProblemReferenceBinding(
1009 CharOperation.subarray(compoundName, 0, currentIndex),
1010 binding.problemId());
1011 if (!(binding instanceof PackageBinding))
1013 packageBinding = (PackageBinding) binding;
1015 if (binding instanceof PackageBinding) return binding;
1016 checkVisibility = true;
1018 // binding is now a ReferenceBinding
1019 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1020 if (checkVisibility) // handles the fall through case
1021 if (!typeBinding.canBeSeenBy(this))
1022 return new ProblemReferenceBinding(
1023 CharOperation.subarray(compoundName, 0, currentIndex),
1027 while (currentIndex < nameLength) {
1028 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
1029 // checks visibility
1030 if (!typeBinding.isValidBinding())
1031 return new ProblemReferenceBinding(
1032 CharOperation.subarray(compoundName, 0, currentIndex),
1033 typeBinding.problemId());
1038 /* Internal use only
1040 final Binding getTypeOrPackage(char[] name, int mask) {
1042 ReferenceBinding foundType = null;
1043 if ((mask & TYPE) == 0) {
1045 while ((next = scope.parent) != null)
1048 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1049 switch (scope.kind) {
1052 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
1053 if (localType != null) {
1054 if (foundType != null && foundType != localType)
1055 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1060 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
1061 // 6.5.5.1 - simple name favors member type over top-level type in same unit
1062 ReferenceBinding memberType = findMemberType(name, sourceType);
1063 if (memberType != null) { // skip it if we did not find anything
1064 if (memberType.problemId() == Ambiguous) {
1065 if (foundType == null || foundType.problemId() == NotVisible)
1066 // supercedes any potential InheritedNameHidesEnclosingName problem
1069 // make the user qualify the type, likely wants the first inherited type
1070 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1072 // if (memberType.isValidBinding()) {
1073 // if (sourceType == memberType.enclosingType()
1074 // || environment().options.complianceLevel >= CompilerOptions.JDK1_4) {
1075 // // found a valid type in the 'immediate' scope (ie. not inherited)
1076 // // OR in 1.4 mode (inherited shadows enclosing)
1077 // if (foundType == null)
1078 // return memberType;
1079 // if (foundType.isValidBinding())
1080 // // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
1081 // if (foundType != memberType)
1082 // return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1085 if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
1086 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
1087 foundType = memberType;
1089 if (CharOperation.equals(sourceType.sourceName, name)) {
1090 if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
1091 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1095 case COMPILATION_UNIT_SCOPE :
1098 scope = scope.parent;
1100 if (foundType != null && foundType.problemId() != NotVisible)
1104 // at this point the scope is a compilation unit scope
1105 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1106 PackageBinding currentPackage = unitScope.fPackage;
1107 // ask for the imports + name
1108 if ((mask & TYPE) != 0) {
1109 // check single type imports.
1110 ImportBinding[] imports = unitScope.imports;
1111 if (imports != null) {
1112 // copy the list, since single type imports are removed if they cannot be resolved
1113 for (int i = 0, length = imports.length; i < length; i++) {
1114 ImportBinding typeImport = imports[i];
1115 if (!typeImport.onDemand) {
1116 if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
1117 if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1118 ImportReference importReference = typeImport.reference;
1119 if (importReference != null) importReference.used = true;
1120 return typeImport.resolvedImport; // already know its visible
1126 // check if the name is in the current package, skip it if its a sub-package
1127 unitScope.recordReference(currentPackage.compoundName, name);
1128 Binding binding = currentPackage.getTypeOrPackage(name);
1129 if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
1131 // check on demand imports
1132 boolean foundInImport = false;
1133 ReferenceBinding type = null;
1134 if (imports != null) {
1135 for (int i = 0, length = imports.length; i < length; i++) {
1136 ImportBinding someImport = imports[i];
1137 if (someImport.onDemand) {
1138 Binding resolvedImport = someImport.resolvedImport;
1139 ReferenceBinding temp = resolvedImport instanceof PackageBinding
1140 ? findType(name, (PackageBinding) resolvedImport, currentPackage)
1141 : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
1142 if (temp != null && temp.isValidBinding()) {
1143 // ImportReference importReference = someImport.reference;
1144 // if (importReference != null) importReference.used = true;
1146 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1147 return new ProblemReferenceBinding(name, Ambiguous);
1149 foundInImport = true;
1154 if (type != null) return type;
1157 unitScope.recordSimpleReference(name);
1158 if ((mask & PACKAGE) != 0) {
1159 PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
1160 if (packageBinding != null) return packageBinding;
1163 // Answer error binding -- could not find name
1164 if (foundType != null) return foundType; // problem type from above
1165 return new ProblemReferenceBinding(name, NotFound);
1168 /* Answer whether the type is defined in the same compilation unit as the receiver
1170 public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1171 // find the outer most enclosing type
1172 ReferenceBinding enclosingType = type;
1173 while ((type = enclosingType.enclosingType()) != null)
1174 enclosingType = type;
1176 // find the compilation unit scope
1177 Scope scope, unitScope = this;
1178 while ((scope = unitScope.parent) != null)
1181 // test that the enclosingType is not part of the compilation unit
1182 SourceTypeBinding[] topLevelTypes =
1183 ((CompilationUnitScope) unitScope).topLevelTypes;
1184 for (int i = topLevelTypes.length; --i >= 0;)
1185 if (topLevelTypes[i] == enclosingType)
1190 /* Answer true if the scope is nested inside a given field declaration.
1191 * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed
1192 * e.g. during name resolution.
1194 public final boolean isDefinedInField(FieldBinding field) {
1197 if (scope instanceof MethodScope) {
1198 MethodScope methodScope = (MethodScope) scope;
1199 ReferenceContext refContext = methodScope.referenceContext;
1200 if (refContext instanceof TypeDeclaration
1201 && ((TypeDeclaration)refContext).binding == field.declaringClass
1202 && methodScope.fieldDeclarationIndex == field.id) {
1206 scope = scope.parent;
1207 } while (scope != null);
1211 /* Answer true if the scope is nested inside a given method declaration
1213 public final boolean isDefinedInMethod(MethodBinding method) {
1216 if (scope instanceof MethodScope) {
1217 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
1218 if (refContext instanceof AbstractMethodDeclaration
1219 && ((AbstractMethodDeclaration)refContext).binding == method) {
1223 scope = scope.parent;
1224 } while (scope != null);
1228 /* Answer true if the scope is nested inside a given type declaration
1230 public final boolean isDefinedInType(ReferenceBinding type) {
1233 if (scope instanceof ClassScope)
1234 if (((ClassScope) scope).referenceContext.binding == type){
1237 scope = scope.parent;
1238 } while (scope != null);
1242 public boolean isInsideDeprecatedCode(){
1244 case Scope.BLOCK_SCOPE :
1245 case Scope.METHOD_SCOPE :
1246 MethodScope methodScope = methodScope();
1247 if (!methodScope.isInsideInitializer()){
1248 // check method modifiers to see if deprecated
1249 MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1250 if (context != null && context.isViewedAsDeprecated()) {
1254 SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
1256 // inside field declaration ? check field modifier to see if deprecated
1257 if (methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl) {
1258 for (int i = 0; i < type.fields.length; i++){
1259 if (type.fields[i].id == methodScope.fieldDeclarationIndex) {
1260 // currently inside this field initialization
1261 if (type.fields[i].isViewedAsDeprecated()){
1268 if (type != null && type.isViewedAsDeprecated()) {
1273 case Scope.CLASS_SCOPE :
1274 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1275 if (context != null && context.isViewedAsDeprecated()) {
1283 public final boolean isJavaIoSerializable(TypeBinding tb) {
1284 return tb == getJavaIoSerializable();
1287 public final boolean isJavaLangCloneable(TypeBinding tb) {
1288 return tb == getJavaLangCloneable();
1291 public final boolean isJavaLangObject(TypeBinding type) {
1292 return type.id == T_JavaLangObject;
1295 public final MethodScope methodScope() {
1298 if (scope instanceof MethodScope)
1299 return (MethodScope) scope;
1300 scope = scope.parent;
1301 } while (scope != null);
1305 // Internal use only
1306 /* All methods in visible are acceptable matches for the method in question...
1307 * The methods defined by the receiver type appear before those defined by its
1308 * superclass and so on. We want to find the one which matches best.
1310 * Since the receiver type is a class, we know each method's declaring class is
1311 * either the receiver type or one of its superclasses. It is an error if the best match
1312 * is defined by a superclass, when a lesser match is defined by the receiver type
1313 * or a closer superclass.
1315 protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
1317 MethodBinding method = null;
1318 MethodBinding previous = null;
1320 nextVisible : for (int i = 0; i < visibleSize; i++) {
1321 method = visible[i];
1323 if (previous != null && method.declaringClass != previous.declaringClass)
1324 break; // cannot answer a method farther up the hierarchy than the first method found
1326 for (int j = 0; j < visibleSize; j++) {
1327 if (i == j) continue;
1328 MethodBinding next = visible[j];
1329 if (!areParametersAssignable(next.parameters, method.parameters))
1330 continue nextVisible;
1332 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1335 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1338 // Internal use only
1339 /* All methods in visible are acceptable matches for the method in question...
1340 * Since the receiver type is an interface, we ignore the possibility that 2 inherited
1341 * but unrelated superinterfaces may define the same method in acceptable but
1342 * not identical ways... we just take the best match that we find since any class which
1343 * implements the receiver interface MUST implement all signatures for the method...
1344 * in which case the best match is correct.
1346 * NOTE: This is different than javac... in the following example, the message send of
1347 * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
1348 * interface I MUST implement both signatures for bar. If this class was the receiver of
1349 * the message send instead of the interface I, then no problem would be reported.
1358 interface I extends I1, I2 {}
1361 class X implements J {}
1364 public void foo(I i, X x) { i.bar(x); }
1367 protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
1368 MethodBinding method = null;
1369 nextVisible : for (int i = 0; i < visibleSize; i++) {
1370 method = visible[i];
1371 for (int j = 0; j < visibleSize; j++) {
1372 if (i == j) continue;
1373 MethodBinding next = visible[j];
1374 if (!areParametersAssignable(next.parameters, method.parameters))
1375 continue nextVisible;
1377 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1380 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1383 public final ClassScope outerMostClassScope() {
1384 ClassScope lastClassScope = null;
1387 if (scope instanceof ClassScope)
1388 lastClassScope = (ClassScope) scope;
1389 scope = scope.parent;
1390 } while (scope != null);
1391 return lastClassScope; // may answer null if no class around
1394 public final MethodScope outerMostMethodScope() {
1395 MethodScope lastMethodScope = null;
1398 if (scope instanceof MethodScope)
1399 lastMethodScope = (MethodScope) scope;
1400 scope = scope.parent;
1401 } while (scope != null);
1402 return lastMethodScope; // may answer null if no method around
1405 public final CompilationUnitDeclaration referenceCompilationUnit() {
1406 Scope scope, unitScope = this;
1407 while ((scope = unitScope.parent) != null)
1409 return ((CompilationUnitScope) unitScope).referenceContext;
1411 // start position in this scope - for ordering scopes vs. variables