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.internal.compiler.lookup.BlockScope;
14 import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
15 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
16 import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
17 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
20 import net.sourceforge.phpdt.core.compiler.CharOperation;
21 import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
22 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
23 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
24 import net.sourceforge.phpeclipse.internal.compiler.ast.AbstractMethodDeclaration;
25 import net.sourceforge.phpeclipse.internal.compiler.ast.CompilationUnitDeclaration;
26 import net.sourceforge.phpeclipse.internal.compiler.ast.ImportReference;
27 import net.sourceforge.phpeclipse.internal.compiler.ast.TypeDeclaration;
29 public abstract class Scope
42 public final static int BLOCK_SCOPE = 1;
43 public final static int METHOD_SCOPE = 2;
44 public final static int CLASS_SCOPE = 3;
45 public final static int COMPILATION_UNIT_SCOPE = 4;
46 protected Scope(int kind, Scope parent) {
51 public abstract ProblemReporter problemReporter();
54 protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
55 if (parameters == arguments)
58 int length = parameters.length;
59 if (length != arguments.length)
62 for (int i = 0; i < length; i++)
63 if (parameters[i] != arguments[i])
64 if (!arguments[i].isCompatibleWith(parameters[i]))
69 /* Answer an int describing the relationship between the given types.
72 * EqualOrMoreSpecific : left is compatible with right
73 * MoreGeneric : right is compatible with left
75 public static int compareTypes(TypeBinding left, TypeBinding right) {
76 if (left.isCompatibleWith(right))
77 return EqualOrMoreSpecific;
78 if (right.isCompatibleWith(left))
83 /* Answer an int describing the relationship between the given type and unchecked exceptions.
86 * EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
87 * MoreGeneric : type is a supertype of an actual unchecked exception type
89 public int compareUncheckedException(ReferenceBinding type) {
90 int comparison = compareTypes(type, getJavaLangRuntimeException());
91 if (comparison != 0) return comparison;
92 return compareTypes(type, getJavaLangError());
95 public final CompilationUnitScope compilationUnitScope() {
96 Scope lastScope = null;
100 scope = scope.parent;
101 } while (scope != null);
102 return (CompilationUnitScope) lastScope;
105 public ArrayBinding createArray(TypeBinding type, int dimension) {
106 if (type.isValidBinding())
107 return environment().createArrayType(type, dimension);
109 return new ArrayBinding(type, dimension);
112 public final ClassScope enclosingClassScope() {
114 while ((scope = scope.parent) != null) {
115 if (scope instanceof ClassScope) return (ClassScope)scope;
117 return null; // may answer null if no type around
120 public final MethodScope enclosingMethodScope() {
122 while ((scope = scope.parent) != null) {
123 if (scope instanceof MethodScope) return (MethodScope)scope;
125 return null; // may answer null if no method around
128 /* Answer the receiver's enclosing source type.
130 public final SourceTypeBinding enclosingSourceType() {
133 if (scope instanceof ClassScope)
134 return ((ClassScope) scope).referenceContext.binding;
135 scope = scope.parent;
136 } while (scope != null);
139 public final LookupEnvironment environment() {
140 Scope scope, unitScope = this;
141 while ((scope = unitScope.parent) != null)
143 return ((CompilationUnitScope) unitScope).environment;
147 public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
148 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
149 return null; // know it has no member types (nor inherited member types)
151 SourceTypeBinding enclosingSourceType = enclosingSourceType();
152 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
153 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
154 if (memberType != null) {
155 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
156 if (enclosingSourceType == null
157 ? memberType.canBeSeenBy(getCurrentPackage())
158 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
161 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
167 public MethodBinding findExactMethod(
168 ReferenceBinding receiverType,
170 TypeBinding[] argumentTypes,
171 InvocationSite invocationSite) {
173 compilationUnitScope().recordTypeReference(receiverType);
174 compilationUnitScope().recordTypeReferences(argumentTypes);
175 MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
176 if (exactMethod != null) {
177 compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
178 if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
185 /* Answer the field binding that corresponds to fieldName.
186 Start the lookup at the receiverType.
187 InvocationSite implements
188 isSuperAccess(); this is used to determine if the discovered field is visible.
189 Only fields defined by the receiverType or its supertypes are answered;
190 a field of an enclosing type will not be found using this API.
192 If no visible field is discovered, null is answered.
194 public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
195 if (receiverType.isBaseType()) return null;
196 if (receiverType.isArrayType()) {
197 TypeBinding leafType = receiverType.leafComponentType();
198 if (leafType instanceof ReferenceBinding) {
199 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
200 return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
202 if (CharOperation.equals(fieldName, LENGTH))
203 return ArrayBinding.LengthField;
207 compilationUnitScope().recordTypeReference(receiverType);
209 ReferenceBinding currentType = (ReferenceBinding) receiverType;
210 if (!currentType.canBeSeenBy(this))
211 return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
213 FieldBinding field = currentType.getField(fieldName);
215 if (field.canBeSeenBy(currentType, invocationSite, this))
218 return new ProblemFieldBinding(field.declaringClass, fieldName, NotVisible);
220 // collect all superinterfaces of receiverType until the field is found in a supertype
221 ReferenceBinding[][] interfacesToVisit = null;
222 int lastPosition = -1;
223 FieldBinding visibleField = null;
224 boolean keepLooking = true;
225 boolean notVisible = false;
226 // we could hold onto the not visible field for extra error reporting
227 while (keepLooking) {
228 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
229 if (itsInterfaces != NoSuperInterfaces) {
230 if (interfacesToVisit == null)
231 interfacesToVisit = new ReferenceBinding[5][];
232 if (++lastPosition == interfacesToVisit.length)
236 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
239 interfacesToVisit[lastPosition] = itsInterfaces;
241 if ((currentType = currentType.superclass()) == null)
244 if ((field = currentType.getField(fieldName)) != null) {
246 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
247 if (visibleField == null)
248 visibleField = field;
250 return new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
257 // walk all visible interfaces to find ambiguous references
258 if (interfacesToVisit != null) {
259 ProblemFieldBinding ambiguous = null;
260 done : for (int i = 0; i <= lastPosition; i++) {
261 ReferenceBinding[] interfaces = interfacesToVisit[i];
262 for (int j = 0, length = interfaces.length; j < length; j++) {
263 ReferenceBinding anInterface = interfaces[j];
264 if ((anInterface.tagBits & InterfaceVisited) == 0) {
265 // if interface as not already been visited
266 anInterface.tagBits |= InterfaceVisited;
267 if ((field = anInterface.getField(fieldName)) != null) {
268 if (visibleField == null) {
269 visibleField = field;
271 ambiguous = new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
275 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
276 if (itsInterfaces != NoSuperInterfaces) {
277 if (++lastPosition == interfacesToVisit.length)
281 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
284 interfacesToVisit[lastPosition] = itsInterfaces;
291 // bit reinitialization
292 for (int i = 0; i <= lastPosition; i++) {
293 ReferenceBinding[] interfaces = interfacesToVisit[i];
294 for (int j = 0, length = interfaces.length; j < length; j++)
295 interfaces[j].tagBits &= ~InterfaceVisited;
297 if (ambiguous != null)
301 if (visibleField != null)
304 return new ProblemFieldBinding(currentType, fieldName, NotVisible);
309 public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
310 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
311 return null; // know it has no member types (nor inherited member types)
313 SourceTypeBinding enclosingSourceType = enclosingSourceType();
314 PackageBinding currentPackage = getCurrentPackage();
315 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
316 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
317 if (memberType != null) {
318 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
319 if (enclosingSourceType == null
320 ? memberType.canBeSeenBy(currentPackage)
321 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
324 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
327 // collect all superinterfaces of receiverType until the memberType is found in a supertype
328 ReferenceBinding currentType = enclosingType;
329 ReferenceBinding[][] interfacesToVisit = null;
330 int lastPosition = -1;
331 ReferenceBinding visibleMemberType = null;
332 boolean keepLooking = true;
333 ReferenceBinding notVisible = null;
334 // we could hold onto the not visible field for extra error reporting
335 while (keepLooking) {
336 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
337 if (itsInterfaces != NoSuperInterfaces) {
338 if (interfacesToVisit == null)
339 interfacesToVisit = new ReferenceBinding[5][];
340 if (++lastPosition == interfacesToVisit.length)
344 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
347 interfacesToVisit[lastPosition] = itsInterfaces;
349 if ((currentType = currentType.superclass()) == null)
352 compilationUnitScope().recordReference(currentType.compoundName, typeName);
353 if ((memberType = currentType.getMemberType(typeName)) != null) {
354 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
356 if (enclosingSourceType == null
357 ? memberType.canBeSeenBy(currentPackage)
358 : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
359 if (visibleMemberType == null)
360 visibleMemberType = memberType;
362 return new ProblemReferenceBinding(typeName, Ambiguous);
364 notVisible = memberType;
368 // walk all visible interfaces to find ambiguous references
369 if (interfacesToVisit != null) {
370 ProblemReferenceBinding ambiguous = null;
371 done : for (int i = 0; i <= lastPosition; i++) {
372 ReferenceBinding[] interfaces = interfacesToVisit[i];
373 for (int j = 0, length = interfaces.length; j < length; j++) {
374 ReferenceBinding anInterface = interfaces[j];
375 if ((anInterface.tagBits & InterfaceVisited) == 0) {
376 // if interface as not already been visited
377 anInterface.tagBits |= InterfaceVisited;
378 compilationUnitScope().recordReference(anInterface.compoundName, typeName);
379 if ((memberType = anInterface.getMemberType(typeName)) != null) {
380 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
381 if (visibleMemberType == null) {
382 visibleMemberType = memberType;
384 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
388 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
389 if (itsInterfaces != NoSuperInterfaces) {
390 if (++lastPosition == interfacesToVisit.length)
394 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
397 interfacesToVisit[lastPosition] = itsInterfaces;
404 // bit reinitialization
405 for (int i = 0; i <= lastPosition; i++) {
406 ReferenceBinding[] interfaces = interfacesToVisit[i];
407 for (int j = 0, length = interfaces.length; j < length; j++)
408 interfaces[j].tagBits &= ~InterfaceVisited;
410 if (ambiguous != null)
413 if (visibleMemberType != null)
414 return visibleMemberType;
415 if (notVisible != null)
416 return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
421 public MethodBinding findMethod(
422 ReferenceBinding receiverType,
424 TypeBinding[] argumentTypes,
425 InvocationSite invocationSite) {
427 ReferenceBinding currentType = receiverType;
428 MethodBinding matchingMethod = null;
429 ObjectVector found = new ObjectVector();
431 compilationUnitScope().recordTypeReference(receiverType);
432 compilationUnitScope().recordTypeReferences(argumentTypes);
434 if (currentType.isInterface()) {
435 MethodBinding[] currentMethods = currentType.getMethods(selector);
436 int currentLength = currentMethods.length;
437 if (currentLength == 1) {
438 matchingMethod = currentMethods[0];
439 } else if (currentLength > 1) {
440 found.addAll(currentMethods);
442 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
443 currentType = getJavaLangObject();
446 // boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= CompilerOptions.JDK1_4;
448 ReferenceBinding classHierarchyStart = currentType;
449 while (currentType != null) {
450 MethodBinding[] currentMethods = currentType.getMethods(selector);
451 int currentLength = currentMethods.length;
454 * if 1.4 compliant, must filter out redundant protected methods from superclasses
456 // if (isCompliant14){
457 // nextMethod: for (int i = 0; i < currentLength; i++){
458 // MethodBinding currentMethod = currentMethods[i];
459 // // protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
460 // // when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
461 // if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
462 // if (matchingMethod != null){
463 // if (currentMethod.areParametersEqual(matchingMethod)){
465 // currentMethods[i] = null; // discard this match
466 // continue nextMethod;
469 // for (int j = 0, max = found.size; j < max; j++) {
470 // if (((MethodBinding)found.elementAt(j)).areParametersEqual(currentMethod)){
472 // currentMethods[i] = null;
473 // continue nextMethod;
480 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
481 matchingMethod = currentMethods[0];
482 } else if (currentLength > 0) {
483 if (matchingMethod != null) {
484 found.add(matchingMethod);
485 matchingMethod = null;
487 // append currentMethods, filtering out null entries
488 int maxMethod = currentMethods.length;
489 if (maxMethod == currentLength) { // no method was eliminated for 1.4 compliance (see above)
490 found.addAll(currentMethods);
492 for (int i = 0, max = currentMethods.length; i < max; i++) {
493 MethodBinding currentMethod = currentMethods[i];
494 if (currentMethod != null) found.add(currentMethod);
498 currentType = currentType.superclass();
501 int foundSize = found.size;
502 if (foundSize == 0) {
503 if (matchingMethod != null && areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
504 // (if no default abstract) must explicitly look for one instead, which could be a better match
505 if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
506 // ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
507 MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);
508 if (interfaceMethod != null) return interfaceMethod;
510 return matchingMethod;
512 return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
515 MethodBinding[] candidates = new MethodBinding[foundSize];
516 int candidatesCount = 0;
517 // argument type compatibility check
518 for (int i = 0; i < foundSize; i++) {
519 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
520 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
521 candidates[candidatesCount++] = methodBinding;
523 if (candidatesCount == 1) {
524 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
525 return candidates[0]; // have not checked visibility
527 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
528 MethodBinding interfaceMethod =
529 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
530 if (interfaceMethod != null) return interfaceMethod;
532 int argLength = argumentTypes.length;
533 foundSize = found.size;
534 nextMethod : for (int i = 0; i < foundSize; i++) {
535 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
536 TypeBinding[] params = methodBinding.parameters;
537 int paramLength = params.length;
538 nextArg: for (int a = 0; a < argLength; a++) {
539 TypeBinding arg = argumentTypes[a];
540 for (int p = 0; p < paramLength; p++)
541 if (params[p] == arg)
545 return methodBinding;
547 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
551 int visiblesCount = 0;
552 for (int i = 0; i < candidatesCount; i++) {
553 MethodBinding methodBinding = candidates[i];
554 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
555 if (visiblesCount != i) {
556 candidates[i] = null;
557 candidates[visiblesCount] = methodBinding;
562 if (visiblesCount == 1) {
563 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
564 return candidates[0];
566 if (visiblesCount == 0) {
567 MethodBinding interfaceMethod =
568 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
569 if (interfaceMethod != null) return interfaceMethod;
570 return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
572 if (candidates[0].declaringClass.isClass()) {
573 return mostSpecificClassMethodBinding(candidates, visiblesCount);
575 return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
579 // abstract method lookup lookup (since maybe missing default abstract methods)
580 public MethodBinding findDefaultAbstractMethod(
581 ReferenceBinding receiverType,
583 TypeBinding[] argumentTypes,
584 InvocationSite invocationSite,
585 ReferenceBinding classHierarchyStart,
586 MethodBinding matchingMethod,
587 ObjectVector found) {
589 int startFoundSize = found.size;
590 ReferenceBinding currentType = classHierarchyStart;
591 while (currentType != null) {
592 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
593 currentType = currentType.superclass();
595 int foundSize = found.size;
596 if (foundSize == startFoundSize) return matchingMethod; // maybe null
598 MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
599 int candidatesCount = 0;
600 // argument type compatibility check
601 for (int i = startFoundSize; i < foundSize; i++) {
602 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
603 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
604 candidates[candidatesCount++] = methodBinding;
606 if (candidatesCount == 1) {
607 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
608 return candidates[0];
610 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
611 int argLength = argumentTypes.length;
612 nextMethod : for (int i = 0; i < foundSize; i++) {
613 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
614 TypeBinding[] params = methodBinding.parameters;
615 int paramLength = params.length;
616 nextArg: for (int a = 0; a < argLength; a++) {
617 TypeBinding arg = argumentTypes[a];
618 for (int p = 0; p < paramLength; p++)
619 if (params[p] == arg)
623 return methodBinding;
625 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
627 // no need to check for visibility - interface methods are public
628 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
631 public MethodBinding findMethodInSuperInterfaces(
632 ReferenceBinding currentType,
635 MethodBinding matchingMethod) {
637 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
638 if (itsInterfaces != NoSuperInterfaces) {
639 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
640 int lastPosition = -1;
641 if (++lastPosition == interfacesToVisit.length)
643 interfacesToVisit, 0,
644 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
646 interfacesToVisit[lastPosition] = itsInterfaces;
648 for (int i = 0; i <= lastPosition; i++) {
649 ReferenceBinding[] interfaces = interfacesToVisit[i];
650 for (int j = 0, length = interfaces.length; j < length; j++) {
651 currentType = interfaces[j];
652 if ((currentType.tagBits & InterfaceVisited) == 0) {
653 // if interface as not already been visited
654 currentType.tagBits |= InterfaceVisited;
656 MethodBinding[] currentMethods = currentType.getMethods(selector);
657 int currentLength = currentMethods.length;
658 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
659 matchingMethod = currentMethods[0];
660 } else if (currentLength > 0) {
661 if (matchingMethod != null) {
662 found.add(matchingMethod);
663 matchingMethod = null;
665 found.addAll(currentMethods);
667 itsInterfaces = currentType.superInterfaces();
668 if (itsInterfaces != NoSuperInterfaces) {
669 if (++lastPosition == interfacesToVisit.length)
671 interfacesToVisit, 0,
672 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
674 interfacesToVisit[lastPosition] = itsInterfaces;
680 // bit reinitialization
681 for (int i = 0; i <= lastPosition; i++) {
682 ReferenceBinding[] interfaces = interfacesToVisit[i];
683 for (int j = 0, length = interfaces.length; j < length; j++)
684 interfaces[j].tagBits &= ~InterfaceVisited;
687 return matchingMethod;
691 public MethodBinding findMethodForArray(
692 ArrayBinding receiverType,
694 TypeBinding[] argumentTypes,
695 InvocationSite invocationSite) {
697 TypeBinding leafType = receiverType.leafComponentType();
698 if (leafType instanceof ReferenceBinding) {
699 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
700 return new ProblemMethodBinding(selector, MethodBinding.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
703 ReferenceBinding object = getJavaLangObject();
704 MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
705 if (methodBinding != null) {
706 // handle the method clone() specially... cannot be protected or throw exceptions
707 if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
708 return new MethodBinding(
709 (methodBinding.modifiers ^ AccProtected) | AccPublic,
711 methodBinding.returnType,
715 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
716 return methodBinding;
718 // answers closest approximation, may not check argumentTypes or visibility
719 methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
720 if (methodBinding == null)
721 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
722 if (methodBinding.isValidBinding()) {
723 if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
724 return new ProblemMethodBinding(
729 if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
730 return new ProblemMethodBinding(
733 methodBinding.parameters,
736 return methodBinding;
740 public ReferenceBinding findType(
742 PackageBinding declarationPackage,
743 PackageBinding invocationPackage) {
745 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
746 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
747 if (typeBinding == null)
750 if (typeBinding.isValidBinding()) {
751 if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
752 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
757 public TypeBinding getBaseType(char[] name) {
758 // list should be optimized (with most often used first)
759 int length = name.length;
760 if (length > 2 && length < 8) {
763 if (length == 3 && name[1] == 'n' && name[2] == 't')
767 if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
778 return BooleanBinding;
779 if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
783 if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
793 return DoubleBinding;
804 if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
819 public final PackageBinding getCurrentPackage() {
820 Scope scope, unitScope = this;
821 while ((scope = unitScope.parent) != null)
823 return ((CompilationUnitScope) unitScope).fPackage;
826 * Returns the modifiers of the innermost enclosing declaration.
829 public int getDeclarationModifiers(){
831 case Scope.BLOCK_SCOPE :
832 case Scope.METHOD_SCOPE :
833 MethodScope methodScope = methodScope();
834 if (!methodScope.isInsideInitializer()){
835 // check method modifiers to see if deprecated
836 MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
837 if (context != null) {
838 return context.modifiers;
841 SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
843 // inside field declaration ? check field modifier to see if deprecated
844 if (methodScope.initializedField != null) {
845 return methodScope.initializedField.modifiers;
848 return type.modifiers;
852 case Scope.CLASS_SCOPE :
853 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
854 if (context != null) {
855 return context.modifiers;
862 public final ReferenceBinding getJavaIoSerializable() {
863 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
864 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
865 if (type != null) return type;
867 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
868 return null; // will not get here since the above error aborts the compilation
871 public final ReferenceBinding getJavaLangClass() {
872 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
873 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
874 if (type != null) return type;
876 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
877 return null; // will not get here since the above error aborts the compilation
880 public final ReferenceBinding getJavaLangCloneable() {
881 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
882 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
883 if (type != null) return type;
885 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
886 return null; // will not get here since the above error aborts the compilation
889 public final ReferenceBinding getJavaLangError() {
890 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
891 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
892 if (type != null) return type;
894 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
895 return null; // will not get here since the above error aborts the compilation
898 public final ReferenceBinding getJavaLangAssertionError() {
899 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
900 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
901 if (type != null) return type;
902 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
903 return null; // will not get here since the above error aborts the compilation
906 public final ReferenceBinding getJavaLangObject() {
907 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
908 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
909 if (type != null) return type;
911 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
912 return null; // will not get here since the above error aborts the compilation
915 public final ReferenceBinding getJavaLangRuntimeException() {
916 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
917 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
918 if (type != null) return type;
920 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
921 return null; // will not get here since the above error aborts the compilation
924 public final ReferenceBinding getJavaLangString() {
925 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
926 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
927 if (type != null) return type;
929 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
930 return null; // will not get here since the above error aborts the compilation
933 public final ReferenceBinding getJavaLangThrowable() {
934 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
935 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
936 if (type != null) return type;
938 // problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
939 return null; // will not get here since the above error aborts the compilation
942 /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
944 public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
945 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
946 if (memberType != null) return memberType;
947 return new ProblemReferenceBinding(typeName, NotFound);
950 /* Answer the type binding corresponding to the compoundName.
952 * NOTE: If a problem binding is returned, senders should extract the compound name
953 * from the binding & not assume the problem applies to the entire compoundName.
955 public final TypeBinding getType(char[][] compoundName) {
956 int typeNameLength = compoundName.length;
957 if (typeNameLength == 1) {
958 // Would like to remove this test and require senders to specially handle base types
959 TypeBinding binding = getBaseType(compoundName[0]);
960 if (binding != null) return binding;
963 compilationUnitScope().recordQualifiedReference(compoundName);
965 getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
967 return new ProblemReferenceBinding(compoundName[0], NotFound);
968 if (!binding.isValidBinding())
969 return (ReferenceBinding) binding;
971 int currentIndex = 1;
972 boolean checkVisibility = false;
973 if (binding instanceof PackageBinding) {
974 PackageBinding packageBinding = (PackageBinding) binding;
975 while (currentIndex < typeNameLength) {
976 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
978 return new ProblemReferenceBinding(
979 CharOperation.subarray(compoundName, 0, currentIndex),
981 if (!binding.isValidBinding())
982 return new ProblemReferenceBinding(
983 CharOperation.subarray(compoundName, 0, currentIndex),
984 binding.problemId());
985 if (!(binding instanceof PackageBinding))
987 packageBinding = (PackageBinding) binding;
989 if (binding instanceof PackageBinding)
990 return new ProblemReferenceBinding(
991 CharOperation.subarray(compoundName, 0, currentIndex),
993 checkVisibility = true;
996 // binding is now a ReferenceBinding
997 ReferenceBinding typeBinding = (ReferenceBinding) binding;
998 compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
999 if (checkVisibility) // handles the fall through case
1000 if (!typeBinding.canBeSeenBy(this))
1001 return new ProblemReferenceBinding(
1002 CharOperation.subarray(compoundName, 0, currentIndex),
1006 while (currentIndex < typeNameLength) {
1007 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
1008 if (!typeBinding.isValidBinding())
1009 return new ProblemReferenceBinding(
1010 CharOperation.subarray(compoundName, 0, currentIndex),
1011 typeBinding.problemId());
1016 /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
1017 * The name provided is a simple source name (e.g., "Object" , "Point", ...)
1019 // The return type of this method could be ReferenceBinding if we did not answer base types.
1020 // NOTE: We could support looking for Base Types last in the search, however any code using
1021 // this feature would be extraordinarily slow. Therefore we don't do this
1022 public final TypeBinding getType(char[] name) {
1023 // Would like to remove this test and require senders to specially handle base types
1024 TypeBinding binding = getBaseType(name);
1025 if (binding != null) return binding;
1026 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
1029 // Added for code assist... NOT Public API
1030 public final Binding getTypeOrPackage(char[][] compoundName) {
1031 int nameLength = compoundName.length;
1032 if (nameLength == 1) {
1033 TypeBinding binding = getBaseType(compoundName[0]);
1034 if (binding != null) return binding;
1036 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
1037 if (!binding.isValidBinding()) return binding;
1039 int currentIndex = 1;
1040 boolean checkVisibility = false;
1041 if (binding instanceof PackageBinding) {
1042 PackageBinding packageBinding = (PackageBinding) binding;
1044 while (currentIndex < nameLength) {
1045 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
1046 if (binding == null)
1047 return new ProblemReferenceBinding(
1048 CharOperation.subarray(compoundName, 0, currentIndex),
1050 if (!binding.isValidBinding())
1051 return new ProblemReferenceBinding(
1052 CharOperation.subarray(compoundName, 0, currentIndex),
1053 binding.problemId());
1054 if (!(binding instanceof PackageBinding))
1056 packageBinding = (PackageBinding) binding;
1058 if (binding instanceof PackageBinding) return binding;
1059 checkVisibility = true;
1061 // binding is now a ReferenceBinding
1062 ReferenceBinding typeBinding = (ReferenceBinding) binding;
1063 if (checkVisibility) // handles the fall through case
1064 if (!typeBinding.canBeSeenBy(this))
1065 return new ProblemReferenceBinding(
1066 CharOperation.subarray(compoundName, 0, currentIndex),
1070 while (currentIndex < nameLength) {
1071 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
1072 // checks visibility
1073 if (!typeBinding.isValidBinding())
1074 return new ProblemReferenceBinding(
1075 CharOperation.subarray(compoundName, 0, currentIndex),
1076 typeBinding.problemId());
1081 /* Internal use only
1083 final Binding getTypeOrPackage(char[] name, int mask) {
1085 ReferenceBinding foundType = null;
1086 if ((mask & TYPE) == 0) {
1088 while ((next = scope.parent) != null)
1091 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1092 switch (scope.kind) {
1095 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
1096 if (localType != null) {
1097 if (foundType != null && foundType != localType)
1098 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1103 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
1104 // 6.5.5.1 - simple name favors member type over top-level type in same unit
1105 ReferenceBinding memberType = findMemberType(name, sourceType);
1106 if (memberType != null) { // skip it if we did not find anything
1107 if (memberType.problemId() == Ambiguous) {
1108 if (foundType == null || foundType.problemId() == NotVisible)
1109 // supercedes any potential InheritedNameHidesEnclosingName problem
1112 // make the user qualify the type, likely wants the first inherited type
1113 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1115 // if (memberType.isValidBinding()) {
1116 // if (sourceType == memberType.enclosingType()
1117 // || environment().options.complianceLevel >= CompilerOptions.JDK1_4) {
1118 // // found a valid type in the 'immediate' scope (ie. not inherited)
1119 // // OR in 1.4 mode (inherited shadows enclosing)
1120 // if (foundType == null)
1121 // return memberType;
1122 // if (foundType.isValidBinding())
1123 // // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
1124 // if (foundType != memberType)
1125 // return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1128 if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
1129 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
1130 foundType = memberType;
1132 if (CharOperation.equals(sourceType.sourceName, name)) {
1133 if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
1134 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1138 case COMPILATION_UNIT_SCOPE :
1141 scope = scope.parent;
1143 if (foundType != null && foundType.problemId() != NotVisible)
1147 // at this point the scope is a compilation unit scope
1148 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1149 PackageBinding currentPackage = unitScope.fPackage;
1150 // ask for the imports + name
1151 if ((mask & TYPE) != 0) {
1152 // check single type imports.
1153 ImportBinding[] imports = unitScope.imports;
1154 if (imports != null) {
1155 // copy the list, since single type imports are removed if they cannot be resolved
1156 for (int i = 0, length = imports.length; i < length; i++) {
1157 ImportBinding typeImport = imports[i];
1158 if (!typeImport.onDemand) {
1159 if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
1160 if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1161 ImportReference importReference = typeImport.reference;
1162 if (importReference != null) importReference.used = true;
1163 return typeImport.resolvedImport; // already know its visible
1169 // check if the name is in the current package, skip it if its a sub-package
1170 unitScope.recordReference(currentPackage.compoundName, name);
1171 Binding binding = currentPackage.getTypeOrPackage(name);
1172 if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
1174 // check on demand imports
1175 boolean foundInImport = false;
1176 ReferenceBinding type = null;
1177 if (imports != null) {
1178 for (int i = 0, length = imports.length; i < length; i++) {
1179 ImportBinding someImport = imports[i];
1180 if (someImport.onDemand) {
1181 Binding resolvedImport = someImport.resolvedImport;
1182 ReferenceBinding temp = resolvedImport instanceof PackageBinding
1183 ? findType(name, (PackageBinding) resolvedImport, currentPackage)
1184 : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
1185 if (temp != null && temp.isValidBinding()) {
1186 // ImportReference importReference = someImport.reference;
1187 // if (importReference != null) importReference.used = true;
1189 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1190 return new ProblemReferenceBinding(name, Ambiguous);
1192 foundInImport = true;
1197 if (type != null) return type;
1200 unitScope.recordSimpleReference(name);
1201 if ((mask & PACKAGE) != 0) {
1202 PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
1203 if (packageBinding != null) return packageBinding;
1206 // Answer error binding -- could not find name
1207 if (foundType != null) return foundType; // problem type from above
1208 return new ProblemReferenceBinding(name, NotFound);
1211 /* Answer whether the type is defined in the same compilation unit as the receiver
1213 public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1214 // find the outer most enclosing type
1215 ReferenceBinding enclosingType = type;
1216 while ((type = enclosingType.enclosingType()) != null)
1217 enclosingType = type;
1219 // find the compilation unit scope
1220 Scope scope, unitScope = this;
1221 while ((scope = unitScope.parent) != null)
1224 // test that the enclosingType is not part of the compilation unit
1225 SourceTypeBinding[] topLevelTypes =
1226 ((CompilationUnitScope) unitScope).topLevelTypes;
1227 for (int i = topLevelTypes.length; --i >= 0;)
1228 if (topLevelTypes[i] == enclosingType)
1233 /* Answer true if the scope is nested inside a given field declaration.
1234 * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed
1235 * e.g. during name resolution.
1237 public final boolean isDefinedInField(FieldBinding field) {
1240 if (scope instanceof MethodScope) {
1241 MethodScope methodScope = (MethodScope) scope;
1242 ReferenceContext refContext = methodScope.referenceContext;
1243 if (refContext instanceof TypeDeclaration
1244 && ((TypeDeclaration)refContext).binding == field.declaringClass
1245 && methodScope.fieldDeclarationIndex == field.id) {
1249 scope = scope.parent;
1250 } while (scope != null);
1254 /* Answer true if the scope is nested inside a given method declaration
1256 public final boolean isDefinedInMethod(MethodBinding method) {
1259 if (scope instanceof MethodScope) {
1260 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
1261 if (refContext instanceof AbstractMethodDeclaration
1262 && ((AbstractMethodDeclaration)refContext).binding == method) {
1266 scope = scope.parent;
1267 } while (scope != null);
1271 /* Answer true if the scope is nested inside a given type declaration
1273 public final boolean isDefinedInType(ReferenceBinding type) {
1276 if (scope instanceof ClassScope)
1277 if (((ClassScope) scope).referenceContext.binding == type){
1280 scope = scope.parent;
1281 } while (scope != null);
1285 public boolean isInsideDeprecatedCode(){
1287 case Scope.BLOCK_SCOPE :
1288 case Scope.METHOD_SCOPE :
1289 MethodScope methodScope = methodScope();
1290 if (!methodScope.isInsideInitializer()){
1291 // check method modifiers to see if deprecated
1292 MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1293 if (context != null && context.isViewedAsDeprecated()) {
1297 SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
1299 // inside field declaration ? check field modifier to see if deprecated
1300 if (methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl) {
1301 for (int i = 0; i < type.fields.length; i++){
1302 if (type.fields[i].id == methodScope.fieldDeclarationIndex) {
1303 // currently inside this field initialization
1304 if (type.fields[i].isViewedAsDeprecated()){
1311 if (type != null && type.isViewedAsDeprecated()) {
1316 case Scope.CLASS_SCOPE :
1317 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1318 if (context != null && context.isViewedAsDeprecated()) {
1326 public final boolean isJavaIoSerializable(TypeBinding tb) {
1327 return tb == getJavaIoSerializable();
1330 public final boolean isJavaLangCloneable(TypeBinding tb) {
1331 return tb == getJavaLangCloneable();
1334 public final boolean isJavaLangObject(TypeBinding type) {
1335 return type.id == T_JavaLangObject;
1338 public final MethodScope methodScope() {
1341 if (scope instanceof MethodScope)
1342 return (MethodScope) scope;
1343 scope = scope.parent;
1344 } while (scope != null);
1348 // Internal use only
1349 /* All methods in visible are acceptable matches for the method in question...
1350 * The methods defined by the receiver type appear before those defined by its
1351 * superclass and so on. We want to find the one which matches best.
1353 * Since the receiver type is a class, we know each method's declaring class is
1354 * either the receiver type or one of its superclasses. It is an error if the best match
1355 * is defined by a superclass, when a lesser match is defined by the receiver type
1356 * or a closer superclass.
1358 protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
1360 MethodBinding method = null;
1361 MethodBinding previous = null;
1363 nextVisible : for (int i = 0; i < visibleSize; i++) {
1364 method = visible[i];
1366 if (previous != null && method.declaringClass != previous.declaringClass)
1367 break; // cannot answer a method farther up the hierarchy than the first method found
1369 for (int j = 0; j < visibleSize; j++) {
1370 if (i == j) continue;
1371 MethodBinding next = visible[j];
1372 if (!areParametersAssignable(next.parameters, method.parameters))
1373 continue nextVisible;
1375 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1378 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1381 // Internal use only
1382 /* All methods in visible are acceptable matches for the method in question...
1383 * Since the receiver type is an interface, we ignore the possibility that 2 inherited
1384 * but unrelated superinterfaces may define the same method in acceptable but
1385 * not identical ways... we just take the best match that we find since any class which
1386 * implements the receiver interface MUST implement all signatures for the method...
1387 * in which case the best match is correct.
1389 * NOTE: This is different than javac... in the following example, the message send of
1390 * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
1391 * interface I MUST implement both signatures for bar. If this class was the receiver of
1392 * the message send instead of the interface I, then no problem would be reported.
1401 interface I extends I1, I2 {}
1404 class X implements J {}
1407 public void foo(I i, X x) { i.bar(x); }
1410 protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
1411 MethodBinding method = null;
1412 nextVisible : for (int i = 0; i < visibleSize; i++) {
1413 method = visible[i];
1414 for (int j = 0; j < visibleSize; j++) {
1415 if (i == j) continue;
1416 MethodBinding next = visible[j];
1417 if (!areParametersAssignable(next.parameters, method.parameters))
1418 continue nextVisible;
1420 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1423 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1426 public final ClassScope outerMostClassScope() {
1427 ClassScope lastClassScope = null;
1430 if (scope instanceof ClassScope)
1431 lastClassScope = (ClassScope) scope;
1432 scope = scope.parent;
1433 } while (scope != null);
1434 return lastClassScope; // may answer null if no class around
1437 public final MethodScope outerMostMethodScope() {
1438 MethodScope lastMethodScope = null;
1441 if (scope instanceof MethodScope)
1442 lastMethodScope = (MethodScope) scope;
1443 scope = scope.parent;
1444 } while (scope != null);
1445 return lastMethodScope; // may answer null if no method around
1448 public final CompilationUnitDeclaration referenceCompilationUnit() {
1449 Scope scope, unitScope = this;
1450 while ((scope = unitScope.parent) != null)
1452 return ((CompilationUnitScope) unitScope).referenceContext;
1454 // start position in this scope - for ordering scopes vs. variables