1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 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 org.eclipse.jdt.internal.compiler.lookup;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
18 import org.eclipse.jdt.core.compiler.CharOperation;
19 import org.eclipse.jdt.internal.compiler.ast.*;
20 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
21 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
22 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
23 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
24 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
25 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
27 public abstract class Scope
28 implements BaseTypes, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
30 public final static int BLOCK_SCOPE = 1;
31 public final static int CLASS_SCOPE = 3;
32 public final static int COMPILATION_UNIT_SCOPE = 4;
33 public final static int METHOD_SCOPE = 2;
35 public final static int NOT_COMPATIBLE = -1;
36 public final static int COMPATIBLE = 0;
37 public final static int AUTOBOX_COMPATIBLE = 1;
38 public final static int VARARGS_COMPATIBLE = 2;
40 /* Answer an int describing the relationship between the given types.
43 * EqualOrMoreSpecific : left is compatible with right
44 * MoreGeneric : right is compatible with left
46 public static int compareTypes(TypeBinding left, TypeBinding right) {
47 if (left.isCompatibleWith(right))
48 return EqualOrMoreSpecific;
49 if (right.isCompatibleWith(left))
55 * Returns an array of types, where original types got substituted given a substitution.
56 * Only allocate an array if anything is different.
58 public static ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
59 ReferenceBinding[] substitutedTypes = originalTypes;
60 for (int i = 0, length = originalTypes.length; i < length; i++) {
61 ReferenceBinding originalType = originalTypes[i];
62 ReferenceBinding substitutedParameter = (ReferenceBinding)substitution.substitute(originalType);
63 if (substitutedParameter != originalType) {
64 if (substitutedTypes == originalTypes) {
65 System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
67 substitutedTypes[i] = substitutedParameter;
68 } else if (substitutedTypes != originalTypes) {
69 substitutedTypes[i] = originalType;
72 return substitutedTypes;
76 * Returns an array of types, where original types got substituted given a substitution.
77 * Only allocate an array if anything is different.
79 public static TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
80 TypeBinding[] substitutedTypes = originalTypes;
81 for (int i = 0, length = originalTypes.length; i < length; i++) {
82 TypeBinding originalType = originalTypes[i];
83 TypeBinding substitutedParameter = substitution.substitute(originalType);
84 if (substitutedParameter != originalType) {
85 if (substitutedTypes == originalTypes) {
86 System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
88 substitutedTypes[i] = substitutedParameter;
89 } else if (substitutedTypes != originalTypes) {
90 substitutedTypes[i] = originalType;
93 return substitutedTypes;
99 protected Scope(int kind, Scope parent) {
101 this.parent = parent;
107 public int boxing(int id) {
110 return T_JavaLangInteger;
112 return T_JavaLangByte;
114 return T_JavaLangShort;
116 return T_JavaLangCharacter;
118 return T_JavaLangLong;
120 return T_JavaLangFloat;
122 return T_JavaLangDouble;
124 return T_JavaLangBoolean;
126 return T_JavaLangVoid;
133 public TypeBinding boxing(TypeBinding type) {
134 TypeBinding boxedType;
137 boxedType = environment().getType(JAVA_LANG_INTEGER);
138 if (boxedType != null) return boxedType;
139 return new ProblemReferenceBinding( JAVA_LANG_INTEGER, NotFound);
141 boxedType = environment().getType(JAVA_LANG_BYTE);
142 if (boxedType != null) return boxedType;
143 return new ProblemReferenceBinding( JAVA_LANG_BYTE, NotFound);
145 boxedType = environment().getType(JAVA_LANG_SHORT);
146 if (boxedType != null) return boxedType;
147 return new ProblemReferenceBinding( JAVA_LANG_SHORT, NotFound);
149 boxedType = environment().getType(JAVA_LANG_CHARACTER);
150 if (boxedType != null) return boxedType;
151 return new ProblemReferenceBinding( JAVA_LANG_CHARACTER, NotFound);
153 boxedType = environment().getType(JAVA_LANG_LONG);
154 if (boxedType != null) return boxedType;
155 return new ProblemReferenceBinding( JAVA_LANG_LONG, NotFound);
157 boxedType = environment().getType(JAVA_LANG_FLOAT);
158 if (boxedType != null) return boxedType;
159 return new ProblemReferenceBinding( JAVA_LANG_FLOAT, NotFound);
161 boxedType = environment().getType(JAVA_LANG_DOUBLE);
162 if (boxedType != null) return boxedType;
163 return new ProblemReferenceBinding( JAVA_LANG_DOUBLE, NotFound);
165 boxedType = environment().getType(JAVA_LANG_BOOLEAN);
166 if (boxedType != null) return boxedType;
167 return new ProblemReferenceBinding( JAVA_LANG_BOOLEAN, NotFound);
169 boxedType = environment().getType(JAVA_LANG_VOID);
170 if (boxedType != null) return boxedType;
171 return new ProblemReferenceBinding( JAVA_LANG_VOID, NotFound);
176 public final ClassScope classScope() {
179 if (scope instanceof ClassScope)
180 return (ClassScope) scope;
181 scope = scope.parent;
182 } while (scope != null);
186 /* Answer an int describing the relationship between the given type and unchecked exceptions.
189 * EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
190 * MoreGeneric : type is a supertype of an actual unchecked exception type
192 public int compareUncheckedException(ReferenceBinding type) {
193 int comparison = compareTypes(type, getJavaLangRuntimeException());
194 if (comparison != 0) return comparison;
195 return compareTypes(type, getJavaLangError());
198 public final CompilationUnitScope compilationUnitScope() {
199 Scope lastScope = null;
203 scope = scope.parent;
204 } while (scope != null);
205 return (CompilationUnitScope) lastScope;
210 * Given a method, returns null if arguments cannot be converted to parameters.
211 * Will answer a subsituted method in case the method was generic and type inference got triggered;
212 * in case the method was originally compatible, then simply answer it back.
214 protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite) {
216 TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments();
217 TypeBinding[] parameters = method.parameters;
218 TypeVariableBinding[] typeVariables = method.typeVariables;
219 if (parameters == arguments
220 && (method.returnType.tagBits & HasTypeVariable) == 0
221 && genericTypeArguments == null
222 && typeVariables == NoTypeVariables)
225 int argLength = arguments.length;
226 int paramLength = parameters.length;
227 boolean isVarArgs = method.isVarargs();
228 if (argLength != paramLength)
229 if (!isVarArgs || argLength < paramLength - 1)
230 return null; // incompatible
232 if (typeVariables != NoTypeVariables) { // generic method
233 method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite);
234 if (method == null) return null; // incompatible
235 if (!method.isValidBinding()) return method; // bound check issue is taking precedence
236 parameters = method.parameters; // reacquire them after type inference has performed
237 } else if (genericTypeArguments != null) {
238 if (method instanceof ParameterizedGenericMethodBinding) {
239 if (!((ParameterizedGenericMethodBinding) method).wasInferred) {
240 // attempt to invoke generic method of raw type with type hints <String>foo()
241 return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeArgumentsForRawGenericMethod);
244 return new ProblemMethodBinding(method, method.selector, genericTypeArguments, TypeParameterArityMismatch);
248 if (parameterCompatibilityLevel(method, arguments) > NOT_COMPATIBLE)
250 if (genericTypeArguments != null)
251 return new ProblemMethodBinding(method, method.selector, arguments, ParameterizedMethodTypeMismatch);
252 return null; // incompatible
255 protected boolean connectTypeVariables(TypeParameter[] typeParameters) {
256 boolean noProblems = true;
257 if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5) return true;
259 nextVariable : for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++) {
260 TypeParameter typeParameter = typeParameters[i];
261 TypeVariableBinding typeVariable = typeParameter.binding;
262 if (typeVariable == null) return false;
264 typeVariable.superclass = getJavaLangObject();
265 typeVariable.superInterfaces = NoSuperInterfaces;
266 // set firstBound to the binding of the first explicit bound in parameter declaration
267 typeVariable.firstBound = null; // first bound used to compute erasure
269 TypeReference typeRef = typeParameter.type;
271 continue nextVariable;
272 ReferenceBinding superType = this.kind == METHOD_SCOPE
273 ? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false/*no bound check*/)
274 : (ReferenceBinding) typeRef.resolveType((ClassScope)this);
275 if (superType == null) {
276 typeVariable.tagBits |= HierarchyHasProblems;
278 continue nextVariable;
280 if (superType.isTypeVariable()) {
281 TypeVariableBinding varSuperType = (TypeVariableBinding) superType;
282 if (varSuperType.rank >= typeVariable.rank && varSuperType.declaringElement == typeVariable.declaringElement) {
283 problemReporter().forwardTypeVariableReference(typeParameter, varSuperType);
284 typeVariable.tagBits |= HierarchyHasProblems;
286 continue nextVariable;
289 if (superType.isFinal())
290 problemReporter().finalVariableBound(typeVariable, typeRef);
291 typeRef.resolvedType = superType; // hold onto the problem type
292 if (superType.isClass()) {
293 typeVariable.superclass = superType;
295 typeVariable.superInterfaces = new ReferenceBinding[] {superType};
296 typeVariable.modifiers |= AccInterface;
298 typeVariable.firstBound = superType; // first bound used to compute erasure
300 TypeReference[] boundRefs = typeParameter.bounds;
301 if (boundRefs != null) {
302 for (int j = 0, k = boundRefs.length; j < k; j++) {
303 typeRef = boundRefs[j];
304 superType = this.kind == METHOD_SCOPE
305 ? (ReferenceBinding) typeRef.resolveType((BlockScope)this, false)
306 : (ReferenceBinding) typeRef.resolveType((ClassScope)this);
307 if (superType == null) {
308 typeVariable.tagBits |= HierarchyHasProblems;
310 continue nextVariable;
312 typeRef.resolvedType = superType; // hold onto the problem type
313 if (superType.isClass()) {
314 problemReporter().boundsMustBeAnInterface(typeRef, superType);
315 typeVariable.tagBits |= HierarchyHasProblems;
317 continue nextVariable;
319 if (superType.isParameterizedType()) {
320 ReferenceBinding match = typeVariable.superclass.findSuperTypeErasingTo((ReferenceBinding) superType.erasure());
321 boolean isCollision = match != null && match != superType;
322 for (int index = typeVariable.superInterfaces.length; !isCollision && --index >= 0;) {
323 ReferenceBinding temp = typeVariable.superInterfaces[index];
324 isCollision = superType != temp && superType.erasure() == temp.erasure();
327 problemReporter().boundHasConflictingArguments(typeRef, superType);
328 typeVariable.tagBits |= HierarchyHasProblems;
330 continue nextVariable;
333 int size = typeVariable.superInterfaces.length;
334 System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.superInterfaces = new ReferenceBinding[size + 1], 0, size);
335 typeVariable.superInterfaces[size] = superType;
342 public TypeBinding convertToRawType(TypeBinding type) {
343 int dimension = type.dimensions();
344 TypeBinding originalType = type.leafComponentType();
345 if (originalType instanceof ReferenceBinding) {
346 ReferenceBinding convertedType = (ReferenceBinding) originalType;
347 ReferenceBinding originalEnclosing = originalType.enclosingType();
348 ReferenceBinding convertedEnclosing = originalEnclosing;
349 if (originalEnclosing != null && convertedType.isStatic() && originalEnclosing.isGenericType()) {
350 convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
352 if (originalType.isGenericType()) {
353 convertedType = environment().createRawType(convertedType, convertedEnclosing);
354 } else if (originalEnclosing != convertedEnclosing) {
355 convertedType = createParameterizedType(convertedType, null, convertedEnclosing);
357 if (originalType != convertedType) {
358 return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType;
363 // TypeBinding leafType = type.leafComponentType();
364 // int dimension = type.dimensions();
365 // ReferenceBinding originalEnclosing = leafType.enclosingType();
366 // ReferenceBinding convertedEnclosing = originalEnclosing;
367 // if (originalEnclosing != null && ((ReferenceBinding)leafType).isStatic()) {
368 // convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
370 // if (leafType.isGenericType()) {
371 // type = environment().createRawType((ReferenceBinding) leafType, convertedEnclosing);
372 // if (dimension > 0)
373 // type = createArrayType(type, dimension);
374 // } else if (originalEnclosing != convertedEnclosing) {
375 // type = createParameterizedType((ReferenceBinding)leafType, null, convertedEnclosing);
376 // if (dimension > 0)
377 // type = createArrayType(type, dimension);
381 public ArrayBinding createArrayType(TypeBinding type, int dimension) {
382 if (type.isValidBinding())
383 return environment().createArrayType(type, dimension);
384 // do not cache obvious invalid types
385 return new ArrayBinding(type, dimension, environment());
388 public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] arguments, ReferenceBinding enclosingType) {
390 if (!genericType.isValidBinding()) break valid;
391 for (int i = 0, max = arguments == null ? 0 : arguments.length; i < max; i++)
392 if (!arguments[i].isValidBinding()) break valid;
393 return environment().createParameterizedType(genericType, arguments, enclosingType);
395 return new ParameterizedTypeBinding(genericType, arguments, enclosingType, environment());
398 public TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) {
400 PackageBinding unitPackage = compilationUnitScope().fPackage;
402 // do not construct type variables if source < 1.5
403 if (typeParameters == null || environment().options.sourceLevel < ClassFileConstants.JDK1_5)
404 return NoTypeVariables;
405 TypeVariableBinding[] typeVariableBindings = NoTypeVariables;
407 int length = typeParameters.length;
408 typeVariableBindings = new TypeVariableBinding[length];
409 HashtableOfObject knownTypeParameterNames = new HashtableOfObject(length);
411 nextParameter : for (int i = 0; i < length; i++) {
412 TypeParameter typeParameter = typeParameters[i];
413 TypeVariableBinding parameterBinding = new TypeVariableBinding(typeParameter.name, declaringElement, i);
414 parameterBinding.fPackage = unitPackage;
415 typeParameter.binding = parameterBinding;
417 if (knownTypeParameterNames.containsKey(typeParameter.name)) {
418 TypeVariableBinding previousBinding = (TypeVariableBinding) knownTypeParameterNames.get(typeParameter.name);
419 if (previousBinding != null) {
420 for (int j = 0; j < i; j++) {
421 TypeParameter previousParameter = typeParameters[j];
422 if (previousParameter.binding == previousBinding) {
423 problemReporter().duplicateTypeParameterInType(previousParameter);
424 previousParameter.binding = null;
429 knownTypeParameterNames.put(typeParameter.name, null); // ensure that the duplicate parameter is found & removed
430 problemReporter().duplicateTypeParameterInType(typeParameter);
431 typeParameter.binding = null;
433 knownTypeParameterNames.put(typeParameter.name, parameterBinding);
434 // remember that we have seen a field with this name
435 if (parameterBinding != null)
436 typeVariableBindings[count++] = parameterBinding;
438 // TODO should offer warnings to inform about hiding declaring, enclosing or member types
439 // ReferenceBinding type = sourceType;
440 // // check that the member does not conflict with an enclosing type
442 // if (CharOperation.equals(type.sourceName, memberContext.name)) {
443 // problemReporter().hidingEnclosingType(memberContext);
444 // continue nextParameter;
446 // type = type.enclosingType();
447 // } while (type != null);
448 // // check that the member type does not conflict with another sibling member type
449 // for (int j = 0; j < i; j++) {
450 // if (CharOperation.equals(referenceContext.memberTypes[j].name, memberContext.name)) {
451 // problemReporter().duplicateNestedType(memberContext);
452 // continue nextParameter;
456 if (count != length) {
457 System.arraycopy(typeVariableBindings, 0, typeVariableBindings = new TypeVariableBinding[count], 0, count);
459 return typeVariableBindings;
462 public final ClassScope enclosingClassScope() {
464 while ((scope = scope.parent) != null) {
465 if (scope instanceof ClassScope) return (ClassScope) scope;
467 return null; // may answer null if no type around
470 public final MethodScope enclosingMethodScope() {
472 while ((scope = scope.parent) != null) {
473 if (scope instanceof MethodScope) return (MethodScope) scope;
475 return null; // may answer null if no method around
478 /* Answer the receiver's enclosing source type.
480 public final SourceTypeBinding enclosingSourceType() {
483 if (scope instanceof ClassScope)
484 return ((ClassScope) scope).referenceContext.binding;
485 scope = scope.parent;
486 } while (scope != null);
489 public final LookupEnvironment environment() {
490 Scope scope, unitScope = this;
491 while ((scope = unitScope.parent) != null)
493 return ((CompilationUnitScope) unitScope).environment;
496 // abstract method lookup lookup (since maybe missing default abstract methods)
497 public MethodBinding findDefaultAbstractMethod(
498 ReferenceBinding receiverType,
500 TypeBinding[] argumentTypes,
501 InvocationSite invocationSite,
502 ReferenceBinding classHierarchyStart,
503 MethodBinding matchingMethod,
504 ObjectVector found) {
506 int startFoundSize = found.size;
507 ReferenceBinding currentType = classHierarchyStart;
508 while (currentType != null) {
509 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
510 currentType = currentType.superclass();
512 CompilationUnitScope unitScope = compilationUnitScope();
513 int foundSize = found.size;
514 if (foundSize == startFoundSize) {
515 if (matchingMethod != null)
516 unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
517 return matchingMethod; // maybe null
519 MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
520 int candidatesCount = 0;
521 MethodBinding problemMethod = null;
522 // argument type compatibility check
523 for (int i = startFoundSize; i < foundSize; i++) {
524 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
525 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
526 if (compatibleMethod != null) {
527 if (compatibleMethod.isValidBinding())
528 candidates[candidatesCount++] = compatibleMethod;
529 else if (problemMethod == null)
530 problemMethod = compatibleMethod;
534 if (candidatesCount == 1) {
535 unitScope.recordTypeReferences(candidates[0].thrownExceptions);
536 return candidates[0];
538 if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
539 if (problemMethod != null) return problemMethod;
540 int argLength = argumentTypes.length;
541 nextMethod : for (int i = 0; i < foundSize; i++) {
542 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
543 TypeBinding[] params = methodBinding.parameters;
544 int paramLength = params.length;
545 nextArg: for (int a = 0; a < argLength; a++) {
546 TypeBinding arg = argumentTypes[a];
547 for (int p = 0; p < paramLength; p++)
548 if (params[p] == arg)
552 return methodBinding;
554 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
556 // no need to check for visibility - interface methods are public
557 boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
559 return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite);
560 return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite);
564 public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
565 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
566 return null; // know it has no member types (nor inherited member types)
568 SourceTypeBinding enclosingSourceType = enclosingSourceType();
569 CompilationUnitScope unitScope = compilationUnitScope();
570 unitScope.recordReference(enclosingType, typeName);
571 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
572 if (memberType != null) {
573 unitScope.recordTypeReference(memberType);
574 if (enclosingSourceType == null
575 ? memberType.canBeSeenBy(getCurrentPackage())
576 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
578 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
584 public MethodBinding findExactMethod(
585 ReferenceBinding receiverType,
587 TypeBinding[] argumentTypes,
588 InvocationSite invocationSite) {
590 CompilationUnitScope unitScope = compilationUnitScope();
591 unitScope.recordTypeReferences(argumentTypes);
592 MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope);
593 if (exactMethod != null) {
594 unitScope.recordTypeReferences(exactMethod.thrownExceptions);
595 // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type)
596 if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this)) {
597 if (receiverType.id != T_JavaLangObject
598 && argumentTypes == NoParameters
599 && CharOperation.equals(selector, GETCLASS)
600 && exactMethod.returnType.isParameterizedType()/*1.5*/) {
601 return ParameterizedMethodBinding.instantiateGetClass(receiverType, exactMethod, this);
603 // targeting a generic method could find an exact match with variable return type
604 if (exactMethod.typeVariables != NoTypeVariables || invocationSite.genericTypeArguments() != null)
605 exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite);
613 /* Answer the field binding that corresponds to fieldName.
614 Start the lookup at the receiverType.
615 InvocationSite implements
616 isSuperAccess(); this is used to determine if the discovered field is visible.
617 Only fields defined by the receiverType or its supertypes are answered;
618 a field of an enclosing type will not be found using this API.
620 If no visible field is discovered, null is answered.
622 public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
623 if (receiverType.isBaseType()) return null;
625 CompilationUnitScope unitScope = compilationUnitScope();
626 unitScope.recordTypeReference(receiverType);
627 if (receiverType.isArrayType()) {
628 TypeBinding leafType = receiverType.leafComponentType();
629 if (leafType instanceof ReferenceBinding)
630 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
631 return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
632 if (CharOperation.equals(fieldName, LENGTH))
633 return ArrayBinding.ArrayLength;
637 ReferenceBinding currentType = (ReferenceBinding) receiverType;
638 if (!currentType.canBeSeenBy(this))
639 return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
641 FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
643 if (invocationSite == null
644 ? field.canBeSeenBy(getCurrentPackage())
645 : field.canBeSeenBy(currentType, invocationSite, this))
647 return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible);
649 // collect all superinterfaces of receiverType until the field is found in a supertype
650 ReferenceBinding[][] interfacesToVisit = null;
651 int lastPosition = -1;
652 FieldBinding visibleField = null;
653 boolean keepLooking = true;
654 boolean notVisible = false;
655 // we could hold onto the not visible field for extra error reporting
656 while (keepLooking) {
657 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
658 if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
659 ((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
660 itsInterfaces = currentType.superInterfaces();
662 if (itsInterfaces != NoSuperInterfaces) {
663 if (interfacesToVisit == null)
664 interfacesToVisit = new ReferenceBinding[5][];
665 if (++lastPosition == interfacesToVisit.length)
666 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
667 interfacesToVisit[lastPosition] = itsInterfaces;
669 if ((currentType = currentType.superclass()) == null)
672 unitScope.recordTypeReference(currentType);
673 if ((field = currentType.getField(fieldName, needResolve)) != null) {
675 if (field.canBeSeenBy(receiverType, invocationSite, this)) {
676 if (visibleField == null)
677 visibleField = field;
679 return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
686 // walk all visible interfaces to find ambiguous references
687 if (interfacesToVisit != null) {
688 ProblemFieldBinding ambiguous = null;
689 done : for (int i = 0; i <= lastPosition; i++) {
690 ReferenceBinding[] interfaces = interfacesToVisit[i];
691 for (int j = 0, length = interfaces.length; j < length; j++) {
692 ReferenceBinding anInterface = interfaces[j];
693 if ((anInterface.tagBits & InterfaceVisited) == 0) {
694 // if interface as not already been visited
695 anInterface.tagBits |= InterfaceVisited;
696 unitScope.recordTypeReference(anInterface);
697 if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
698 if (visibleField == null) {
699 visibleField = field;
701 ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
705 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
706 if (itsInterfaces != NoSuperInterfaces) {
707 if (++lastPosition == interfacesToVisit.length)
708 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
709 interfacesToVisit[lastPosition] = itsInterfaces;
716 // bit reinitialization
717 for (int i = 0; i <= lastPosition; i++) {
718 ReferenceBinding[] interfaces = interfacesToVisit[i];
719 for (int j = 0, length = interfaces.length; j < length; j++)
720 interfaces[j].tagBits &= ~InterfaceVisited;
722 if (ambiguous != null)
726 if (visibleField != null)
729 return new ProblemFieldBinding(currentType, fieldName, NotVisible);
734 public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
735 if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
736 return null; // know it has no member types (nor inherited member types)
738 SourceTypeBinding enclosingSourceType = enclosingSourceType();
739 PackageBinding currentPackage = getCurrentPackage();
740 CompilationUnitScope unitScope = compilationUnitScope();
741 unitScope.recordReference(enclosingType, typeName);
742 ReferenceBinding memberType = enclosingType.getMemberType(typeName);
743 if (memberType != null) {
744 unitScope.recordTypeReference(memberType);
745 if (enclosingSourceType == null
746 ? memberType.canBeSeenBy(currentPackage)
747 : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
749 return new ProblemReferenceBinding(typeName, memberType, NotVisible);
752 // collect all superinterfaces of receiverType until the memberType is found in a supertype
753 ReferenceBinding currentType = enclosingType;
754 ReferenceBinding[][] interfacesToVisit = null;
755 int lastPosition = -1;
756 ReferenceBinding visibleMemberType = null;
757 boolean keepLooking = true;
758 ReferenceBinding notVisible = null;
759 // we could hold onto the not visible field for extra error reporting
760 while (keepLooking) {
761 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
762 if (itsInterfaces == null) { // needed for statically imported types which don't know their hierarchy yet
763 ((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
764 itsInterfaces = currentType.superInterfaces();
766 if (itsInterfaces != NoSuperInterfaces) {
767 if (interfacesToVisit == null)
768 interfacesToVisit = new ReferenceBinding[5][];
769 if (++lastPosition == interfacesToVisit.length)
770 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
771 interfacesToVisit[lastPosition] = itsInterfaces;
773 if ((currentType = currentType.superclass()) == null)
776 unitScope.recordReference(currentType, typeName);
777 if ((memberType = currentType.getMemberType(typeName)) != null) {
778 unitScope.recordTypeReference(memberType);
780 if (enclosingSourceType == null
781 ? memberType.canBeSeenBy(currentPackage)
782 : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
783 if (visibleMemberType == null)
784 visibleMemberType = memberType;
786 return new ProblemReferenceBinding(typeName, Ambiguous);
788 notVisible = memberType;
792 // walk all visible interfaces to find ambiguous references
793 if (interfacesToVisit != null) {
794 ProblemReferenceBinding ambiguous = null;
795 done : for (int i = 0; i <= lastPosition; i++) {
796 ReferenceBinding[] interfaces = interfacesToVisit[i];
797 for (int j = 0, length = interfaces.length; j < length; j++) {
798 ReferenceBinding anInterface = interfaces[j];
799 if ((anInterface.tagBits & InterfaceVisited) == 0) {
800 // if interface as not already been visited
801 anInterface.tagBits |= InterfaceVisited;
802 unitScope.recordReference(anInterface, typeName);
803 if ((memberType = anInterface.getMemberType(typeName)) != null) {
804 unitScope.recordTypeReference(memberType);
805 if (visibleMemberType == null) {
806 visibleMemberType = memberType;
808 ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
812 ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
813 if (itsInterfaces != NoSuperInterfaces) {
814 if (++lastPosition == interfacesToVisit.length)
815 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
816 interfacesToVisit[lastPosition] = itsInterfaces;
823 // bit reinitialization
824 for (int i = 0; i <= lastPosition; i++) {
825 ReferenceBinding[] interfaces = interfacesToVisit[i];
826 for (int j = 0, length = interfaces.length; j < length; j++)
827 interfaces[j].tagBits &= ~InterfaceVisited;
829 if (ambiguous != null)
832 if (visibleMemberType != null)
833 return visibleMemberType;
834 if (notVisible != null)
835 return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
840 public MethodBinding findMethod(
841 ReferenceBinding receiverType,
843 TypeBinding[] argumentTypes,
844 InvocationSite invocationSite) {
846 ReferenceBinding currentType = receiverType;
847 MethodBinding matchingMethod = null;
848 ObjectVector found = new ObjectVector(); //TODO (kent) should rewrite to remove #matchingMethod since found is allocated anyway
850 CompilationUnitScope unitScope = compilationUnitScope();
851 unitScope.recordTypeReferences(argumentTypes);
853 if (currentType.isInterface()) {
854 unitScope.recordTypeReference(currentType);
855 MethodBinding[] currentMethods = currentType.getMethods(selector);
856 int currentLength = currentMethods.length;
857 if (currentLength == 1) {
858 matchingMethod = currentMethods[0];
859 } else if (currentLength > 1) {
860 found.addAll(currentMethods);
862 matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
863 currentType = getJavaLangObject();
866 boolean isCompliant14 = unitScope.environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
868 ReferenceBinding classHierarchyStart = currentType;
869 while (currentType != null) {
870 unitScope.recordTypeReference(currentType);
871 MethodBinding[] currentMethods = currentType.getMethods(selector);
872 int currentLength = currentMethods.length;
874 if (isCompliant14 && matchingMethod != null || found.size > 0) {
875 nextMethod: for (int i = 0; i < currentLength; i++) {
876 MethodBinding currentMethod = currentMethods[i];
877 // if 1.4 compliant, must filter out redundant protected methods from superclasses
878 // protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
879 // when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
880 // if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
881 // BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
882 if (matchingMethod != null) {
883 if (currentMethod.areParametersEqual(matchingMethod)) {
885 currentMethods[i] = null; // discard this match
889 for (int j = 0, max = found.size; j < max; j++) {
890 if (((MethodBinding) found.elementAt(j)).areParametersEqual(currentMethod)) {
892 currentMethods[i] = null;
900 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
901 matchingMethod = currentMethods[0];
902 } else if (currentLength > 0) {
903 if (matchingMethod != null) {
904 found.add(matchingMethod);
905 matchingMethod = null;
907 // append currentMethods, filtering out null entries
908 int maxMethod = currentMethods.length;
909 if (maxMethod == currentLength) { // no method was eliminated for 1.4 compliance (see above)
910 found.addAll(currentMethods);
912 for (int i = 0, max = currentMethods.length; i < max; i++) {
913 MethodBinding currentMethod = currentMethods[i];
914 if (currentMethod != null) found.add(currentMethod);
918 currentType = currentType.superclass();
921 // if found several candidates, then eliminate those not matching argument types
922 int foundSize = found.size;
923 MethodBinding[] candidates = null;
924 int candidatesCount = 0;
925 boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ?
926 MethodBinding problemMethod = null;
928 // argument type compatibility check
929 for (int i = 0; i < foundSize; i++) {
930 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
931 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
932 if (compatibleMethod != null) {
933 if (compatibleMethod.isValidBinding()) {
934 switch (candidatesCount) {
936 matchingMethod = compatibleMethod; // if only one match, reuse matchingMethod
937 checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
940 candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
941 candidates[0] = matchingMethod; // copy back
942 matchingMethod = null;
945 candidates[candidatesCount] = compatibleMethod;
948 } else if (problemMethod == null) {
949 problemMethod = compatibleMethod;
954 if (candidatesCount > 0)
955 problemMethod = null; // forget the problem method if candidates were found
957 // if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod
958 if (matchingMethod != null) {
959 if (!checkedMatchingMethod) {
960 MethodBinding compatibleMethod = computeCompatibleMethod(matchingMethod, argumentTypes, invocationSite);
961 if (compatibleMethod != null) {
962 if (compatibleMethod.isValidBinding()) {
963 matchingMethod = compatibleMethod;
964 checkedMatchingMethod = true;
966 problemMethod = compatibleMethod;
970 if (checkedMatchingMethod) {
971 // (if no default abstract) must explicitly look for one instead, which could be a better match
972 if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
973 // ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
974 MethodBinding interfaceMethod =
975 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);
976 if (interfaceMethod != null) return interfaceMethod;
977 unitScope.recordTypeReferences(matchingMethod.thrownExceptions);
978 return matchingMethod;
982 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
983 if (matchingMethod != null) return matchingMethod;
984 return problemMethod;
987 // no match was found, try to find a close match when the parameter order is wrong or missing some parameters
988 if (candidatesCount == 0) {
989 MethodBinding interfaceMethod =
990 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
991 if (interfaceMethod != null) return interfaceMethod;
992 if (problemMethod != null) return problemMethod;
994 int argLength = argumentTypes.length;
995 foundSize = found.size;
996 nextMethod : for (int i = 0; i < foundSize; i++) {
997 MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
998 TypeBinding[] params = methodBinding.parameters;
999 int paramLength = params.length;
1000 nextArg: for (int a = 0; a < argLength; a++) {
1001 TypeBinding arg = argumentTypes[a];
1002 for (int p = 0; p < paramLength; p++)
1003 if (params[p] == arg)
1005 continue nextMethod;
1007 return methodBinding;
1009 if (found.size == 0) return null;
1010 return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
1013 // check for duplicate parameterized methods
1014 if (unitScope.environment.options.sourceLevel >= ClassFileConstants.JDK1_5) {
1015 for (int i = 0; i < candidatesCount; i++) {
1016 MethodBinding current = candidates[i];
1017 if (current instanceof ParameterizedGenericMethodBinding)
1018 current = ((ParameterizedGenericMethodBinding) current).originalMethod;
1019 if (current instanceof ParameterizedMethodBinding)
1020 for (int j = i + 1; j < candidatesCount; j++)
1021 if (current.declaringClass == candidates[j].declaringClass && current.areParametersEqual(candidates[j]))
1022 return new ProblemMethodBinding(candidates[i].selector, candidates[i].parameters, Ambiguous);
1026 // tiebreak using visibility check
1027 int visiblesCount = 0;
1028 for (int i = 0; i < candidatesCount; i++) {
1029 MethodBinding methodBinding = candidates[i];
1030 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
1031 if (visiblesCount != i) {
1032 candidates[i] = null;
1033 candidates[visiblesCount] = methodBinding;
1038 if (visiblesCount == 1) {
1039 unitScope.recordTypeReferences(candidates[0].thrownExceptions);
1040 return candidates[0];
1042 if (visiblesCount == 0) {
1043 MethodBinding interfaceMethod =
1044 findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
1045 if (interfaceMethod != null) return interfaceMethod;
1046 return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
1049 return mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite);
1050 return candidates[0].declaringClass.isClass()
1051 ? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
1052 : mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
1055 // Internal use only
1056 public MethodBinding findMethodForArray(
1057 ArrayBinding receiverType,
1059 TypeBinding[] argumentTypes,
1060 InvocationSite invocationSite) {
1062 TypeBinding leafType = receiverType.leafComponentType();
1063 if (leafType instanceof ReferenceBinding) {
1064 if (!((ReferenceBinding) leafType).canBeSeenBy(this))
1065 return new ProblemMethodBinding(selector, TypeConstants.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
1068 ReferenceBinding object = getJavaLangObject();
1069 MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
1070 if (methodBinding != null) {
1071 // handle the method clone() specially... cannot be protected or throw exceptions
1072 if (argumentTypes == NoParameters) {
1073 switch (selector[0]) {
1075 if (CharOperation.equals(selector, CLONE)) {
1076 return new UpdatedMethodBinding(
1077 environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
1078 (methodBinding.modifiers & ~AccProtected) | AccPublic,
1080 methodBinding.returnType,
1087 if (CharOperation.equals(selector, GETCLASS) && methodBinding.returnType.isParameterizedType()/*1.5*/) {
1088 return ParameterizedMethodBinding.instantiateGetClass(receiverType, methodBinding, this);
1093 if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
1094 return methodBinding;
1096 // answers closest approximation, may not check argumentTypes or visibility
1097 methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
1098 if (methodBinding == null)
1099 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1100 if (methodBinding.isValidBinding()) {
1101 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1102 if (compatibleMethod == null)
1103 return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
1104 if (!compatibleMethod.isValidBinding())
1105 return compatibleMethod;
1107 methodBinding = compatibleMethod;
1108 if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
1109 return new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
1111 return methodBinding;
1114 public MethodBinding findMethodInSuperInterfaces(
1115 ReferenceBinding currentType,
1118 MethodBinding matchingMethod) {
1120 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
1121 if (itsInterfaces != NoSuperInterfaces) {
1122 ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
1123 int lastPosition = -1;
1124 if (++lastPosition == interfacesToVisit.length)
1126 interfacesToVisit, 0,
1127 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
1129 interfacesToVisit[lastPosition] = itsInterfaces;
1131 for (int i = 0; i <= lastPosition; i++) {
1132 ReferenceBinding[] interfaces = interfacesToVisit[i];
1133 for (int j = 0, length = interfaces.length; j < length; j++) {
1134 currentType = interfaces[j];
1135 if ((currentType.tagBits & InterfaceVisited) == 0) {
1136 // if interface as not already been visited
1137 currentType.tagBits |= InterfaceVisited;
1139 compilationUnitScope().recordTypeReference(currentType);
1140 MethodBinding[] currentMethods = currentType.getMethods(selector);
1141 int currentLength = currentMethods.length;
1142 if (currentLength == 1 && matchingMethod == null && found.size == 0) {
1143 matchingMethod = currentMethods[0];
1144 } else if (currentLength > 0) {
1145 if (matchingMethod != null) {
1146 found.add(matchingMethod);
1147 matchingMethod = null;
1149 found.addAll(currentMethods);
1151 itsInterfaces = currentType.superInterfaces();
1152 if (itsInterfaces != NoSuperInterfaces) {
1153 if (++lastPosition == interfacesToVisit.length)
1155 interfacesToVisit, 0,
1156 interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
1158 interfacesToVisit[lastPosition] = itsInterfaces;
1164 // bit reinitialization
1165 for (int i = 0; i <= lastPosition; i++) {
1166 ReferenceBinding[] interfaces = interfacesToVisit[i];
1167 for (int j = 0, length = interfaces.length; j < length; j++)
1168 interfaces[j].tagBits &= ~InterfaceVisited;
1171 return matchingMethod;
1174 // Internal use only
1175 public ReferenceBinding findType(
1177 PackageBinding declarationPackage,
1178 PackageBinding invocationPackage) {
1180 compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
1181 ReferenceBinding typeBinding = declarationPackage.getType(typeName);
1182 if (typeBinding == null)
1185 if (typeBinding.isValidBinding()) {
1186 if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
1187 return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
1192 public LocalVariableBinding findVariable(char[] variable) {
1197 public static TypeBinding getBaseType(char[] name) {
1198 // list should be optimized (with most often used first)
1199 int length = name.length;
1200 if (length > 2 && length < 8) {
1203 if (length == 3 && name[1] == 'n' && name[2] == 't')
1207 if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
1218 return BooleanBinding;
1219 if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
1223 if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
1233 return DoubleBinding;
1241 return FloatBinding;
1244 if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
1253 return ShortBinding;
1261 * Answer the binding that corresponds to the argument name.
1262 * flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
1263 * Only bindings corresponding to the mask can be answered.
1265 * For example, getBinding("foo", VARIABLE, site) will answer
1266 * the binding for the field or local named "foo" (or an error binding if none exists).
1267 * If a type named "foo" exists, it will not be detected (and an error binding will be answered)
1269 * The VARIABLE mask has precedence over the TYPE mask.
1271 * If the VARIABLE mask is not set, neither fields nor locals will be looked for.
1273 * InvocationSite implements:
1274 * isSuperAccess(); this is used to determine if the discovered field is visible.
1276 * Limitations: cannot request FIELD independently of LOCAL, or vice versa
1278 public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
1281 Binding binding = null;
1282 FieldBinding problemField = null;
1283 if ((mask & Binding.VARIABLE) != 0) {
1284 boolean insideStaticContext = false;
1285 boolean insideConstructorCall = false;
1287 FieldBinding foundField = null;
1288 // can be a problem field which is answered if a valid field is not found
1289 ProblemFieldBinding foundInsideProblem = null;
1290 // inside Constructor call or inside static context
1294 ReferenceBinding foundActualReceiverType = null;
1295 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1296 switch (scope.kind) {
1298 MethodScope methodScope = (MethodScope) scope;
1299 insideStaticContext |= methodScope.isStatic;
1300 insideConstructorCall |= methodScope.isConstructorCall;
1301 // Fall through... could duplicate the code below to save a cast - questionable optimization
1303 LocalVariableBinding variableBinding = scope.findVariable(name);
1304 // looks in this scope only
1305 if (variableBinding != null) {
1306 if (foundField != null && foundField.isValidBinding())
1307 return new ProblemFieldBinding(
1308 foundField, // closest match
1309 foundField.declaringClass,
1311 InheritedNameHidesEnclosingName);
1313 invocationSite.setDepth(depth);
1314 return variableBinding;
1318 ClassScope classScope = (ClassScope) scope;
1319 SourceTypeBinding enclosingType = classScope.referenceContext.binding;
1320 FieldBinding fieldBinding = classScope.findField(enclosingType, name, invocationSite, needResolve);
1321 // Use next line instead if willing to enable protected access accross inner types
1322 // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
1324 // SourceTypeBinding initialType = this.enclosingSourceType();
1325 // if ((fieldBinding == null || !fieldBinding.isValidBinding()) && enclosingType.hasMemberTypes()) { // check member enums
1326 // ReferenceBinding[] memberTypes = enclosingType.memberTypes();
1327 // for (int i = 0, length = memberTypes.length; i < length; i++) {
1328 // ReferenceBinding memberType = memberTypes[i];
1329 // if (memberType != initialType && memberType.isEnum()) { // do not find one's field through its enclosing members
1330 // FieldBinding enumField = ((SourceTypeBinding)memberType).scope.findField(memberType, name, invocationSite, needResolve);
1331 // if (enumField != null && (enumField.modifiers & AccEnum) != 0) {
1332 // // grant access to enum constants of enclosing members
1333 // // TODO (kent) need to revisit to see whether should walk sibling enums and issue an ambiguous match
1334 // return enumField;
1339 if (fieldBinding != null) { // skip it if we did not find anything
1340 if (fieldBinding.problemId() == Ambiguous) {
1341 if (foundField == null || foundField.problemId() == NotVisible)
1342 // supercedes any potential InheritedNameHidesEnclosingName problem
1343 return fieldBinding;
1344 // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
1345 return new ProblemFieldBinding(
1346 foundField, // closest match
1347 foundField.declaringClass,
1349 InheritedNameHidesEnclosingName);
1352 ProblemFieldBinding insideProblem = null;
1353 if (fieldBinding.isValidBinding()) {
1354 if (!fieldBinding.isStatic()) {
1355 if (insideConstructorCall) {
1357 new ProblemFieldBinding(
1358 fieldBinding, // closest match
1359 fieldBinding.declaringClass,
1361 NonStaticReferenceInConstructorInvocation);
1362 } else if (insideStaticContext) {
1364 new ProblemFieldBinding(
1365 fieldBinding, // closest match
1366 fieldBinding.declaringClass,
1368 NonStaticReferenceInStaticContext);
1371 if (enclosingType == fieldBinding.declaringClass || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
1372 // found a valid field in the 'immediate' scope (ie. not inherited)
1373 // OR in 1.4 mode (inherited shadows enclosing)
1374 if (foundField == null) {
1376 invocationSite.setDepth(depth);
1377 invocationSite.setActualReceiverType(enclosingType);
1379 // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
1380 return insideProblem == null ? fieldBinding : insideProblem;
1382 if (foundField.isValidBinding())
1383 // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
1384 if (foundField.declaringClass != fieldBinding.declaringClass)
1385 // ie. have we found the same field - do not trust field identity yet
1386 return new ProblemFieldBinding(
1387 foundField, // closest match
1388 foundField.declaringClass,
1390 InheritedNameHidesEnclosingName);
1394 if (foundField == null || (foundField.problemId() == NotVisible && fieldBinding.problemId() != NotVisible)) {
1395 // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
1397 foundActualReceiverType = enclosingType;
1398 foundInsideProblem = insideProblem;
1399 foundField = fieldBinding;
1403 insideStaticContext |= enclosingType.isStatic();
1404 // 1EX5I8Z - accessing outer fields within a constructor call is permitted
1405 // in order to do so, we change the flag as we exit from the type, not the method
1406 // itself, because the class scope is used to retrieve the fields.
1407 MethodScope enclosingMethodScope = scope.methodScope();
1408 insideConstructorCall =
1409 enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
1411 case COMPILATION_UNIT_SCOPE :
1414 scope = scope.parent;
1417 if (foundInsideProblem != null)
1418 return foundInsideProblem;
1419 if (foundField != null) {
1420 if (foundField.isValidBinding()) {
1421 if (foundDepth > 0) {
1422 invocationSite.setDepth(foundDepth);
1423 invocationSite.setActualReceiverType(foundActualReceiverType);
1427 problemField = foundField;
1430 if (environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
1431 // at this point the scope is a compilation unit scope & need to check for imported static fields
1432 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1433 ImportBinding[] imports = unitScope.imports;
1434 if (imports != null) {
1435 // check single static imports
1436 for (int i = 0, length = imports.length; i < length; i++) {
1437 ImportBinding importBinding = imports[i];
1438 if (importBinding.isStatic() && !importBinding.onDemand) {
1439 if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
1440 if (unitScope.resolveSingleImport(importBinding) != null && importBinding.resolvedImport instanceof FieldBinding) {
1441 ImportReference importReference = importBinding.reference;
1442 if (importReference != null) importReference.used = true;
1443 return importBinding.resolvedImport; // already know its visible
1448 // check on demand imports
1449 boolean foundInImport = false;
1450 for (int i = 0, length = imports.length; i < length; i++) {
1451 ImportBinding importBinding = imports[i];
1452 if (importBinding.isStatic() && importBinding.onDemand) {
1453 Binding resolvedImport = importBinding.resolvedImport;
1454 if (resolvedImport instanceof ReferenceBinding) {
1455 FieldBinding temp = findField((ReferenceBinding) resolvedImport, name, invocationSite, needResolve);
1457 if (!temp.isValidBinding()) {
1458 problemField = temp;
1459 } else if (temp.isStatic()) {
1460 ImportReference importReference = importBinding.reference;
1461 if (importReference != null) importReference.used = true;
1463 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
1464 return new ProblemReferenceBinding(name, Ambiguous);
1466 foundInImport = true;
1472 if (foundField != null) return foundField;
1477 // We did not find a local or instance variable.
1478 if ((mask & Binding.TYPE) != 0) {
1479 if ((binding = getBaseType(name)) != null)
1481 binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
1482 if (binding.isValidBinding() || mask == Binding.TYPE)
1484 // answer the problem type binding if we are only looking for a type
1485 } else if ((mask & Binding.PACKAGE) != 0) {
1486 compilationUnitScope().recordSimpleReference(name);
1487 if ((binding = environment().getTopLevelPackage(name)) != null)
1490 if (problemField != null) return problemField;
1491 return new ProblemBinding(name, enclosingSourceType(), NotFound);
1492 } catch (AbortCompilation e) {
1493 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1498 public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1500 CompilationUnitScope unitScope = compilationUnitScope();
1501 unitScope.recordTypeReference(receiverType);
1502 unitScope.recordTypeReferences(argumentTypes);
1503 MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
1504 if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) {
1505 // targeting a non generic constructor with type arguments ?
1506 if (invocationSite.genericTypeArguments() != null)
1507 methodBinding = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1508 return methodBinding;
1510 MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
1511 if (methods == NoMethods)
1512 return new ProblemMethodBinding(
1517 MethodBinding[] compatible = new MethodBinding[methods.length];
1518 int compatibleIndex = 0;
1519 MethodBinding problemMethod = null;
1520 for (int i = 0, length = methods.length; i < length; i++) {
1521 MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
1522 if (compatibleMethod != null) {
1523 if (compatibleMethod.isValidBinding())
1524 compatible[compatibleIndex++] = compatibleMethod;
1525 else if (problemMethod == null)
1526 problemMethod = compatibleMethod;
1529 if (compatibleIndex == 0) {
1530 if (problemMethod == null)
1531 return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, NotFound);
1532 return problemMethod;
1534 // need a more descriptive error... cannot convert from X to Y
1536 MethodBinding[] visible = new MethodBinding[compatibleIndex];
1537 int visibleIndex = 0;
1538 for (int i = 0; i < compatibleIndex; i++) {
1539 MethodBinding method = compatible[i];
1540 if (method.canBeSeenBy(invocationSite, this))
1541 visible[visibleIndex++] = method;
1543 if (visibleIndex == 1) return visible[0];
1544 if (visibleIndex == 0)
1545 return new ProblemMethodBinding(
1548 compatible[0].parameters,
1550 // all of visible are from the same declaringClass, even before 1.4 we can call this method instead of mostSpecificClassMethodBinding
1551 return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite);
1552 } catch (AbortCompilation e) {
1553 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1558 public final PackageBinding getCurrentPackage() {
1559 Scope scope, unitScope = this;
1560 while ((scope = unitScope.parent) != null)
1562 return ((CompilationUnitScope) unitScope).fPackage;
1566 * Returns the modifiers of the innermost enclosing declaration.
1569 public int getDeclarationModifiers(){
1571 case Scope.BLOCK_SCOPE :
1572 case Scope.METHOD_SCOPE :
1573 MethodScope methodScope = methodScope();
1574 if (!methodScope.isInsideInitializer()){
1575 // check method modifiers to see if deprecated
1576 MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
1577 if (context != null)
1578 return context.modifiers;
1580 SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
1582 // inside field declaration ? check field modifier to see if deprecated
1583 if (methodScope.initializedField != null)
1584 return methodScope.initializedField.modifiers;
1586 return type.modifiers;
1589 case Scope.CLASS_SCOPE :
1590 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
1591 if (context != null)
1592 return context.modifiers;
1598 public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
1600 FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/);
1601 if (field != null) return field;
1603 return new ProblemFieldBinding(
1604 receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
1607 } catch (AbortCompilation e) {
1608 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1615 * Answer the method binding that corresponds to selector, argumentTypes.
1616 * Start the lookup at the enclosing type of the receiver.
1617 * InvocationSite implements
1618 * isSuperAccess(); this is used to determine if the discovered method is visible.
1619 * setDepth(int); this is used to record the depth of the discovered method
1620 * relative to the enclosing type of the receiver. (If the method is defined
1621 * in the enclosing type of the receiver, the depth is 0; in the next enclosing
1622 * type, the depth is 1; and so on
1624 * If no visible method is discovered, an error binding is answered.
1626 public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1628 boolean insideStaticContext = false;
1629 boolean insideConstructorCall = false;
1630 MethodBinding foundMethod = null;
1631 MethodBinding foundFuzzyProblem = null;
1632 // the weird method lookup case (matches method name in scope, then arg types, then visibility)
1633 MethodBinding foundInsideProblem = null;
1634 // inside Constructor call or inside static context
1637 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
1638 switch (scope.kind) {
1640 MethodScope methodScope = (MethodScope) scope;
1641 insideStaticContext |= methodScope.isStatic;
1642 insideConstructorCall |= methodScope.isConstructorCall;
1645 ClassScope classScope = (ClassScope) scope;
1646 SourceTypeBinding receiverType = classScope.referenceContext.binding;
1647 boolean isExactMatch = true;
1648 // retrieve an exact visible match (if possible)
1649 // compilationUnitScope().recordTypeReference(receiverType); not needed since receiver is the source type
1650 MethodBinding methodBinding =
1651 (foundMethod == null)
1652 ? classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite)
1653 : classScope.findExactMethod(receiverType, foundMethod.selector, foundMethod.parameters, invocationSite);
1654 if (methodBinding == null) {
1655 // answers closest approximation, may not check argumentTypes or visibility
1656 isExactMatch = false;
1657 methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite);
1658 // methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
1660 if (methodBinding != null) { // skip it if we did not find anything
1661 if (methodBinding.problemId() == Ambiguous) {
1662 if (foundMethod == null || foundMethod.problemId() == NotVisible) {
1663 // supercedes any potential InheritedNameHidesEnclosingName problem
1664 return methodBinding;
1666 // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
1667 return new ProblemMethodBinding(
1668 methodBinding, // closest match
1671 InheritedNameHidesEnclosingName);
1673 MethodBinding fuzzyProblem = null;
1674 MethodBinding insideProblem = null;
1675 if (methodBinding.isValidBinding()) {
1676 if (!isExactMatch) {
1677 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1678 if (compatibleMethod == null) {
1679 if (foundMethod == null || foundMethod.problemId() == NotVisible)
1680 // inherited mismatch is reported directly, not looking at enclosing matches
1681 return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
1682 // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
1683 fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, InheritedNameHidesEnclosingName);
1684 } else if (!compatibleMethod.isValidBinding()) {
1685 fuzzyProblem = compatibleMethod;
1687 methodBinding = compatibleMethod;
1688 if (!methodBinding.canBeSeenBy(receiverType, invocationSite, classScope)) {
1689 // using <classScope> instead of <this> for visibility check does grant all access to innerclass
1690 fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, NotVisible);
1694 if (fuzzyProblem == null && !methodBinding.isStatic()) {
1695 if (insideConstructorCall) {
1697 new ProblemMethodBinding(
1698 methodBinding, // closest match
1699 methodBinding.selector,
1700 methodBinding.parameters,
1701 NonStaticReferenceInConstructorInvocation);
1702 } else if (insideStaticContext) {
1704 new ProblemMethodBinding(
1705 methodBinding, // closest match
1706 methodBinding.selector,
1707 methodBinding.parameters,
1708 NonStaticReferenceInStaticContext);
1712 if (receiverType == methodBinding.declaringClass
1713 || (receiverType.getMethods(selector)) != NoMethods
1714 || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)) {
1715 // found a valid method in the 'immediate' scope (ie. not inherited)
1716 // OR the receiverType implemented a method with the correct name
1717 // OR in 1.4 mode (inherited visible shadows enclosing)
1718 if (foundMethod == null) {
1720 invocationSite.setDepth(depth);
1721 invocationSite.setActualReceiverType(receiverType);
1723 // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
1724 if (fuzzyProblem != null)
1725 return fuzzyProblem;
1726 if (insideProblem != null)
1727 return insideProblem;
1728 return methodBinding;
1730 // if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
1731 // NOTE: Unlike fields, a non visible method hides a visible method
1732 if (foundMethod.declaringClass != methodBinding.declaringClass)
1733 // ie. have we found the same method - do not trust field identity yet
1734 return new ProblemMethodBinding(
1735 methodBinding, // closest match
1736 methodBinding.selector,
1737 methodBinding.parameters,
1738 InheritedNameHidesEnclosingName);
1742 if (foundMethod == null || (foundMethod.problemId() == NotVisible && methodBinding.problemId() != NotVisible)) {
1743 // only remember the methodBinding if its the first one found or the previous one was not visible & methodBinding is...
1744 // remember that private methods are visible if defined directly by an enclosing class
1746 invocationSite.setDepth(depth);
1747 invocationSite.setActualReceiverType(receiverType);
1749 foundFuzzyProblem = fuzzyProblem;
1750 foundInsideProblem = insideProblem;
1751 if (fuzzyProblem == null)
1752 foundMethod = methodBinding; // only keep it if no error was found
1756 insideStaticContext |= receiverType.isStatic();
1757 // 1EX5I8Z - accessing outer fields within a constructor call is permitted
1758 // in order to do so, we change the flag as we exit from the type, not the method
1759 // itself, because the class scope is used to retrieve the fields.
1760 MethodScope enclosingMethodScope = scope.methodScope();
1761 insideConstructorCall =
1762 enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
1764 case COMPILATION_UNIT_SCOPE :
1767 scope = scope.parent;
1770 if (foundFuzzyProblem != null)
1771 return foundFuzzyProblem;
1772 if (foundInsideProblem != null)
1773 return foundInsideProblem;
1774 if (foundMethod != null)
1777 if (insideStaticContext && environment().options.complianceLevel >= ClassFileConstants.JDK1_5) {
1778 // at this point the scope is a compilation unit scope & need to check for imported static methods
1779 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
1780 ImportBinding[] imports = unitScope.imports;
1781 if (imports != null) {
1782 // check on demand imports
1783 boolean foundInImport = false;
1784 for (int i = 0, length = imports.length; i < length; i++) {
1785 ImportBinding importBinding = imports[i];
1786 if (importBinding.isStatic() && importBinding.onDemand) {
1787 Binding resolvedImport = importBinding.resolvedImport;
1788 if (resolvedImport instanceof ReferenceBinding) {
1789 // answers closest approximation, may not check argumentTypes or visibility
1790 MethodBinding temp = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite);
1792 if (!temp.isValidBinding()) {
1793 if (foundMethod == null)
1795 } else if (temp.isStatic()) {
1796 MethodBinding compatibleMethod = computeCompatibleMethod(temp, argumentTypes, invocationSite);
1797 if (compatibleMethod != null) {
1798 if (compatibleMethod.isValidBinding()) {
1799 if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
1800 ImportReference importReference = importBinding.reference;
1801 if (importReference != null) importReference.used = true;
1803 // Answer error binding -- import on demand conflict; name found in two import on demand types.
1804 return new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, Ambiguous);
1805 foundMethod = compatibleMethod;
1806 foundInImport = true;
1807 } else if (foundMethod == null) {
1808 foundMethod = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, NotVisible);
1811 } else if (foundMethod == null) {
1812 foundMethod = new ProblemMethodBinding(temp, selector, argumentTypes, NotFound);
1820 if (foundMethod != null)
1823 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1826 public final ReferenceBinding getJavaIoSerializable() {
1827 compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
1828 ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
1829 if (type != null) return type;
1831 problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
1832 return null; // will not get here since the above error aborts the compilation
1835 public final ReferenceBinding getJavaLangAnnotationAnnotation() {
1836 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ANNOTATION_ANNOTATION);
1837 ReferenceBinding type = environment().getType(JAVA_LANG_ANNOTATION_ANNOTATION);
1838 if (type != null) return type;
1840 problemReporter().isClassPathCorrect(JAVA_LANG_ANNOTATION_ANNOTATION, referenceCompilationUnit());
1841 return null; // will not get here since the above error aborts the compilation
1844 public final ReferenceBinding getJavaLangAssertionError() {
1845 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
1846 ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
1847 if (type != null) return type;
1848 problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
1849 return null; // will not get here since the above error aborts the compilation
1852 public final ReferenceBinding getJavaLangClass() {
1853 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
1854 ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
1855 if (type != null) return type;
1857 problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
1858 return null; // will not get here since the above error aborts the compilation
1861 public final ReferenceBinding getJavaLangCloneable() {
1862 compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
1863 ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
1864 if (type != null) return type;
1866 problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, referenceCompilationUnit());
1867 return null; // will not get here since the above error aborts the compilation
1869 public final ReferenceBinding getJavaLangEnum() {
1870 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ENUM);
1871 ReferenceBinding type = environment().getType(JAVA_LANG_ENUM);
1872 if (type != null) return type;
1874 problemReporter().isClassPathCorrect(JAVA_LANG_ENUM, referenceCompilationUnit());
1875 return null; // will not get here since the above error aborts the compilation
1877 public final ReferenceBinding getJavaLangError() {
1878 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ERROR);
1879 ReferenceBinding type = environment().getType(JAVA_LANG_ERROR);
1880 if (type != null) return type;
1882 problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, referenceCompilationUnit());
1883 return null; // will not get here since the above error aborts the compilation
1885 public final ReferenceBinding getJavaLangIterable() {
1886 compilationUnitScope().recordQualifiedReference(JAVA_LANG_ITERABLE);
1887 ReferenceBinding type = environment().getType(JAVA_LANG_ITERABLE);
1888 if (type != null) return type;
1890 problemReporter().isClassPathCorrect(JAVA_LANG_ITERABLE, referenceCompilationUnit());
1891 return null; // will not get here since the above error aborts the compilation
1893 public final ReferenceBinding getJavaLangObject() {
1894 compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
1895 ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
1896 if (type != null) return type;
1898 problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
1899 return null; // will not get here since the above error aborts the compilation
1902 public final ReferenceBinding getJavaLangRuntimeException() {
1903 compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
1904 ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
1905 if (type != null) return type;
1907 problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
1908 return null; // will not get here since the above error aborts the compilation
1911 public final ReferenceBinding getJavaLangString() {
1912 compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
1913 ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
1914 if (type != null) return type;
1916 problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
1917 return null; // will not get here since the above error aborts the compilation
1920 public final ReferenceBinding getJavaLangThrowable() {
1921 compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
1922 ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
1923 if (type != null) return type;
1925 problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
1926 return null; // will not get here since the above error aborts the compilation
1928 public final ReferenceBinding getJavaUtilIterator() {
1929 compilationUnitScope().recordQualifiedReference(JAVA_UTIL_ITERATOR);
1930 ReferenceBinding type = environment().getType(JAVA_UTIL_ITERATOR);
1931 if (type != null) return type;
1933 problemReporter().isClassPathCorrect(JAVA_UTIL_ITERATOR, referenceCompilationUnit());
1934 return null; // will not get here since the above error aborts the compilation
1937 /* Answer the type binding corresponding to the typeName argument, relative to the enclosingType.
1939 public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
1940 ReferenceBinding memberType = findMemberType(typeName, enclosingType);
1941 if (memberType != null) return memberType;
1942 return new ProblemReferenceBinding(typeName, NotFound);
1945 public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
1947 if (receiverType.isBaseType())
1948 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1950 compilationUnitScope().recordTypeReference(receiverType);
1951 if (receiverType.isArrayType())
1952 return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
1954 ReferenceBinding currentType = (ReferenceBinding) receiverType;
1955 if (!currentType.canBeSeenBy(this))
1956 return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
1958 // retrieve an exact visible match (if possible)
1959 MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
1960 if (methodBinding != null) return methodBinding;
1962 // TODO (kent) performance - we are accumulating super methods which are *hidden* during the walk (see testcase from bug 69141)
1963 // answers closest approximation, may not check argumentTypes or visibility
1964 methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
1965 if (methodBinding == null)
1966 return new ProblemMethodBinding(selector, argumentTypes, NotFound);
1967 if (methodBinding.isValidBinding()) {
1968 MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
1969 if (compatibleMethod == null)
1970 return new ProblemMethodBinding(methodBinding, selector, argumentTypes, NotFound);
1971 if (!compatibleMethod.isValidBinding())
1972 return compatibleMethod;
1974 methodBinding = compatibleMethod;
1975 if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
1976 return new ProblemMethodBinding( methodBinding, selector, methodBinding.parameters, NotVisible);
1978 return methodBinding;
1979 } catch (AbortCompilation e) {
1980 e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
1985 /* Answer the package from the compoundName or null if it begins with a type.
1986 * Intended to be used while resolving a qualified type name.
1988 * NOTE: If a problem binding is returned, senders should extract the compound name
1989 * from the binding & not assume the problem applies to the entire compoundName.
1991 public final Binding getPackage(char[][] compoundName) {
1992 compilationUnitScope().recordQualifiedReference(compoundName);
1993 Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
1994 if (binding == null)
1995 return new ProblemReferenceBinding(compoundName[0], NotFound);
1996 if (!binding.isValidBinding())
1997 return (ReferenceBinding) binding;
1999 if (!(binding instanceof PackageBinding)) return null; // compoundName does not start with a package
2001 int currentIndex = 1;
2002 PackageBinding packageBinding = (PackageBinding) binding;
2003 while (currentIndex < compoundName.length) {
2004 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
2005 if (binding == null)
2006 return new ProblemReferenceBinding(
2007 CharOperation.subarray(compoundName, 0, currentIndex),
2009 if (!binding.isValidBinding())
2010 return new ProblemReferenceBinding(
2011 CharOperation.subarray(compoundName, 0, currentIndex),
2012 binding.problemId());
2013 if (!(binding instanceof PackageBinding))
2014 return packageBinding;
2015 packageBinding = (PackageBinding) binding;
2017 return new ProblemReferenceBinding(compoundName, NotFound);
2020 /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
2021 * The name provided is a simple source name (e.g., "Object" , "Point", ...)
2023 // The return type of this method could be ReferenceBinding if we did not answer base types.
2024 // NOTE: We could support looking for Base Types last in the search, however any code using
2025 // this feature would be extraordinarily slow. Therefore we don't do this
2026 public final TypeBinding getType(char[] name) {
2027 // Would like to remove this test and require senders to specially handle base types
2028 TypeBinding binding = getBaseType(name);
2029 if (binding != null) return binding;
2030 return (ReferenceBinding) getTypeOrPackage(name, Binding.TYPE);
2033 /* Answer the type binding that corresponds to the given name, starting the lookup in the receiver
2034 * or the packageBinding if provided.
2035 * The name provided is a simple source name (e.g., "Object" , "Point", ...)
2037 public final TypeBinding getType(char[] name, PackageBinding packageBinding) {
2038 if (packageBinding == null)
2039 return getType(name);
2041 Binding binding = packageBinding.getTypeOrPackage(name);
2042 if (binding == null)
2043 return new ProblemReferenceBinding(
2044 CharOperation.arrayConcat(packageBinding.compoundName, name),
2046 if (!binding.isValidBinding())
2047 return new ProblemReferenceBinding(
2048 CharOperation.arrayConcat(packageBinding.compoundName, name),
2049 binding.problemId());
2051 ReferenceBinding typeBinding = (ReferenceBinding) binding;
2052 if (!typeBinding.canBeSeenBy(this))
2053 return new ProblemReferenceBinding(
2054 CharOperation.arrayConcat(packageBinding.compoundName, name),
2060 /* Answer the type binding corresponding to the compoundName.
2062 * NOTE: If a problem binding is returned, senders should extract the compound name
2063 * from the binding & not assume the problem applies to the entire compoundName.
2065 public final TypeBinding getType(char[][] compoundName, int typeNameLength) {
2066 if (typeNameLength == 1) {
2067 // Would like to remove this test and require senders to specially handle base types
2068 TypeBinding binding = getBaseType(compoundName[0]);
2069 if (binding != null) return binding;
2072 CompilationUnitScope unitScope = compilationUnitScope();
2073 unitScope.recordQualifiedReference(compoundName);
2075 getTypeOrPackage(compoundName[0], typeNameLength == 1 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE);
2076 if (binding == null)
2077 return new ProblemReferenceBinding(compoundName[0], NotFound);
2078 if (!binding.isValidBinding())
2079 return (ReferenceBinding) binding;
2081 int currentIndex = 1;
2082 boolean checkVisibility = false;
2083 if (binding instanceof PackageBinding) {
2084 PackageBinding packageBinding = (PackageBinding) binding;
2085 while (currentIndex < typeNameLength) {
2086 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
2087 if (binding == null)
2088 return new ProblemReferenceBinding(
2089 CharOperation.subarray(compoundName, 0, currentIndex),
2091 if (!binding.isValidBinding())
2092 return new ProblemReferenceBinding(
2093 CharOperation.subarray(compoundName, 0, currentIndex),
2094 binding.problemId());
2095 if (!(binding instanceof PackageBinding))
2097 packageBinding = (PackageBinding) binding;
2099 if (binding instanceof PackageBinding)
2100 return new ProblemReferenceBinding(
2101 CharOperation.subarray(compoundName, 0, currentIndex),
2103 checkVisibility = true;
2106 // binding is now a ReferenceBinding
2107 ReferenceBinding typeBinding = (ReferenceBinding) binding;
2108 unitScope.recordTypeReference(typeBinding);
2109 if (checkVisibility) // handles the fall through case
2110 if (!typeBinding.canBeSeenBy(this))
2111 return new ProblemReferenceBinding(
2112 CharOperation.subarray(compoundName, 0, currentIndex),
2116 while (currentIndex < typeNameLength) {
2117 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
2118 if (!typeBinding.isValidBinding()) {
2119 if (typeBinding instanceof ProblemReferenceBinding) {
2120 ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding;
2121 return new ProblemReferenceBinding(
2122 CharOperation.subarray(compoundName, 0, currentIndex),
2123 problemBinding.original,
2124 typeBinding.problemId());
2126 return new ProblemReferenceBinding(
2127 CharOperation.subarray(compoundName, 0, currentIndex),
2128 typeBinding.problemId());
2134 /* Internal use only
2136 final Binding getTypeOrPackage(char[] name, int mask) {
2138 ReferenceBinding foundType = null;
2139 boolean insideStaticContext = false;
2140 if ((mask & Binding.TYPE) == 0) {
2142 while ((next = scope.parent) != null)
2145 done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
2146 switch (scope.kind) {
2148 MethodScope methodScope = (MethodScope) scope;
2149 AbstractMethodDeclaration methodDecl = methodScope.referenceMethod();
2150 if (methodDecl != null && methodDecl.binding != null) {
2151 TypeVariableBinding typeVariable = methodDecl.binding.getTypeVariable(name);
2152 if (typeVariable != null) return typeVariable;
2154 insideStaticContext |= methodScope.isStatic;
2156 ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
2157 if (localType != null) {
2158 if (foundType != null && foundType != localType)
2159 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2164 SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
2165 if (sourceType.isHierarchyBeingConnected()) {
2166 // type variables take precedence over the source type, ex. class X <X> extends X == class X <Y> extends Y
2167 TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
2168 if (typeVariable != null)
2169 return typeVariable;
2170 if (CharOperation.equals(name, sourceType.sourceName))
2174 // type variables take precedence over member types
2175 TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
2176 if (typeVariable != null) {
2177 if (insideStaticContext) // do not consider this type modifiers: access is legite within same type
2178 return new ProblemReferenceBinding(name, NonStaticReferenceInStaticContext);
2179 return typeVariable;
2181 insideStaticContext |= (sourceType.modifiers & AccStatic) != 0; // not isStatic()
2182 // 6.5.5.1 - member types have precedence over top-level type in same unit
2183 ReferenceBinding memberType = findMemberType(name, sourceType);
2184 if (memberType != null) { // skip it if we did not find anything
2185 if (memberType.problemId() == Ambiguous) {
2186 if (foundType == null || foundType.problemId() == NotVisible)
2187 // supercedes any potential InheritedNameHidesEnclosingName problem
2189 // make the user qualify the type, likely wants the first inherited type
2190 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2192 if (memberType.isValidBinding()) {
2193 if (sourceType == memberType.enclosingType()
2194 || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
2195 // found a valid type in the 'immediate' scope (ie. not inherited)
2196 // OR in 1.4 mode (inherited shadows enclosing)
2197 if (foundType == null)
2199 // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
2200 if (foundType.isValidBinding() && foundType != memberType)
2201 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2204 if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
2205 // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
2206 foundType = memberType;
2208 if (CharOperation.equals(sourceType.sourceName, name)) {
2209 if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
2210 return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
2214 case COMPILATION_UNIT_SCOPE :
2217 scope = scope.parent;
2219 if (foundType != null && foundType.problemId() != NotVisible)
2223 // at this point the scope is a compilation unit scope
2224 CompilationUnitScope unitScope = (CompilationUnitScope) scope;
2225 PackageBinding currentPackage = unitScope.fPackage;
2226 // ask for the imports + name
2227 if ((mask & Binding.TYPE) != 0) {
2228 // check single type imports.
2230 ImportBinding[] imports = unitScope.imports;
2231 if (imports != null) {
2232 HashtableOfObject typeImports = unitScope.resolvedSingeTypeImports;
2233 if (typeImports != null) {
2234 ImportBinding typeImport = (ImportBinding) typeImports.get(name);
2235 if (typeImport != null) {
2236 ImportReference importReference = typeImport.reference;
2237 if (importReference != null) importReference.used = true;
2238 return typeImport.resolvedImport; // already know its visible
2241 // walk all the imports since resolvedSingeTypeImports is not yet initialized
2242 for (int i = 0, length = imports.length; i < length; i++) {
2243 ImportBinding typeImport = imports[i];
2244 if (!typeImport.onDemand) {
2245 if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
2246 if (unitScope.resolveSingleImport(typeImport) != null) {
2247 ImportReference importReference = typeImport.reference;
2248 if (importReference != null)
2249 importReference.used = true;
2250 return typeImport.resolvedImport; // already know its visible
2257 // check if the name is in the current package, skip it if its a sub-package
2258 unitScope.recordReference(currentPackage.compoundName, name);
2259 Binding binding = currentPackage.getTypeOrPackage(name);
2260 if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
2262 // check on demand imports
2263 if (imports != null) {
2264 boolean foundInImport = false;
2265 ReferenceBinding type = null;
2266 for (int i = 0, length = imports.length; i < length; i++) {
2267 ImportBinding someImport = imports[i];
2268 if (someImport.onDemand) {
2269 Binding resolvedImport = someImport.resolvedImport;
2270 ReferenceBinding temp = resolvedImport instanceof PackageBinding
2271 ? findType(name, (PackageBinding) resolvedImport, currentPackage)
2272 : (someImport.isStatic()
2273 ? findMemberType(name, (ReferenceBinding) resolvedImport) // static imports are allowed to see inherited member types
2274 : findDirectMemberType(name, (ReferenceBinding) resolvedImport));
2276 if (temp.isValidBinding()) {
2277 ImportReference importReference = someImport.reference;
2278 if (importReference != null) importReference.used = true;
2280 // Answer error binding -- import on demand conflict; name found in two import on demand packages.
2281 return new ProblemReferenceBinding(name, Ambiguous);
2283 foundInImport = true;
2284 } else if (foundType == null) {
2290 if (type != null) return type;
2294 unitScope.recordSimpleReference(name);
2295 if ((mask & Binding.PACKAGE) != 0) {
2296 PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
2297 if (packageBinding != null) return packageBinding;
2300 // Answer error binding -- could not find name
2301 if (foundType != null) return foundType; // problem type from above
2302 return new ProblemReferenceBinding(name, NotFound);
2305 // Added for code assist... NOT Public API
2306 // DO NOT USE to resolve import references since this method assumes 'A.B' is relative to a single type import of 'p1.A'
2307 // when it may actually mean the type B in the package A
2308 // use CompilationUnitScope.getImport(char[][]) instead
2309 public final Binding getTypeOrPackage(char[][] compoundName) {
2310 int nameLength = compoundName.length;
2311 if (nameLength == 1) {
2312 TypeBinding binding = getBaseType(compoundName[0]);
2313 if (binding != null) return binding;
2315 Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE);
2316 if (!binding.isValidBinding()) return binding;
2318 int currentIndex = 1;
2319 boolean checkVisibility = false;
2320 if (binding instanceof PackageBinding) {
2321 PackageBinding packageBinding = (PackageBinding) binding;
2323 while (currentIndex < nameLength) {
2324 binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
2325 if (binding == null)
2326 return new ProblemReferenceBinding(
2327 CharOperation.subarray(compoundName, 0, currentIndex),
2329 if (!binding.isValidBinding())
2330 return new ProblemReferenceBinding(
2331 CharOperation.subarray(compoundName, 0, currentIndex),
2332 binding.problemId());
2333 if (!(binding instanceof PackageBinding))
2335 packageBinding = (PackageBinding) binding;
2337 if (binding instanceof PackageBinding) return binding;
2338 checkVisibility = true;
2340 // binding is now a ReferenceBinding
2341 ReferenceBinding qualifiedType = null;
2343 ReferenceBinding typeBinding = (ReferenceBinding) binding;
2344 if (typeBinding.isGenericType()) {
2345 qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
2347 qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
2348 ? this.createParameterizedType(typeBinding, null, qualifiedType)
2352 if (checkVisibility) // handles the fall through case
2353 if (!typeBinding.canBeSeenBy(this))
2354 return new ProblemReferenceBinding(
2355 CharOperation.subarray(compoundName, 0, currentIndex),
2359 while (currentIndex < nameLength) {
2360 typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
2362 if (typeBinding.isGenericType()) {
2363 qualifiedType = this.environment().createRawType(typeBinding, qualifiedType);
2365 qualifiedType = (qualifiedType != null && (qualifiedType.isRawType() || qualifiedType.isParameterizedType()))
2366 ? this.createParameterizedType(typeBinding, null, qualifiedType)
2370 // checks visibility
2371 if (!qualifiedType.isValidBinding())
2372 return new ProblemReferenceBinding(
2373 CharOperation.subarray(compoundName, 0, currentIndex),
2374 qualifiedType.problemId());
2376 return qualifiedType;
2380 public TypeBinding[] greaterLowerBound(TypeBinding[] types) {
2381 if (types == null) return null;
2382 int length = types.length;
2383 TypeBinding[] result = types;
2385 for (int i = 0; i < length; i++) {
2386 TypeBinding iType = result[i];
2387 for (int j = 0; j < length; j++) {
2388 if (i == j) continue;
2389 TypeBinding jType = result[j];
2390 if (jType == null) continue;
2391 if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
2392 if (result == types) { // defensive copy
2393 System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
2400 if (removed == 0) return result;
2401 TypeBinding[] trimmedResult = new TypeBinding[length - removed];
2402 for (int i = 0, index = 0; i < length; i++) {
2403 TypeBinding iType = result[i];
2404 if (iType != null) {
2405 trimmedResult[index++] = iType;
2408 return trimmedResult;
2411 public boolean isBoxingCompatibleWith(TypeBinding left, TypeBinding right) {
2412 return left.isBaseType() != right.isBaseType() && environment().isBoxingCompatibleWith(left, right);
2415 /* Answer true if the scope is nested inside a given field declaration.
2416 * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed
2417 * e.g. during name resolution.
2419 public final boolean isDefinedInField(FieldBinding field) {
2422 if (scope instanceof MethodScope) {
2423 MethodScope methodScope = (MethodScope) scope;
2424 if (methodScope.initializedField == field) return true;
2426 scope = scope.parent;
2427 } while (scope != null);
2431 /* Answer true if the scope is nested inside a given method declaration
2433 public final boolean isDefinedInMethod(MethodBinding method) {
2436 if (scope instanceof MethodScope) {
2437 ReferenceContext refContext = ((MethodScope) scope).referenceContext;
2438 if (refContext instanceof AbstractMethodDeclaration)
2439 if (((AbstractMethodDeclaration) refContext).binding == method)
2442 scope = scope.parent;
2443 } while (scope != null);
2447 /* Answer whether the type is defined in the same compilation unit as the receiver
2449 public final boolean isDefinedInSameUnit(ReferenceBinding type) {
2450 // find the outer most enclosing type
2451 ReferenceBinding enclosingType = type;
2452 while ((type = enclosingType.enclosingType()) != null)
2453 enclosingType = type;
2455 // find the compilation unit scope
2456 Scope scope, unitScope = this;
2457 while ((scope = unitScope.parent) != null)
2460 // test that the enclosingType is not part of the compilation unit
2461 SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
2462 for (int i = topLevelTypes.length; --i >= 0;)
2463 if (topLevelTypes[i] == enclosingType)
2468 /* Answer true if the scope is nested inside a given type declaration
2470 public final boolean isDefinedInType(ReferenceBinding type) {
2473 if (scope instanceof ClassScope)
2474 if (((ClassScope) scope).referenceContext.binding == type)
2476 scope = scope.parent;
2477 } while (scope != null);
2481 public boolean isInsideDeprecatedCode(){
2483 case Scope.BLOCK_SCOPE :
2484 case Scope.METHOD_SCOPE :
2485 MethodScope methodScope = methodScope();
2486 if (!methodScope.isInsideInitializer()){
2487 // check method modifiers to see if deprecated
2488 MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
2489 if (context != null && context.isViewedAsDeprecated())
2492 SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
2493 // inside field declaration ? check field modifier to see if deprecated
2494 if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated())
2496 if (type != null && type.isViewedAsDeprecated())
2500 case Scope.CLASS_SCOPE :
2501 ReferenceBinding context = ((ClassScope)this).referenceType().binding;
2502 if (context != null && context.isViewedAsDeprecated())
2508 private TypeBinding leastContainingInvocation(TypeBinding mec, List invocations) {
2509 int length = invocations.size();
2510 if (length == 0) return mec;
2511 if (length == 1) return (TypeBinding) invocations.get(0);
2512 int argLength = mec.typeVariables().length;
2513 if (argLength == 0) return mec; // should be caught by no invocation check
2515 // infer proper parameterized type from invocations
2516 TypeBinding[] bestArguments = new TypeBinding[argLength];
2517 for (int i = 0; i < length; i++) {
2518 TypeBinding invocation = (TypeBinding)invocations.get(i);
2519 TypeVariableBinding[] invocationVariables = invocation.typeVariables();
2520 if (invocation.isGenericType()) {
2521 for (int j = 0; j < argLength; j++) {
2522 TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], invocationVariables[j], (ReferenceBinding) mec, j);
2523 if (bestArgument == null) return null;
2524 bestArguments[j] = bestArgument;
2526 } else if (invocation.isParameterizedType()) {
2527 ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)invocation;
2528 for (int j = 0; j < argLength; j++) {
2529 TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], parameterizedType.arguments[j], (ReferenceBinding) mec, j);
2530 if (bestArgument == null) return null;
2531 bestArguments[j] = bestArgument;
2533 } else if (invocation.isRawType()) {
2534 return invocation; // raw type is taking precedence
2537 return createParameterizedType((ReferenceBinding) mec.erasure(), bestArguments, null);
2541 private TypeBinding leastContainingTypeArgument(TypeBinding u, TypeBinding v, ReferenceBinding genericType, int rank) {
2542 if (u == null) return v;
2543 if (u == v) return u;
2544 if (v.isWildcard()) {
2545 WildcardBinding wildV = (WildcardBinding) v;
2546 if (u.isWildcard()) {
2547 WildcardBinding wildU = (WildcardBinding) u;
2548 switch (wildU.kind) {
2550 case Wildcard.EXTENDS :
2551 switch(wildV.kind) {
2552 // ? extends U, ? extends V
2553 case Wildcard.EXTENDS :
2554 TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound,wildV.bound});
2555 if (lub == null) return null;
2556 return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
2557 // ? extends U, ? SUPER V
2558 case Wildcard.SUPER :
2559 if (wildU.bound == wildV.bound) return wildU.bound;
2560 return environment().createWildcard(genericType, rank, null, Wildcard.UNBOUND);
2564 case Wildcard.SUPER :
2565 // ? super U, ? super V
2566 if (wildU.kind == Wildcard.SUPER) {
2567 TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound});
2568 if (glb == null) return null;
2569 return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2573 switch (wildV.kind) {
2575 case Wildcard.EXTENDS :
2576 TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,wildV.bound});
2577 if (lub == null) return null;
2578 return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
2580 case Wildcard.SUPER :
2581 TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound});
2582 if (glb == null) return null;
2583 return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2584 case Wildcard.UNBOUND :
2587 } else if (u.isWildcard()) {
2588 WildcardBinding wildU = (WildcardBinding) u;
2589 switch (wildU.kind) {
2591 case Wildcard.EXTENDS :
2592 TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound, v});
2593 if (lub == null) return null;
2594 return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
2596 case Wildcard.SUPER :
2597 TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v});
2598 if (glb == null) return null;
2599 return environment().createWildcard(genericType, rank, glb[0], Wildcard.SUPER); // TODO (philippe) need to capture entire bounds
2600 case Wildcard.UNBOUND :
2603 TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,v});
2604 if (lub == null) return null;
2605 return environment().createWildcard(genericType, rank, lub, Wildcard.EXTENDS);
2609 public TypeBinding lowerUpperBound(TypeBinding[] types) {
2611 if (types.length == 1) {
2612 TypeBinding type = types[0];
2613 return type == null ? VoidBinding : type;
2615 ArrayList invocations = new ArrayList(1);
2616 TypeBinding mec = minimalErasedCandidate(types, invocations);
2617 return leastContainingInvocation(mec, invocations);
2620 public final MethodScope methodScope() {
2623 if (scope instanceof MethodScope)
2624 return (MethodScope) scope;
2625 scope = scope.parent;
2626 } while (scope != null);
2631 * Returns the most specific type compatible with all given types.
2632 * (i.e. most specific common super type)
2633 * If no types is given, will return VoidBinding. If not compatible
2634 * reference type is found, returns null.
2636 private TypeBinding minimalErasedCandidate(TypeBinding[] types, List invocations) {
2637 Map allInvocations = new HashMap(2);
2638 int length = types.length;
2639 int indexOfFirst = -1, actualLength = 0;
2640 for (int i = 0; i < length; i++) {
2641 TypeBinding type = types[i];
2642 if (type == null) continue;
2643 if (type.isBaseType()) return null;
2644 if (indexOfFirst < 0) indexOfFirst = i;
2647 switch (actualLength) {
2648 case 0: return VoidBinding;
2649 case 1: return types[indexOfFirst];
2652 // record all supertypes of type
2653 // intersect with all supertypes of otherType
2654 TypeBinding firstType = types[indexOfFirst];
2655 TypeBinding[] superTypes;
2657 if (firstType.isBaseType()) {
2659 } else if (firstType.isArrayType()) {
2661 if (firstType.erasure() != firstType) {
2662 ArrayList someInvocations = new ArrayList(1);
2663 someInvocations.add(firstType);
2664 allInvocations.put(firstType.erasure(), someInvocations);
2666 superTypes = new TypeBinding[] {
2667 firstType.erasure(),
2668 getJavaIoSerializable(),
2669 getJavaLangCloneable(),
2670 getJavaLangObject(),
2673 ArrayList typesToVisit = new ArrayList(5);
2674 if (firstType.erasure() != firstType) {
2675 ArrayList someInvocations = new ArrayList(1);
2676 someInvocations.add(firstType);
2677 allInvocations.put(firstType.erasure(), someInvocations);
2679 typesToVisit.add(firstType.erasure());
2680 ReferenceBinding currentType = (ReferenceBinding)firstType;
2681 for (int i = 0, max = 1; i < max; i++) {
2682 currentType = (ReferenceBinding) typesToVisit.get(i);
2683 TypeBinding itsSuperclass = currentType.superclass();
2684 if (itsSuperclass != null) {
2685 TypeBinding itsSuperclassErasure = itsSuperclass.erasure();
2686 if (!typesToVisit.contains(itsSuperclassErasure)) {
2687 if (itsSuperclassErasure != itsSuperclass) {
2688 ArrayList someInvocations = new ArrayList(1);
2689 someInvocations.add(itsSuperclass);
2690 allInvocations.put(itsSuperclassErasure, someInvocations);
2692 typesToVisit.add(itsSuperclassErasure);
2696 ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
2697 for (int j = 0, count = itsInterfaces.length; j < count; j++) {
2698 TypeBinding itsInterface = itsInterfaces[j];
2699 TypeBinding itsInterfaceErasure = itsInterface.erasure();
2700 if (!typesToVisit.contains(itsInterfaceErasure)) {
2701 if (itsInterfaceErasure != itsInterface) {
2702 ArrayList someInvocations = new ArrayList(1);
2703 someInvocations.add(itsInterface);
2704 allInvocations.put(itsInterfaceErasure, someInvocations);
2706 typesToVisit.add(itsInterfaceErasure);
2711 superLength = typesToVisit.size();
2712 superTypes = new TypeBinding[superLength];
2713 typesToVisit.toArray(superTypes);
2715 int remaining = superLength;
2716 nextOtherType: for (int i = indexOfFirst+1; i < length; i++) {
2717 TypeBinding otherType = types[i];
2718 if (otherType == null)
2719 continue nextOtherType;
2720 else if (otherType.isArrayType()) {
2721 nextSuperType: for (int j = 0; j < superLength; j++) {
2722 TypeBinding superType = superTypes[j];
2723 if (superType == null || superType == otherType) continue nextSuperType;
2724 switch (superType.id) {
2725 case T_JavaIoSerializable :
2726 case T_JavaLangCloneable :
2727 case T_JavaLangObject :
2728 continue nextSuperType;
2730 superTypes[j] = null;
2731 if (--remaining == 0) return null;
2734 continue nextOtherType;
2736 ReferenceBinding otherRefType = (ReferenceBinding) otherType;
2737 nextSuperType: for (int j = 0; j < superLength; j++) {
2738 TypeBinding superType = superTypes[j];
2739 if (superType == null) continue nextSuperType;
2740 if (otherRefType.erasure().isCompatibleWith(superType)) {
2741 TypeBinding match = otherRefType.findSuperTypeErasingTo((ReferenceBinding)superType);
2742 if (match != null && match.erasure() != match) { // match can be null: interface.findSuperTypeErasingTo(Object)
2743 ArrayList someInvocations = (ArrayList) allInvocations.get(superType);
2744 if (someInvocations == null) someInvocations = new ArrayList(1);
2745 someInvocations.add(match);
2746 allInvocations.put(superType, someInvocations);
2748 break nextSuperType;
2750 superTypes[j] = null;
2751 if (--remaining == 0) return null;
2755 // per construction, first non-null supertype is most specific common supertype
2756 for (int i = 0; i < superLength; i++) {
2757 TypeBinding superType = superTypes[i];
2758 if (superType != null) {
2759 List matchingInvocations = (List)allInvocations.get(superType);
2760 if (matchingInvocations != null) invocations.addAll(matchingInvocations);
2767 // Internal use only
2768 /* All methods in visible are acceptable matches for the method in question...
2769 * The methods defined by the receiver type appear before those defined by its
2770 * superclass and so on. We want to find the one which matches best.
2772 * Since the receiver type is a class, we know each method's declaring class is
2773 * either the receiver type or one of its superclasses. It is an error if the best match
2774 * is defined by a superclass, when a lesser match is defined by the receiver type
2775 * or a closer superclass.
2777 protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
2778 MethodBinding problemMethod = null;
2779 MethodBinding previous = null;
2780 nextVisible : for (int i = 0; i < visibleSize; i++) {
2781 MethodBinding method = visible[i];
2782 if (previous != null && method.declaringClass != previous.declaringClass)
2783 break; // cannot answer a method farther up the hierarchy than the first method found
2785 if (!method.isStatic()) previous = method; // no ambiguity for static methods
2786 for (int j = 0; j < visibleSize; j++) {
2787 if (i == j) continue;
2788 if (!visible[j].areParametersCompatibleWith(method.parameters))
2789 continue nextVisible;
2791 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
2794 if (problemMethod == null)
2795 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
2796 return problemMethod;
2799 // Internal use only
2800 /* All methods in visible are acceptable matches for the method in question...
2801 * Since the receiver type is an interface, we ignore the possibility that 2 inherited
2802 * but unrelated superinterfaces may define the same method in acceptable but
2803 * not identical ways... we just take the best match that we find since any class which
2804 * implements the receiver interface MUST implement all signatures for the method...
2805 * in which case the best match is correct.
2807 * NOTE: This is different than javac... in the following example, the message send of
2808 * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
2809 * interface I MUST implement both signatures for bar. If this class was the receiver of
2810 * the message send instead of the interface I, then no problem would be reported.
2819 interface I extends I1, I2 {}
2822 class X implements J {}
2825 public void foo(I i, X x) { i.bar(x); }
2828 protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
2829 MethodBinding problemMethod = null;
2830 nextVisible : for (int i = 0; i < visibleSize; i++) {
2831 MethodBinding method = visible[i];
2832 for (int j = 0; j < visibleSize; j++) {
2833 if (i == j) continue;
2834 if (!visible[j].areParametersCompatibleWith(method.parameters))
2835 continue nextVisible;
2837 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
2840 if (problemMethod == null)
2841 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
2842 return problemMethod;
2845 protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
2846 int[] compatibilityLevels = new int[visibleSize];
2847 for (int i = 0; i < visibleSize; i++)
2848 compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes);
2850 for (int level = 0; level <= 2; level++) {
2851 nextVisible : for (int i = 0; i < visibleSize; i++) {
2852 if (compatibilityLevels[i] != level) continue nextVisible; // skip this method for now
2853 MethodBinding method = visible[i];
2854 for (int j = 0; j < visibleSize; j++) {
2855 if (i == j || compatibilityLevels[j] != level) continue;
2856 // tiebreak generic methods using variant where type params are substituted by their erasures
2857 if (!visible[j].tiebreakMethod().areParametersCompatibleWith(method.tiebreakMethod().parameters)) {
2858 if (method.isVarargs() && visible[j].isVarargs()) {
2859 int paramLength = method.parameters.length;
2860 if (paramLength == visible[j].parameters.length && paramLength == argumentTypes.length + 1) {
2861 TypeBinding elementsType = ((ArrayBinding) visible[j].parameters[paramLength - 1]).elementsType();
2862 if (method.parameters[paramLength - 1].isCompatibleWith(elementsType))
2863 continue; // special case to choose between 2 varargs methods when the last arg is missing
2866 continue nextVisible;
2869 compilationUnitScope().recordTypeReferences(method.thrownExceptions);
2873 return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
2876 public final ClassScope outerMostClassScope() {
2877 ClassScope lastClassScope = null;
2880 if (scope instanceof ClassScope)
2881 lastClassScope = (ClassScope) scope;
2882 scope = scope.parent;
2883 } while (scope != null);
2884 return lastClassScope; // may answer null if no class around
2887 public final MethodScope outerMostMethodScope() {
2888 MethodScope lastMethodScope = null;
2891 if (scope instanceof MethodScope)
2892 lastMethodScope = (MethodScope) scope;
2893 scope = scope.parent;
2894 } while (scope != null);
2895 return lastMethodScope; // may answer null if no method around
2898 protected int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
2899 TypeBinding[] parameters = method.parameters;
2900 int paramLength = parameters.length;
2901 int argLength = arguments.length;
2902 int lastIndex = argLength;
2903 int level = COMPATIBLE; // no autoboxing or varargs support needed
2904 if (method.isVarargs()) {
2905 lastIndex = paramLength - 1;
2906 if (paramLength == argLength) { // accept X or X[] but not X[][]
2907 TypeBinding param = parameters[lastIndex]; // is an ArrayBinding by definition
2908 TypeBinding arg = arguments[lastIndex];
2909 if (param != arg && !arg.isCompatibleWith(param)) {
2910 if (isBoxingCompatibleWith(arg, param)) {
2911 level = AUTOBOX_COMPATIBLE; // autoboxing support needed
2913 // expect X[], called with X
2914 param = ((ArrayBinding) param).elementsType();
2915 if (!arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
2916 return NOT_COMPATIBLE;
2917 level = VARARGS_COMPATIBLE; // varargs support needed
2921 if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
2922 TypeBinding param = ((ArrayBinding) parameters[lastIndex]).elementsType();
2923 for (int i = lastIndex; i < argLength; i++) {
2924 TypeBinding arg = arguments[i];
2925 if (param != arg && !arg.isCompatibleWith(param) && !isBoxingCompatibleWith(arg, param))
2926 return NOT_COMPATIBLE;
2928 } else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
2929 return NOT_COMPATIBLE;
2931 level = VARARGS_COMPATIBLE; // varargs support needed
2933 // now compare standard arguments from 0 to lastIndex
2935 for (int i = 0; i < lastIndex; i++) {
2936 TypeBinding param = parameters[i];
2937 TypeBinding arg = arguments[i];
2938 if (arg != param && !arg.isCompatibleWith(param)) {
2939 if (!isBoxingCompatibleWith(arg, param))
2940 return NOT_COMPATIBLE;
2941 level = AUTOBOX_COMPATIBLE; // autoboxing support needed
2947 public abstract ProblemReporter problemReporter();
2949 public final CompilationUnitDeclaration referenceCompilationUnit() {
2950 Scope scope, unitScope = this;
2951 while ((scope = unitScope.parent) != null)
2953 return ((CompilationUnitScope) unitScope).referenceContext;
2955 // start position in this scope - for ordering scopes vs. variables
2961 * Returns the immediately enclosing switchCase statement (carried by closest blockScope),
2963 public CaseStatement switchCase() {
2966 if (scope instanceof BlockScope)
2967 return ((BlockScope) scope).switchCase;
2968 scope = scope.parent;
2969 } while (scope != null);
2973 * Unboxing primitive
2975 public int unboxing(int id) {
2977 case T_JavaLangInteger :
2979 case T_JavaLangByte :
2981 case T_JavaLangShort :
2983 case T_JavaLangCharacter :
2985 case T_JavaLangLong :
2987 case T_JavaLangFloat :
2989 case T_JavaLangDouble :
2991 case T_JavaLangBoolean :
2993 case T_JavaLangVoid :
2999 * Unboxing primitive
3001 public TypeBinding unboxing(TypeBinding type) {
3003 case T_JavaLangInteger :
3005 case T_JavaLangByte :
3007 case T_JavaLangShort :
3008 return ShortBinding;
3009 case T_JavaLangCharacter :
3011 case T_JavaLangLong :
3013 case T_JavaLangFloat :
3014 return FloatBinding;
3015 case T_JavaLangDouble :
3016 return DoubleBinding;
3017 case T_JavaLangBoolean :
3018 return BooleanBinding;
3019 case T_JavaLangVoid :