1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.lookup;
13 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
14 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
15 import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
16 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
17 import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
19 public abstract class Scope
32 public final static int BLOCK_SCOPE = 1;
33 public final static int METHOD_SCOPE = 2;
34 public final static int CLASS_SCOPE = 3;
35 public final static int COMPILATION_UNIT_SCOPE = 4;
36 protected Scope(int kind, Scope parent) {
41 public abstract ProblemReporter problemReporter();
44 protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
45 if (parameters == arguments)
48 int length = parameters.length;
49 if (length != arguments.length)
52 for (int i = 0; i < length; i++)
53 if (parameters[i] != arguments[i])
54 if (!arguments[i].isCompatibleWith(parameters[i]))
59 /* Answer true if the left type can be assigned to right
61 public static boolean areTypesCompatible(TypeBinding left, TypeBinding right) {
62 return left.isCompatibleWith(right);
65 /* Answer an int describing the relationship between the given types.
68 * EqualOrMoreSpecific : left is compatible with right
69 * MoreGeneric : right is compatible with left
71 public static int compareTypes(TypeBinding left, TypeBinding right) {
72 if (areTypesCompatible(left, right))
73 return EqualOrMoreSpecific;
74 if (areTypesCompatible(right, left))
79 /* Answer an int describing the relationship between the given type and unchecked exceptions.
82 * EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
83 * MoreGeneric : type is a supertype of an actual unchecked exception type
85 public int compareUncheckedException(ReferenceBinding type) {
86 int comparison = compareTypes(type, getJavaLangRuntimeException());
87 if (comparison != 0) return comparison;
88 return compareTypes(type, getJavaLangError());
91 public final CompilationUnitScope compilationUnitScope() {
92 Scope lastScope = null;
97 } while (scope != null);
98 return (CompilationUnitScope) lastScope;
101 public ArrayBinding createArray(TypeBinding type, int dimension) {
102 if (type.isValidBinding())
103 return environment().createArrayType(type, dimension);
105 return new ArrayBinding(type, dimension);
108 /* Answer the receiver's enclosing source type.
110 public final SourceTypeBinding enclosingSourceType() {
113 if (scope instanceof ClassScope)
114 return ((ClassScope) scope).referenceContext.binding;
115 scope = scope.parent;
116 } while (scope != null);
119 public final LookupEnvironment environment() {
120 Scope scope, unitScope = this;
121 while ((scope = unitScope.parent) != null)
123 return ((CompilationUnitScope) unitScope).environment;
127 public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
128 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
129 return null; // know it has no member types (nor inherited member types)
131 SourceTypeBinding enclosingSourceType = enclosingSourceType();
132 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
133 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
134 if (memberType != null) {
135 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
136 if (enclosingSourceType == null
137 ? memberType.canBeSeenBy(getCurrentPackage())
138 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
141 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
147 public MethodBinding findExactMethod(
148 ReferenceBinding receiverType,
150 TypeBinding[] argumentTypes,
151 InvocationSite invocationSite) {
153 compilationUnitScope().recordTypeReference(receiverType);
154 compilationUnitScope().recordTypeReferences(argumentTypes);
155 MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
156 if (exactMethod != null) {
157 compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
158 if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
165 /* Answer the field binding that corresponds to fieldName.
166 Start the lookup at the receiverType.
167 InvocationSite implements
168 isSuperAccess(); this is used to determine if the discovered field is visible.
169 Only fields defined by the receiverType or its supertypes are answered;
170 a field of an enclosing type will not be found using this API.
172 If no visible field is discovered, null is answered.
174 public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
175 if (receiverType.isBaseType()) return null;
176 if (receiverType.isArrayType()) {
177 if (CharOperation.equals(fieldName, LENGTH))
178 return ArrayBinding.LengthField;
182 compilationUnitScope().recordTypeReference(receiverType);
184 ReferenceBinding currentType = (ReferenceBinding) receiverType;
185 if (!currentType.canBeSeenBy(this))
186 return new ProblemFieldBinding(currentType, fieldName, NotVisible);
187 // *** Need a new problem id - TypeNotVisible?
189 FieldBinding field = currentType.getField(fieldName);
191 if (field.canBeSeenBy(currentType, invocationSite, this))
194 return new ProblemFieldBinding(field.declaringClass, fieldName, NotVisible);
196 // collect all superinterfaces of receiverType until the field is found in a supertype
197 ReferenceBinding[][] interfacesToVisit = null;
198 int lastPosition = -1;
199 FieldBinding visibleField = null;
200 boolean keepLooking = true;
201 boolean notVisible = false;
202 // we could hold onto the not visible field for extra error reporting
203 while (keepLooking) {
204 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
205 if (itsInterfaces != NoSuperInterfaces) {
206 if (interfacesToVisit == null)
207 interfacesToVisit = new ReferenceBinding[5][];
208 if (++lastPosition == interfacesToVisit.length)
212 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
215 interfacesToVisit[lastPosition] = itsInterfaces;
217 if ((currentType = currentType.superclass()) == null)
220 if ((field = currentType.getField(fieldName)) != null) {
222 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
223 if (visibleField == null)
224 visibleField = field;
226 return new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
233 // walk all visible interfaces to find ambiguous references
234 if (interfacesToVisit != null) {
235 ProblemFieldBinding ambiguous = null;
236 done : for (int i = 0; i <= lastPosition; i++) {
237 ReferenceBinding[] interfaces = interfacesToVisit[i];
238 for (int j = 0, length = interfaces.length; j < length; j++) {
239 ReferenceBinding anInterface = interfaces[j];
240 if ((anInterface.tagBits & InterfaceVisited) == 0) {
241 // if interface as not already been visited
242 anInterface.tagBits |= InterfaceVisited;
243 if ((field = anInterface.getField(fieldName)) != null) {
244 if (visibleField == null) {
245 visibleField = field;
247 ambiguous = new ProblemFieldBinding(visibleField.declaringClass, fieldName, Ambiguous);
251 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
252 if (itsInterfaces != NoSuperInterfaces) {
253 if (++lastPosition == interfacesToVisit.length)
257 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
260 interfacesToVisit[lastPosition] = itsInterfaces;
267 // bit reinitialization
268 for (int i = 0; i <= lastPosition; i++) {
269 ReferenceBinding[] interfaces = interfacesToVisit[i];
270 for (int j = 0, length = interfaces.length; j < length; j++)
271 interfaces[j].tagBits &= ~InterfaceVisited;
273 if (ambiguous != null)
277 if (visibleField != null)
280 return new ProblemFieldBinding(currentType, fieldName, NotVisible);
285 public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
286 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
287 return null; // know it has no member types (nor inherited member types)
289 SourceTypeBinding enclosingSourceType = enclosingSourceType();
290 PackageBinding currentPackage = getCurrentPackage();
291 compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
292 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
293 if (memberType != null) {
294 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
295 if (enclosingSourceType == null
296 ? memberType.canBeSeenBy(currentPackage)
297 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
300 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
303 // collect all superinterfaces of receiverType until the memberType is found in a supertype
304 ReferenceBinding currentType = enclosingType;
305 ReferenceBinding[][] interfacesToVisit = null;
306 int lastPosition = -1;
307 ReferenceBinding visibleMemberType = null;
308 boolean keepLooking = true;
309 ReferenceBinding notVisible = null;
310 // we could hold onto the not visible field for extra error reporting
311 while (keepLooking) {
312 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
313 if (itsInterfaces != NoSuperInterfaces) {
314 if (interfacesToVisit == null)
315 interfacesToVisit = new ReferenceBinding[5][];
316 if (++lastPosition == interfacesToVisit.length)
320 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
323 interfacesToVisit[lastPosition] = itsInterfaces;
325 if ((currentType = currentType.superclass()) == null)
328 compilationUnitScope().recordReference(currentType.compoundName, typeName);
329 if ((memberType = currentType.getMemberType(typeName)) != null) {
330 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
332 if (enclosingSourceType == null
333 ? memberType.canBeSeenBy(currentPackage)
334 : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
335 if (visibleMemberType == null)
336 visibleMemberType = memberType;
338 return new ProblemReferenceBinding(typeName, Ambiguous);
340 notVisible = memberType;
344 // walk all visible interfaces to find ambiguous references
345 if (interfacesToVisit != null) {
346 ProblemReferenceBinding ambiguous = null;
347 done : for (int i = 0; i <= lastPosition; i++) {
348 ReferenceBinding[] interfaces = interfacesToVisit[i];
349 for (int j = 0, length = interfaces.length; j < length; j++) {
350 ReferenceBinding anInterface = interfaces[j];
351 if ((anInterface.tagBits & InterfaceVisited) == 0) {
352 // if interface as not already been visited
353 anInterface.tagBits |= InterfaceVisited;
354 compilationUnitScope().recordReference(anInterface.compoundName, typeName);
355 if ((memberType = anInterface.getMemberType(typeName)) != null) {
356 compilationUnitScope().recordTypeReference(memberType); // to record supertypes
357 if (visibleMemberType == null) {
358 visibleMemberType = memberType;
360 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
364 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
365 if (itsInterfaces != NoSuperInterfaces) {
366 if (++lastPosition == interfacesToVisit.length)
370 interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
373 interfacesToVisit[lastPosition] = itsInterfaces;
380 // bit reinitialization
381 for (int i = 0; i <= lastPosition; i++) {
382 ReferenceBinding[] interfaces = interfacesToVisit[i];
383 for (int j = 0, length = interfaces.length; j < length; j++)
384 interfaces[j].tagBits &= ~InterfaceVisited;
386 if (ambiguous != null)
389 if (visibleMemberType != null)
390 return visibleMemberType;
391 if (notVisible != null)
392 return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
397 public MethodBinding findMethod(
398 ReferenceBinding receiverType,
400 TypeBinding[] argumentTypes,
401 InvocationSite invocationSite) {
403 ReferenceBinding currentType = receiverType;
404 MethodBinding matchingMethod = null;
405 ObjectVector found = new ObjectVector();
407 compilationUnitScope().recordTypeReference(receiverType);
408 compilationUnitScope().recordTypeReferences(argumentTypes);
410 if (currentType.isInterface()) {
411 MethodBinding[] currentMethods = currentType.getMethods(selector);
412 int currentLength = currentMethods.length;
413 if (currentLength == 1) {
414 matchingMethod = currentMethods[0];
415 } else if (currentLength > 1) {
416 found.addAll(currentMethods);
418 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
419 currentType = getJavaLangObject();
423 ReferenceBinding classHierarchyStart = currentType;
424 while (currentType != null) {
425 MethodBinding[] currentMethods = currentType.getMethods(selector);
426 int currentLength = currentMethods.length;
427 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
428 matchingMethod = currentMethods[0];
429 } else if (currentLength > 0) {
430 if (matchingMethod != null) {
431 found.add(matchingMethod);
432 matchingMethod = null;
434 found.addAll(currentMethods);
436 currentType = currentType.superclass();
439 int foundSize = found.size;
440 if (foundSize == 0) {
441 if (matchingMethod != null && areParametersAssignable(matchingMethod.parameters, argumentTypes))
442 return matchingMethod;
443 return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
446 MethodBinding[] candidates = new MethodBinding[foundSize];
447 int candidatesCount = 0;
448 // argument type compatibility check
449 for (int i = 0; i < foundSize; i++) {
450 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
451 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
452 candidates[candidatesCount++] = methodBinding;
454 if (candidatesCount == 1) {
455 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
456 return candidates[0]; // have not checked visibility
458 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
459 MethodBinding interfaceMethod =
460 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
461 if (interfaceMethod != null) return interfaceMethod;
463 int argLength = argumentTypes.length;
464 foundSize = found.size;
465 nextMethod : for (int i = 0; i < foundSize; i++) {
466 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
467 TypeBinding[] params = methodBinding.parameters;
468 int paramLength = params.length;
469 nextArg: for (int a = 0; a < argLength; a++) {
470 TypeBinding arg = argumentTypes[a];
471 for (int p = 0; p < paramLength; p++)
472 if (params[p] == arg)
476 return methodBinding;
478 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
482 int visiblesCount = 0;
483 for (int i = 0; i < candidatesCount; i++) {
484 MethodBinding methodBinding = candidates[i];
485 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
486 if (visiblesCount != i) {
487 candidates[i] = null;
488 candidates[visiblesCount] = methodBinding;
493 if (visiblesCount == 1) {
494 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
495 return candidates[0];
497 if (visiblesCount == 0) {
498 MethodBinding interfaceMethod =
499 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
500 if (interfaceMethod != null) return interfaceMethod;
501 return new ProblemMethodBinding(candidates[0].selector, argumentTypes, candidates[0].declaringClass, NotVisible);
503 if (candidates[0].declaringClass.isClass()) {
504 return mostSpecificClassMethodBinding(candidates, visiblesCount);
506 return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
510 // abstract method lookup lookup (since maybe missing default abstract methods)
511 public MethodBinding findDefaultAbstractMethod(
512 ReferenceBinding receiverType,
514 TypeBinding[] argumentTypes,
515 InvocationSite invocationSite,
516 ReferenceBinding classHierarchyStart,
517 MethodBinding matchingMethod,
518 ObjectVector found) {
520 int startFoundSize = found.size;
521 ReferenceBinding currentType = classHierarchyStart;
522 while (currentType != null) {
523 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
524 currentType = currentType.superclass();
526 int foundSize = found.size;
527 if (foundSize == startFoundSize) return matchingMethod; // maybe null
529 MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
530 int candidatesCount = 0;
531 // argument type compatibility check
532 for (int i = startFoundSize; i < foundSize; i++) {
533 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
534 if (areParametersAssignable(methodBinding.parameters, argumentTypes))
535 candidates[candidatesCount++] = methodBinding;
537 if (candidatesCount == 1) {
538 compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
539 return candidates[0];
541 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
542 int argLength = argumentTypes.length;
543 nextMethod : for (int i = 0; i < foundSize; i++) {
544 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
545 TypeBinding[] params = methodBinding.parameters;
546 int paramLength = params.length;
547 nextArg: for (int a = 0; a < argLength; a++) {
548 TypeBinding arg = argumentTypes[a];
549 for (int p = 0; p < paramLength; p++)
550 if (params[p] == arg)
554 return methodBinding;
556 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
558 // no need to check for visibility - interface methods are public
559 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
562 public MethodBinding findMethodInSuperInterfaces(
563 ReferenceBinding currentType,
566 MethodBinding matchingMethod) {
568 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
569 if (itsInterfaces != NoSuperInterfaces) {
570 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
571 int lastPosition = -1;
572 if (++lastPosition == interfacesToVisit.length)
574 interfacesToVisit, 0,
575 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
577 interfacesToVisit[lastPosition] = itsInterfaces;
579 for (int i = 0; i <= lastPosition; i++) {
580 ReferenceBinding[] interfaces = interfacesToVisit[i];
581 for (int j = 0, length = interfaces.length; j < length; j++) {
582 currentType = interfaces[j];
583 if ((currentType.tagBits & InterfaceVisited) == 0) {
584 // if interface as not already been visited
585 currentType.tagBits |= InterfaceVisited;
587 MethodBinding[] currentMethods = currentType.getMethods(selector);
588 int currentLength = currentMethods.length;
589 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
590 matchingMethod = currentMethods[0];
591 } else if (currentLength > 0) {
592 if (matchingMethod != null) {
593 found.add(matchingMethod);
594 matchingMethod = null;
596 found.addAll(currentMethods);
598 itsInterfaces = currentType.superInterfaces();
599 if (itsInterfaces != NoSuperInterfaces) {
600 if (++lastPosition == interfacesToVisit.length)
602 interfacesToVisit, 0,
603 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
605 interfacesToVisit[lastPosition] = itsInterfaces;
611 // bit reinitialization
612 for (int i = 0; i <= lastPosition; i++) {
613 ReferenceBinding[] interfaces = interfacesToVisit[i];
614 for (int j = 0, length = interfaces.length; j < length; j++)
615 interfaces[j].tagBits &= ~InterfaceVisited;
618 return matchingMethod;
622 public MethodBinding findMethodForArray(
623 ArrayBinding receiverType,
625 TypeBinding[] argumentTypes,
626 InvocationSite invocationSite) {
628 ReferenceBinding object = getJavaLangObject();
629 MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
630 if (methodBinding != null) {
631 // handle the method clone() specially... cannot be protected or throw exceptions
632 if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
633 return new MethodBinding(
634 (methodBinding.modifiers ^ AccProtected) | AccPublic,
636 methodBinding.returnType,
640 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
641 return methodBinding;
643 // answers closest approximation, may not check argumentTypes or visibility
644 methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
645 if (methodBinding == null)
646 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
647 if (methodBinding.isValidBinding()) {
648 if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
649 return new ProblemMethodBinding(
654 if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
655 return new ProblemMethodBinding(
658 methodBinding.declaringClass,
661 return methodBinding;
665 public ReferenceBinding findType(
667 PackageBinding declarationPackage,
668 PackageBinding invocationPackage) {
670 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
671 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
672 if (typeBinding == null)
675 if (typeBinding.isValidBinding()) {
676 // Not convinced that this is necessary
677 // compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
678 if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
679 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
684 public TypeBinding getBaseType(char[] name) {
685 // list should be optimized (with most often used first)
686 int length = name.length;
687 if (length > 2 && length < 8) {
690 if (length == 3 && name[1] == 'n' && name[2] == 't')
694 if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
705 return BooleanBinding;
706 if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
710 if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
720 return DoubleBinding;
731 if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
746 public final PackageBinding getCurrentPackage() {
747 Scope scope, unitScope = this;
748 while ((scope = unitScope.parent) != null)
750 return ((CompilationUnitScope) unitScope).fPackage;
753 public final ReferenceBinding getJavaIoSerializable() {
754 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
755 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
756 if (type != null) return type;
758 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
759 return null; // will not get here since the above error aborts the compilation
762 public final ReferenceBinding getJavaLangClass() {
763 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
764 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
765 if (type != null) return type;
767 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
768 return null; // will not get here since the above error aborts the compilation
771 public final ReferenceBinding getJavaLangCloneable() {
772 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
773 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
774 if (type != null) return type;
776 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
777 return null; // will not get here since the above error aborts the compilation
780 public final ReferenceBinding getJavaLangError() {
781 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
782 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
783 if (type != null) return type;
785 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
786 return null; // will not get here since the above error aborts the compilation
789 public final ReferenceBinding getJavaLangAssertionError() {
790 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
791 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
792 if (type != null) return type;
793 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
794 return null; // will not get here since the above error aborts the compilation
797 public final ReferenceBinding getJavaLangObject() {
798 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
799 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
800 if (type != null) return type;
802 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
803 return null; // will not get here since the above error aborts the compilation
806 public final ReferenceBinding getJavaLangRuntimeException() {
807 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
808 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
809 if (type != null) return type;
811 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
812 return null; // will not get here since the above error aborts the compilation
815 public final ReferenceBinding getJavaLangString() {
816 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
817 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
818 if (type != null) return type;
820 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
821 return null; // will not get here since the above error aborts the compilation
824 public final ReferenceBinding getJavaLangThrowable() {
825 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
826 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
827 if (type != null) return type;
829 problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
830 return null; // will not get here since the above error aborts the compilation
833 /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
835 public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
836 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
837 if (memberType != null) return memberType;
838 return new ProblemReferenceBinding(typeName, NotFound);
841 /* Answer the type binding corresponding to the compoundName.
843 * NOTE: If a problem binding is returned, senders should extract the compound name
844 * from the binding & not assume the problem applies to the entire compoundName.
846 public final TypeBinding getType(char[][] compoundName) {
847 int typeNameLength = compoundName.length;
848 if (typeNameLength == 1) {
849 // Would like to remove this test and require senders to specially handle base types
850 TypeBinding binding = getBaseType(compoundName[0]);
851 if (binding != null) return binding;
854 compilationUnitScope().recordQualifiedReference(compoundName);
856 getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
858 return new ProblemReferenceBinding(compoundName[0], NotFound);
859 if (!binding.isValidBinding())
860 return (ReferenceBinding) binding;
862 int currentIndex = 1;
863 boolean checkVisibility = false;
864 if (binding instanceof PackageBinding) {
865 PackageBinding packageBinding = (PackageBinding) binding;
866 while (currentIndex < typeNameLength) {
867 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
869 return new ProblemReferenceBinding(
870 CharOperation.subarray(compoundName, 0, currentIndex),
872 if (!binding.isValidBinding())
873 return new ProblemReferenceBinding(
874 CharOperation.subarray(compoundName, 0, currentIndex),
875 binding.problemId());
876 if (!(binding instanceof PackageBinding))
878 packageBinding = (PackageBinding) binding;
880 if (binding instanceof PackageBinding)
881 return new ProblemReferenceBinding(
882 CharOperation.subarray(compoundName, 0, currentIndex),
884 checkVisibility = true;
887 // binding is now a ReferenceBinding
888 ReferenceBinding typeBinding = (ReferenceBinding) binding;
889 compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
890 if (checkVisibility) // handles the fall through case
891 if (!typeBinding.canBeSeenBy(this))
892 return new ProblemReferenceBinding(
893 CharOperation.subarray(compoundName, 0, currentIndex),
897 while (currentIndex < typeNameLength) {
898 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
899 if (!typeBinding.isValidBinding())
900 return new ProblemReferenceBinding(
901 CharOperation.subarray(compoundName, 0, currentIndex),
902 typeBinding.problemId());
907 /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
908 * The name provided is a simple source name (e.g., "Object" , "Point", ...)
910 // The return type of this method could be ReferenceBinding if we did not answer base types.
911 // NOTE: We could support looking for Base Types last in the search, however any code using
912 // this feature would be extraordinarily slow. Therefore we don't do this
913 public final TypeBinding getType(char[] name) {
914 // Would like to remove this test and require senders to specially handle base types
915 TypeBinding binding = getBaseType(name);
916 if (binding != null) return binding;
917 return (ReferenceBinding) getTypeOrPackage(name, TYPE);
920 // Added for code assist... NOT Public API
921 public final Binding getTypeOrPackage(char[][] compoundName) {
922 int nameLength = compoundName.length;
923 if (nameLength == 1) {
924 TypeBinding binding = getBaseType(compoundName[0]);
925 if (binding != null) return binding;
927 Binding binding = getTypeOrPackage(compoundName[0], TYPE | PACKAGE);
928 if (!binding.isValidBinding()) return binding;
930 int currentIndex = 1;
931 boolean checkVisibility = false;
932 if (binding instanceof PackageBinding) {
933 PackageBinding packageBinding = (PackageBinding) binding;
935 while (currentIndex < nameLength) {
936 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
938 return new ProblemReferenceBinding(
939 CharOperation.subarray(compoundName, 0, currentIndex),
941 if (!binding.isValidBinding())
942 return new ProblemReferenceBinding(
943 CharOperation.subarray(compoundName, 0, currentIndex),
944 binding.problemId());
945 if (!(binding instanceof PackageBinding))
947 packageBinding = (PackageBinding) binding;
949 if (binding instanceof PackageBinding) return binding;
950 checkVisibility = true;
952 // binding is now a ReferenceBinding
953 ReferenceBinding typeBinding = (ReferenceBinding) binding;
954 if (checkVisibility) // handles the fall through case
955 if (!typeBinding.canBeSeenBy(this))
956 return new ProblemReferenceBinding(
957 CharOperation.subarray(compoundName, 0, currentIndex),
961 while (currentIndex < nameLength) {
962 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
964 if (!typeBinding.isValidBinding())
965 return new ProblemReferenceBinding(
966 CharOperation.subarray(compoundName, 0, currentIndex),
967 typeBinding.problemId());
974 final Binding getTypeOrPackage(char[] name, int mask) {
977 ReferenceBinding foundType = null;
978 if ((mask & TYPE) == 0) {
980 while ((next = scope.parent) != null)
983 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
984 switch (scope.kind) {
987 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
988 if (localType != null) {
989 if (foundType != null && foundType != localType)
990 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
995 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
996 if (CharOperation.equals(sourceType.sourceName, name)) {
997 if (foundType != null && foundType != sourceType)
998 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1002 ReferenceBinding memberType = findMemberType(name, sourceType);
1003 if (memberType != null) { // skip it if we did not find anything
1004 if (memberType.problemId() == Ambiguous) {
1005 if (foundType == null || foundType.problemId() == NotVisible)
1006 // supercedes any potential InheritedNameHidesEnclosingName problem
1009 // make the user qualify the type, likely wants the first inherited type
1010 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1012 if (memberType.isValidBinding()) {
1013 if (sourceType == memberType.enclosingType()
1014 || environment().options.complianceLevel >= CompilerOptions.JDK1_4) {
1015 // found a valid type in the 'immediate' scope (ie. not inherited)
1016 // OR in 1.4 mode (inherited shadows enclosing)
1017 if (foundType == null)
1019 if (foundType.isValidBinding())
1020 // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
1021 if (foundType != memberType)
1022 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
1025 if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
1026 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
1027 foundType = memberType;
1030 case COMPILATION_UNIT_SCOPE :
1033 scope = scope.parent;
1035 if (foundType != null && foundType.problemId() != NotVisible)
1039 // at this point the scope is a compilation unit scope
1040 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1041 // ask for the imports + name
1042 if ((mask & TYPE) != 0) {
1043 // check single type imports.
1044 ImportBinding[] imports = unitScope.imports;
1045 if (imports != null){
1046 // copy the list, since single type imports are removed if they cannot be resolved
1047 for (int i = 0, length = imports.length; i < length; i++) {
1048 ImportBinding typeImport = imports[i];
1049 if (!typeImport.onDemand)
1050 if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name))
1051 if (unitScope.resolveSingleTypeImport(typeImport) != null) {
1052 if (typeImport.reference != null) typeImport.reference.used = true;
1053 return typeImport.resolvedImport; // already know its visible
1057 // check if the name is in the current package (answer the problem binding unless its not found in which case continue to look)
1058 ReferenceBinding type = findType(name, unitScope.fPackage, unitScope.fPackage); // is always visible
1059 if (type != null) return type;
1061 // check on demand imports
1062 boolean foundInImport = false;
1063 if (imports != null){
1064 for (int i = 0, length = imports.length; i < length; i++) {
1065 ImportBinding someImport = imports[i];
1066 if (someImport.onDemand) {
1067 Binding resolvedImport = someImport.resolvedImport;
1068 ReferenceBinding temp =
1069 (resolvedImport instanceof PackageBinding)
1070 ? findType(name, (PackageBinding) resolvedImport, unitScope.fPackage)
1071 : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
1072 if (temp != null && temp.isValidBinding()) {
1073 if (someImport.reference != null) someImport.reference.used = true;
1075 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1076 return new ProblemReferenceBinding(name, Ambiguous);
1078 foundInImport = true;
1086 // see if the name is a package
1087 if ((mask & PACKAGE) != 0) {
1088 compilationUnitScope().recordSimpleReference(name);
1089 PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
1090 if (packageBinding != null)
1091 return packageBinding;
1094 compilationUnitScope().recordSimpleReference(name);
1095 // Answer error binding -- could not find name
1096 if (foundType != null){
1099 return new ProblemReferenceBinding(name, NotFound);
1102 /* Answer whether the type is defined in the same compilation unit as the receiver
1104 public final boolean isDefinedInSameUnit(ReferenceBinding type) {
1105 // find the outer most enclosing type
1106 ReferenceBinding enclosingType = type;
1107 while ((type = enclosingType.enclosingType()) != null)
1108 enclosingType = type;
1110 // find the compilation unit scope
1111 Scope scope, unitScope = this;
1112 while ((scope = unitScope.parent) != null)
1115 // test that the enclosingType is not part of the compilation unit
1116 SourceTypeBinding[] topLevelTypes =
1117 ((CompilationUnitScope) unitScope).topLevelTypes;
1118 for (int i = topLevelTypes.length; --i >= 0;)
1119 if (topLevelTypes[i] == enclosingType)
1124 public final boolean isJavaIoSerializable(TypeBinding tb) {
1125 //a first -none optimized version-...:-)....
1126 //please modify as needed
1128 return tb == getJavaIoSerializable();
1131 public final boolean isJavaLangCloneable(TypeBinding tb) {
1132 //a first -none optimized version-...:-)....
1133 //please modify as needed
1135 return tb == getJavaLangCloneable();
1138 public final boolean isJavaLangObject(TypeBinding type) {
1139 return type.id == T_JavaLangObject;
1142 public final MethodScope methodScope() {
1145 if (scope instanceof MethodScope)
1146 return (MethodScope) scope;
1147 scope = scope.parent;
1148 } while (scope != null);
1152 // Internal use only
1153 /* All methods in visible are acceptable matches for the method in question...
1154 * The methods defined by the receiver type appear before those defined by its
1155 * superclass and so on. We want to find the one which matches best.
1157 * Since the receiver type is a class, we know each method's declaring class is
1158 * either the receiver type or one of its superclasses. It is an error if the best match
1159 * is defined by a superclass, when a lesser match is defined by the receiver type
1160 * or a closer superclass.
1162 protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize) {
1164 MethodBinding method = null;
1165 MethodBinding previous = null;
1167 nextVisible : for (int i = 0; i < visibleSize; i++) {
1168 method = visible[i];
1170 if (previous != null && method.declaringClass != previous.declaringClass)
1171 break; // cannot answer a method farther up the hierarchy than the first method found
1173 for (int j = 0; j < visibleSize; j++) {
1174 if (i == j) continue;
1175 MethodBinding next = visible[j];
1176 if (!areParametersAssignable(next.parameters, method.parameters))
1177 continue nextVisible;
1179 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1182 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1185 // Internal use only
1186 /* All methods in visible are acceptable matches for the method in question...
1187 * Since the receiver type is an interface, we ignore the possibility that 2 inherited
1188 * but unrelated superinterfaces may define the same method in acceptable but
1189 * not identical ways... we just take the best match that we find since any class which
1190 * implements the receiver interface MUST implement all signatures for the method...
1191 * in which case the best match is correct.
1193 * NOTE: This is different than javac... in the following example, the message send of
1194 * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
1195 * interface I MUST implement both signatures for bar. If this class was the receiver of
1196 * the message send instead of the interface I, then no problem would be reported.
1205 interface I extends I1, I2 {}
1208 class X implements J {}
1211 public void foo(I i, X x) { i.bar(x); }
1214 protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize) {
1215 MethodBinding method = null;
1216 nextVisible : for (int i = 0; i < visibleSize; i++) {
1217 method = visible[i];
1218 for (int j = 0; j < visibleSize; j++) {
1219 if (i == j) continue;
1220 MethodBinding next = visible[j];
1221 if (!areParametersAssignable(next.parameters, method.parameters))
1222 continue nextVisible;
1224 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
1227 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
1230 public final ClassScope outerMostClassScope() {
1231 ClassScope lastClassScope = null;
1234 if (scope instanceof ClassScope)
1235 lastClassScope = (ClassScope) scope;
1236 scope = scope.parent;
1237 } while (scope != null);
1238 return lastClassScope; // may answer null if no class around
1241 public final MethodScope outerMostMethodScope() {
1242 MethodScope lastMethodScope = null;
1245 if (scope instanceof MethodScope)
1246 lastMethodScope = (MethodScope) scope;
1247 scope = scope.parent;
1248 } while (scope != null);
1249 return lastMethodScope; // may answer null if no method around
1252 public final CompilationUnitDeclaration referenceCompilationUnit() {
1253 Scope scope, unitScope = this;
1254 while ((scope = unitScope.parent) != null)
1256 return ((CompilationUnitScope) unitScope).referenceContext;
1258 // start position in this scope - for ordering scopes vs. variables