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.ast.AbstractMethodDeclaration;
15 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
16 import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
17 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
18 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
19 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
20 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
22 public abstract class Scope implements BaseTypes, BindingIds,
23 CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
29 public final static int BLOCK_SCOPE = 1;
31 public final static int METHOD_SCOPE = 2;
33 public final static int CLASS_SCOPE = 3;
35 public final static int COMPILATION_UNIT_SCOPE = 4;
37 protected Scope(int kind, Scope parent) {
42 public abstract ProblemReporter problemReporter();
45 protected final boolean areParametersAssignable(TypeBinding[] parameters,
46 TypeBinding[] arguments) {
47 if (parameters == arguments)
50 int length = parameters.length;
51 if (length != arguments.length)
54 for (int i = 0; i < length; i++)
55 if (parameters[i] != arguments[i])
56 if (!arguments[i].isCompatibleWith(parameters[i]))
62 * Answer an int describing the relationship between the given types.
64 * NotRelated EqualOrMoreSpecific : left is compatible with right
65 * MoreGeneric : right is compatible with left
67 public static int compareTypes(TypeBinding left, TypeBinding right) {
68 if (left.isCompatibleWith(right))
69 return EqualOrMoreSpecific;
70 if (right.isCompatibleWith(left))
76 * Answer an int describing the relationship between the given type and
77 * unchecked exceptions.
79 * NotRelated EqualOrMoreSpecific : type is known for sure to be an
80 * unchecked exception type MoreGeneric : type is a supertype of an actual
81 * unchecked exception type
83 public int compareUncheckedException(ReferenceBinding type) {
84 int comparison = compareTypes(type, getJavaLangRuntimeException());
87 return compareTypes(type, getJavaLangError());
90 public final CompilationUnitScope compilationUnitScope() {
91 Scope lastScope = null;
96 } while (scope != null);
97 return (CompilationUnitScope) lastScope;
100 public ArrayBinding createArray(TypeBinding type, int dimension) {
101 if (type.isValidBinding())
102 return environment().createArrayType(type, dimension);
104 return new ArrayBinding(type, dimension);
107 public final ClassScope enclosingClassScope() {
109 while ((scope = scope.parent) != null) {
110 if (scope instanceof ClassScope)
111 return (ClassScope) scope;
113 return null; // may answer null if no type around
116 public final MethodScope enclosingMethodScope() {
118 while ((scope = scope.parent) != null) {
119 if (scope instanceof MethodScope)
120 return (MethodScope) scope;
122 return null; // may answer null if no method around
126 * Answer the receiver's enclosing source type.
128 public final SourceTypeBinding enclosingSourceType() {
131 if (scope instanceof ClassScope)
132 return ((ClassScope) scope).referenceContext.binding;
133 scope = scope.parent;
134 } while (scope != null);
138 public final LookupEnvironment environment() {
139 Scope scope, unitScope = this;
140 while ((scope = unitScope.parent) != null)
142 return ((CompilationUnitScope) unitScope).environment;
146 public ReferenceBinding findDirectMemberType(char[] typeName,
147 ReferenceBinding enclosingType) {
148 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
149 return null; // know it has no member types (nor inherited member
152 SourceTypeBinding enclosingSourceType = enclosingSourceType();
153 compilationUnitScope().recordReference(enclosingType.compoundName,
155 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
156 if (memberType != null) {
157 compilationUnitScope().recordTypeReference(memberType); // to record
159 if (enclosingSourceType == null ? memberType
160 .canBeSeenBy(getCurrentPackage()) : memberType.canBeSeenBy(
161 enclosingType, enclosingSourceType))
164 return new ProblemReferenceBinding(typeName, memberType,
171 public MethodBinding findExactMethod(ReferenceBinding receiverType,
172 char[] selector, TypeBinding[] argumentTypes,
173 InvocationSite invocationSite) {
175 compilationUnitScope().recordTypeReference(receiverType);
176 compilationUnitScope().recordTypeReferences(argumentTypes);
177 MethodBinding exactMethod = receiverType.getExactMethod(selector,
179 if (exactMethod != null) {
180 compilationUnitScope().recordTypeReferences(
181 exactMethod.thrownExceptions);
182 if (receiverType.isInterface()
183 || exactMethod.canBeSeenBy(receiverType, invocationSite,
192 * Answer the field binding that corresponds to fieldName. Start the lookup
193 * at the receiverType. InvocationSite implements isSuperAccess(); this is
194 * used to determine if the discovered field is visible. Only fields defined
195 * by the receiverType or its supertypes are answered; a field of an
196 * enclosing type will not be found using this API.
198 * If no visible field is discovered, null is answered.
200 public FieldBinding findField(TypeBinding receiverType, char[] fieldName,
201 InvocationSite invocationSite) {
202 if (receiverType.isBaseType())
204 if (receiverType.isArrayType()) {
205 TypeBinding leafType = receiverType.leafComponentType();
206 if (leafType instanceof ReferenceBinding) {
207 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
208 return new ProblemFieldBinding((ReferenceBinding) leafType,
209 fieldName, ReceiverTypeNotVisible);
211 if (CharOperation.equals(fieldName, LENGTH))
212 return ArrayBinding.LengthField;
216 compilationUnitScope().recordTypeReference(receiverType);
218 ReferenceBinding currentType = (ReferenceBinding) receiverType;
219 if (!currentType.canBeSeenBy(this))
220 return new ProblemFieldBinding(currentType, fieldName,
221 ReceiverTypeNotVisible);
223 FieldBinding field = currentType.getField(fieldName);
225 if (field.canBeSeenBy(currentType, invocationSite, this))
228 return new ProblemFieldBinding(field.declaringClass, fieldName,
231 // collect all superinterfaces of receiverType until the field is found
233 ReferenceBinding[][] interfacesToVisit = null;
234 int lastPosition = -1;
235 FieldBinding visibleField = null;
236 boolean keepLooking = true;
237 boolean notVisible = false;
238 // we could hold onto the not visible field for extra error reporting
239 while (keepLooking) {
240 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
241 if (itsInterfaces != NoSuperInterfaces) {
242 if (interfacesToVisit == null)
243 interfacesToVisit = new ReferenceBinding[5][];
244 if (++lastPosition == interfacesToVisit.length)
249 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
251 interfacesToVisit[lastPosition] = itsInterfaces;
253 if ((currentType = currentType.superclass()) == null)
256 if ((field = currentType.getField(fieldName)) != null) {
258 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
259 if (visibleField == null)
260 visibleField = field;
262 return new ProblemFieldBinding(
263 visibleField.declaringClass, fieldName,
271 // walk all visible interfaces to find ambiguous references
272 if (interfacesToVisit != null) {
273 ProblemFieldBinding ambiguous = null;
274 done: for (int i = 0; i <= lastPosition; i++) {
275 ReferenceBinding[] interfaces = interfacesToVisit[i];
276 for (int j = 0, length = interfaces.length; j < length; j++) {
277 ReferenceBinding anInterface = interfaces[j];
278 if ((anInterface.tagBits & InterfaceVisited) == 0) {
279 // if interface as not already been visited
280 anInterface.tagBits |= InterfaceVisited;
281 if ((field = anInterface.getField(fieldName)) != null) {
282 if (visibleField == null) {
283 visibleField = field;
285 ambiguous = new ProblemFieldBinding(
286 visibleField.declaringClass, fieldName,
291 ReferenceBinding[] itsInterfaces = anInterface
293 if (itsInterfaces != NoSuperInterfaces) {
294 if (++lastPosition == interfacesToVisit.length)
299 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
301 interfacesToVisit[lastPosition] = itsInterfaces;
308 // bit reinitialization
309 for (int i = 0; i <= lastPosition; i++) {
310 ReferenceBinding[] interfaces = interfacesToVisit[i];
311 for (int j = 0, length = interfaces.length; j < length; j++)
312 interfaces[j].tagBits &= ~InterfaceVisited;
314 if (ambiguous != null)
318 if (visibleField != null)
321 return new ProblemFieldBinding(currentType, fieldName, NotVisible);
326 public ReferenceBinding findMemberType(char[] typeName,
327 ReferenceBinding enclosingType) {
328 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
329 return null; // know it has no member types (nor inherited member
332 SourceTypeBinding enclosingSourceType = enclosingSourceType();
333 PackageBinding currentPackage = getCurrentPackage();
334 compilationUnitScope().recordReference(enclosingType.compoundName,
336 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
337 if (memberType != null) {
338 compilationUnitScope().recordTypeReference(memberType); // to record
340 if (enclosingSourceType == null ? memberType
341 .canBeSeenBy(currentPackage) : memberType.canBeSeenBy(
342 enclosingType, enclosingSourceType))
345 return new ProblemReferenceBinding(typeName, memberType,
349 // collect all superinterfaces of receiverType until the memberType is
350 // found in a supertype
351 ReferenceBinding currentType = enclosingType;
352 ReferenceBinding[][] interfacesToVisit = null;
353 int lastPosition = -1;
354 ReferenceBinding visibleMemberType = null;
355 boolean keepLooking = true;
356 ReferenceBinding notVisible = null;
357 // we could hold onto the not visible field for extra error reporting
358 while (keepLooking) {
359 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
360 if (itsInterfaces != NoSuperInterfaces) {
361 if (interfacesToVisit == null)
362 interfacesToVisit = new ReferenceBinding[5][];
363 if (++lastPosition == interfacesToVisit.length)
368 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
370 interfacesToVisit[lastPosition] = itsInterfaces;
372 if ((currentType = currentType.superclass()) == null)
375 compilationUnitScope().recordReference(currentType.compoundName,
377 if ((memberType = currentType.getMemberType(typeName)) != null) {
378 compilationUnitScope().recordTypeReference(memberType); // to
382 if (enclosingSourceType == null ? memberType
383 .canBeSeenBy(currentPackage) : memberType.canBeSeenBy(
384 enclosingType, enclosingSourceType)) {
385 if (visibleMemberType == null)
386 visibleMemberType = memberType;
388 return new ProblemReferenceBinding(typeName, Ambiguous);
390 notVisible = memberType;
394 // walk all visible interfaces to find ambiguous references
395 if (interfacesToVisit != null) {
396 ProblemReferenceBinding ambiguous = null;
397 done: for (int i = 0; i <= lastPosition; i++) {
398 ReferenceBinding[] interfaces = interfacesToVisit[i];
399 for (int j = 0, length = interfaces.length; j < length; j++) {
400 ReferenceBinding anInterface = interfaces[j];
401 if ((anInterface.tagBits & InterfaceVisited) == 0) {
402 // if interface as not already been visited
403 anInterface.tagBits |= InterfaceVisited;
404 compilationUnitScope().recordReference(
405 anInterface.compoundName, typeName);
406 if ((memberType = anInterface.getMemberType(typeName)) != null) {
407 compilationUnitScope().recordTypeReference(
408 memberType); // to record supertypes
409 if (visibleMemberType == null) {
410 visibleMemberType = memberType;
412 ambiguous = new ProblemReferenceBinding(
413 typeName, Ambiguous);
417 ReferenceBinding[] itsInterfaces = anInterface
419 if (itsInterfaces != NoSuperInterfaces) {
420 if (++lastPosition == interfacesToVisit.length)
425 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
427 interfacesToVisit[lastPosition] = itsInterfaces;
434 // bit reinitialization
435 for (int i = 0; i <= lastPosition; i++) {
436 ReferenceBinding[] interfaces = interfacesToVisit[i];
437 for (int j = 0, length = interfaces.length; j < length; j++)
438 interfaces[j].tagBits &= ~InterfaceVisited;
440 if (ambiguous != null)
443 if (visibleMemberType != null)
444 return visibleMemberType;
445 if (notVisible != null)
446 return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
451 public MethodBinding findMethod(ReferenceBinding receiverType,
452 char[] selector, TypeBinding[] argumentTypes,
453 InvocationSite invocationSite) {
455 ReferenceBinding currentType = receiverType;
456 MethodBinding matchingMethod = null;
457 ObjectVector found = new ObjectVector();
459 compilationUnitScope().recordTypeReference(receiverType);
460 compilationUnitScope().recordTypeReferences(argumentTypes);
462 if (currentType.isInterface()) {
463 MethodBinding[] currentMethods = currentType.getMethods(selector);
464 int currentLength = currentMethods.length;
465 if (currentLength == 1) {
466 matchingMethod = currentMethods[0];
467 } else if (currentLength > 1) {
468 found.addAll(currentMethods);
470 matchingMethod = findMethodInSuperInterfaces(currentType, selector,
471 found, matchingMethod);
472 currentType = getJavaLangObject();
475 // boolean isCompliant14 =
476 // compilationUnitScope().environment.options.complianceLevel >=
477 // CompilerOptions.JDK1_4;
479 ReferenceBinding classHierarchyStart = currentType;
480 while (currentType != null) {
481 MethodBinding[] currentMethods = currentType.getMethods(selector);
482 int currentLength = currentMethods.length;
485 * if 1.4 compliant, must filter out redundant protected methods
488 // if (isCompliant14){
489 // nextMethod: for (int i = 0; i < currentLength; i++){
490 // MethodBinding currentMethod = currentMethods[i];
491 // // protected method need to be checked only - default access is
492 // already dealt with in #canBeSeen implementation
493 // // when checking that p.C -> q.B -> p.A cannot see default access
494 // members from A through B.
495 // if ((currentMethod.modifiers & AccProtected) == 0) continue
497 // if (matchingMethod != null){
498 // if (currentMethod.areParametersEqual(matchingMethod)){
500 // currentMethods[i] = null; // discard this match
501 // continue nextMethod;
504 // for (int j = 0, max = found.size; j < max; j++) {
506 // (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
508 // currentMethods[i] = null;
509 // continue nextMethod;
515 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
516 matchingMethod = currentMethods[0];
517 } else if (currentLength > 0) {
518 if (matchingMethod != null) {
519 found.add(matchingMethod);
520 matchingMethod = null;
522 // append currentMethods, filtering out null entries
523 int maxMethod = currentMethods.length;
524 if (maxMethod == currentLength) { // no method was eliminated
525 // for 1.4 compliance (see
527 found.addAll(currentMethods);
529 for (int i = 0, max = currentMethods.length; i < max; i++) {
530 MethodBinding currentMethod = currentMethods[i];
531 if (currentMethod != null)
532 found.add(currentMethod);
536 currentType = currentType.superclass();
539 int foundSize = found.size;
540 if (foundSize == 0) {
541 if (matchingMethod != null
542 && areParametersAssignable(matchingMethod.parameters,
544 // (if no default abstract) must explicitly look for one
545 // instead, which could be a better match
546 if (!matchingMethod.canBeSeenBy(receiverType, invocationSite,
548 // ignore matching method (to be consistent with multiple
549 // matches, none visible (matching method is then null)
550 MethodBinding interfaceMethod = findDefaultAbstractMethod(
551 receiverType, selector, argumentTypes,
552 invocationSite, classHierarchyStart, null, found);
553 if (interfaceMethod != null)
554 return interfaceMethod;
556 return matchingMethod;
558 return findDefaultAbstractMethod(receiverType, selector,
559 argumentTypes, invocationSite, classHierarchyStart,
560 matchingMethod, found);
563 MethodBinding[] candidates = new MethodBinding[foundSize];
564 int candidatesCount = 0;
565 // argument type compatibility check
566 for (int i = 0; i < foundSize; i++) {
567 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
568 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
569 candidates[candidatesCount++] = methodBinding;
571 if (candidatesCount == 1) {
572 compilationUnitScope().recordTypeReferences(
573 candidates[0].thrownExceptions);
574 return candidates[0]; // have not checked visibility
576 if (candidatesCount == 0) { // try to find a close match when the
577 // parameter order is wrong or missing some
579 MethodBinding interfaceMethod = findDefaultAbstractMethod(
580 receiverType, selector, argumentTypes, invocationSite,
581 classHierarchyStart, matchingMethod, found);
582 if (interfaceMethod != null)
583 return interfaceMethod;
585 int argLength = argumentTypes.length;
586 foundSize = found.size;
587 nextMethod: for (int i = 0; i < foundSize; i++) {
588 MethodBinding methodBinding = (MethodBinding) found
590 TypeBinding[] params = methodBinding.parameters;
591 int paramLength = params.length;
592 nextArg: for (int a = 0; a < argLength; a++) {
593 TypeBinding arg = argumentTypes[a];
594 for (int p = 0; p < paramLength; p++)
595 if (params[p] == arg)
599 return methodBinding;
601 return (MethodBinding) found.elementAt(0); // no good match so just
607 int visiblesCount = 0;
608 for (int i = 0; i < candidatesCount; i++) {
609 MethodBinding methodBinding = candidates[i];
610 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
611 if (visiblesCount != i) {
612 candidates[i] = null;
613 candidates[visiblesCount] = methodBinding;
618 if (visiblesCount == 1) {
619 compilationUnitScope().recordTypeReferences(
620 candidates[0].thrownExceptions);
621 return candidates[0];
623 if (visiblesCount == 0) {
624 MethodBinding interfaceMethod = findDefaultAbstractMethod(
625 receiverType, selector, argumentTypes, invocationSite,
626 classHierarchyStart, matchingMethod, found);
627 if (interfaceMethod != null)
628 return interfaceMethod;
629 return new ProblemMethodBinding(candidates[0],
630 candidates[0].selector, candidates[0].parameters,
633 if (candidates[0].declaringClass.isClass()) {
634 return mostSpecificClassMethodBinding(candidates, visiblesCount);
636 return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
640 // abstract method lookup lookup (since maybe missing default abstract
642 public MethodBinding findDefaultAbstractMethod(
643 ReferenceBinding receiverType, char[] selector,
644 TypeBinding[] argumentTypes, InvocationSite invocationSite,
645 ReferenceBinding classHierarchyStart, MethodBinding matchingMethod,
646 ObjectVector found) {
648 int startFoundSize = found.size;
649 ReferenceBinding currentType = classHierarchyStart;
650 while (currentType != null) {
651 matchingMethod = findMethodInSuperInterfaces(currentType, selector,
652 found, matchingMethod);
653 currentType = currentType.superclass();
655 int foundSize = found.size;
656 if (foundSize == startFoundSize)
657 return matchingMethod; // maybe null
659 MethodBinding[] candidates = new MethodBinding[foundSize
661 int candidatesCount = 0;
662 // argument type compatibility check
663 for (int i = startFoundSize; i < foundSize; i++) {
664 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
665 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
666 candidates[candidatesCount++] = methodBinding;
668 if (candidatesCount == 1) {
669 compilationUnitScope().recordTypeReferences(
670 candidates[0].thrownExceptions);
671 return candidates[0];
673 if (candidatesCount == 0) { // try to find a close match when the
674 // parameter order is wrong or missing some
676 int argLength = argumentTypes.length;
677 nextMethod: for (int i = 0; i < foundSize; i++) {
678 MethodBinding methodBinding = (MethodBinding) found
680 TypeBinding[] params = methodBinding.parameters;
681 int paramLength = params.length;
682 nextArg: for (int a = 0; a < argLength; a++) {
683 TypeBinding arg = argumentTypes[a];
684 for (int p = 0; p < paramLength; p++)
685 if (params[p] == arg)
689 return methodBinding;
691 return (MethodBinding) found.elementAt(0); // no good match so just
695 // no need to check for visibility - interface methods are public
696 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
699 public MethodBinding findMethodInSuperInterfaces(
700 ReferenceBinding currentType, char[] selector, ObjectVector found,
701 MethodBinding matchingMethod) {
703 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
704 if (itsInterfaces != NoSuperInterfaces) {
705 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
706 int lastPosition = -1;
707 if (++lastPosition == interfacesToVisit.length)
712 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
714 interfacesToVisit[lastPosition] = itsInterfaces;
716 for (int i = 0; i <= lastPosition; i++) {
717 ReferenceBinding[] interfaces = interfacesToVisit[i];
718 for (int j = 0, length = interfaces.length; j < length; j++) {
719 currentType = interfaces[j];
720 if ((currentType.tagBits & InterfaceVisited) == 0) {
721 // if interface as not already been visited
722 currentType.tagBits |= InterfaceVisited;
724 MethodBinding[] currentMethods = currentType
725 .getMethods(selector);
726 int currentLength = currentMethods.length;
727 if (currentLength == 1 && matchingMethod == null
728 && found.size == 0) {
729 matchingMethod = currentMethods[0];
730 } else if (currentLength > 0) {
731 if (matchingMethod != null) {
732 found.add(matchingMethod);
733 matchingMethod = null;
735 found.addAll(currentMethods);
737 itsInterfaces = currentType.superInterfaces();
738 if (itsInterfaces != NoSuperInterfaces) {
739 if (++lastPosition == interfacesToVisit.length)
744 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
746 interfacesToVisit[lastPosition] = itsInterfaces;
752 // bit reinitialization
753 for (int i = 0; i <= lastPosition; i++) {
754 ReferenceBinding[] interfaces = interfacesToVisit[i];
755 for (int j = 0, length = interfaces.length; j < length; j++)
756 interfaces[j].tagBits &= ~InterfaceVisited;
759 return matchingMethod;
763 public MethodBinding findMethodForArray(ArrayBinding receiverType,
764 char[] selector, TypeBinding[] argumentTypes,
765 InvocationSite invocationSite) {
767 TypeBinding leafType = receiverType.leafComponentType();
768 if (leafType instanceof ReferenceBinding) {
769 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
770 return new ProblemMethodBinding(selector,
771 MethodBinding.NoParameters,
772 (ReferenceBinding) leafType, ReceiverTypeNotVisible);
775 ReferenceBinding object = getJavaLangObject();
776 MethodBinding methodBinding = object.getExactMethod(selector,
778 if (methodBinding != null) {
779 // handle the method clone() specially... cannot be protected or
781 if (argumentTypes == NoParameters
782 && CharOperation.equals(selector, CLONE))
783 return new MethodBinding(
784 (methodBinding.modifiers ^ AccProtected) | AccPublic,
785 CLONE, methodBinding.returnType, argumentTypes, null,
787 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
788 return methodBinding;
790 // answers closest approximation, may not check argumentTypes or
792 methodBinding = findMethod(object, selector, argumentTypes,
794 if (methodBinding == null)
795 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
796 if (methodBinding.isValidBinding()) {
797 if (!areParametersAssignable(methodBinding.parameters,
799 return new ProblemMethodBinding(methodBinding, selector,
800 argumentTypes, NotFound);
801 if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
802 return new ProblemMethodBinding(methodBinding, selector,
803 methodBinding.parameters, NotVisible);
805 return methodBinding;
809 public ReferenceBinding findType(char[] typeName,
810 PackageBinding declarationPackage, PackageBinding invocationPackage) {
812 compilationUnitScope().recordReference(declarationPackage.compoundName,
814 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
815 if (typeBinding == null)
818 if (typeBinding.isValidBinding()) {
819 if (declarationPackage != invocationPackage
820 && !typeBinding.canBeSeenBy(invocationPackage))
821 return new ProblemReferenceBinding(typeName, typeBinding,
827 public TypeBinding getBaseType(char[] name) {
828 // list should be optimized (with most often used first)
829 int length = name.length;
830 if (length > 2 && length < 8) {
833 if (length == 3 && name[1] == 'n' && name[2] == 't')
837 if (length == 4 && name[1] == 'o' && name[2] == 'i'
842 if (length == 7 && name[1] == 'o' && name[2] == 'o'
843 && name[3] == 'l' && name[4] == 'e' && name[5] == 'a'
845 return BooleanBinding;
846 if (length == 4 && name[1] == 'y' && name[2] == 't'
851 if (length == 4 && name[1] == 'h' && name[2] == 'a'
856 if (length == 6 && name[1] == 'o' && name[2] == 'u'
857 && name[3] == 'b' && name[4] == 'l' && name[5] == 'e')
858 return DoubleBinding;
861 if (length == 5 && name[1] == 'l' && name[2] == 'o'
862 && name[3] == 'a' && name[4] == 't')
866 if (length == 4 && name[1] == 'o' && name[2] == 'n'
871 if (length == 5 && name[1] == 'h' && name[2] == 'o'
872 && name[3] == 'r' && name[4] == 't')
879 public final PackageBinding getCurrentPackage() {
880 Scope scope, unitScope = this;
881 while ((scope = unitScope.parent) != null)
883 return ((CompilationUnitScope) unitScope).fPackage;
887 * Returns the modifiers of the innermost enclosing declaration.
891 public int getDeclarationModifiers() {
893 case Scope.BLOCK_SCOPE:
894 case Scope.METHOD_SCOPE:
895 MethodScope methodScope = methodScope();
896 if (!methodScope.isInsideInitializer()) {
897 // check method modifiers to see if deprecated
898 MethodBinding context = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
899 if (context != null) {
900 return context.modifiers;
903 SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
905 // inside field declaration ? check field modifier to see if
907 if (methodScope.initializedField != null) {
908 return methodScope.initializedField.modifiers;
911 return type.modifiers;
915 case Scope.CLASS_SCOPE:
916 ReferenceBinding context = ((ClassScope) this).referenceType().binding;
917 if (context != null) {
918 return context.modifiers;
925 public final ReferenceBinding getJavaIoSerializable() {
926 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
927 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
931 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE,
932 referenceCompilationUnit());
933 return null; // will not get here since the above error aborts the
937 public final ReferenceBinding getJavaLangClass() {
938 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
939 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
943 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS,
944 referenceCompilationUnit());
945 return null; // will not get here since the above error aborts the
949 public final ReferenceBinding getJavaLangCloneable() {
950 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
951 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
955 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE,
956 referenceCompilationUnit());
957 return null; // will not get here since the above error aborts the
961 public final ReferenceBinding getJavaLangError() {
962 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
963 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
967 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR,
968 referenceCompilationUnit());
969 return null; // will not get here since the above error aborts the
973 public final ReferenceBinding getJavaLangAssertionError() {
974 compilationUnitScope().recordQualifiedReference(
975 JAVA_LANG_ASSERTIONERROR);
976 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
979 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR,
980 referenceCompilationUnit());
981 return null; // will not get here since the above error aborts the
985 public final ReferenceBinding getJavaLangObject() {
986 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
987 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
991 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT,
992 referenceCompilationUnit());
993 return null; // will not get here since the above error aborts the
997 public final ReferenceBinding getJavaLangRuntimeException() {
998 compilationUnitScope().recordQualifiedReference(
999 JAVA_LANG_RUNTIMEEXCEPTION);
1000 ReferenceBinding type = environment().getType(
1001 JAVA_LANG_RUNTIMEEXCEPTION);
1005 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION,
1006 referenceCompilationUnit());
1007 return null; // will not get here since the above error aborts the
1011 public final ReferenceBinding getJavaLangString() {
1012 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
1013 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
1017 problemReporter().isClassPathCorrect(JAVA_LANG_STRING,
1018 referenceCompilationUnit());
1019 return null; // will not get here since the above error aborts the
1023 public final ReferenceBinding getJavaLangThrowable() {
1024 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
1025 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
1029 // problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE,
1030 // referenceCompilationUnit());
1031 return null; // will not get here since the above error aborts the
1036 * Answer the type binding corresponding to the typeName argument, relative
1037 * to the enclosingType.
1039 public final ReferenceBinding getMemberType(char[] typeName,
1040 ReferenceBinding enclosingType) {
1041 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
1042 if (memberType != null)
1044 return new ProblemReferenceBinding(typeName, NotFound);
1048 * Answer the type binding corresponding to the compoundName.
1050 * NOTE: If a problem binding is returned, senders should extract the
1051 * compound name from the binding & not assume the problem applies to the
1052 * entire compoundName.
1054 public final TypeBinding getType(char[][] compoundName) {
1055 int typeNameLength = compoundName.length;
1056 if (typeNameLength == 1) {
1057 // Would like to remove this test and require senders to specially
1058 // handle base types
1059 TypeBinding binding = getBaseType(compoundName[0]);
1060 if (binding != null)
1064 compilationUnitScope().recordQualifiedReference(compoundName);
1065 Binding binding = getTypeOrPackage(compoundName[0],
1066 typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
1067 if (binding == null)
1068 return new ProblemReferenceBinding(compoundName[0], NotFound);
1069 if (!binding.isValidBinding())
1070 return (ReferenceBinding) binding;
1072 int currentIndex = 1;
1073 boolean checkVisibility = false;
1074 if (binding instanceof PackageBinding) {
1075 PackageBinding packageBinding = (PackageBinding) binding;
1076 while (currentIndex < typeNameLength) {
1077 binding = packageBinding
1078 .getTypeOrPackage(compoundName[currentIndex++]); // does
1082 if (binding == null)
1083 return new ProblemReferenceBinding(CharOperation.subarray(
1084 compoundName, 0, currentIndex), NotFound);
1085 if (!binding.isValidBinding())
1086 return new ProblemReferenceBinding(CharOperation.subarray(
1087 compoundName, 0, currentIndex), binding.problemId());
1088 if (!(binding instanceof PackageBinding))
1090 packageBinding = (PackageBinding) binding;
1092 if (binding instanceof PackageBinding)
1093 return new ProblemReferenceBinding(CharOperation.subarray(
1094 compoundName, 0, currentIndex), NotFound);
1095 checkVisibility = true;
1098 // binding is now a ReferenceBinding
1099 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1100 compilationUnitScope().recordTypeReference(typeBinding); // to record
1102 if (checkVisibility) // handles the fall through case
1103 if (!typeBinding.canBeSeenBy(this))
1104 return new ProblemReferenceBinding(CharOperation.subarray(
1105 compoundName, 0, currentIndex), typeBinding, NotVisible);
1107 while (currentIndex < typeNameLength) {
1108 typeBinding = getMemberType(compoundName[currentIndex++],
1110 if (!typeBinding.isValidBinding())
1111 return new ProblemReferenceBinding(CharOperation.subarray(
1112 compoundName, 0, currentIndex), typeBinding.problemId());
1118 * Answer the type binding that corresponds the given name, starting the
1119 * lookup in the receiver. The name provided is a simple source name (e.g.,
1120 * "Object" , "Point", ...)
1122 // The return type of this method could be ReferenceBinding if we did not
1123 // answer base types.
1124 // NOTE: We could support looking for Base Types last in the search, however
1126 // this feature would be extraordinarily slow. Therefore we don't do this
1127 public final TypeBinding getType(char[] name) {
1128 // Would like to remove this test and require senders to specially
1129 // handle base types
1130 TypeBinding binding = getBaseType(name);
1131 if (binding != null)
1133 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
1136 // Added for code assist... NOT Public API
1137 public final Binding getTypeOrPackage(char[][] compoundName) {
1138 int nameLength = compoundName.length;
1139 if (nameLength == 1) {
1140 TypeBinding binding = getBaseType(compoundName[0]);
1141 if (binding != null)
1144 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
1145 if (!binding.isValidBinding())
1148 int currentIndex = 1;
1149 boolean checkVisibility = false;
1150 if (binding instanceof PackageBinding) {
1151 PackageBinding packageBinding = (PackageBinding) binding;
1153 while (currentIndex < nameLength) {
1154 binding = packageBinding
1155 .getTypeOrPackage(compoundName[currentIndex++]);
1156 if (binding == null)
1157 return new ProblemReferenceBinding(CharOperation.subarray(
1158 compoundName, 0, currentIndex), NotFound);
1159 if (!binding.isValidBinding())
1160 return new ProblemReferenceBinding(CharOperation.subarray(
1161 compoundName, 0, currentIndex), binding.problemId());
1162 if (!(binding instanceof PackageBinding))
1164 packageBinding = (PackageBinding) binding;
1166 if (binding instanceof PackageBinding)
1168 checkVisibility = true;
1170 // binding is now a ReferenceBinding
1171 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1172 if (checkVisibility) // handles the fall through case
1173 if (!typeBinding.canBeSeenBy(this))
1174 return new ProblemReferenceBinding(CharOperation.subarray(
1175 compoundName, 0, currentIndex), typeBinding, NotVisible);
1177 while (currentIndex < nameLength) {
1178 typeBinding = getMemberType(compoundName[currentIndex++],
1180 // checks visibility
1181 if (!typeBinding.isValidBinding())
1182 return new ProblemReferenceBinding(CharOperation.subarray(
1183 compoundName, 0, currentIndex), typeBinding.problemId());
1191 final Binding getTypeOrPackage(char[] name, int mask) {
1193 ReferenceBinding foundType = null;
1194 if ((mask & TYPE) == 0) {
1196 while ((next = scope.parent) != null)
1199 done: while (true) { // done when a COMPILATION_UNIT_SCOPE is
1201 switch (scope.kind) {
1204 ReferenceBinding localType = ((BlockScope) scope)
1205 .findLocalType(name); // looks in this scope only
1206 if (localType != null) {
1207 if (foundType != null && foundType != localType)
1208 return new ProblemReferenceBinding(name,
1209 InheritedNameHidesEnclosingName);
1214 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
1215 // 6.5.5.1 - simple name favors member type over top-level
1216 // type in same unit
1217 ReferenceBinding memberType = findMemberType(name,
1219 if (memberType != null) { // skip it if we did not find
1221 if (memberType.problemId() == Ambiguous) {
1222 if (foundType == null
1223 || foundType.problemId() == NotVisible)
1224 // supercedes any potential
1225 // InheritedNameHidesEnclosingName problem
1228 // make the user qualify the type, likely wants
1229 // the first inherited type
1230 return new ProblemReferenceBinding(name,
1231 InheritedNameHidesEnclosingName);
1233 // if (memberType.isValidBinding()) {
1234 // if (sourceType == memberType.enclosingType()
1235 // || environment().options.complianceLevel >=
1236 // CompilerOptions.JDK1_4) {
1237 // // found a valid type in the 'immediate' scope (ie.
1239 // // OR in 1.4 mode (inherited shadows enclosing)
1240 // if (foundType == null)
1241 // return memberType;
1242 // if (foundType.isValidBinding())
1243 // // if a valid type was found, complain when another
1244 // is found in an 'immediate' enclosing type (ie. not
1246 // if (foundType != memberType)
1247 // return new ProblemReferenceBinding(name,
1248 // InheritedNameHidesEnclosingName);
1251 if (foundType == null
1252 || (foundType.problemId() == NotVisible && memberType
1253 .problemId() != NotVisible))
1254 // only remember the memberType if its the first one
1255 // found or the previous one was not visible &
1257 foundType = memberType;
1259 if (CharOperation.equals(sourceType.sourceName, name)) {
1260 if (foundType != null && foundType != sourceType
1261 && foundType.problemId() != NotVisible)
1262 return new ProblemReferenceBinding(name,
1263 InheritedNameHidesEnclosingName);
1267 case COMPILATION_UNIT_SCOPE:
1270 scope = scope.parent;
1272 if (foundType != null && foundType.problemId() != NotVisible)
1276 // at this point the scope is a compilation unit scope
1277 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1278 PackageBinding currentPackage = unitScope.fPackage;
1279 // ask for the imports + name
1280 if ((mask & TYPE) != 0) {
1281 // check single type imports.
1282 ImportBinding[] imports = unitScope.imports;
1283 if (imports != null) {
1284 // copy the list, since single type imports are removed if they
1285 // cannot be resolved
1286 for (int i = 0, length = imports.length; i < length; i++) {
1287 ImportBinding typeImport = imports[i];
1288 if (!typeImport.onDemand) {
1291 typeImport.compoundName[typeImport.compoundName.length - 1],
1293 if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1294 ImportReference importReference = typeImport.reference;
1295 if (importReference != null)
1296 importReference.used = true;
1297 return typeImport.resolvedImport; // already
1305 // check if the name is in the current package, skip it if its a
1307 unitScope.recordReference(currentPackage.compoundName, name);
1308 Binding binding = currentPackage.getTypeOrPackage(name);
1309 if (binding instanceof ReferenceBinding)
1310 return binding; // type is always visible to its own package
1312 // check on demand imports
1313 boolean foundInImport = false;
1314 ReferenceBinding type = null;
1315 if (imports != null) {
1316 for (int i = 0, length = imports.length; i < length; i++) {
1317 ImportBinding someImport = imports[i];
1318 if (someImport.onDemand) {
1319 Binding resolvedImport = someImport.resolvedImport;
1320 ReferenceBinding temp = resolvedImport instanceof PackageBinding ? findType(
1321 name, (PackageBinding) resolvedImport,
1323 : findDirectMemberType(name,
1324 (ReferenceBinding) resolvedImport);
1325 if (temp != null && temp.isValidBinding()) {
1326 // ImportReference importReference =
1327 // someImport.reference;
1328 // if (importReference != null) importReference.used
1331 // Answer error binding -- import on demand
1332 // conflict; name found in two import on demand
1334 return new ProblemReferenceBinding(name,
1337 foundInImport = true;
1346 unitScope.recordSimpleReference(name);
1347 if ((mask & PACKAGE) != 0) {
1348 PackageBinding packageBinding = unitScope.environment
1349 .getTopLevelPackage(name);
1350 if (packageBinding != null)
1351 return packageBinding;
1354 // Answer error binding -- could not find name
1355 if (foundType != null)
1356 return foundType; // problem type from above
1357 return new ProblemReferenceBinding(name, NotFound);
1361 * Answer whether the type is defined in the same compilation unit as the
1364 public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1365 // find the outer most enclosing type
1366 ReferenceBinding enclosingType = type;
1367 while ((type = enclosingType.enclosingType()) != null)
1368 enclosingType = type;
1370 // find the compilation unit scope
1371 Scope scope, unitScope = this;
1372 while ((scope = unitScope.parent) != null)
1375 // test that the enclosingType is not part of the compilation unit
1376 SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
1377 for (int i = topLevelTypes.length; --i >= 0;)
1378 if (topLevelTypes[i] == enclosingType)
1384 * Answer true if the scope is nested inside a given field declaration.
1385 * Note: it works as long as the scope.fieldDeclarationIndex is reflecting
1386 * the field being traversed e.g. during name resolution.
1388 public final boolean isDefinedInField(FieldBinding field) {
1391 if (scope instanceof MethodScope) {
1392 MethodScope methodScope = (MethodScope) scope;
1393 ReferenceContext refContext = methodScope.referenceContext;
1394 if (refContext instanceof TypeDeclaration
1395 && ((TypeDeclaration) refContext).binding == field.declaringClass
1396 && methodScope.fieldDeclarationIndex == field.id) {
1400 scope = scope.parent;
1401 } while (scope != null);
1406 * Answer true if the scope is nested inside a given method declaration
1408 public final boolean isDefinedInMethod(MethodBinding method) {
1411 if (scope instanceof MethodScope) {
1412 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
1413 if (refContext instanceof AbstractMethodDeclaration
1414 && ((AbstractMethodDeclaration) refContext).binding == method) {
1418 scope = scope.parent;
1419 } while (scope != null);
1424 * Answer true if the scope is nested inside a given type declaration
1426 public final boolean isDefinedInType(ReferenceBinding type) {
1429 if (scope instanceof ClassScope)
1430 if (((ClassScope) scope).referenceContext.binding == type) {
1433 scope = scope.parent;
1434 } while (scope != null);
1438 public boolean isInsideDeprecatedCode() {
1440 case Scope.BLOCK_SCOPE:
1441 case Scope.METHOD_SCOPE:
1442 MethodScope methodScope = methodScope();
1443 if (!methodScope.isInsideInitializer()) {
1444 // check method modifiers to see if deprecated
1445 MethodBinding context = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
1446 if (context != null && context.isViewedAsDeprecated()) {
1450 SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
1452 // inside field declaration ? check field modifier to see if
1454 if (methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl) {
1455 for (int i = 0; i < type.fields.length; i++) {
1456 if (type.fields[i].id == methodScope.fieldDeclarationIndex) {
1457 // currently inside this field initialization
1458 if (type.fields[i].isViewedAsDeprecated()) {
1465 if (type != null && type.isViewedAsDeprecated()) {
1470 case Scope.CLASS_SCOPE:
1471 ReferenceBinding context = ((ClassScope) this).referenceType().binding;
1472 if (context != null && context.isViewedAsDeprecated()) {
1480 public final boolean isJavaIoSerializable(TypeBinding tb) {
1481 return tb == getJavaIoSerializable();
1484 public final boolean isJavaLangCloneable(TypeBinding tb) {
1485 return tb == getJavaLangCloneable();
1488 public final boolean isJavaLangObject(TypeBinding type) {
1489 return type.id == T_JavaLangObject;
1492 public final MethodScope methodScope() {
1495 if (scope instanceof MethodScope)
1496 return (MethodScope) scope;
1497 scope = scope.parent;
1498 } while (scope != null);
1502 // Internal use only
1504 * All methods in visible are acceptable matches for the method in
1505 * question... The methods defined by the receiver type appear before those
1506 * defined by its superclass and so on. We want to find the one which
1509 * Since the receiver type is a class, we know each method's declaring class
1510 * is either the receiver type or one of its superclasses. It is an error if
1511 * the best match is defined by a superclass, when a lesser match is defined
1512 * by the receiver type or a closer superclass.
1514 protected final MethodBinding mostSpecificClassMethodBinding(
1515 MethodBinding[] visible, int visibleSize) {
1517 MethodBinding method = null;
1518 MethodBinding previous = null;
1520 nextVisible: for (int i = 0; i < visibleSize; i++) {
1521 method = visible[i];
1523 if (previous != null
1524 && method.declaringClass != previous.declaringClass)
1525 break; // cannot answer a method farther up the hierarchy than
1526 // the first method found
1528 for (int j = 0; j < visibleSize; j++) {
1531 MethodBinding next = visible[j];
1532 if (!areParametersAssignable(next.parameters, method.parameters))
1533 continue nextVisible;
1535 compilationUnitScope()
1536 .recordTypeReferences(method.thrownExceptions);
1539 return new ProblemMethodBinding(visible[0].selector,
1540 visible[0].parameters, Ambiguous);
1543 // Internal use only
1545 * All methods in visible are acceptable matches for the method in
1546 * question... Since the receiver type is an interface, we ignore the
1547 * possibility that 2 inherited but unrelated superinterfaces may define the
1548 * same method in acceptable but not identical ways... we just take the best
1549 * match that we find since any class which implements the receiver
1550 * interface MUST implement all signatures for the method... in which case
1551 * the best match is correct.
1553 * NOTE: This is different than javac... in the following example, the
1554 * message send of bar(X) in class Y is supposed to be ambiguous. But any
1555 * class which implements the interface I MUST implement both signatures for
1556 * bar. If this class was the receiver of the message send instead of the
1557 * interface I, then no problem would be reported.
1559 * interface I1 { void bar(J j); } interface I2 { // void bar(J j); void
1560 * bar(Object o); } interface I extends I1, I2 {} interface J {}
1562 * class X implements J {}
1564 * class Y extends X { public void foo(I i, X x) { i.bar(x); } }
1566 protected final MethodBinding mostSpecificInterfaceMethodBinding(
1567 MethodBinding[] visible, int visibleSize) {
1568 MethodBinding method = null;
1569 nextVisible: for (int i = 0; i < visibleSize; i++) {
1570 method = visible[i];
1571 for (int j = 0; j < visibleSize; j++) {
1574 MethodBinding next = visible[j];
1575 if (!areParametersAssignable(next.parameters, method.parameters))
1576 continue nextVisible;
1578 compilationUnitScope()
1579 .recordTypeReferences(method.thrownExceptions);
1582 return new ProblemMethodBinding(visible[0].selector,
1583 visible[0].parameters, Ambiguous);
1586 public final ClassScope outerMostClassScope() {
1587 ClassScope lastClassScope = null;
1590 if (scope instanceof ClassScope)
1591 lastClassScope = (ClassScope) scope;
1592 scope = scope.parent;
1593 } while (scope != null);
1594 return lastClassScope; // may answer null if no class around
1597 public final MethodScope outerMostMethodScope() {
1598 MethodScope lastMethodScope = null;
1601 if (scope instanceof MethodScope)
1602 lastMethodScope = (MethodScope) scope;
1603 scope = scope.parent;
1604 } while (scope != null);
1605 return lastMethodScope; // may answer null if no method around
1608 public final CompilationUnitDeclaration referenceCompilationUnit() {
1609 Scope scope, unitScope = this;
1610 while ((scope = unitScope.parent) != null)
1612 return ((CompilationUnitScope) unitScope).referenceContext;
1615 // start position in this scope - for ordering scopes vs. variables