package org.eclipse.jdt.internal.compiler.lookup;
import java.util.*;
import java.util.function.Function;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
@SuppressWarnings({ "rawtypes", "unchecked" })
public abstract class Scope {
public static Binding NOT_REDUNDANT = new Binding() {
@Override
public int kind() {
throw new IllegalStateException();
}
@Override
public char[] readableName() {
throw new IllegalStateException();
}
};
public final static int BLOCK_SCOPE = 1;
public final static int CLASS_SCOPE = 3;
public final static int COMPILATION_UNIT_SCOPE = 4;
public final static int METHOD_SCOPE = 2;
public final static int NOT_COMPATIBLE = -1;
public final static int COMPATIBLE = 0;
public final static int AUTOBOX_COMPATIBLE = 1;
public final static int VARARGS_COMPATIBLE = 2;
public static final int EQUAL_OR_MORE_SPECIFIC = -1;
public static final int NOT_RELATED = 0;
public static final int MORE_GENERIC = 1;
public int kind;
public Scope parent;
private static class NullDefaultRange {
final int start, end;
int value;
private Annotation[] annotations;
Binding target;
NullDefaultRange(int value, Annotation annotation, int start, int end, Binding target) {
this.start = start;
this.end = end;
this.value = value;
this.annotations = new Annotation[] { annotation };
this.target = target;
}
boolean contains(Annotation annotation) {
for (Annotation annotation2 : this.annotations) {
if (annotation2 == annotation)
return true;
}
return false;
}
void merge(int nextValue, Annotation nextAnnotation, Binding nextTarget) {
int len = this.annotations.length;
System.arraycopy(this.annotations, 0, this.annotations = new Annotation[len + 1], 0, len);
this.annotations[len] = nextAnnotation;
this.target = nextTarget;
this.value |= nextValue;
}
}
private ArrayList<NullDefaultRange> nullDefaultRanges;
protected Scope(int kind, Scope parent) {
this.kind = kind;
this.parent = parent;
}
public static int compareTypes(TypeBinding left, TypeBinding right) {
if (left.isCompatibleWith(right))
return Scope.EQUAL_OR_MORE_SPECIFIC;
if (right.isCompatibleWith(left))
return Scope.MORE_GENERIC;
return Scope.NOT_RELATED;
}
public static TypeBinding convertEliminatingTypeVariables(TypeBinding originalType, ReferenceBinding genericType, int rank, Set eliminatedVariables) {
if ((originalType.tagBits & TagBits.HasTypeVariable) != 0) {
switch (originalType.kind()) {
case Binding.ARRAY_TYPE :
ArrayBinding originalArrayType = (ArrayBinding) originalType;
TypeBinding originalLeafComponentType = originalArrayType.leafComponentType;
TypeBinding substitute = convertEliminatingTypeVariables(originalLeafComponentType, genericType, rank, eliminatedVariables);
if (TypeBinding.notEquals(substitute, originalLeafComponentType)) {
return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalArrayType.dimensions());
}
break;
case Binding.PARAMETERIZED_TYPE :
ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType;
ReferenceBinding originalEnclosing = paramType.enclosingType();
ReferenceBinding substitutedEnclosing = originalEnclosing;
if (originalEnclosing != null) {
substitutedEnclosing = (ReferenceBinding) convertEliminatingTypeVariables(originalEnclosing, genericType, rank, eliminatedVariables);
}
TypeBinding[] originalArguments = paramType.arguments;
TypeBinding[] substitutedArguments = originalArguments;
for (int i = 0, length = originalArguments == null ? 0 : originalArguments.length; i < length; i++) {
TypeBinding originalArgument = originalArguments[i];
TypeBinding substitutedArgument = convertEliminatingTypeVariables(originalArgument, paramType.genericType(), i, eliminatedVariables);
if (TypeBinding.notEquals(substitutedArgument, originalArgument)) {
if (substitutedArguments == originalArguments) {
System.arraycopy(originalArguments, 0, substitutedArguments = new TypeBinding[length], 0, i);
}
substitutedArguments[i] = substitutedArgument;
} else if (substitutedArguments != originalArguments) {
substitutedArguments[i] = originalArgument;
}
}
if (TypeBinding.notEquals(originalEnclosing, substitutedEnclosing) || originalArguments != substitutedArguments) {
return paramType.environment.createParameterizedType(paramType.genericType(), substitutedArguments, substitutedEnclosing);
}
break;
case Binding.TYPE_PARAMETER :
if (genericType == null) {
break;
}
TypeVariableBinding originalVariable = (TypeVariableBinding) originalType;
if (eliminatedVariables != null && eliminatedVariables.contains(originalType)) {
return originalVariable.environment.createWildcard(genericType, rank, null, null, Wildcard.UNBOUND);
}
TypeBinding originalUpperBound = originalVariable.upperBound();
if (eliminatedVariables == null) {
eliminatedVariables = new HashSet(2);
}
eliminatedVariables.add(originalVariable);
TypeBinding substitutedUpperBound = convertEliminatingTypeVariables(originalUpperBound, genericType, rank, eliminatedVariables);
eliminatedVariables.remove(originalVariable);
return originalVariable.environment.createWildcard(genericType, rank, substitutedUpperBound, null, Wildcard.EXTENDS);
case Binding.RAW_TYPE :
break;
case Binding.GENERIC_TYPE :
ReferenceBinding currentType = (ReferenceBinding) originalType;
originalEnclosing = currentType.enclosingType();
substitutedEnclosing = originalEnclosing;
if (originalEnclosing != null) {
substitutedEnclosing = (ReferenceBinding) convertEliminatingTypeVariables(originalEnclosing, genericType, rank, eliminatedVariables);
}
originalArguments = currentType.typeVariables();
substitutedArguments = originalArguments;
for (int i = 0, length = originalArguments == null ? 0 : originalArguments.length; i < length; i++) {
TypeBinding originalArgument = originalArguments[i];
TypeBinding substitutedArgument = convertEliminatingTypeVariables(originalArgument, currentType, i, eliminatedVariables);
if (TypeBinding.notEquals(substitutedArgument, originalArgument)) {
if (substitutedArguments == originalArguments) {
System.arraycopy(originalArguments, 0, substitutedArguments = new TypeBinding[length], 0, i);
}
substitutedArguments[i] = substitutedArgument;
} else if (substitutedArguments != originalArguments) {
substitutedArguments[i] = originalArgument;
}
}
if (TypeBinding.notEquals(originalEnclosing, substitutedEnclosing) || originalArguments != substitutedArguments) {
return ((TypeVariableBinding)originalArguments[0]).environment.createParameterizedType(genericType, substitutedArguments, substitutedEnclosing);
}
break;
case Binding.WILDCARD_TYPE :
WildcardBinding wildcard = (WildcardBinding) originalType;
TypeBinding originalBound = wildcard.bound;
TypeBinding substitutedBound = originalBound;
if (originalBound != null) {
substitutedBound = convertEliminatingTypeVariables(originalBound, genericType, rank, eliminatedVariables);
if (TypeBinding.notEquals(substitutedBound, originalBound)) {
return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, null, wildcard.boundKind);
}
}
break;
case Binding.INTERSECTION_TYPE :
WildcardBinding intersection = (WildcardBinding) originalType;
originalBound = intersection.bound;
substitutedBound = originalBound;
if (originalBound != null) {
substitutedBound = convertEliminatingTypeVariables(originalBound, genericType, rank, eliminatedVariables);
}
TypeBinding[] originalOtherBounds = intersection.otherBounds;
TypeBinding[] substitutedOtherBounds = originalOtherBounds;
for (int i = 0, length = originalOtherBounds == null ? 0 : originalOtherBounds.length; i < length; i++) {
TypeBinding originalOtherBound = originalOtherBounds[i];
TypeBinding substitutedOtherBound = convertEliminatingTypeVariables(originalOtherBound, genericType, rank, eliminatedVariables);
if (TypeBinding.notEquals(substitutedOtherBound, originalOtherBound)) {
if (substitutedOtherBounds == originalOtherBounds) {
System.arraycopy(originalOtherBounds, 0, substitutedOtherBounds = new TypeBinding[length], 0, i);
}
substitutedOtherBounds[i] = substitutedOtherBound;
} else if (substitutedOtherBounds != originalOtherBounds) {
substitutedOtherBounds[i] = originalOtherBound;
}
}
if (TypeBinding.notEquals(substitutedBound, originalBound) || substitutedOtherBounds != originalOtherBounds) {
return intersection.environment.createWildcard(intersection.genericType, intersection.rank, substitutedBound, substitutedOtherBounds, intersection.boundKind);
}
break;
}
}
return originalType;
}
public static TypeBinding getBaseType(char[] name) {
int length = name.length;
if (length > 2 && length < 8) {
switch (name[0]) {
case 'i' :
if (length == 3 && name[1] == 'n' && name[2] == 't')
return TypeBinding.INT;
break;
case 'v' :
if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
return TypeBinding.VOID;
break;
case 'b' :
if (length == 7
&& name[1] == 'o'
&& name[2] == 'o'
&& name[3] == 'l'
&& name[4] == 'e'
&& name[5] == 'a'
&& name[6] == 'n')
return TypeBinding.BOOLEAN;
if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
return TypeBinding.BYTE;
break;
case 'c' :
if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
return TypeBinding.CHAR;
break;
case 'd' :
if (length == 6
&& name[1] == 'o'
&& name[2] == 'u'
&& name[3] == 'b'
&& name[4] == 'l'
&& name[5] == 'e')
return TypeBinding.DOUBLE;
break;
case 'f' :
if (length == 5
&& name[1] == 'l'
&& name[2] == 'o'
&& name[3] == 'a'
&& name[4] == 't')
return TypeBinding.FLOAT;
break;
case 'l' :
if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
return TypeBinding.LONG;
break;
case 's' :
if (length == 5
&& name[1] == 'h'
&& name[2] == 'o'
&& name[3] == 'r'
&& name[4] == 't')
return TypeBinding.SHORT;
}
}
return null;
}
public static ReferenceBinding[] greaterLowerBound(ReferenceBinding[] types) {
if (types == null) return null;
types = filterValidTypes(types, ReferenceBinding[]::new);
int length = types.length;
if (length == 0) return null;
ReferenceBinding[] result = types;
int removed = 0;
for (int i = 0; i < length; i++) {
ReferenceBinding iType = result[i];
if (iType == null) continue;
for (int j = 0; j < length; j++) {
if (i == j) continue;
ReferenceBinding jType = result[j];
if (jType == null) continue;
if (isMalformedPair(iType, jType, null)) {
return null;
}
if (iType.isCompatibleWith(jType)) {
if (result == types) {
System.arraycopy(result, 0, result = new ReferenceBinding[length], 0, length);
}
result[j] = null;
removed ++;
}
}
}
if (removed == 0) return result;
if (length == removed) return null;
ReferenceBinding[] trimmedResult = new ReferenceBinding[length - removed];
for (int i = 0, index = 0; i < length; i++) {
ReferenceBinding iType = result[i];
if (iType != null) {
trimmedResult[index++] = iType;
}
}
return trimmedResult;
}
public static TypeBinding[] greaterLowerBound(TypeBinding[] types, Scope scope, LookupEnvironment environment) {
if (types == null) return null;
types = filterValidTypes(types, TypeBinding[]::new);
int length = types.length;
if (length == 0) return null;
TypeBinding[] result = types;
int removed = 0;
for (int i = 0; i < length; i++) {
TypeBinding iType = result[i];
if (iType == null) continue;
for (int j = 0; j < length; j++) {
if (i == j) continue;
TypeBinding jType = result[j];
if (jType == null) continue;
if (isMalformedPair(iType, jType, scope)) {
return null;
}
if (iType.isCompatibleWith(jType, scope)) {
if (result == types) {
System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
}
result[j] = null;
removed ++;
} else if (!jType.isCompatibleWith(iType, scope)) {
if (iType.isParameterizedType() && jType.isParameterizedType()) {
ParameterizedTypeBinding wideType, narrowType;
if (iType.original().isCompatibleWith(jType.original(), scope)) {
wideType = (ParameterizedTypeBinding) jType;
narrowType = (ParameterizedTypeBinding) iType;
} else if (jType.original().isCompatibleWith(iType.original(), scope)) {
wideType = (ParameterizedTypeBinding) iType;
narrowType = (ParameterizedTypeBinding) jType;
} else {
continue;
}
if (wideType.arguments == null)
continue;
if (!narrowType.isProperType(false) || !wideType.isProperType(false))
continue;
int numTypeArgs = wideType.arguments.length;
TypeBinding[] bounds = new TypeBinding[numTypeArgs];
for (int k = 0; k < numTypeArgs; k++) {
TypeBinding argument = wideType.arguments[k];
bounds[k] = argument.isTypeVariable() ? ((TypeVariableBinding)argument).upperBound() : argument;
}
ReferenceBinding wideOriginal = (ReferenceBinding) wideType.original();
TypeBinding substitutedWideType =
environment.createParameterizedType(wideOriginal, bounds, wideOriginal.enclosingType());
if (!narrowType.isCompatibleWith(substitutedWideType, scope)) {
return null;
}
}
}
}
}
if (removed == 0) return result;
if (length == removed) return null;
TypeBinding[] trimmedResult = new TypeBinding[length - removed];
for (int i = 0, index = 0; i < length; i++) {
TypeBinding iType = result[i];
if (iType != null) {
trimmedResult[index++] = iType;
}
}
return trimmedResult;
}
static <T extends TypeBinding> T[] filterValidTypes(T[] allTypes, Function<Integer,T[]> ctor) {
T[] valid = ctor.apply(allTypes.length);
int count = 0;
for (int i = 0; i < allTypes.length; i++) {
if (allTypes[i].isValidBinding())
valid[count++] = allTypes[i];
}
if (count == allTypes.length)
return allTypes;
if (count == 0 && allTypes.length > 0)
return Arrays.copyOf(allTypes, 1);
return Arrays.copyOf(valid, count);
}
static boolean isMalformedPair(TypeBinding t1, TypeBinding t2, Scope scope) {
switch (t1.kind()) {
case Binding.TYPE:
case Binding.GENERIC_TYPE:
case Binding.PARAMETERIZED_TYPE:
case Binding.RAW_TYPE:
if (t1.isClass()) {
if (t2.getClass() == TypeVariableBinding.class) {
TypeBinding bound = ((TypeVariableBinding) t2).firstBound;
if (bound == null || !bound.erasure().isCompatibleWith(t1.erasure())) {
return true;
}
}
}
}
return false;
}
public static ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
return defaultSubstitutor.substitute(substitution, originalTypes);
}
public static TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
return defaultSubstitutor.substitute(substitution, originalType);
}
public static TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
return defaultSubstitutor.substitute(substitution, originalTypes);
}
private static Substitutor defaultSubstitutor = new Substitutor();
public static class Substitutor {
public ReferenceBinding[] substitute(Substitution substitution, ReferenceBinding[] originalTypes) {
if (originalTypes == null) return null;
ReferenceBinding[] substitutedTypes = originalTypes;
for (int i = 0, length = originalTypes.length; i < length; i++) {
ReferenceBinding originalType = originalTypes[i];
TypeBinding substitutedType = substitute(substitution, originalType);
if (!(substitutedType instanceof ReferenceBinding)) {
return null;
}
if (substitutedType != originalType) {
if (substitutedTypes == originalTypes) {
System.arraycopy(originalTypes, 0, substitutedTypes = new ReferenceBinding[length], 0, i);
}
substitutedTypes[i] = (ReferenceBinding)substitutedType;
} else if (substitutedTypes != originalTypes) {
substitutedTypes[i] = originalType;
}
}
return substitutedTypes;
}
public TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
if (originalType == null) return null;
switch (originalType.kind()) {
case Binding.TYPE_PARAMETER:
return substitution.substitute((TypeVariableBinding) originalType);
case Binding.PARAMETERIZED_TYPE:
ParameterizedTypeBinding originalParameterizedType = (ParameterizedTypeBinding) originalType;
ReferenceBinding originalEnclosing = originalType.enclosingType();
ReferenceBinding substitutedEnclosing = originalEnclosing;
if (originalEnclosing != null && originalParameterizedType.hasEnclosingInstanceContext()) {
substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
return originalParameterizedType.environment.createRawType(
originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
}
TypeBinding[] originalArguments = originalParameterizedType.arguments;
TypeBinding[] substitutedArguments = originalArguments;
if (originalArguments != null) {
if (substitution.isRawSubstitution()) {
return originalParameterizedType.environment.createRawType(originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
}
substitutedArguments = substitute(substitution, originalArguments);
}
if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
return originalParameterizedType.environment.createParameterizedType(
originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
}
break;
case Binding.ARRAY_TYPE:
ArrayBinding originalArrayType = (ArrayBinding) originalType;
TypeBinding originalLeafComponentType = originalArrayType.leafComponentType;
TypeBinding substitute = substitute(substitution, originalLeafComponentType);
if (substitute != originalLeafComponentType) {
return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions(), originalType.getTypeAnnotations());
}
break;
case Binding.WILDCARD_TYPE:
case Binding.INTERSECTION_TYPE:
WildcardBinding wildcard = (WildcardBinding) originalType;
if (wildcard.boundKind != Wildcard.UNBOUND) {
TypeBinding originalBound = wildcard.bound;
TypeBinding substitutedBound = substitute(substitution, originalBound);
TypeBinding[] originalOtherBounds = wildcard.otherBounds;
TypeBinding[] substitutedOtherBounds = substitute(substitution, originalOtherBounds);
if (substitutedBound != originalBound || originalOtherBounds != substitutedOtherBounds) {
if (originalOtherBounds != null) {
TypeBinding [] bounds = new TypeBinding[1 + substitutedOtherBounds.length];
bounds[0] = substitutedBound;
System.arraycopy(substitutedOtherBounds, 0, bounds, 1, substitutedOtherBounds.length);
TypeBinding[] glb = Scope.greaterLowerBound(bounds, null, substitution.environment());
if (glb != null && glb != bounds) {
substitutedBound = glb[0];
if (glb.length == 1) {
substitutedOtherBounds = null;
} else {
System.arraycopy(glb, 1, substitutedOtherBounds = new TypeBinding[glb.length - 1], 0, glb.length - 1);
}
}
}
return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, substitutedOtherBounds, wildcard.boundKind, wildcard.getTypeAnnotations());
}
}
break;
case Binding.INTERSECTION_TYPE18:
IntersectionTypeBinding18 intersection = (IntersectionTypeBinding18) originalType;
ReferenceBinding[] types = intersection.getIntersectingTypes();
TypeBinding[] substitutes = substitute(substitution, types);
ReferenceBinding[] refSubsts = new ReferenceBinding[substitutes.length];
System.arraycopy(substitutes, 0, refSubsts, 0, substitutes.length);
return substitution.environment().createIntersectionType18(refSubsts);
case Binding.TYPE:
if (!originalType.isMemberType()) break;
ReferenceBinding originalReferenceType = (ReferenceBinding) originalType;
originalEnclosing = originalType.enclosingType();
substitutedEnclosing = originalEnclosing;
if (originalEnclosing != null) {
substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
}
if (substitutedEnclosing != originalEnclosing && originalReferenceType.hasEnclosingInstanceContext()) {
return substitution.isRawSubstitution()
? substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations())
: substitution.environment().createParameterizedType(originalReferenceType, null, substitutedEnclosing, originalType.getTypeAnnotations());
}
break;
case Binding.GENERIC_TYPE:
originalReferenceType = (ReferenceBinding) originalType.unannotated();
originalEnclosing = originalType.enclosingType();
substitutedEnclosing = originalEnclosing;
if (originalEnclosing != null) {
substitutedEnclosing = (ReferenceBinding) (originalType.isStatic() ? substitution.environment().convertToRawType(originalEnclosing, true) :
(ReferenceBinding) substitute(substitution, originalEnclosing));
if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
}
if (substitution.isRawSubstitution()) {
return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
}
originalArguments = originalReferenceType.typeVariables();
substitutedArguments = substitute(substitution, originalArguments);
return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
}
return originalType;
}
private static boolean isMemberTypeOfRaw(TypeBinding originalType, ReferenceBinding substitutedEnclosing) {
return (substitutedEnclosing != null && substitutedEnclosing.isRawType())
&& ((originalType instanceof ReferenceBinding) && !((ReferenceBinding)originalType).isStatic());
}
public TypeBinding[] substitute(Substitution substitution, TypeBinding[] originalTypes) {
if (originalTypes == null) return null;
TypeBinding[] substitutedTypes = originalTypes;
for (int i = 0, length = originalTypes.length; i < length; i++) {
TypeBinding originalType = originalTypes[i];
TypeBinding substitutedParameter = substitute(substitution, originalType);
if (substitutedParameter != originalType) {
if (substitutedTypes == originalTypes) {
System.arraycopy(originalTypes, 0, substitutedTypes = new TypeBinding[length], 0, i);
}
substitutedTypes[i] = substitutedParameter;
} else if (substitutedTypes != originalTypes) {
substitutedTypes[i] = originalType;
}
}
return substitutedTypes;
}
}
public TypeBinding boxing(TypeBinding type) {
if (type.isBaseType() || type.kind() == Binding.POLY_TYPE)
return environment().computeBoxingType(type);
return type;
}
public final ClassScope classScope() {
Scope scope = this;
do {
if (scope instanceof ClassScope)
return (ClassScope) scope;
scope = scope.parent;
} while (scope != null);
return null;
}
public final CompilationUnitScope compilationUnitScope() {
Scope lastScope = null;
Scope scope = this;
do {
lastScope = scope;
scope = scope.parent;
} while (scope != null);
return (CompilationUnitScope) lastScope;
}
public ModuleBinding module() {
return environment().module;
}
public boolean isLambdaScope() {
return false;
}
public boolean isLambdaSubscope() {
for (Scope scope = this; scope != null; scope = scope.parent) {
switch (scope.kind) {
case BLOCK_SCOPE:
continue;
case METHOD_SCOPE:
return scope.isLambdaScope();
default:
return false;
}
}
return false;
}
public boolean isModuleScope() {
return false;
}
public final CompilerOptions compilerOptions() {
return compilationUnitScope().environment.globalOptions;
}
protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite) {
return computeCompatibleMethod(method, arguments, invocationSite, false);
}
protected final MethodBinding computeCompatibleMethod(MethodBinding method, TypeBinding[] arguments, InvocationSite invocationSite, boolean tiebreakingVarargsMethods)
{
TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments();
TypeBinding[] parameters = method.parameters;
TypeVariableBinding[] typeVariables = method.typeVariables;
if (parameters == arguments
&& (method.returnType.tagBits & TagBits.HasTypeVariable) == 0
&& genericTypeArguments == null
&& typeVariables == Binding.NO_TYPE_VARIABLES)
return method;
int argLength = arguments.length;
int paramLength = parameters.length;
boolean isVarArgs = method.isVarargs();
if (argLength != paramLength)
if (!isVarArgs || argLength < paramLength - 1)
return null;
CompilerOptions compilerOptions = this.compilerOptions();
if (typeVariables != Binding.NO_TYPE_VARIABLES && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) {
TypeBinding[] newArgs = null;
if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_8 || genericTypeArguments != null) {
for (int i = 0; i < argLength; i++) {
TypeBinding param = i < paramLength ? parameters[i] : parameters[paramLength - 1];
if (arguments[i].isBaseType() != param.isBaseType()) {
if (newArgs == null) {
newArgs = new TypeBinding[argLength];
System.arraycopy(arguments, 0, newArgs, 0, argLength);
}
newArgs[i] = environment().computeBoxingType(arguments[i]);
}
}
}
if (newArgs != null)
arguments = newArgs;
method = ParameterizedGenericMethodBinding.computeCompatibleMethod(method, arguments, this, invocationSite);
if (method == null) return null;
if (!method.isValidBinding()) return method;
if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8 && method instanceof ParameterizedGenericMethodBinding && invocationSite instanceof Invocation) {
Invocation invocation = (Invocation) invocationSite;
InferenceContext18 infCtx = invocation.getInferenceContext((ParameterizedGenericMethodBinding) method);
if (infCtx != null)
return method;
}
} else if (genericTypeArguments != null && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) {
if (method instanceof ParameterizedGenericMethodBinding) {
if (!((ParameterizedGenericMethodBinding) method).wasInferred)
return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.TypeArgumentsForRawGenericMethod);
} else if (!method.isOverriding() || !isOverriddenMethodGeneric(method)) {
return new ProblemMethodBinding(method, method.selector, genericTypeArguments, ProblemReasons.TypeParameterArityMismatch);
}
} else if (typeVariables == Binding.NO_TYPE_VARIABLES && method instanceof ParameterizedGenericMethodBinding) {
if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8 && invocationSite instanceof Invocation) {
Invocation invocation = (Invocation) invocationSite;
InferenceContext18 infCtx = invocation.getInferenceContext((ParameterizedGenericMethodBinding) method);
if (infCtx != null)
return method;
}
}
if (tiebreakingVarargsMethods) {
if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7)
tiebreakingVarargsMethods = false;
}
if ((parameterCompatibilityLevel(method, arguments, tiebreakingVarargsMethods)) > NOT_COMPATIBLE) {
if ((method.tagBits & TagBits.AnnotationPolymorphicSignature) != 0) {
return this.environment().createPolymorphicMethod(method, arguments, this);
}
return method;
}
if (genericTypeArguments != null && typeVariables != Binding.NO_TYPE_VARIABLES)
return new ProblemMethodBinding(method, method.selector, arguments, ProblemReasons.ParameterizedMethodTypeMismatch);
if (method instanceof PolyParameterizedGenericMethodBinding)
return new ProblemMethodBinding(method, method.selector, method.parameters, ProblemReasons.InferredApplicableMethodInapplicable);
return null;
}
protected boolean connectTypeVariables(TypeParameter[] typeParameters, boolean checkForErasedCandidateCollisions) {
if (typeParameters == null || typeParameters.length == 0) return true;
Map invocations = new HashMap(2);
boolean noProblems = true;
int paramLength = typeParameters.length;
for (int i = 0; i < paramLength; i++) {
TypeParameter typeParameter = typeParameters[i];
TypeVariableBinding typeVariable = typeParameter.binding;
if (typeVariable == null) return false;
typeVariable.setSuperClass(getJavaLangObject());
typeVariable.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
typeVariable.setFirstBound(null);
}
nextVariable: for (int i = 0; i < paramLength; i++) {
TypeParameter typeParameter = typeParameters[i];
TypeVariableBinding typeVariable = typeParameter.binding;
TypeReference typeRef = typeParameter.type;
if (typeRef == null)
continue nextVariable;
boolean isFirstBoundTypeVariable = false;
TypeBinding superType = this.kind == METHOD_SCOPE
? typeRef.resolveType((BlockScope)this, false, Binding.DefaultLocationTypeBound)
: typeRef.resolveType((ClassScope)this, Binding.DefaultLocationTypeBound);
if (superType == null) {
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
} else {
typeRef.resolvedType = superType;
firstBound: {
switch (superType.kind()) {
case Binding.ARRAY_TYPE :
problemReporter().boundCannotBeArray(typeRef, superType);
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
break firstBound;
case Binding.TYPE_PARAMETER :
isFirstBoundTypeVariable = true;
TypeVariableBinding varSuperType = (TypeVariableBinding) superType;
if (varSuperType.rank >= typeVariable.rank && varSuperType.declaringElement == typeVariable.declaringElement) {
if (compilerOptions().complianceLevel <= ClassFileConstants.JDK1_6) {
problemReporter().forwardTypeVariableReference(typeParameter, varSuperType);
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
break firstBound;
}
}
if (compilerOptions().complianceLevel > ClassFileConstants.JDK1_6) {
if (typeVariable.rank >= varSuperType.rank && varSuperType.declaringElement == typeVariable.declaringElement) {
SimpleSet set = new SimpleSet(typeParameters.length);
set.add(typeVariable);
ReferenceBinding superBinding = varSuperType;
while (superBinding instanceof TypeVariableBinding) {
if (set.includes(superBinding)) {
problemReporter().hierarchyCircularity(typeVariable, varSuperType, typeRef);
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
break firstBound;
} else {
set.add(superBinding);
superBinding = ((TypeVariableBinding)superBinding).superclass;
}
}
}
}
break;
default :
if (((ReferenceBinding) superType).isFinal()) {
if (!environment().usesNullTypeAnnotations() || (superType.tagBits & TagBits.AnnotationNullable) == 0) {
problemReporter().finalVariableBound(typeVariable, typeRef);
}
}
break;
}
ReferenceBinding superRefType = (ReferenceBinding) superType;
if (!superType.isInterface()) {
typeVariable.setSuperClass(superRefType);
} else {
typeVariable.setSuperInterfaces(new ReferenceBinding[] {superRefType});
}
typeVariable.tagBits |= superType.tagBits & TagBits.ContainsNestedTypeReferences;
typeVariable.setFirstBound(superRefType);
}
}
TypeReference[] boundRefs = typeParameter.bounds;
if (boundRefs != null) {
nextBound: for (int j = 0, boundLength = boundRefs.length; j < boundLength; j++) {
typeRef = boundRefs[j];
superType = this.kind == METHOD_SCOPE
? typeRef.resolveType((BlockScope)this, false)
: typeRef.resolveType((ClassScope)this);
if (superType == null) {
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
continue nextBound;
} else {
typeVariable.tagBits |= superType.tagBits & TagBits.ContainsNestedTypeReferences;
boolean didAlreadyComplain = !typeRef.resolvedType.isValidBinding();
if (isFirstBoundTypeVariable && j == 0) {
problemReporter().noAdditionalBoundAfterTypeVariable(typeRef);
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
didAlreadyComplain = true;
} else if (superType.isArrayType()) {
if (!didAlreadyComplain) {
problemReporter().boundCannotBeArray(typeRef, superType);
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
}
continue nextBound;
} else {
if (!superType.isInterface()) {
if (!didAlreadyComplain) {
problemReporter().boundMustBeAnInterface(typeRef, superType);
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
}
continue nextBound;
}
}
if (checkForErasedCandidateCollisions && TypeBinding.equalsEquals(typeVariable.firstBound, typeVariable.superclass)) {
if (hasErasedCandidatesCollisions(superType, typeVariable.superclass, invocations, typeVariable, typeRef)) {
continue nextBound;
}
}
ReferenceBinding superRefType = (ReferenceBinding) superType;
for (int index = typeVariable.superInterfaces.length; --index >= 0;) {
ReferenceBinding previousInterface = typeVariable.superInterfaces[index];
if (TypeBinding.equalsEquals(previousInterface, superRefType)) {
problemReporter().duplicateBounds(typeRef, superType);
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
continue nextBound;
}
if (checkForErasedCandidateCollisions) {
if (hasErasedCandidatesCollisions(superType, previousInterface, invocations, typeVariable, typeRef)) {
continue nextBound;
}
}
}
int size = typeVariable.superInterfaces.length;
System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.setSuperInterfaces(new ReferenceBinding[size + 1]), 0, size);
typeVariable.superInterfaces[size] = superRefType;
}
}
}
noProblems &= (typeVariable.tagBits & TagBits.HierarchyHasProblems) == 0;
}
boolean declaresNullTypeAnnotation = false;
for (int i = 0; i < paramLength; i++) {
resolveTypeParameter(typeParameters[i]);
declaresNullTypeAnnotation |= typeParameters[i].binding.hasNullTypeAnnotations();
}
if (declaresNullTypeAnnotation)
for (int i = 0; i < paramLength; i++)
typeParameters[i].binding.updateTagBits();
return noProblems;
}
public ArrayBinding createArrayType(TypeBinding type, int dimension) {
return createArrayType(type, dimension, Binding.NO_ANNOTATIONS);
}
public ArrayBinding createArrayType(TypeBinding type, int dimension, AnnotationBinding[] annotations) {
if (type.isValidBinding())
return environment().createArrayType(type, dimension, annotations);
return new ArrayBinding(type, dimension, environment());
}
public TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) {
if (typeParameters == null || typeParameters.length == 0)
return Binding.NO_TYPE_VARIABLES;
PackageBinding unitPackage = compilationUnitScope().fPackage;
int length = typeParameters.length;
TypeVariableBinding[] typeVariableBindings = new TypeVariableBinding[length];
int count = 0;
for (int i = 0; i < length; i++) {
TypeParameter typeParameter = typeParameters[i];
TypeVariableBinding parameterBinding = new TypeVariableBinding(typeParameter.name, declaringElement, i, environment());
parameterBinding.fPackage = unitPackage;
typeParameter.binding = parameterBinding;
if ((typeParameter.bits & ASTNode.HasTypeAnnotations) != 0) {
switch(declaringElement.kind()) {
case Binding.METHOD :
MethodBinding methodBinding = (MethodBinding) declaringElement;
AbstractMethodDeclaration sourceMethod = methodBinding.sourceMethod();
if (sourceMethod != null) {
sourceMethod.bits |= ASTNode.HasTypeAnnotations;
}
break;
case Binding.TYPE :
if (declaringElement instanceof SourceTypeBinding) {
SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) declaringElement;
TypeDeclaration typeDeclaration = sourceTypeBinding.scope.referenceContext;
if (typeDeclaration != null) {
typeDeclaration.bits |= ASTNode.HasTypeAnnotations;
}
}
}
}
for (int j = 0; j < count; j++) {
TypeVariableBinding knownVar = typeVariableBindings[j];
if (CharOperation.equals(knownVar.sourceName, typeParameter.name))
problemReporter().duplicateTypeParameterInType(typeParameter);
}
typeVariableBindings[count++] = parameterBinding;
}
if (count != length)
System.arraycopy(typeVariableBindings, 0, typeVariableBindings = new TypeVariableBinding[count], 0, count);
return typeVariableBindings;
}
void resolveTypeParameter(TypeParameter typeParameter) {
}
public final ClassScope enclosingClassScope() {
Scope scope = this;
while ((scope = scope.parent) != null) {
if (scope instanceof ClassScope) return (ClassScope) scope;
}
return null;
}
public final ClassScope enclosingTopMostClassScope() {
Scope scope = this;
while (scope != null) {
Scope t = scope.parent;
if (t instanceof CompilationUnitScope) break;
scope = t;
}
return scope instanceof ClassScope ? ((ClassScope) scope) : null;
}
public final MethodScope enclosingMethodScope() {
Scope scope = this;
while ((scope = scope.parent) != null) {
if (scope instanceof MethodScope) return (MethodScope) scope;
}
return null;
}
public final MethodScope enclosingLambdaScope() {
Scope scope = this;
while ((scope = scope.parent) != null) {
if (scope instanceof MethodScope) {
MethodScope methodScope = (MethodScope) scope;
if (methodScope.referenceContext instanceof LambdaExpression)
return methodScope;
}
}
return null;
}
public final ReferenceBinding enclosingReceiverType() {
Scope scope = this;
do {
if (scope instanceof ClassScope) {
return environment().convertToParameterizedType(((ClassScope) scope).referenceContext.binding);
}
scope = scope.parent;
} while (scope != null);
return null;
}
public ReferenceContext enclosingReferenceContext() {
Scope current = this;
while ((current = current.parent) != null) {
switch(current.kind) {
case METHOD_SCOPE :
return ((MethodScope) current).referenceContext;
case CLASS_SCOPE :
return ((ClassScope) current).referenceContext;
case COMPILATION_UNIT_SCOPE :
return ((CompilationUnitScope) current).referenceContext;
}
}
return null;
}
public final SourceTypeBinding enclosingSourceType() {
Scope scope = this;
do {
if (scope instanceof ClassScope)
return ((ClassScope) scope).referenceContext.binding;
scope = scope.parent;
} while (scope != null);
return null;
}
public final LookupEnvironment environment() {
Scope scope, unitScope = this;
while ((scope = unitScope.parent) != null)
unitScope = scope;
return ((CompilationUnitScope) unitScope).environment;
}
protected MethodBinding findDefaultAbstractMethod(
ReferenceBinding receiverType,
char[] selector,
TypeBinding[] argumentTypes,
InvocationSite invocationSite,
ReferenceBinding classHierarchyStart,
ObjectVector found,
MethodBinding [] concreteMatches) {
int startFoundSize = found.size;
final boolean sourceLevel18 = this.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8;
ReferenceBinding currentType = classHierarchyStart;
List<TypeBinding> visitedTypes = new ArrayList<TypeBinding>();
while (currentType != null) {
findMethodInSuperInterfaces(currentType, selector, found, visitedTypes, invocationSite);
currentType = currentType.superclass();
}
int candidatesCount = concreteMatches == null ? 0 : concreteMatches.length;
int foundSize = found.size;
MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize + candidatesCount];
if (concreteMatches != null)
System.arraycopy(concreteMatches, 0, candidates, 0, candidatesCount);
MethodBinding problemMethod = null;
if (foundSize > startFoundSize) {
final MethodVerifier methodVerifier = environment().methodVerifier();
next:
for (int i = startFoundSize; i < foundSize; i++) {
MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
if (compatibleMethod != null) {
if (compatibleMethod.isValidBinding()) {
if (concreteMatches != null) {
for (int j = 0, length = concreteMatches.length; j < length; j++) {
if (methodVerifier.areMethodsCompatible(concreteMatches[j], compatibleMethod))
continue;
}
}
if (sourceLevel18 || !(compatibleMethod.isVarargs() && compatibleMethod instanceof ParameterizedGenericMethodBinding)) {
for (int j = 0; j < startFoundSize; j++) {
MethodBinding classMethod = (MethodBinding) found.elementAt(j);
if (classMethod != null && methodVerifier.areMethodsCompatible(classMethod, compatibleMethod))
continue next;
}
}
candidates[candidatesCount++] = compatibleMethod;
} else if (problemMethod == null) {
problemMethod = compatibleMethod;
}
}
}
}
MethodBinding concreteMatch = null;
if (candidatesCount < 2) {
if (concreteMatches == null) {
if (candidatesCount == 0)
return problemMethod;
}
concreteMatch = candidates[0];
if (concreteMatch != null)
compilationUnitScope().recordTypeReferences(concreteMatch.thrownExceptions);
return concreteMatch;
}
if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
return mostSpecificMethodBinding(candidates, candidatesCount, argumentTypes, invocationSite, receiverType);
return mostSpecificInterfaceMethodBinding(candidates, candidatesCount, invocationSite);
}
public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0)
return null;
ReferenceBinding enclosingReceiverType = enclosingReceiverType();
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordReference(enclosingType, typeName);
ReferenceBinding memberType = enclosingType.getMemberType(typeName);
if (memberType != null) {
unitScope.recordTypeReference(memberType);
if (enclosingReceiverType == null) {
if (memberType.canBeSeenBy(getCurrentPackage())) {
return memberType;
}
} else if (memberType.canBeSeenBy(enclosingType, enclosingReceiverType)) {
return memberType;
}
return new ProblemReferenceBinding(new char[][]{typeName}, memberType, ProblemReasons.NotVisible);
}
return null;
}
public MethodBinding findExactMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordTypeReferences(argumentTypes);
MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, unitScope);
if (exactMethod != null && exactMethod.typeVariables == Binding.NO_TYPE_VARIABLES && !exactMethod.isBridge()) {
if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5)
for (int i = argumentTypes.length; --i >= 0;) {
TypeBinding t = argumentTypes[i].leafComponentType();
if (! (t instanceof ReferenceBinding))
continue;
ReferenceBinding r = (ReferenceBinding)t;
if (r.isHierarchyConnected()) {
if (isSubtypeOfRawType(r))
return null;
} else if (r.isRawType()) {
return null;
}
}
unitScope.recordTypeReferences(exactMethod.thrownExceptions);
if (exactMethod.isAbstract() && exactMethod.thrownExceptions != Binding.NO_EXCEPTIONS)
return null;
if (exactMethod.canBeSeenBy(receiverType, invocationSite, this)) {
if (argumentTypes == Binding.NO_PARAMETERS
&& CharOperation.equals(selector, TypeConstants.GETCLASS)
&& exactMethod.returnType.isParameterizedType()) {
return environment().createGetClassMethod(receiverType, exactMethod, this);
}
if (invocationSite.genericTypeArguments() != null) {
exactMethod = computeCompatibleMethod(exactMethod, argumentTypes, invocationSite);
} else if ((exactMethod.tagBits & TagBits.AnnotationPolymorphicSignature) != 0) {
return this.environment().createPolymorphicMethod(exactMethod, argumentTypes, this);
}
return exactMethod;
}
}
return null;
}
public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
return findField(receiverType, fieldName, invocationSite, needResolve, false);
}
public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve, boolean invisibleFieldsOk) {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordTypeReference(receiverType);
checkArrayField: {
TypeBinding leafType;
switch (receiverType.kind()) {
case Binding.BASE_TYPE :
return null;
case Binding.WILDCARD_TYPE :
case Binding.INTERSECTION_TYPE:
case Binding.TYPE_PARAMETER :
TypeBinding receiverErasure = receiverType.erasure();
if (!receiverErasure.isArrayType())
break checkArrayField;
leafType = receiverErasure.leafComponentType();
break;
case Binding.ARRAY_TYPE :
leafType = receiverType.leafComponentType();
break;
default:
break checkArrayField;
}
if (leafType instanceof ReferenceBinding)
if (!((ReferenceBinding) leafType).canBeSeenBy(this))
return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ProblemReasons.ReceiverTypeNotVisible);
if (CharOperation.equals(fieldName, TypeConstants.LENGTH)) {
if ((leafType.tagBits & TagBits.HasMissingType) != 0) {
return new ProblemFieldBinding(ArrayBinding.ArrayLength, null, fieldName, ProblemReasons.NotFound);
}
return ArrayBinding.ArrayLength;
}
return null;
}
ReferenceBinding currentType = (ReferenceBinding) receiverType;
if (!currentType.canBeSeenBy(this))
return new ProblemFieldBinding(currentType, fieldName, ProblemReasons.ReceiverTypeNotVisible);
currentType.initializeForStaticImports();
FieldBinding field = currentType.getField(fieldName, needResolve);
boolean insideTypeAnnotations = this instanceof MethodScope && ((MethodScope) this).insideTypeAnnotation;
if (field != null) {
if (invisibleFieldsOk) {
return field;
}
if (invocationSite == null || insideTypeAnnotations
? field.canBeSeenBy(getCurrentPackage())
: field.canBeSeenBy(currentType, invocationSite, this))
return field;
return new ProblemFieldBinding(field , field.declaringClass, fieldName, ProblemReasons.NotVisible);
}
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
FieldBinding visibleField = null;
boolean keepLooking = true;
FieldBinding notVisibleField = null;
while (keepLooking) {
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
if (interfacesToVisit == null) {
interfacesToVisit = itsInterfaces;
nextPosition = interfacesToVisit.length;
} else {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
if ((currentType = currentType.superclass()) == null)
break;
unitScope.recordTypeReference(currentType);
currentType.initializeForStaticImports();
currentType = (ReferenceBinding) currentType.capture(this, invocationSite == null ? 0 : invocationSite.sourceStart(), invocationSite == null ? 0 : invocationSite.sourceEnd());
if ((field = currentType.getField(fieldName, needResolve)) != null) {
if (invisibleFieldsOk) {
return field;
}
keepLooking = false;
if (field.canBeSeenBy(receiverType, invocationSite, this)) {
if (visibleField == null)
visibleField = field;
else
return new ProblemFieldBinding(visibleField , visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous);
} else {
if (notVisibleField == null)
notVisibleField = field;
}
}
}
if (interfacesToVisit != null) {
ProblemFieldBinding ambiguous = null;
done : for (int i = 0; i < nextPosition; i++) {
ReferenceBinding anInterface = interfacesToVisit[i];
unitScope.recordTypeReference(anInterface);
if ((field = anInterface.getField(fieldName, true )) != null) {
if (invisibleFieldsOk) {
return field;
}
if (visibleField == null) {
visibleField = field;
} else {
ambiguous = new ProblemFieldBinding(visibleField , visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous);
break done;
}
} else {
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
if (ambiguous != null)
return ambiguous;
}
if (visibleField != null)
return visibleField;
if (notVisibleField != null) {
return new ProblemFieldBinding(notVisibleField, currentType, fieldName, ProblemReasons.NotVisible);
}
return null;
}
public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0)
return null;
ReferenceBinding enclosingSourceType = enclosingSourceType();
PackageBinding currentPackage = getCurrentPackage();
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordReference(enclosingType, typeName);
ReferenceBinding memberType = enclosingType.getMemberType(typeName);
if (memberType != null) {
unitScope.recordTypeReference(memberType);
if (enclosingSourceType == null || (this.parent == unitScope && (enclosingSourceType.tagBits & TagBits.TypeVariablesAreConnected) == 0)
? memberType.canBeSeenBy(currentPackage)
: memberType.canBeSeenBy(enclosingType, enclosingSourceType))
return memberType;
return new ProblemReferenceBinding(new char[][]{typeName}, memberType, ProblemReasons.NotVisible);
}
ReferenceBinding currentType = enclosingType;
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
ReferenceBinding visibleMemberType = null;
boolean keepLooking = true;
ReferenceBinding notVisible = null;
while (keepLooking) {
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces == null) {
ReferenceBinding sourceType = currentType.isParameterizedType()
? ((ParameterizedTypeBinding) currentType).genericType()
: currentType;
if (sourceType instanceof SourceTypeBinding) {
if (sourceType.isHierarchyBeingConnected())
return null;
((SourceTypeBinding) sourceType).scope.connectTypeHierarchy();
}
itsInterfaces = currentType.superInterfaces();
}
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
if (interfacesToVisit == null) {
interfacesToVisit = itsInterfaces;
nextPosition = interfacesToVisit.length;
} else {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
if ((currentType = currentType.superclass()) == null)
break;
unitScope.recordReference(currentType, typeName);
if ((memberType = currentType.getMemberType(typeName)) != null) {
unitScope.recordTypeReference(memberType);
keepLooking = false;
if (enclosingSourceType == null
? memberType.canBeSeenBy(currentPackage)
: memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
if (visibleMemberType == null)
visibleMemberType = memberType;
else
return new ProblemReferenceBinding(new char[][]{typeName}, visibleMemberType, ProblemReasons.Ambiguous);
} else {
notVisible = memberType;
}
}
}
if (interfacesToVisit != null) {
ProblemReferenceBinding ambiguous = null;
done : for (int i = 0; i < nextPosition; i++) {
ReferenceBinding anInterface = interfacesToVisit[i];
unitScope.recordReference(anInterface, typeName);
if ((memberType = anInterface.getMemberType(typeName)) != null) {
unitScope.recordTypeReference(memberType);
if (visibleMemberType == null) {
visibleMemberType = memberType;
} else {
ambiguous = new ProblemReferenceBinding(new char[][]{typeName}, visibleMemberType, ProblemReasons.Ambiguous);
break done;
}
} else {
ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
if (ambiguous != null)
return ambiguous;
}
if (visibleMemberType != null)
return visibleMemberType;
if (notVisible != null)
return new ProblemReferenceBinding(new char[][]{typeName}, notVisible, ProblemReasons.NotVisible);
return null;
}
public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite, boolean inStaticContext) {
MethodBinding method = findMethod0(receiverType, selector, argumentTypes, invocationSite, inStaticContext);
if (method != null && method.isValidBinding() && method.isVarargs()) {
TypeBinding elementType = method.parameters[method.parameters.length - 1].leafComponentType();
if (elementType instanceof ReferenceBinding) {
if (!((ReferenceBinding) elementType).canBeSeenBy(this)) {
return new ProblemMethodBinding(method, method.selector, invocationSite.genericTypeArguments(), ProblemReasons.VarargsElementTypeNotVisible);
}
}
}
return method;
}
public MethodBinding findMethod0(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite, boolean inStaticContext) {
ReferenceBinding currentType = receiverType;
boolean receiverTypeIsInterface = receiverType.isInterface();
ObjectVector found = new ObjectVector(3);
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordTypeReferences(argumentTypes);
List<TypeBinding> visitedTypes = new ArrayList<TypeBinding>();
if (receiverTypeIsInterface) {
unitScope.recordTypeReference(receiverType);
MethodBinding[] receiverMethods = receiverType.getMethods(selector, argumentTypes.length);
if (receiverMethods.length > 0)
found.addAll(receiverMethods);
findMethodInSuperInterfaces(receiverType, selector, found, visitedTypes, invocationSite);
currentType = getJavaLangObject();
}
long complianceLevel = compilerOptions().complianceLevel;
boolean isCompliant14 = complianceLevel >= ClassFileConstants.JDK1_4;
boolean isCompliant15 = complianceLevel >= ClassFileConstants.JDK1_5;
boolean soureLevel18 = compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8;
ReferenceBinding classHierarchyStart = currentType;
MethodVerifier verifier = environment().methodVerifier();
while (currentType != null) {
unitScope.recordTypeReference(currentType);
currentType = (ReferenceBinding) currentType.capture(this, invocationSite == null ? 0 : invocationSite.sourceStart(), invocationSite == null ? 0 : invocationSite.sourceEnd());
MethodBinding[] currentMethods = currentType.getMethods(selector, argumentTypes.length);
int currentLength = currentMethods.length;
if (currentLength > 0) {
if (isCompliant14 && (receiverTypeIsInterface || found.size > 0)) {
nextMethod: for (int i = 0, l = currentLength; i < l; i++) {
MethodBinding currentMethod = currentMethods[i];
if (currentMethod == null) continue nextMethod;
if (receiverTypeIsInterface && !currentMethod.isPublic()) {
currentLength--;
currentMethods[i] = null;
continue nextMethod;
}
for (int j = 0, max = found.size; j < max; j++) {
MethodBinding matchingMethod = (MethodBinding) found.elementAt(j);
MethodBinding matchingOriginal = matchingMethod.original();
MethodBinding currentOriginal = matchingOriginal.findOriginalInheritedMethod(currentMethod);
if (currentOriginal != null && verifier.isParameterSubsignature(matchingOriginal, currentOriginal)) {
if (isCompliant15) {
if (matchingMethod.isBridge() && !currentMethod.isBridge())
continue nextMethod;
}
currentLength--;
currentMethods[i] = null;
continue nextMethod;
}
}
}
}
if (currentLength > 0) {
if (currentMethods.length == currentLength) {
found.addAll(currentMethods);
} else {
for (int i = 0, max = currentMethods.length; i < max; i++) {
MethodBinding currentMethod = currentMethods[i];
if (currentMethod != null)
found.add(currentMethod);
}
}
}
}
currentType = currentType.superclass();
}
int foundSize = found.size;
MethodBinding[] candidates = null;
int candidatesCount = 0;
MethodBinding problemMethod = null;
boolean searchForDefaultAbstractMethod = soureLevel18 || (isCompliant14 && ! receiverTypeIsInterface && (receiverType.isAbstract() || receiverType.isTypeVariable()));
if (foundSize > 0) {
for (int i = 0; i < foundSize; i++) {
MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
if (compatibleMethod != null) {
if (compatibleMethod.isValidBinding() || compatibleMethod.problemId() == ProblemReasons.InvocationTypeInferenceFailure) {
if (foundSize == 1 && compatibleMethod.canBeSeenBy(receiverType, invocationSite, this)) {
if (searchForDefaultAbstractMethod)
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, new MethodBinding [] {compatibleMethod});
unitScope.recordTypeReferences(compatibleMethod.thrownExceptions);
return compatibleMethod;
}
if (candidatesCount == 0)
candidates = new MethodBinding[foundSize];
candidates[candidatesCount++] = compatibleMethod;
} else if (problemMethod == null) {
problemMethod = compatibleMethod;
}
}
}
}
if (candidatesCount == 0) {
if (problemMethod != null) {
switch (problemMethod.problemId()) {
case ProblemReasons.TypeArgumentsForRawGenericMethod :
case ProblemReasons.TypeParameterArityMismatch :
return problemMethod;
}
}
MethodBinding interfaceMethod =
findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null);
if (interfaceMethod != null) {
if (soureLevel18 && foundSize > 0 && interfaceMethod.isVarargs() && interfaceMethod instanceof ParameterizedGenericMethodBinding) {
MethodBinding original = interfaceMethod.original();
for (int i = 0; i < foundSize; i++) {
MethodBinding classMethod = (MethodBinding) found.elementAt(i);
if (!classMethod.isAbstract()) {
MethodBinding substitute = verifier.computeSubstituteMethod(original, classMethod);
if (substitute != null && verifier.isSubstituteParameterSubsignature(classMethod, substitute))
return new ProblemMethodBinding(interfaceMethod, selector, argumentTypes, ProblemReasons.ApplicableMethodOverriddenByInapplicable);
}
}
}
return interfaceMethod;
}
if (found.size == 0) return null;
if (problemMethod != null) return problemMethod;
int bestArgMatches = -1;
MethodBinding bestGuess = (MethodBinding) found.elementAt(0);
int argLength = argumentTypes.length;
foundSize = found.size;
nextMethod : for (int i = 0; i < foundSize; i++) {
MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
TypeBinding[] params = methodBinding.parameters;
int paramLength = params.length;
int argMatches = 0;
next: for (int a = 0; a < argLength; a++) {
TypeBinding arg = argumentTypes[a];
for (int p = a == 0 ? 0 : a - 1; p < paramLength && p < a + 1; p++) {
if (TypeBinding.equalsEquals(params[p], arg)) {
argMatches++;
continue next;
}
}
}
if (argMatches < bestArgMatches)
continue nextMethod;
if (argMatches == bestArgMatches) {
int diff1 = paramLength < argLength ? 2 * (argLength - paramLength) : paramLength - argLength;
int bestLength = bestGuess.parameters.length;
int diff2 = bestLength < argLength ? 2 * (argLength - bestLength) : bestLength - argLength;
if (diff1 >= diff2)
continue nextMethod;
}
if (bestGuess != methodBinding && MethodVerifier.doesMethodOverride(bestGuess, methodBinding, this.environment()))
continue;
bestArgMatches = argMatches;
bestGuess = methodBinding;
}
return new ProblemMethodBinding(bestGuess, bestGuess.selector, argumentTypes, ProblemReasons.NotFound);
}
int visiblesCount = 0;
for (int i = 0; i < candidatesCount; i++) {
MethodBinding methodBinding = candidates[i];
if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
if (visiblesCount != i) {
candidates[i] = null;
candidates[visiblesCount] = methodBinding;
}
visiblesCount++;
}
}
switch (visiblesCount) {
case 0 :
MethodBinding interfaceMethod =
findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null);
if (interfaceMethod != null) return interfaceMethod;
MethodBinding candidate = candidates[0];
int reason = ProblemReasons.NotVisible;
if (candidate.isStatic() && candidate.declaringClass.isInterface() && !candidate.isPrivate()) {
if (soureLevel18)
reason = ProblemReasons.NonStaticOrAlienTypeReceiver;
else
reason = ProblemReasons.InterfaceMethodInvocationNotBelow18;
}
return new ProblemMethodBinding(candidate, candidate.selector, candidate.parameters, reason);
case 1 :
if (searchForDefaultAbstractMethod)
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, new MethodBinding [] { candidates[0] });
candidate = candidates[0];
if (candidate != null)
unitScope.recordTypeReferences(candidate.thrownExceptions);
return candidate;
default :
break;
}
if (complianceLevel <= ClassFileConstants.JDK1_3) {
ReferenceBinding declaringClass = candidates[0].declaringClass;
return !declaringClass.isInterface()
? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
: mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
}
if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
for (int i = 0; i < visiblesCount; i++) {
MethodBinding candidate = candidates[i];
if (candidate.isParameterizedGeneric())
candidate = candidate.shallowOriginal();
if (candidate.hasSubstitutedParameters()) {
for (int j = i + 1; j < visiblesCount; j++) {
MethodBinding otherCandidate = candidates[j];
if (otherCandidate.hasSubstitutedParameters()) {
if (otherCandidate == candidate
|| (TypeBinding.equalsEquals(candidate.declaringClass, otherCandidate.declaringClass) && candidate.areParametersEqual(otherCandidate))) {
return new ProblemMethodBinding(candidates[i], candidates[i].selector, candidates[i].parameters, ProblemReasons.Ambiguous);
}
}
}
}
}
}
if (inStaticContext) {
MethodBinding[] staticCandidates = new MethodBinding[visiblesCount];
int staticCount = 0;
for (int i = 0; i < visiblesCount; i++)
if (candidates[i].isStatic())
staticCandidates[staticCount++] = candidates[i];
if (staticCount == 1)
return staticCandidates[0];
if (staticCount > 1)
return mostSpecificMethodBinding(staticCandidates, staticCount, argumentTypes, invocationSite, receiverType);
}
if (visiblesCount != candidates.length)
System.arraycopy(candidates, 0, candidates = new MethodBinding[visiblesCount], 0, visiblesCount);
return searchForDefaultAbstractMethod ? findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, candidates)
: mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite, receiverType);
}
public MethodBinding findMethodForArray(
ArrayBinding receiverType,
char[] selector,
TypeBinding[] argumentTypes,
InvocationSite invocationSite) {
TypeBinding leafType = receiverType.leafComponentType();
if (leafType instanceof ReferenceBinding) {
if (!((ReferenceBinding) leafType).canBeSeenBy(this))
return new ProblemMethodBinding(selector, Binding.NO_PARAMETERS, (ReferenceBinding)leafType, ProblemReasons.ReceiverTypeNotVisible);
}
ReferenceBinding object = getJavaLangObject();
MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes, null);
if (methodBinding != null) {
if (argumentTypes == Binding.NO_PARAMETERS) {
switch (selector[0]) {
case 'c':
if (CharOperation.equals(selector, TypeConstants.CLONE)) {
return receiverType.getCloneMethod(methodBinding);
}
break;
case 'g':
if (CharOperation.equals(selector, TypeConstants.GETCLASS) && methodBinding.returnType.isParameterizedType()) {
return environment().createGetClassMethod(receiverType, methodBinding, this);
}
break;
}
}
if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
return methodBinding;
}
methodBinding = findMethod(object, selector, argumentTypes, invocationSite, false);
if (methodBinding == null)
return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NoSuchMethodOnArray);
return methodBinding;
}
protected void findMethodInSuperInterfaces(ReferenceBinding receiverType, char[] selector, ObjectVector found, List<TypeBinding> visitedTypes, InvocationSite invocationSite) {
ReferenceBinding currentType = receiverType;
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
ReferenceBinding[] interfacesToVisit = itsInterfaces;
int nextPosition = interfacesToVisit.length;
interfaces: for (int i = 0; i < nextPosition; i++) {
currentType = interfacesToVisit[i];
if (visitedTypes != null) {
TypeBinding uncaptured = currentType.uncapture(this);
for (TypeBinding visited : visitedTypes) {
if (uncaptured.isEquivalentTo(visited))
continue interfaces;
}
visitedTypes.add(uncaptured);
}
compilationUnitScope().recordTypeReference(currentType);
currentType = (ReferenceBinding) currentType.capture(this, invocationSite == null ? 0 : invocationSite.sourceStart(), invocationSite == null ? 0 : invocationSite.sourceEnd());
MethodBinding[] currentMethods = currentType.getMethods(selector);
if (currentMethods.length > 0) {
int foundSize = found.size;
next : for (int c = 0, l = currentMethods.length; c < l; c++) {
MethodBinding current = currentMethods[c];
if (!current.canBeSeenBy(receiverType, invocationSite, this)) continue next;
if (foundSize > 0) {
for (int f = 0; f < foundSize; f++)
if (current == found.elementAt(f)) continue next;
}
found.add(current);
}
}
if ((itsInterfaces = currentType.superInterfaces()) != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
}
}
public ReferenceBinding findType(
char[] typeName,
PackageBinding declarationPackage,
PackageBinding invocationPackage) {
compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
ReferenceBinding typeBinding = declarationPackage.getType(typeName, module());
if (typeBinding == null)
return null;
if (typeBinding.isValidBinding()) {
if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
return new ProblemReferenceBinding(new char[][]{typeName}, typeBinding, ProblemReasons.NotVisible);
}
return typeBinding;
}
public LocalVariableBinding findVariable(char[] variable) {
return null;
}
public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
CompilationUnitScope unitScope = compilationUnitScope();
LookupEnvironment env = unitScope.environment;
try {
env.missingClassFileLocation = invocationSite;
Binding binding = null;
FieldBinding problemField = null;
if ((mask & Binding.VARIABLE) != 0) {
boolean insideStaticContext = false;
boolean insideConstructorCall = false;
boolean insideTypeAnnotation = false;
FieldBinding foundField = null;
ProblemFieldBinding foundInsideProblem = null;
Scope scope = this;
MethodScope methodScope = null;
int depth = 0;
int foundDepth = 0;
boolean shouldTrackOuterLocals = false;
ReferenceBinding foundActualReceiverType = null;
done : while (true) {
switch (scope.kind) {
case METHOD_SCOPE :
methodScope = (MethodScope) scope;
insideStaticContext |= methodScope.isStatic;
insideConstructorCall |= methodScope.isConstructorCall;
insideTypeAnnotation = methodScope.insideTypeAnnotation;
case BLOCK_SCOPE :
LocalVariableBinding variableBinding = scope.findVariable(name);
if (variableBinding != null) {
if (foundField != null && foundField.isValidBinding())
return new ProblemFieldBinding(
foundField,
foundField.declaringClass,
name,
ProblemReasons.InheritedNameHidesEnclosingName);
if (depth > 0)
invocationSite.setDepth(depth);
if (shouldTrackOuterLocals) {
if (invocationSite instanceof NameReference) {
NameReference nameReference = (NameReference) invocationSite;
nameReference.bits |= ASTNode.IsCapturedOuterLocal;
} else if (invocationSite instanceof AbstractVariableDeclaration) {
AbstractVariableDeclaration variableDeclaration = (AbstractVariableDeclaration) invocationSite;
variableDeclaration.bits |= ASTNode.ShadowsOuterLocal;
}
}
return variableBinding;
}
break;
case CLASS_SCOPE :
ClassScope classScope = (ClassScope) scope;
ReferenceBinding receiverType = classScope.enclosingReceiverType();
if (!insideTypeAnnotation) {
FieldBinding fieldBinding = classScope.findField(receiverType, name, invocationSite, needResolve);
if (fieldBinding != null) {
if (fieldBinding.problemId() == ProblemReasons.Ambiguous) {
if (foundField == null || foundField.problemId() == ProblemReasons.NotVisible)
return fieldBinding;
return new ProblemFieldBinding(
foundField,
foundField.declaringClass,
name,
ProblemReasons.InheritedNameHidesEnclosingName);
}
ProblemFieldBinding insideProblem = null;
if (fieldBinding.isValidBinding()) {
if (!fieldBinding.isStatic()) {
if (insideConstructorCall) {
insideProblem =
new ProblemFieldBinding(
fieldBinding,
fieldBinding.declaringClass,
name,
ProblemReasons.NonStaticReferenceInConstructorInvocation);
} else if (insideStaticContext) {
insideProblem =
new ProblemFieldBinding(
fieldBinding,
fieldBinding.declaringClass,
name,
ProblemReasons.NonStaticReferenceInStaticContext);
}
}
if (TypeBinding.equalsEquals(receiverType, fieldBinding.declaringClass) || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
if (foundField == null || foundField.problemId() == ProblemReasons.NotVisible) {
if (depth > 0){
invocationSite.setDepth(depth);
invocationSite.setActualReceiverType(receiverType);
}
return insideProblem == null ? fieldBinding : insideProblem;
}
if (foundField.isValidBinding())
if (TypeBinding.notEquals(foundField.declaringClass, fieldBinding.declaringClass) &&
TypeBinding.notEquals(foundField.declaringClass, foundActualReceiverType))
return new ProblemFieldBinding(
foundField,
foundField.declaringClass,
name,
ProblemReasons.InheritedNameHidesEnclosingName);
}
}
if (foundField == null || (foundField.problemId() == ProblemReasons.NotVisible && fieldBinding.problemId() != ProblemReasons.NotVisible)) {
foundDepth = depth;
foundActualReceiverType = receiverType;
foundInsideProblem = insideProblem;
foundField = fieldBinding;
}
}
}
insideTypeAnnotation = false;
depth++;
shouldTrackOuterLocals = true;
insideStaticContext |= receiverType.isStatic();
MethodScope enclosingMethodScope = scope.methodScope();
insideConstructorCall = enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
break;
case COMPILATION_UNIT_SCOPE :
break done;
}
if (scope.isLambdaScope())
shouldTrackOuterLocals = true;
scope = scope.parent;
}
if (foundInsideProblem != null)
return foundInsideProblem;
if (foundField != null) {
if (foundField.isValidBinding()) {
if (foundDepth > 0) {
invocationSite.setDepth(foundDepth);
invocationSite.setActualReceiverType(foundActualReceiverType);
}
return foundField;
}
problemField = foundField;
foundField = null;
}
if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
unitScope.faultInImports();
ImportBinding[] imports = unitScope.imports;
if (imports != null) {
for (int i = 0, length = imports.length; i < length; i++) {
ImportBinding importBinding = imports[i];
if (importBinding.isStatic() && !importBinding.onDemand) {
if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
if (unitScope.resolveSingleImport(importBinding, Binding.TYPE | Binding.FIELD | Binding.METHOD) != null && importBinding.resolvedImport instanceof FieldBinding) {
foundField = (FieldBinding) importBinding.resolvedImport;
ImportReference importReference = importBinding.reference;
if (importReference != null && needResolve) {
importReference.bits |= ASTNode.Used;
}
invocationSite.setActualReceiverType(foundField.declaringClass);
if (foundField.isValidBinding()) {
return foundField;
}
if (problemField == null)
problemField = foundField;
}
}
}
}
boolean foundInImport = false;
for (int i = 0, length = imports.length; i < length; i++) {
ImportBinding importBinding = imports[i];
if (importBinding.isStatic() && importBinding.onDemand) {
Binding resolvedImport = importBinding.resolvedImport;
if (resolvedImport instanceof ReferenceBinding) {
FieldBinding temp = findField((ReferenceBinding) resolvedImport, name, invocationSite, needResolve);
if (temp != null) {
if (!temp.isValidBinding()) {
if (problemField == null)
problemField = temp;
} else if (temp.isStatic()) {
if (foundField == temp) continue;
ImportReference importReference = importBinding.reference;
if (importReference != null && needResolve) {
importReference.bits |= ASTNode.Used;
}
if (foundInImport)
return new ProblemFieldBinding(
foundField,
foundField.declaringClass,
name,
ProblemReasons.Ambiguous);
foundField = temp;
foundInImport = true;
}
}
}
}
}
if (foundField != null) {
invocationSite.setActualReceiverType(foundField.declaringClass);
return foundField;
}
}
}
}
if ((mask & Binding.TYPE) != 0) {
if ((binding = getBaseType(name)) != null)
return binding;
binding = getTypeOrPackage(name, (mask & Binding.PACKAGE) == 0 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE, needResolve);
if (binding.isValidBinding() || mask == Binding.TYPE)
return binding;
} else if ((mask & Binding.PACKAGE) != 0) {
unitScope.recordSimpleReference(name);
if ((binding = env.getTopLevelPackage(name)) != null)
return binding;
}
if (problemField != null) return problemField;
if (binding != null && binding.problemId() != ProblemReasons.NotFound)
return binding;
return new ProblemBinding(name, enclosingSourceType(), ProblemReasons.NotFound);
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
} finally {
env.missingClassFileLocation = null;
}
}
class MethodClashException extends RuntimeException {
private static final long serialVersionUID = -7996779527641476028L;
}
private MethodBinding getExactMethod(TypeBinding receiverType, TypeBinding type, char[] selector, InvocationSite invocationSite, MethodBinding candidate) {
if (type == null)
return null;
TypeBinding [] superInterfaces = type.superInterfaces();
TypeBinding [] typePlusSupertypes = new TypeBinding[2 + superInterfaces.length];
typePlusSupertypes[0] = type;
typePlusSupertypes[1] = type.superclass();
if (superInterfaces.length != 0)
System.arraycopy(superInterfaces, 0, typePlusSupertypes, 2, superInterfaces.length);
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordTypeReference(type);
type = type.capture(this, invocationSite.sourceStart(), invocationSite.sourceEnd());
for (int i = 0, typesLength = typePlusSupertypes.length; i < typesLength; i++) {
MethodBinding[] methods = i == 0 ? type.getMethods(selector) : new MethodBinding [] { getExactMethod(receiverType, typePlusSupertypes[i], selector, invocationSite, candidate) };
for (int j = 0, length = methods.length; j < length; j++) {
MethodBinding currentMethod = methods[j];
if (currentMethod == null || candidate == currentMethod)
continue;
if (i == 0 && (!currentMethod.canBeSeenBy(receiverType, invocationSite, this) || currentMethod.isSynthetic() || currentMethod.isBridge()))
continue;
if (candidate != null) {
if (!candidate.areParameterErasuresEqual(currentMethod))
throw new MethodClashException();
} else {
candidate = currentMethod;
}
}
}
return candidate;
}
public MethodBinding getExactMethod(TypeBinding receiverType, char[] selector, InvocationSite invocationSite) {
if (receiverType == null || !receiverType.isValidBinding() || receiverType.isBaseType())
return null;
TypeBinding currentType = receiverType;
if (currentType.isArrayType()) {
if (!currentType.leafComponentType().canBeSeenBy(this))
return null;
currentType = getJavaLangObject();
}
MethodBinding exactMethod = null;
try {
exactMethod = getExactMethod(receiverType, currentType, selector, invocationSite, null);
} catch (MethodClashException e) {
return null;
}
if (exactMethod == null || !exactMethod.canBeSeenBy(invocationSite, this))
return null;
final TypeBinding[] typeArguments = invocationSite.genericTypeArguments();
TypeVariableBinding[] typeVariables = exactMethod.typeVariables();
if (exactMethod.isVarargs() || (typeVariables != Binding.NO_TYPE_VARIABLES && (typeArguments == null || typeArguments.length != typeVariables.length)))
return null;
if (receiverType.isArrayType()) {
if (CharOperation.equals(selector, TypeConstants.CLONE))
return ((ArrayBinding) receiverType).getCloneMethod(exactMethod);
if (CharOperation.equals(selector, TypeConstants.GETCLASS))
return environment().createGetClassMethod(receiverType, exactMethod, this);
}
if (exactMethod.declaringClass.id == TypeIds.T_JavaLangObject
&& CharOperation.equals(selector, TypeConstants.GETCLASS)
&& exactMethod.returnType.isParameterizedType())
{
return environment().createGetClassMethod(receiverType, exactMethod, this);
}
if (typeVariables != Binding.NO_TYPE_VARIABLES)
return environment().createParameterizedGenericMethod(exactMethod, typeArguments);
return exactMethod;
}
public MethodBinding getExactConstructor(TypeBinding receiverType, InvocationSite invocationSite) {
if (receiverType == null || !receiverType.isValidBinding() || !receiverType.canBeInstantiated() || receiverType.isBaseType())
return null;
if (receiverType.isArrayType()) {
TypeBinding leafType = receiverType.leafComponentType();
if (!leafType.canBeSeenBy(this) || !leafType.isReifiable())
return null;
return new MethodBinding(ClassFileConstants.AccPublic | ClassFileConstants.AccSynthetic, TypeConstants.INIT,
receiverType,
new TypeBinding[] { TypeBinding.INT },
Binding.NO_EXCEPTIONS,
getJavaLangObject());
}
CompilationUnitScope unitScope = compilationUnitScope();
MethodBinding exactConstructor = null;
unitScope.recordTypeReference(receiverType);
MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
final TypeBinding[] genericTypeArguments = invocationSite.genericTypeArguments();
for (int i = 0, length = methods.length; i < length; i++) {
MethodBinding constructor = methods[i];
if (!constructor.canBeSeenBy(invocationSite, this))
continue;
if (constructor.isVarargs())
return null;
if (constructor.typeVariables() != Binding.NO_TYPE_VARIABLES && genericTypeArguments == null)
return null;
if (exactConstructor == null) {
exactConstructor = constructor;
} else {
return null;
}
}
if (exactConstructor != null) {
final TypeVariableBinding[] typeVariables = exactConstructor.typeVariables();
if (typeVariables != Binding.NO_TYPE_VARIABLES) {
if (typeVariables.length != genericTypeArguments.length)
return null;
exactConstructor = environment().createParameterizedGenericMethod(exactConstructor, genericTypeArguments);
}
}
return exactConstructor;
}
public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
MethodBinding method = getConstructor0(receiverType, argumentTypes, invocationSite);
if (method != null && method.isValidBinding() && method.isVarargs()) {
TypeBinding elementType = method.parameters[method.parameters.length - 1].leafComponentType();
if (elementType instanceof ReferenceBinding) {
if (!((ReferenceBinding) elementType).canBeSeenBy(this)) {
return new ProblemMethodBinding(method, method.selector, invocationSite.genericTypeArguments(), ProblemReasons.VarargsElementTypeNotVisible);
}
}
}
return method;
}
public MethodBinding getConstructor0(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
CompilationUnitScope unitScope = compilationUnitScope();
LookupEnvironment env = unitScope.environment;
try {
env.missingClassFileLocation = invocationSite;
unitScope.recordTypeReference(receiverType);
unitScope.recordTypeReferences(argumentTypes);
MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this)) {
if (invocationSite.genericTypeArguments() != null)
methodBinding = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
return methodBinding;
}
MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT, argumentTypes.length);
if (methods == Binding.NO_METHODS)
return new ProblemMethodBinding(
TypeConstants.INIT,
argumentTypes,
ProblemReasons.NotFound);
MethodBinding[] compatible = new MethodBinding[methods.length];
int compatibleIndex = 0;
MethodBinding problemMethod = null;
for (int i = 0, length = methods.length; i < length; i++) {
MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
if (compatibleMethod != null) {
if (compatibleMethod.isValidBinding())
compatible[compatibleIndex++] = compatibleMethod;
else if (problemMethod == null)
problemMethod = compatibleMethod;
}
}
if (compatibleIndex == 0) {
if (problemMethod == null)
return new ProblemMethodBinding(methods[0], TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound);
return problemMethod;
}
MethodBinding[] visible = new MethodBinding[compatibleIndex];
int visibleIndex = 0;
for (int i = 0; i < compatibleIndex; i++) {
MethodBinding method = compatible[i];
if (method.canBeSeenBy(invocationSite, this))
visible[visibleIndex++] = method;
}
if (visibleIndex == 1) {
return visible[0];
}
if (visibleIndex == 0)
return new ProblemMethodBinding(
compatible[0],
TypeConstants.INIT,
compatible[0].parameters,
ProblemReasons.NotVisible);
return mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, invocationSite, receiverType);
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
} finally {
env.missingClassFileLocation = null;
}
}
public final PackageBinding getCurrentPackage() {
Scope scope, unitScope = this;
while ((scope = unitScope.parent) != null)
unitScope = scope;
return ((CompilationUnitScope) unitScope).fPackage;
}
public int getDeclarationModifiers(){
switch(this.kind){
case Scope.BLOCK_SCOPE :
case Scope.METHOD_SCOPE :
MethodScope methodScope = methodScope();
if (!methodScope.isInsideInitializer()){
ReferenceContext ref = methodScope.referenceContext();
if (ref instanceof ModuleDeclaration) {
return ((ModuleDeclaration)ref).modifiers;
}
MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
if (context != null)
return context.modifiers;
} else {
SourceTypeBinding type = ((BlockScope) this).referenceType().binding;
if (methodScope.initializedField != null)
return methodScope.initializedField.modifiers;
if (type != null)
return type.modifiers;
}
break;
case Scope.CLASS_SCOPE :
ReferenceBinding context = ((ClassScope)this).referenceType().binding;
if (context != null)
return context.modifiers;
break;
}
return -1;
}
public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
LookupEnvironment env = environment();
try {
env.missingClassFileLocation = invocationSite;
FieldBinding field = findField(receiverType, fieldName, invocationSite, true );
if (field != null) return field;
return new ProblemFieldBinding(
receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
fieldName,
ProblemReasons.NotFound);
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
} finally {
env.missingClassFileLocation = null;
}
}
public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
boolean insideStaticContext = false;
boolean insideConstructorCall = false;
boolean insideTypeAnnotation = false;
MethodBinding foundMethod = null;
MethodBinding foundProblem = null;
boolean foundProblemVisible = false;
Scope scope = this;
MethodScope methodScope = null;
int depth = 0;
CompilerOptions options;
boolean inheritedHasPrecedence = (options = compilerOptions()).complianceLevel >= ClassFileConstants.JDK1_4;
done : while (true) {
switch (scope.kind) {
case METHOD_SCOPE :
methodScope = (MethodScope) scope;
insideStaticContext |= methodScope.isStatic;
insideConstructorCall |= methodScope.isConstructorCall;
insideTypeAnnotation = methodScope.insideTypeAnnotation;
break;
case CLASS_SCOPE :
ClassScope classScope = (ClassScope) scope;
ReferenceBinding receiverType = classScope.enclosingReceiverType();
if (!insideTypeAnnotation) {
MethodBinding methodBinding = classScope.findExactMethod(receiverType, selector, argumentTypes, invocationSite);
if (methodBinding == null)
methodBinding = classScope.findMethod(receiverType, selector, argumentTypes, invocationSite, false);
if (methodBinding != null) {
if (foundMethod == null) {
if (methodBinding.isValidBinding()) {
if (!methodBinding.isStatic() && (insideConstructorCall || insideStaticContext)) {
if (foundProblem != null && foundProblem.problemId() != ProblemReasons.NotVisible)
return foundProblem;
return new ProblemMethodBinding(
methodBinding,
methodBinding.selector,
methodBinding.parameters,
insideConstructorCall
? ProblemReasons.NonStaticReferenceInConstructorInvocation
: ProblemReasons.NonStaticReferenceInStaticContext);
} else if (!methodBinding.isStatic() && methodScope != null) {
tagAsAccessingEnclosingInstanceStateOf(receiverType, false );
}
if (inheritedHasPrecedence
|| TypeBinding.equalsEquals(receiverType, methodBinding.declaringClass)
|| (receiverType.getMethods(selector)) != Binding.NO_METHODS) {
if (foundProblemVisible) {
return foundProblem;
}
if (depth > 0) {
invocationSite.setDepth(depth);
invocationSite.setActualReceiverType(receiverType);
}
if (argumentTypes == Binding.NO_PARAMETERS
&& CharOperation.equals(selector, TypeConstants.GETCLASS)
&& methodBinding.returnType.isParameterizedType()) {
return environment().createGetClassMethod(receiverType, methodBinding, this);
}
return methodBinding;
}
if (foundProblem == null || foundProblem.problemId() == ProblemReasons.NotVisible) {
if (foundProblem != null) foundProblem = null;
if (depth > 0) {
invocationSite.setDepth(depth);
invocationSite.setActualReceiverType(receiverType);
}
foundMethod = methodBinding;
}
} else {
if (methodBinding.problemId() != ProblemReasons.NotVisible && methodBinding.problemId() != ProblemReasons.NotFound)
return methodBinding;
if (foundProblem == null) {
foundProblem = methodBinding;
}
if (! foundProblemVisible && methodBinding.problemId() == ProblemReasons.NotFound) {
MethodBinding closestMatch = ((ProblemMethodBinding) methodBinding).closestMatch;
if (closestMatch != null && closestMatch.canBeSeenBy(receiverType, invocationSite, this)) {
foundProblem = methodBinding;
foundProblemVisible = true;
}
}
}
} else {
if (methodBinding.problemId() == ProblemReasons.Ambiguous
|| (TypeBinding.notEquals(foundMethod.declaringClass, methodBinding.declaringClass)
&& (TypeBinding.equalsEquals(receiverType, methodBinding.declaringClass) || receiverType.getMethods(selector) != Binding.NO_METHODS)))
return new ProblemMethodBinding(
methodBinding,
selector,
argumentTypes,
ProblemReasons.InheritedNameHidesEnclosingName);
}
}
}
insideTypeAnnotation = false;
depth++;
insideStaticContext |= receiverType.isStatic();
MethodScope enclosingMethodScope = scope.methodScope();
insideConstructorCall = enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
break;
case COMPILATION_UNIT_SCOPE :
break done;
}
scope = scope.parent;
}
if (insideStaticContext && options.sourceLevel >= ClassFileConstants.JDK1_5) {
if (foundProblem != null) {
if (foundProblem.declaringClass != null && foundProblem.declaringClass.id == TypeIds.T_JavaLangObject)
return foundProblem;
if (foundProblem.problemId() == ProblemReasons.NotFound && foundProblemVisible) {
return foundProblem;
}
}
CompilationUnitScope unitScope = (CompilationUnitScope) scope;
unitScope.faultInImports();
ImportBinding[] imports = unitScope.imports;
if (imports != null) {
ObjectVector visible = null;
boolean skipOnDemand = false;
for (int i = 0, length = imports.length; i < length; i++) {
ImportBinding importBinding = imports[i];
if (importBinding.isStatic()) {
Binding resolvedImport = importBinding.resolvedImport;
MethodBinding possible = null;
if (importBinding.onDemand) {
if (!skipOnDemand && resolvedImport instanceof ReferenceBinding)
possible = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes, invocationSite, true);
} else {
if (resolvedImport instanceof MethodBinding) {
MethodBinding staticMethod = (MethodBinding) resolvedImport;
if (CharOperation.equals(staticMethod.selector, selector))
possible = findMethod(staticMethod.declaringClass, selector, argumentTypes, invocationSite, true);
} else if (resolvedImport instanceof FieldBinding) {
FieldBinding staticField = (FieldBinding) resolvedImport;
if (CharOperation.equals(staticField.name, selector)) {
char[][] importName = importBinding.reference.tokens;
TypeBinding referencedType = getType(importName, importName.length - 1);
if (referencedType != null)
possible = findMethod((ReferenceBinding) referencedType, selector, argumentTypes, invocationSite, true);
}
}
}
if (possible != null && possible != foundProblem) {
if (!possible.isValidBinding()) {
if (foundProblem == null)
foundProblem = possible;
} else if (possible.isStatic()) {
MethodBinding compatibleMethod = computeCompatibleMethod(possible, argumentTypes, invocationSite);
if (compatibleMethod != null) {
if (compatibleMethod.isValidBinding()) {
if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
if (!skipOnDemand && !importBinding.onDemand) {
visible = null;
skipOnDemand = true;
}
if (visible == null || !visible.contains(compatibleMethod)) {
ImportReference importReference = importBinding.reference;
if (importReference != null) {
importReference.bits |= ASTNode.Used;
}
if (visible == null)
visible = new ObjectVector(3);
visible.add(compatibleMethod);
}
} else if (foundProblem == null) {
foundProblem = new ProblemMethodBinding(compatibleMethod, selector, compatibleMethod.parameters, ProblemReasons.NotVisible);
}
} else if (foundProblem == null) {
foundProblem = compatibleMethod;
}
} else if (foundProblem == null) {
foundProblem = new ProblemMethodBinding(possible, selector, argumentTypes, ProblemReasons.NotFound);
}
}
}
}
}
if (visible != null) {
if (visible.size == 1) {
foundMethod = (MethodBinding) visible.elementAt(0);
} else {
MethodBinding[] temp = new MethodBinding[visible.size];
visible.copyInto(temp);
foundMethod = mostSpecificMethodBinding(temp, temp.length, argumentTypes, invocationSite, null);
}
}
}
}
if (foundMethod != null) {
invocationSite.setActualReceiverType(foundMethod.declaringClass);
return foundMethod;
}
if (foundProblem != null)
return foundProblem;
return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
}
public final ReferenceBinding getJavaIoSerializable() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_IO_SERIALIZABLE);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_IO_SERIALIZABLE, this);
}
public final ReferenceBinding getJavaLangAnnotationAnnotation() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ANNOTATION_ANNOTATION, this);
}
public final ReferenceBinding getJavaLangAssertionError() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ASSERTIONERROR);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ASSERTIONERROR, this);
}
public final ReferenceBinding getJavaLangClass() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLASS);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_CLASS, this);
}
public final ReferenceBinding getJavaLangCloneable() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLONEABLE);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_CLONEABLE, this);
}
public final ReferenceBinding getJavaLangClassNotFoundException() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_CLASSNOTFOUNDEXCEPTION);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_CLASSNOTFOUNDEXCEPTION, this);
}
public final ReferenceBinding getJavaLangNoSuchFieldError() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_NOSUCHFIELDERROR);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_NOSUCHFIELDERROR, this);
}
public final ReferenceBinding getJavaLangEnum() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ENUM);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ENUM, this);
}
public final ReferenceBinding getJavaLangInvokeLambdaMetafactory() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY, this);
}
public final ReferenceBinding getJavaLangInvokeSerializedLambda() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_INVOKE_SERIALIZEDLAMBDA);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_INVOKE_SERIALIZEDLAMBDA, this);
}
public final ReferenceBinding getJavaLangInvokeMethodHandlesLookup() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLES);
ReferenceBinding outerType = unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_INVOKE_METHODHANDLES, this);
return findDirectMemberType("Lookup".toCharArray(), outerType);
}
public final ReferenceBinding getJavaLangIterable() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ITERABLE);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ITERABLE, this);
}
public final ReferenceBinding getJavaLangObject() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_OBJECT);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, this);
}
public final ReferenceBinding getJavaLangString() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_STRING);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_STRING, this);
}
public final ReferenceBinding getJavaLangThrowable() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_THROWABLE);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_THROWABLE, this);
}
public final ReferenceBinding getJavaLangIllegalArgumentException() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_LANG_ILLEGALARGUMENTEXCEPTION);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_ILLEGALARGUMENTEXCEPTION, this);
}
public final ReferenceBinding getJavaUtilIterator() {
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(TypeConstants.JAVA_UTIL_ITERATOR);
return unitScope.environment.getResolvedJavaBaseType(TypeConstants.JAVA_UTIL_ITERATOR, this);
}
public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
ReferenceBinding memberType = findMemberType(typeName, enclosingType);
if (memberType != null) return memberType;
char[][] compoundName = new char[][] { typeName };
return new ProblemReferenceBinding(compoundName, null, ProblemReasons.NotFound);
}
public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
CompilationUnitScope unitScope = compilationUnitScope();
LookupEnvironment env = unitScope.environment;
try {
env.missingClassFileLocation = invocationSite;
switch (receiverType.kind()) {
case Binding.BASE_TYPE :
return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
case Binding.ARRAY_TYPE :
unitScope.recordTypeReference(receiverType);
return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
}
unitScope.recordTypeReference(receiverType);
ReferenceBinding currentType = (ReferenceBinding) receiverType;
if (!currentType.canBeSeenBy(this))
return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.ReceiverTypeNotVisible);
MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
if (methodBinding != null && methodBinding.isValidBinding())
return methodBinding;
methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite, false);
if (methodBinding == null)
return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
if (!methodBinding.isValidBinding())
return methodBinding;
if (argumentTypes == Binding.NO_PARAMETERS
&& CharOperation.equals(selector, TypeConstants.GETCLASS)
&& methodBinding.returnType.isParameterizedType()) {
return environment().createGetClassMethod(receiverType, methodBinding, this);
}
return methodBinding;
} catch (AbortCompilation e) {
e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
throw e;
} finally {
env.missingClassFileLocation = null;
}
}
public final Binding getPackage(char[][] compoundName) {
compilationUnitScope().recordQualifiedReference(compoundName);
Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE, true);
if (binding == null) {
char[][] qName = new char[][] { compoundName[0] };
return new ProblemReferenceBinding(qName, environment().createMissingType(null, compoundName), ProblemReasons.NotFound);
}
if (!binding.isValidBinding()) {
if (binding instanceof PackageBinding) {
char[][] qName = new char[][] { compoundName[0] };
return new ProblemReferenceBinding(qName, null , ProblemReasons.NotFound);
}
return problemType(compoundName, -1, binding);
}
if (!(binding instanceof PackageBinding)) return null;
int currentIndex = 1, length = compoundName.length;
PackageBinding packageBinding = (PackageBinding) binding;
while (currentIndex < length) {
binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<length);
if (binding == null) {
return problemType(compoundName, currentIndex, null);
}
if (!binding.isValidBinding() && binding.problemId() != ProblemReasons.Ambiguous)
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null,
binding.problemId());
if (!(binding instanceof PackageBinding))
return packageBinding;
packageBinding = (PackageBinding) binding;
}
return new ProblemReferenceBinding(compoundName, null , ProblemReasons.NotFound);
}
Binding problemType(char[][] compoundName, int currentIndex, Binding previousProblem) {
if (previousProblem != null && previousProblem.problemId() != ProblemReasons.NotFound)
return previousProblem;
LookupEnvironment environment = environment();
if (environment.useModuleSystem && module() != environment.UnNamedModule) {
ReferenceBinding notAccessibleType = environment.root.getType(compoundName, environment.UnNamedModule);
if (notAccessibleType != null && notAccessibleType.isValidBinding())
return new ProblemReferenceBinding(compoundName, notAccessibleType, ProblemReasons.NotAccessible);
}
return previousProblem != null
? previousProblem
: new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound);
}
public final Binding getOnlyPackage(char[][] compoundName) {
compilationUnitScope().recordQualifiedReference(compoundName);
Binding binding = getTypeOrPackage(compoundName[0], Binding.PACKAGE, true);
if (binding == null || !binding.isValidBinding()) {
char[][] qName = new char[][] { compoundName[0] };
return new ProblemReferenceBinding(qName, null , ProblemReasons.NotFound);
}
if (!(binding instanceof PackageBinding)) {
return null;
}
int currentIndex = 1, length = compoundName.length;
PackageBinding packageBinding = (PackageBinding) binding;
while (currentIndex < length) {
binding = packageBinding.getPackage(compoundName[currentIndex++], module());
if (binding == null) {
return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null , ProblemReasons.NotFound);
}
if (!binding.isValidBinding()) {
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null,
binding.problemId());
}
packageBinding = (PackageBinding) binding;
}
return packageBinding;
}
public final TypeBinding getType(char[] name) {
TypeBinding binding = getBaseType(name);
if (binding != null) return binding;
return (ReferenceBinding) getTypeOrPackage(name, Binding.TYPE, true);
}
public final TypeBinding getType(char[] name, PackageBinding packageBinding) {
if (packageBinding == null)
return getType(name);
Binding binding = packageBinding.getTypeOrPackage(name, module(), false);
if (binding == null) {
return new ProblemReferenceBinding(
CharOperation.arrayConcat(packageBinding.compoundName, name),
null,
ProblemReasons.NotFound);
}
if (!binding.isValidBinding()) {
return new ProblemReferenceBinding(
binding instanceof ReferenceBinding ? ((ReferenceBinding)binding).compoundName : CharOperation.arrayConcat(packageBinding.compoundName, name),
binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null,
binding.problemId());
}
ReferenceBinding typeBinding = (ReferenceBinding) binding;
if (!typeBinding.canBeSeenBy(this))
return new ProblemReferenceBinding(
typeBinding.compoundName,
typeBinding,
ProblemReasons.NotVisible);
return typeBinding;
}
public final TypeBinding getType(char[][] compoundName, int typeNameLength) {
if (typeNameLength == 1) {
TypeBinding binding = getBaseType(compoundName[0]);
if (binding != null) return binding;
}
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordQualifiedReference(compoundName);
Binding binding = getTypeOrPackage(compoundName[0], typeNameLength == 1 ? Binding.TYPE : Binding.TYPE | Binding.PACKAGE, true);
if (binding == null) {
char[][] qName = new char[][] { compoundName[0] };
return new ProblemReferenceBinding(qName, environment().createMissingType(compilationUnitScope().getCurrentPackage(), qName), ProblemReasons.NotFound);
}
if (!binding.isValidBinding()) {
if (binding instanceof PackageBinding) {
char[][] qName = new char[][] { compoundName[0] };
return new ProblemReferenceBinding(
qName,
environment().createMissingType(null, qName),
ProblemReasons.NotFound);
}
return (ReferenceBinding) binding;
}
int currentIndex = 1;
boolean checkVisibility = false;
if (binding instanceof PackageBinding) {
PackageBinding packageBinding = (PackageBinding) binding;
while (currentIndex < typeNameLength) {
binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<typeNameLength);
if (binding == null) {
char[][] qName = CharOperation.subarray(compoundName, 0, currentIndex);
return new ProblemReferenceBinding(
qName,
environment().createMissingType(packageBinding, qName),
ProblemReasons.NotFound);
}
if (!binding.isValidBinding())
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null,
binding.problemId());
if (!(binding instanceof PackageBinding))
break;
packageBinding = (PackageBinding) binding;
}
if (binding instanceof PackageBinding) {
char[][] qName = CharOperation.subarray(compoundName, 0, currentIndex);
return new ProblemReferenceBinding(
qName,
environment().createMissingType(null, qName),
ProblemReasons.NotFound);
}
checkVisibility = true;
}
ReferenceBinding typeBinding = (ReferenceBinding) binding;
unitScope.recordTypeReference(typeBinding);
if (checkVisibility)
if (!typeBinding.canBeSeenBy(this))
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
typeBinding,
ProblemReasons.NotVisible);
while (currentIndex < typeNameLength) {
typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
if (!typeBinding.isValidBinding()) {
if (typeBinding instanceof ProblemReferenceBinding) {
ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding;
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
problemBinding.closestReferenceMatch(),
typeBinding.problemId());
}
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
(ReferenceBinding)((ReferenceBinding)binding).closestMatch(),
typeBinding.problemId());
}
}
return typeBinding;
}
final Binding getTypeOrPackage(char[] name, int mask, boolean needResolve) {
Scope scope = this;
MethodScope methodScope = null;
ReferenceBinding foundType = null;
boolean insideStaticContext = false;
boolean insideTypeAnnotation = false;
if ((mask & Binding.TYPE) == 0) {
Scope next = scope;
while ((next = scope.parent) != null)
scope = next;
} else {
boolean inheritedHasPrecedence = compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
done : while (true) {
switch (scope.kind) {
case METHOD_SCOPE :
methodScope = (MethodScope) scope;
AbstractMethodDeclaration methodDecl = methodScope.referenceMethod();
if (methodDecl != null) {
if (methodDecl.binding != null) {
TypeVariableBinding typeVariable = methodDecl.binding.getTypeVariable(name);
if (typeVariable != null)
return typeVariable;
} else {
TypeParameter[] params = methodDecl.typeParameters();
for (int i = params == null ? 0 : params.length; --i >= 0;)
if (CharOperation.equals(params[i].name, name))
if (params[i].binding != null && params[i].binding.isValidBinding())
return params[i].binding;
}
}
insideStaticContext |= methodScope.isStatic;
insideTypeAnnotation = methodScope.insideTypeAnnotation;
case BLOCK_SCOPE :
ReferenceBinding localType = ((BlockScope) scope).findLocalType(name);
if (localType != null) {
if (foundType != null && TypeBinding.notEquals(foundType, localType))
return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
return localType;
}
break;
case CLASS_SCOPE :
SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
if (scope == this && (sourceType.tagBits & TagBits.TypeVariablesAreConnected) == 0) {
TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
if (typeVariable != null)
return typeVariable;
if (CharOperation.equals(name, sourceType.sourceName))
return sourceType;
insideStaticContext |= sourceType.isStatic();
break;
}
if (!insideTypeAnnotation) {
ReferenceBinding memberType = findMemberType(name, sourceType);
if (memberType != null) {
if (memberType.problemId() == ProblemReasons.Ambiguous) {
if (foundType == null || foundType.problemId() == ProblemReasons.NotVisible)
return memberType;
return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
}
if (memberType.isValidBinding()) {
if (TypeBinding.equalsEquals(sourceType, memberType.enclosingType()) || inheritedHasPrecedence) {
if (insideStaticContext && !memberType.isStatic() && sourceType.isGenericType())
return new ProblemReferenceBinding(new char[][]{name}, memberType, ProblemReasons.NonStaticReferenceInStaticContext);
if (foundType == null || (inheritedHasPrecedence && foundType.problemId() == ProblemReasons.NotVisible))
return memberType;
if (foundType.isValidBinding() && TypeBinding.notEquals(foundType, memberType))
return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
}
}
if (foundType == null || (foundType.problemId() == ProblemReasons.NotVisible && memberType.problemId() != ProblemReasons.NotVisible))
foundType = memberType;
}
}
TypeVariableBinding typeVariable = sourceType.getTypeVariable(name);
if (typeVariable != null) {
if (insideStaticContext)
return new ProblemReferenceBinding(new char[][]{name}, typeVariable, ProblemReasons.NonStaticReferenceInStaticContext);
return typeVariable;
}
insideStaticContext |= sourceType.isStatic();
insideTypeAnnotation = false;
if (CharOperation.equals(sourceType.sourceName, name)) {
if (foundType != null && TypeBinding.notEquals(foundType, sourceType) && foundType.problemId() != ProblemReasons.NotVisible)
return new ProblemReferenceBinding(new char[][]{name}, foundType, ProblemReasons.InheritedNameHidesEnclosingName);
return sourceType;
}
break;
case COMPILATION_UNIT_SCOPE :
break done;
}
scope = scope.parent;
}
if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible)
return foundType;
}
CompilationUnitScope unitScope = (CompilationUnitScope) scope;
HashtableOfObject typeOrPackageCache = unitScope.typeOrPackageCache;
if (typeOrPackageCache != null) {
Binding cachedBinding = (Binding) typeOrPackageCache.get(name);
if (cachedBinding != null) {
if (cachedBinding instanceof ImportBinding) {
ImportReference importReference = ((ImportBinding) cachedBinding).reference;
if (importReference != null) {
importReference.bits |= ASTNode.Used;
}
if (cachedBinding instanceof ImportConflictBinding)
typeOrPackageCache.put(name, cachedBinding = ((ImportConflictBinding) cachedBinding).conflictingTypeBinding);
else
typeOrPackageCache.put(name, cachedBinding = ((ImportBinding) cachedBinding).resolvedImport);
}
if ((mask & Binding.TYPE) != 0) {
if (foundType != null && foundType.problemId() != ProblemReasons.NotVisible && cachedBinding.problemId() != ProblemReasons.Ambiguous)
return foundType;
if (cachedBinding instanceof ReferenceBinding)
return cachedBinding;
}
if ((mask & Binding.PACKAGE) != 0 && cachedBinding instanceof PackageBinding)
return cachedBinding;
}
}
if ((mask & Binding.TYPE) != 0) {
ImportBinding[] imports = unitScope.imports;
if (imports != null && typeOrPackageCache == null) {
nextImport : for (int i = 0, length = imports.length; i < length; i++) {
ImportBinding importBinding = imports[i];
if (!importBinding.onDemand) {
if (CharOperation.equals(importBinding.compoundName[importBinding.compoundName.length - 1], name)) {
Binding resolvedImport = unitScope.resolveSingleImport(importBinding, Binding.TYPE);
if (resolvedImport == null) continue nextImport;
if (resolvedImport instanceof TypeBinding) {
ImportReference importReference = importBinding.reference;
if (importReference != null)
importReference.bits |= ASTNode.Used;
return resolvedImport;
}
}
}
}
}
PackageBinding currentPackage = unitScope.fPackage;
unitScope.recordReference(currentPackage.compoundName, name);
Binding binding = currentPackage.getTypeOrPackage(name, module(), false);
if (binding instanceof ReferenceBinding) {
ReferenceBinding referenceType = (ReferenceBinding) binding;
if ((referenceType.tagBits & TagBits.HasMissingType) == 0) {
if (typeOrPackageCache != null)
typeOrPackageCache.put(name, referenceType);
return referenceType;
}
}
if (imports != null) {
boolean foundInImport = false;
ReferenceBinding type = null;
for (int i = 0, length = imports.length; i < length; i++) {
ImportBinding someImport = imports[i];
if (someImport.onDemand) {
Binding resolvedImport = someImport.resolvedImport;
ReferenceBinding temp = null;
if (resolvedImport instanceof PackageBinding) {
temp = findType(name, (PackageBinding) resolvedImport, currentPackage);
} else if (someImport.isStatic()) {
temp = compilationUnitScope().findMemberType(name, (ReferenceBinding) resolvedImport);
if (temp != null && !temp.isStatic())
temp = null;
} else {
temp = compilationUnitScope().findDirectMemberType(name, (ReferenceBinding) resolvedImport);
}
if (TypeBinding.notEquals(temp, type) && temp != null) {
if (temp.isValidBinding()) {
ImportReference importReference = someImport.reference;
if (importReference != null) {
importReference.bits |= ASTNode.Used;
}
if (foundInImport) {
temp = new ProblemReferenceBinding(new char[][]{name}, type, ProblemReasons.Ambiguous);
if (typeOrPackageCache != null)
typeOrPackageCache.put(name, temp);
return temp;
}
type = temp;
foundInImport = true;
} else if (foundType == null) {
foundType = temp;
}
}
}
}
if (type != null) {
if (typeOrPackageCache != null)
typeOrPackageCache.put(name, type);
return type;
}
}
}
unitScope.recordSimpleReference(name);
if ((mask & Binding.PACKAGE) != 0) {
PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
if (packageBinding != null && (packageBinding.tagBits & TagBits.HasMissingType) == 0) {
if (typeOrPackageCache != null)
typeOrPackageCache.put(name, packageBinding);
return packageBinding;
}
}
if (foundType == null) {
char[][] qName = new char[][] { name };
ReferenceBinding closestMatch = null;
if ((mask & Binding.PACKAGE) != 0) {
if (needResolve) {
closestMatch = environment().createMissingType(unitScope.fPackage, qName);
}
} else {
PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
if (packageBinding == null || !packageBinding.isValidBinding()) {
if (needResolve) {
closestMatch = environment().createMissingType(unitScope.fPackage, qName);
}
}
}
foundType = new ProblemReferenceBinding(qName, closestMatch, ProblemReasons.NotFound);
if (typeOrPackageCache != null && (mask & Binding.PACKAGE) != 0) {
typeOrPackageCache.put(name, foundType);
}
} else if ((foundType.tagBits & TagBits.HasMissingType) != 0) {
char[][] qName = new char[][] { name };
foundType = new ProblemReferenceBinding(qName, foundType, ProblemReasons.NotFound);
if (typeOrPackageCache != null && (mask & Binding.PACKAGE) != 0)
typeOrPackageCache.put(name, foundType);
}
return foundType;
}
public final Binding getTypeOrPackage(char[][] compoundName) {
int nameLength = compoundName.length;
if (nameLength == 1) {
TypeBinding binding = getBaseType(compoundName[0]);
if (binding != null) return binding;
}
Binding binding = getTypeOrPackage(compoundName[0], Binding.TYPE | Binding.PACKAGE, true);
if (!binding.isValidBinding()) return binding;
int currentIndex = 1;
boolean checkVisibility = false;
if (binding instanceof PackageBinding) {
PackageBinding packageBinding = (PackageBinding) binding;
while (currentIndex < nameLength) {
binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++], module(), currentIndex<nameLength);
if (binding == null)
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
null,
ProblemReasons.NotFound);
if (!binding.isValidBinding())
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
binding instanceof ReferenceBinding ? (ReferenceBinding)((ReferenceBinding)binding).closestMatch() : null,
binding.problemId());
if (!(binding instanceof PackageBinding))
break;
packageBinding = (PackageBinding) binding;
}
if (binding instanceof PackageBinding) return binding;
checkVisibility = true;
}
ReferenceBinding typeBinding = (ReferenceBinding) binding;
ReferenceBinding qualifiedType = (ReferenceBinding) environment().convertToRawType(typeBinding, false );
if (checkVisibility)
if (!typeBinding.canBeSeenBy(this))
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
typeBinding,
ProblemReasons.NotVisible);
while (currentIndex < nameLength) {
typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
if (!typeBinding.isValidBinding())
return new ProblemReferenceBinding(
CharOperation.subarray(compoundName, 0, currentIndex),
(ReferenceBinding)typeBinding.closestMatch(),
typeBinding.problemId());
if (typeBinding.isGenericType()) {
qualifiedType = environment().createRawType(typeBinding, qualifiedType);
} else {
qualifiedType = environment().maybeCreateParameterizedType(typeBinding, qualifiedType);
}
}
return qualifiedType;
}
public boolean hasErasedCandidatesCollisions(TypeBinding one, TypeBinding two, Map invocations, ReferenceBinding type, ASTNode typeRef) {
invocations.clear();
TypeBinding[] mecs = minimalErasedCandidates(new TypeBinding[] {one, two}, invocations);
if (mecs != null) {
nextCandidate: for (int k = 0, max = mecs.length; k < max; k++) {
TypeBinding mec = mecs[k];
if (mec == null) continue nextCandidate;
Object value = invocations.get(mec);
if (value instanceof TypeBinding[]) {
TypeBinding[] invalidInvocations = (TypeBinding[]) value;
problemReporter().superinterfacesCollide(invalidInvocations[0].erasure(), typeRef, invalidInvocations[0], invalidInvocations[1]);
type.tagBits |= TagBits.HierarchyHasProblems;
return true;
}
}
}
return false;
}
public CaseStatement innermostSwitchCase() {
Scope scope = this;
do {
if (scope instanceof BlockScope)
return ((BlockScope) scope).enclosingCase;
scope = scope.parent;
} while (scope != null);
return null;
}
protected boolean isAcceptableMethod(MethodBinding one, MethodBinding two) {
TypeBinding[] oneParams = one.parameters;
TypeBinding[] twoParams = two.parameters;
int oneParamsLength = oneParams.length;
int twoParamsLength = twoParams.length;
if (oneParamsLength == twoParamsLength) {
boolean applyErasure = environment().globalOptions.sourceLevel < ClassFileConstants.JDK1_5;
next : for (int i = 0; i < oneParamsLength; i++) {
TypeBinding oneParam = applyErasure ? oneParams[i].erasure() : oneParams[i];
TypeBinding twoParam = applyErasure ? twoParams[i].erasure() : twoParams[i];
if (TypeBinding.equalsEquals(oneParam, twoParam) || oneParam.isCompatibleWith(twoParam)) {
if (two.declaringClass.isRawType()) continue next;
TypeBinding leafComponentType = two.original().parameters[i].leafComponentType();
TypeBinding originalTwoParam = applyErasure ? leafComponentType.erasure() : leafComponentType;
switch (originalTwoParam.kind()) {
case Binding.TYPE_PARAMETER :
if (((TypeVariableBinding) originalTwoParam).hasOnlyRawBounds())
continue next;
case Binding.WILDCARD_TYPE :
case Binding.INTERSECTION_TYPE:
case Binding.PARAMETERIZED_TYPE :
TypeBinding originalOneParam = one.original().parameters[i].leafComponentType();
switch (originalOneParam.kind()) {
case Binding.TYPE :
case Binding.GENERIC_TYPE :
TypeBinding inheritedTwoParam = oneParam.findSuperTypeOriginatingFrom(twoParam);
if (inheritedTwoParam == null || !inheritedTwoParam.leafComponentType().isRawType()) break;
return false;
case Binding.TYPE_PARAMETER :
if (!((TypeVariableBinding) originalOneParam).upperBound().isRawType()) break;
return false;
case Binding.RAW_TYPE:
return false;
}
}
} else {
if (i == oneParamsLength - 1 && one.isVarargs() && two.isVarargs()) {
TypeBinding oType = ((ArrayBinding) oneParam).elementsType();
TypeBinding eType = ((ArrayBinding) twoParam).elementsType();
if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && this.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7) {
if (TypeBinding.equalsEquals(oneParam, eType) || oneParam.isCompatibleWith(eType))
return true;
} else {
if (TypeBinding.equalsEquals(oType, eType) || oType.isCompatibleWith(eType))
return true;
}
}
return false;
}
}
return true;
}
if (one.isVarargs() && two.isVarargs()) {
if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && this.compilerOptions().complianceLevel < ClassFileConstants.JDK1_7 &&
oneParamsLength > twoParamsLength) {
if (((ArrayBinding) twoParams[twoParamsLength - 1]).elementsType().id != TypeIds.T_JavaLangObject)
return false;
}
for (int i = (oneParamsLength > twoParamsLength ? twoParamsLength : oneParamsLength) - 2; i >= 0; i--)
if (TypeBinding.notEquals(oneParams[i], twoParams[i]) && !oneParams[i].isCompatibleWith(twoParams[i]))
return false;
if (parameterCompatibilityLevel(one, twoParams, true) == NOT_COMPATIBLE
&& parameterCompatibilityLevel(two, oneParams, true) == VARARGS_COMPATIBLE)
return true;
}
return false;
}
public boolean isBoxingCompatibleWith(TypeBinding expressionType, TypeBinding targetType) {
LookupEnvironment environment = environment();
if (environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5 || expressionType.isBaseType() == targetType.isBaseType())
return false;
TypeBinding convertedType = environment.computeBoxingType(expressionType);
return TypeBinding.equalsEquals(convertedType, targetType) || convertedType.isCompatibleWith(targetType, this);
}
public final boolean isDefinedInField(FieldBinding field) {
Scope scope = this;
do {
if (scope instanceof MethodScope) {
MethodScope methodScope = (MethodScope) scope;
if (methodScope.initializedField == field) return true;
}
scope = scope.parent;
} while (scope != null);
return false;
}
public final boolean isDefinedInMethod(MethodBinding method) {
method = method.original();
Scope scope = this;
do {
if (scope instanceof MethodScope) {
ReferenceContext refContext = ((MethodScope) scope).referenceContext;
if (refContext instanceof AbstractMethodDeclaration)
if (((AbstractMethodDeclaration) refContext).binding == method)
return true;
}
scope = scope.parent;
} while (scope != null);
return false;
}
public final boolean isDefinedInSameUnit(ReferenceBinding type) {
ReferenceBinding enclosingType = type;
while ((type = enclosingType.enclosingType()) != null)
enclosingType = type;
Scope scope, unitScope = this;
while ((scope = unitScope.parent) != null)
unitScope = scope;
SourceTypeBinding[] topLevelTypes = ((CompilationUnitScope) unitScope).topLevelTypes;
for (int i = topLevelTypes.length; --i >= 0;)
if (TypeBinding.equalsEquals(topLevelTypes[i], enclosingType.original()))
return true;
return false;
}
public final boolean isDefinedInType(ReferenceBinding type) {
Scope scope = this;
do {
if (scope instanceof ClassScope)
if (TypeBinding.equalsEquals(((ClassScope) scope).referenceContext.binding, type))
return true;
scope = scope.parent;
} while (scope != null);
return false;
}
public boolean isInsideCase(CaseStatement caseStatement) {
Scope scope = this;
do {
switch (scope.kind) {
case Scope.BLOCK_SCOPE :
if (((BlockScope) scope).enclosingCase == caseStatement) {
return true;
}
}
scope = scope.parent;
} while (scope != null);
return false;
}
public boolean isInsideDeprecatedCode(){
switch(this.kind){
case Scope.BLOCK_SCOPE :
case Scope.METHOD_SCOPE :
MethodScope methodScope = methodScope();
if (!methodScope.isInsideInitializer()){
ReferenceContext referenceContext = methodScope.referenceContext();
if (referenceContext instanceof AbstractMethodDeclaration) {
MethodBinding context = ((AbstractMethodDeclaration) referenceContext).binding;
if (context != null && context.isViewedAsDeprecated())
return true;
} else if (referenceContext instanceof LambdaExpression) {
MethodBinding context = ((LambdaExpression) referenceContext).binding;
if (context != null && context.isViewedAsDeprecated())
return true;
} else if (referenceContext instanceof ModuleDeclaration) {
ModuleBinding context = ((ModuleDeclaration) referenceContext).binding;
return context != null && context.isDeprecated();
}
} else if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated()) {
return true;
}
SourceTypeBinding declaringType = ((BlockScope)this).referenceType().binding;
if (declaringType != null) {
declaringType.initializeDeprecatedAnnotationTagBits();
if (declaringType.isViewedAsDeprecated())
return true;
}
break;
case Scope.CLASS_SCOPE :
ReferenceBinding context = ((ClassScope)this).referenceType().binding;
if (context != null) {
context.initializeDeprecatedAnnotationTagBits();
if (context.isViewedAsDeprecated())
return true;
}
break;
case Scope.COMPILATION_UNIT_SCOPE :
CompilationUnitDeclaration unit = referenceCompilationUnit();
if (unit.types != null && unit.types.length > 0) {
SourceTypeBinding type = unit.types[0].binding;
if (type != null) {
type.initializeDeprecatedAnnotationTagBits();
if (type.isViewedAsDeprecated())
return true;
}
}
}
return false;
}
private boolean isOverriddenMethodGeneric(MethodBinding method) {
MethodVerifier verifier = environment().methodVerifier();
ReferenceBinding currentType = method.declaringClass.superclass();
while (currentType != null) {
MethodBinding[] currentMethods = currentType.getMethods(method.selector);
for (int i = 0, l = currentMethods.length; i < l; i++) {
MethodBinding currentMethod = currentMethods[i];
if (currentMethod != null && currentMethod.original().typeVariables != Binding.NO_TYPE_VARIABLES)
if (verifier.doesMethodOverride(method, currentMethod))
return true;
}
currentType = currentType.superclass();
}
return false;
}
public boolean isSubtypeOfRawType(TypeBinding paramType) {
TypeBinding t = paramType.leafComponentType();
if (t.isBaseType()) return false;
ReferenceBinding currentType = (ReferenceBinding) t;
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
do {
if (currentType.isRawType()) return true;
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
if (interfacesToVisit == null) {
interfacesToVisit = itsInterfaces;
nextPosition = interfacesToVisit.length;
} else {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
} while ((currentType = currentType.superclass()) != null);
for (int i = 0; i < nextPosition; i++) {
currentType = interfacesToVisit[i];
if (currentType.isRawType()) return true;
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null && itsInterfaces != Binding.NO_SUPERINTERFACES) {
int itsLength = itsInterfaces.length;
if (nextPosition + itsLength >= interfacesToVisit.length)
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
nextInterface : for (int a = 0; a < itsLength; a++) {
ReferenceBinding next = itsInterfaces[a];
for (int b = 0; b < nextPosition; b++)
if (TypeBinding.equalsEquals(next, interfacesToVisit[b])) continue nextInterface;
interfacesToVisit[nextPosition++] = next;
}
}
}
return false;
}
private TypeBinding leastContainingInvocation(TypeBinding mec, Object invocationData, ArrayList lubStack) {
if (invocationData == null) return mec;
if (invocationData instanceof TypeBinding) {
return (TypeBinding) invocationData;
}
TypeBinding[] invocations = (TypeBinding[]) invocationData;
int dim = mec.dimensions();
mec = mec.leafComponentType();
int argLength = mec.typeVariables().length;
if (argLength == 0) return mec;
TypeBinding[] bestArguments = new TypeBinding[argLength];
for (int i = 0, length = invocations.length; i < length; i++) {
TypeBinding invocation = invocations[i].leafComponentType();
switch (invocation.kind()) {
case Binding.GENERIC_TYPE :
TypeVariableBinding[] invocationVariables = invocation.typeVariables();
for (int j = 0; j < argLength; j++) {
TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], invocationVariables[j], (ReferenceBinding) mec, j, (ArrayList)lubStack.clone());
if (bestArgument == null) return null;
bestArguments[j] = bestArgument;
}
break;
case Binding.PARAMETERIZED_TYPE :
ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding)invocation;
for (int j = 0; j < argLength; j++) {
TypeBinding bestArgument = leastContainingTypeArgument(bestArguments[j], parameterizedType.arguments[j], (ReferenceBinding) mec, j, (ArrayList)lubStack.clone());
if (bestArgument == null) return null;
bestArguments[j] = bestArgument;
}
break;
case Binding.RAW_TYPE :
return dim == 0 ? invocation : environment().createArrayType(invocation, dim);
}
}
TypeBinding least = environment().createParameterizedType((ReferenceBinding) mec.erasure(), bestArguments, mec.enclosingType());
return dim == 0 ? least : environment().createArrayType(least, dim);
}
private TypeBinding leastContainingTypeArgument(TypeBinding u, TypeBinding v, ReferenceBinding genericType, int rank, ArrayList lubStack) {
if (u == null) return v;
if (TypeBinding.equalsEquals(u, v)) return u;
if (v.isWildcard()) {
WildcardBinding wildV = (WildcardBinding) v;
if (u.isWildcard()) {
WildcardBinding wildU = (WildcardBinding) u;
switch (wildU.boundKind) {
case Wildcard.EXTENDS :
switch(wildV.boundKind) {
case Wildcard.EXTENDS :
TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound,wildV.bound}, lubStack);
if (lub == null) return null;
if (TypeBinding.equalsEquals(lub, TypeBinding.INT)) return environment().createWildcard(genericType, rank, null, null , Wildcard.UNBOUND);
return environment().createWildcard(genericType, rank, lub, null , Wildcard.EXTENDS);
case Wildcard.SUPER :
if (TypeBinding.equalsEquals(wildU.bound, wildV.bound)) return wildU.bound;
return environment().createWildcard(genericType, rank, null, null , Wildcard.UNBOUND);
}
break;
case Wildcard.SUPER :
if (wildU.boundKind == Wildcard.SUPER) {
TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound,wildV.bound}, this, this.environment());
if (glb == null) return null;
return environment().createWildcard(genericType, rank, glb[0], null , Wildcard.SUPER);
}
}
} else {
switch (wildV.boundKind) {
case Wildcard.EXTENDS :
TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,wildV.bound}, lubStack);
if (lub == null) return null;
if (TypeBinding.equalsEquals(lub, TypeBinding.INT)) return environment().createWildcard(genericType, rank, null, null , Wildcard.UNBOUND);
return environment().createWildcard(genericType, rank, lub, null , Wildcard.EXTENDS);
case Wildcard.SUPER :
TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{u,wildV.bound}, this, this.environment());
if (glb == null) return null;
return environment().createWildcard(genericType, rank, glb[0], null , Wildcard.SUPER);
case Wildcard.UNBOUND :
}
}
} else if (u.isWildcard()) {
WildcardBinding wildU = (WildcardBinding) u;
switch (wildU.boundKind) {
case Wildcard.EXTENDS :
TypeBinding lub = lowerUpperBound(new TypeBinding[]{wildU.bound, v}, lubStack);
if (lub == null) return null;
if (TypeBinding.equalsEquals(lub, TypeBinding.INT)) return environment().createWildcard(genericType, rank, null, null , Wildcard.UNBOUND);
return environment().createWildcard(genericType, rank, lub, null , Wildcard.EXTENDS);
case Wildcard.SUPER :
TypeBinding[] glb = greaterLowerBound(new TypeBinding[]{wildU.bound, v}, this, this.environment());
if (glb == null) return null;
return environment().createWildcard(genericType, rank, glb[0], null , Wildcard.SUPER);
case Wildcard.UNBOUND :
}
}
TypeBinding lub = lowerUpperBound(new TypeBinding[]{u,v}, lubStack);
if (lub == null) return null;
if (TypeBinding.equalsEquals(lub, TypeBinding.INT)) return environment().createWildcard(genericType, rank, null, null , Wildcard.UNBOUND);
return environment().createWildcard(genericType, rank, lub, null , Wildcard.EXTENDS);
}
public TypeBinding lowerUpperBound(TypeBinding[] types) {
int typeLength = types.length;
if (typeLength == 1) {
TypeBinding type = types[0];
return type == null ? TypeBinding.VOID : type;
}
return lowerUpperBound(types, new ArrayList(1));
}
private TypeBinding lowerUpperBound(TypeBinding[] types, ArrayList lubStack) {
int typeLength = types.length;
if (typeLength == 1) {
TypeBinding type = types[0];
return type == null ? TypeBinding.VOID : type;
}
int stackLength = lubStack.size();
nextLubCheck: for (int i = 0; i < stackLength; i++) {
TypeBinding[] lubTypes = (TypeBinding[])lubStack.get(i);
int lubTypeLength = lubTypes.length;
if (lubTypeLength < typeLength) continue nextLubCheck;
nextTypeCheck: for (int j = 0; j < typeLength; j++) {
TypeBinding type = types[j];
if (type == null) continue nextTypeCheck;
for (int k = 0; k < lubTypeLength; k++) {
TypeBinding lubType = lubTypes[k];
if (lubType == null) continue;
if (TypeBinding.equalsEquals(lubType, type) || lubType.isEquivalentTo(type)) continue nextTypeCheck;
}
continue nextLubCheck;
}
return TypeBinding.INT;
}
lubStack.add(types);
Map invocations = new HashMap(1);
TypeBinding[] mecs = minimalErasedCandidates(types, invocations);
if (mecs == null) return null;
int length = mecs.length;
if (length == 0) return TypeBinding.VOID;
int count = 0;
TypeBinding firstBound = null;
int commonDim = -1;
for (int i = 0; i < length; i++) {
TypeBinding mec = mecs[i];
if (mec == null) continue;
mec = leastContainingInvocation(mec, invocations.get(mec), lubStack);
if (mec == null) return null;
int dim = mec.dimensions();
if (commonDim == -1) {
commonDim = dim;
} else if (dim != commonDim) {
return null;
}
if (firstBound == null && !mec.leafComponentType().isInterface()) firstBound = mec.leafComponentType();
mecs[count++] = mec;
}
switch (count) {
case 0 : return TypeBinding.VOID;
case 1 : return mecs[0];
case 2 :
if ((commonDim == 0 ? mecs[1].id : mecs[1].leafComponentType().id) == TypeIds.T_JavaLangObject) return mecs[0];
if ((commonDim == 0 ? mecs[0].id : mecs[0].leafComponentType().id) == TypeIds.T_JavaLangObject) return mecs[1];
}
TypeBinding[] otherBounds = new TypeBinding[count - 1];
int rank = 0;
for (int i = 0; i < count; i++) {
TypeBinding mec = commonDim == 0 ? mecs[i] : mecs[i].leafComponentType();
if (mec.isInterface()) {
otherBounds[rank++] = mec;
}
}
TypeBinding intersectionType;
if (environment().globalOptions.complianceLevel < ClassFileConstants.JDK1_8) {
intersectionType = environment().createWildcard(null, 0, firstBound, otherBounds, Wildcard.EXTENDS);
} else {
ReferenceBinding[] intersectingTypes = new ReferenceBinding[otherBounds.length+1];
intersectingTypes[0] = (ReferenceBinding) firstBound;
System.arraycopy(otherBounds, 0, intersectingTypes, 1, otherBounds.length);
intersectionType = environment().createIntersectionType18(intersectingTypes);
}
return commonDim == 0 ? intersectionType : environment().createArrayType(intersectionType, commonDim);
}
public final MethodScope methodScope() {
Scope scope = this;
do {
if (scope instanceof MethodScope)
return (MethodScope) scope;
scope = scope.parent;
} while (scope != null);
return null;
}
public final MethodScope namedMethodScope() {
Scope scope = this;
do {
if (scope instanceof MethodScope && !scope.isLambdaScope())
return (MethodScope) scope;
scope = scope.parent;
} while (scope != null);
return null;
}
protected TypeBinding[] minimalErasedCandidates(TypeBinding[] types, Map allInvocations) {
int length = types.length;
int indexOfFirst = -1, actualLength = 0;
for (int i = 0; i < length; i++) {
TypeBinding type = types[i];
if (type == TypeBinding.NULL)
types[i] = type = null;
if (type == null) continue;
if (type.isBaseType()) return null;
if (indexOfFirst < 0) indexOfFirst = i;
actualLength ++;
}
switch (actualLength) {
case 0: return Binding.NO_TYPES;
case 1: return types;
}
TypeBinding firstType = types[indexOfFirst];
if (firstType.isBaseType()) return null;
ArrayList typesToVisit = new ArrayList(5);
int dim = firstType.dimensions();
TypeBinding leafType = firstType.leafComponentType();
TypeBinding firstErasure;
switch(leafType.kind()) {
case Binding.PARAMETERIZED_TYPE :
case Binding.RAW_TYPE :
case Binding.ARRAY_TYPE :
firstErasure = firstType.erasure();
break;
default :
firstErasure = firstType;
break;
}
if (TypeBinding.notEquals(firstErasure, firstType)) {
allInvocations.put(firstErasure, firstType);
}
typesToVisit.add(firstType);
int max = 1;
ReferenceBinding currentType;
for (int i = 0; i < max; i++) {
TypeBinding typeToVisit = (TypeBinding) typesToVisit.get(i);
dim = typeToVisit.dimensions();
if (dim > 0) {
leafType = typeToVisit.leafComponentType();
switch(leafType.id) {
case TypeIds.T_JavaLangObject:
if (dim > 1) {
TypeBinding elementType = ((ArrayBinding)typeToVisit).elementsType();
if (!typesToVisit.contains(elementType)) {
typesToVisit.add(elementType);
max++;
}
continue;
}
case TypeIds.T_byte:
case TypeIds.T_short:
case TypeIds.T_char:
case TypeIds.T_boolean:
case TypeIds.T_int:
case TypeIds.T_long:
case TypeIds.T_float:
case TypeIds.T_double:
TypeBinding superType = getJavaIoSerializable();
if (!typesToVisit.contains(superType)) {
typesToVisit.add(superType);
max++;
}
superType = getJavaLangCloneable();
if (!typesToVisit.contains(superType)) {
typesToVisit.add(superType);
max++;
}
superType = getJavaLangObject();
if (!typesToVisit.contains(superType)) {
typesToVisit.add(superType);
max++;
}
continue;
default:
}
typeToVisit = leafType;
}
currentType = (ReferenceBinding) typeToVisit;
if (currentType.isCapture()) {
TypeBinding firstBound = ((CaptureBinding) currentType).firstBound;
if (firstBound != null && firstBound.isArrayType()) {
TypeBinding superType = dim == 0 ? firstBound : (TypeBinding)environment().createArrayType(firstBound, dim);
if (!typesToVisit.contains(superType)) {
typesToVisit.add(superType);
max++;
TypeBinding superTypeErasure = (firstBound.isTypeVariable() || firstBound.isWildcard() ) ? superType : superType.erasure();
if (TypeBinding.notEquals(superTypeErasure, superType)) {
allInvocations.put(superTypeErasure, superType);
}
}
continue;
}
}
ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
if (itsInterfaces != null) {
for (int j = 0, count = itsInterfaces.length; j < count; j++) {
TypeBinding itsInterface = itsInterfaces[j];
TypeBinding superType = dim == 0 ? itsInterface : (TypeBinding)environment().createArrayType(itsInterface, dim);
if (!typesToVisit.contains(superType)) {
typesToVisit.add(superType);
max++;
TypeBinding superTypeErasure = (itsInterface.isTypeVariable() || itsInterface.isWildcard() ) ? superType : superType.erasure();
if (TypeBinding.notEquals(superTypeErasure, superType)) {
allInvocations.put(superTypeErasure, superType);
}
}
}
}
TypeBinding itsSuperclass = currentType.superclass();
if (itsSuperclass != null) {
TypeBinding superType = dim == 0 ? itsSuperclass : (TypeBinding)environment().createArrayType(itsSuperclass, dim);
if (!typesToVisit.contains(superType)) {
typesToVisit.add(superType);
max++;
TypeBinding superTypeErasure = (itsSuperclass.isTypeVariable() || itsSuperclass.isWildcard() ) ? superType : superType.erasure();
if (TypeBinding.notEquals(superTypeErasure, superType)) {
allInvocations.put(superTypeErasure, superType);
}
}
}
}
int superLength = typesToVisit.size();
TypeBinding[] erasedSuperTypes = new TypeBinding[superLength];
int rank = 0;
for (Iterator iter = typesToVisit.iterator(); iter.hasNext();) {
TypeBinding type = (TypeBinding)iter.next();
leafType = type.leafComponentType();
erasedSuperTypes[rank++] = (leafType.isTypeVariable() || leafType.isWildcard() ) ? type : type.erasure();
}
int remaining = superLength;
nextOtherType: for (int i = indexOfFirst+1; i < length; i++) {
TypeBinding otherType = types[i];
if (otherType == null) continue nextOtherType;
if (otherType.isArrayType()) {
nextSuperType: for (int j = 0; j < superLength; j++) {
TypeBinding erasedSuperType = erasedSuperTypes[j];
if (erasedSuperType == null || TypeBinding.equalsEquals(erasedSuperType, otherType)) continue nextSuperType;
TypeBinding match;
if ((match = otherType.findSuperTypeOriginatingFrom(erasedSuperType)) == null) {
erasedSuperTypes[j] = null;
if (--remaining == 0) return null;
continue nextSuperType;
}
Object invocationData = allInvocations.get(erasedSuperType);
if (invocationData == null) {
allInvocations.put(erasedSuperType, match);
} else if (invocationData instanceof TypeBinding) {
if (TypeBinding.notEquals(match, (TypeBinding) invocationData)) {
TypeBinding[] someInvocations = { (TypeBinding) invocationData, match, };
allInvocations.put(erasedSuperType, someInvocations);
}
} else {
TypeBinding[] someInvocations = (TypeBinding[]) invocationData;
checkExisting: {
int invocLength = someInvocations.length;
for (int k = 0; k < invocLength; k++) {
if (TypeBinding.equalsEquals(someInvocations[k], match)) break checkExisting;
}
System.arraycopy(someInvocations, 0, someInvocations = new TypeBinding[invocLength+1], 0, invocLength);
allInvocations.put(erasedSuperType, someInvocations);
someInvocations[invocLength] = match;
}
}
}
continue nextOtherType;
}
nextSuperType: for (int j = 0; j < superLength; j++) {
TypeBinding erasedSuperType = erasedSuperTypes[j];
if (erasedSuperType == null) continue nextSuperType;
TypeBinding match;
if (TypeBinding.equalsEquals(erasedSuperType, otherType) || erasedSuperType.id == TypeIds.T_JavaLangObject && otherType.isInterface()) {
match = erasedSuperType;
} else {
if (erasedSuperType.isArrayType()) {
match = null;
} else {
match = otherType.findSuperTypeOriginatingFrom(erasedSuperType);
}
if (match == null) {
erasedSuperTypes[j] = null;
if (--remaining == 0) return null;
continue nextSuperType;
}
}
Object invocationData = allInvocations.get(erasedSuperType);
if (invocationData == null) {
allInvocations.put(erasedSuperType, match);
} else if (invocationData instanceof TypeBinding) {
if (TypeBinding.notEquals(match, (TypeBinding) invocationData)) {
TypeBinding[] someInvocations = { (TypeBinding) invocationData, match, };
allInvocations.put(erasedSuperType, someInvocations);
}
} else {
TypeBinding[] someInvocations = (TypeBinding[]) invocationData;
checkExisting: {
int invocLength = someInvocations.length;
for (int k = 0; k < invocLength; k++) {
if (TypeBinding.equalsEquals(someInvocations[k], match)) break checkExisting;
}
System.arraycopy(someInvocations, 0, someInvocations = new TypeBinding[invocLength+1], 0, invocLength);
allInvocations.put(erasedSuperType, someInvocations);
someInvocations[invocLength] = match;
}
}
}
}
if (remaining > 1) {
nextType: for (int i = 0; i < superLength; i++) {
TypeBinding erasedSuperType = erasedSuperTypes[i];
if (erasedSuperType == null) continue nextType;
nextOtherType: for (int j = 0; j < superLength; j++) {
if (i == j) continue nextOtherType;
TypeBinding otherType = erasedSuperTypes[j];
if (otherType == null) continue nextOtherType;
if (erasedSuperType instanceof ReferenceBinding) {
if (otherType.id == TypeIds.T_JavaLangObject && erasedSuperType.isInterface()) continue nextOtherType;
if (erasedSuperType.findSuperTypeOriginatingFrom(otherType) != null) {
erasedSuperTypes[j] = null;
remaining--;
}
} else if (erasedSuperType.isArrayType()) {
if (otherType.isArrayType()
&& otherType.leafComponentType().id == TypeIds.T_JavaLangObject
&& otherType.dimensions() == erasedSuperType.dimensions()
&& erasedSuperType.leafComponentType().isInterface()) continue nextOtherType;
if (erasedSuperType.findSuperTypeOriginatingFrom(otherType) != null) {
erasedSuperTypes[j] = null;
remaining--;
}
}
}
}
}
return erasedSuperTypes;
}
protected final MethodBinding mostSpecificClassMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
MethodBinding previous = null;
nextVisible : for (int i = 0; i < visibleSize; i++) {
MethodBinding method = visible[i];
if (previous != null && TypeBinding.notEquals(method.declaringClass, previous.declaringClass))
break;
if (!method.isStatic()) previous = method;
for (int j = 0; j < visibleSize; j++) {
if (i == j) continue;
if (!visible[j].areParametersCompatibleWith(method.parameters))
continue nextVisible;
}
compilationUnitScope().recordTypeReferences(method.thrownExceptions);
return method;
}
return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
}
protected final MethodBinding mostSpecificInterfaceMethodBinding(MethodBinding[] visible, int visibleSize, InvocationSite invocationSite) {
nextVisible : for (int i = 0; i < visibleSize; i++) {
MethodBinding method = visible[i];
for (int j = 0; j < visibleSize; j++) {
if (i == j) continue;
if (!visible[j].areParametersCompatibleWith(method.parameters))
continue nextVisible;
}
compilationUnitScope().recordTypeReferences(method.thrownExceptions);
return method;
}
return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
}
protected final MethodBinding mostSpecificMethodBinding(MethodBinding[] visible, int visibleSize, TypeBinding[] argumentTypes, final InvocationSite invocationSite, ReferenceBinding receiverType) {
boolean isJdk18 = compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8;
if (isJdk18 && invocationSite.checkingPotentialCompatibility()) {
if (visibleSize != visible.length)
System.arraycopy(visible, 0, visible = new MethodBinding[visibleSize], 0, visibleSize);
invocationSite.acceptPotentiallyCompatibleMethods(visible);
}
int[] compatibilityLevels = new int[visibleSize];
int compatibleCount = 0;
for (int i = 0; i < visibleSize; i++)
if ((compatibilityLevels[i] = parameterCompatibilityLevel(visible[i], argumentTypes, invocationSite)) != NOT_COMPATIBLE) {
if (i != compatibleCount) {
visible[compatibleCount] = visible[i];
compatibilityLevels[compatibleCount] = compatibilityLevels[i];
}
compatibleCount++;
}
if (compatibleCount == 0) {
return new ProblemMethodBinding(visible[0].selector, argumentTypes, ProblemReasons.NotFound);
} else if (compatibleCount == 1) {
MethodBinding candidate = visible[0];
if (candidate != null)
compilationUnitScope().recordTypeReferences(candidate.thrownExceptions);
return candidate;
}
if (compatibleCount != visibleSize) {
System.arraycopy(visible, 0, visible = new MethodBinding[visibleSize = compatibleCount], 0, compatibleCount);
System.arraycopy(compatibilityLevels, 0, compatibilityLevels = new int[compatibleCount], 0, compatibleCount);
}
MethodBinding[] moreSpecific = new MethodBinding[visibleSize];
if (isJdk18) {
int count = 0;
nextJ: for (int j = 0; j < visibleSize; j++) {
MethodBinding mbj = visible[j].genericMethod();
final TypeBinding[] mbjParameters = mbj.parameters;
int levelj = compatibilityLevels[j];
nextK: for (int k = 0; k < visibleSize; k++) {
if (j == k) continue;
int levelk = compatibilityLevels[k];
if (levelj > -1 && levelk > -1 && levelj != levelk) {
if (levelj < levelk)
continue nextK;
else
continue nextJ;
}
MethodBinding mbk = visible[k].genericMethod();
final TypeBinding[] mbkParameters = mbk.parameters;
if (((invocationSite instanceof Invocation) || (invocationSite instanceof ReferenceExpression))
&& mbk.typeVariables() != Binding.NO_TYPE_VARIABLES)
{
Expression[] expressions = null;
if (invocationSite instanceof Invocation) {
expressions = ((Invocation)invocationSite).arguments();
} else {
expressions = ((ReferenceExpression)invocationSite).createPseudoExpressions(argumentTypes);
}
InferenceContext18 ic18 = new InferenceContext18(this, expressions, null, null);
if (!ic18.isMoreSpecificThan(mbj, mbk, levelj == VARARGS_COMPATIBLE, levelk == VARARGS_COMPATIBLE)) {
continue nextJ;
}
} else {
for (int i = 0, length = argumentTypes.length; i < length; i++) {
TypeBinding argumentType = argumentTypes[i];
TypeBinding s = InferenceContext18.getParameter(mbjParameters, i, levelj == VARARGS_COMPATIBLE);
TypeBinding t = InferenceContext18.getParameter(mbkParameters, i, levelk == VARARGS_COMPATIBLE);
if (TypeBinding.equalsEquals(s, t))
continue;
if (!argumentType.sIsMoreSpecific(s,t, this)) {
continue nextJ;
}
}
if (levelj == VARARGS_COMPATIBLE && levelk == VARARGS_COMPATIBLE) {
TypeBinding s = InferenceContext18.getParameter(mbjParameters, argumentTypes.length, true);
TypeBinding t = InferenceContext18.getParameter(mbkParameters, argumentTypes.length, true);
if (TypeBinding.notEquals(s, t) && t.isSubtypeOf(s, false))
continue nextJ;
}
}
}
moreSpecific[count++] = visible[j];
}
if (count == 0) {
return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
} else if (count == 1) {
MethodBinding candidate = moreSpecific[0];
if (candidate != null)
compilationUnitScope().recordTypeReferences(candidate.thrownExceptions);
return candidate;
} else {
visibleSize = count;
}
} else {
InvocationSite tieBreakInvocationSite = new InvocationSite() {
@Override
public TypeBinding[] genericTypeArguments() { return null; }
@Override
public boolean isSuperAccess() { return invocationSite.isSuperAccess(); }
@Override
public boolean isTypeAccess() { return invocationSite.isTypeAccess(); }
@Override
public void setActualReceiverType(ReferenceBinding actualReceiverType) { }
@Override
public void setDepth(int depth) { }
@Override
public void setFieldIndex(int depth) { }
@Override
public int sourceStart() { return invocationSite.sourceStart(); }
@Override
public int sourceEnd() { return invocationSite.sourceStart(); }
@Override
public TypeBinding invocationTargetType() { return invocationSite.invocationTargetType(); }
@Override
public boolean receiverIsImplicitThis() { return invocationSite.receiverIsImplicitThis();}
@Override
public InferenceContext18 freshInferenceContext(Scope scope) { return null; }
@Override
public ExpressionContext getExpressionContext() { return ExpressionContext.VANILLA_CONTEXT; }
@Override
public boolean isQualifiedSuper() { return invocationSite.isQualifiedSuper(); }
@Override
public boolean checkingPotentialCompatibility() { return false; }
@Override
public void acceptPotentiallyCompatibleMethods(MethodBinding[] methods) {}
};
int count = 0;
for (int level = 0, max = VARARGS_COMPATIBLE; level <= max; level++) {
nextVisible : for (int i = 0; i < visibleSize; i++) {
if (compatibilityLevels[i] != level) continue nextVisible;
max = level;
MethodBinding current = visible[i];
MethodBinding original = current.original();
MethodBinding tiebreakMethod = current.tiebreakMethod();
for (int j = 0; j < visibleSize; j++) {
if (i == j || compatibilityLevels[j] != level) continue;
MethodBinding next = visible[j];
if (original == next.original()) {
compatibilityLevels[j] = -1;
continue;
}
MethodBinding methodToTest = next;
if (next instanceof ParameterizedGenericMethodBinding) {
ParameterizedGenericMethodBinding pNext = (ParameterizedGenericMethodBinding) next;
if (pNext.isRaw && !pNext.isStatic()) {
} else {
methodToTest = pNext.originalMethod;
}
}
MethodBinding acceptable = computeCompatibleMethod(methodToTest, tiebreakMethod.parameters,
tieBreakInvocationSite, level == VARARGS_COMPATIBLE);
if (acceptable == null || !acceptable.isValidBinding())
continue nextVisible;
if (!isAcceptableMethod(tiebreakMethod, acceptable))
continue nextVisible;
if (current.isBridge() && !next.isBridge())
if (tiebreakMethod.areParametersEqual(acceptable))
continue nextVisible;
}
moreSpecific[i] = current;
count++;
}
}
if (count == 1) {
for (int i = 0; i < visibleSize; i++) {
if (moreSpecific[i] != null) {
MethodBinding candidate = visible[i];
if (candidate != null)
compilationUnitScope().recordTypeReferences(candidate.thrownExceptions);
return candidate;
}
}
} else if (count == 0) {
return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
}
}
if (receiverType != null)
receiverType = receiverType instanceof CaptureBinding ? receiverType : (ReferenceBinding) receiverType.erasure();
nextSpecific : for (int i = 0; i < visibleSize; i++) {
MethodBinding current = moreSpecific[i];
if (current != null) {
ReferenceBinding[] mostSpecificExceptions = null;
MethodBinding original = current.original();
boolean shouldIntersectExceptions = original.declaringClass.isAbstract() && original.thrownExceptions != Binding.NO_EXCEPTIONS;
for (int j = 0; j < visibleSize; j++) {
MethodBinding next = moreSpecific[j];
if (next == null || i == j) continue;
MethodBinding original2 = next.original();
if (TypeBinding.equalsEquals(original.declaringClass, original2.declaringClass))
break nextSpecific;
if (!original.isAbstract()) {
if (original2.isAbstract() || original2.isDefaultMethod())
continue;
original2 = original.findOriginalInheritedMethod(original2);
if (original2 == null)
continue nextSpecific;
if (current.hasSubstitutedParameters() || original.typeVariables != Binding.NO_TYPE_VARIABLES) {
if (!environment().methodVerifier().isParameterSubsignature(original, original2))
continue nextSpecific;
}
} else if (receiverType != null) {
TypeBinding superType = receiverType.findSuperTypeOriginatingFrom(original.declaringClass.erasure());
if (TypeBinding.equalsEquals(original.declaringClass, superType) || !(superType instanceof ReferenceBinding)) {
} else {
MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(original.selector, argumentTypes.length);
for (int m = 0, l = superMethods.length; m < l; m++) {
if (superMethods[m].original() == original) {
original = superMethods[m];
break;
}
}
}
superType = receiverType.findSuperTypeOriginatingFrom(original2.declaringClass.erasure());
if (TypeBinding.equalsEquals(original2.declaringClass, superType) || !(superType instanceof ReferenceBinding)) {
} else {
MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(original2.selector, argumentTypes.length);
for (int m = 0, l = superMethods.length; m < l; m++) {
if (superMethods[m].original() == original2) {
original2 = superMethods[m];
break;
}
}
}
if (original.typeVariables != Binding.NO_TYPE_VARIABLES)
original2 = original.computeSubstitutedMethod(original2, environment());
if (original2 == null || !original.areParameterErasuresEqual(original2))
continue nextSpecific;
if (TypeBinding.notEquals(original.returnType, original2.returnType)) {
if (next.original().typeVariables != Binding.NO_TYPE_VARIABLES) {
if (original.returnType.erasure().findSuperTypeOriginatingFrom(original2.returnType.erasure()) == null)
continue nextSpecific;
} else if (!current.returnType.isCompatibleWith(next.returnType)) {
continue nextSpecific;
}
}
if (shouldIntersectExceptions && original2.declaringClass.isInterface()) {
if (current.thrownExceptions != next.thrownExceptions) {
if (next.thrownExceptions == Binding.NO_EXCEPTIONS) {
mostSpecificExceptions = Binding.NO_EXCEPTIONS;
} else {
if (mostSpecificExceptions == null) {
mostSpecificExceptions = current.thrownExceptions;
}
int mostSpecificLength = mostSpecificExceptions.length;
ReferenceBinding[] nextExceptions = getFilteredExceptions(next);
int nextLength = nextExceptions.length;
SimpleSet temp = new SimpleSet(mostSpecificLength);
boolean changed = false;
nextException : for (int t = 0; t < mostSpecificLength; t++) {
ReferenceBinding exception = mostSpecificExceptions[t];
for (int s = 0; s < nextLength; s++) {
ReferenceBinding nextException = nextExceptions[s];
if (exception.isCompatibleWith(nextException)) {
temp.add(exception);
continue nextException;
} else if (nextException.isCompatibleWith(exception)) {
temp.add(nextException);
changed = true;
continue nextException;
} else {
changed = true;
}
}
}
if (changed) {
mostSpecificExceptions = temp.elementSize == 0 ? Binding.NO_EXCEPTIONS : new ReferenceBinding[temp.elementSize];
temp.asArray(mostSpecificExceptions);
}
}
}
}
}
}
if (mostSpecificExceptions != null && mostSpecificExceptions != current.thrownExceptions) {
return new MostSpecificExceptionMethodBinding(current, mostSpecificExceptions);
}
return current;
}
}
return new ProblemMethodBinding(visible[0], visible[0].selector, visible[0].parameters, ProblemReasons.Ambiguous);
}
private ReferenceBinding[] getFilteredExceptions(MethodBinding method) {
ReferenceBinding[] allExceptions = method.thrownExceptions;
int length = allExceptions.length;
if (length < 2) return allExceptions;
ReferenceBinding[] filteredExceptions = new ReferenceBinding[length];
int count = 0;
currents: for (int i = 0; i < length; i++) {
ReferenceBinding currentException = allExceptions[i];
for (int j = 0; j < length; j++) {
if (i == j) continue;
if (TypeBinding.equalsEquals(currentException, allExceptions[j])) {
if (i < j)
break;
else
continue currents;
}
if (currentException.isCompatibleWith(allExceptions[j])) {
continue currents;
}
}
filteredExceptions[count++] = currentException;
}
if (count != length) {
ReferenceBinding[] tmp = new ReferenceBinding[count];
System.arraycopy(filteredExceptions, 0, tmp, 0, count);
return tmp;
}
return allExceptions;
}
public final ClassScope outerMostClassScope() {
ClassScope lastClassScope = null;
Scope scope = this;
do {
if (scope instanceof ClassScope)
lastClassScope = (ClassScope) scope;
scope = scope.parent;
} while (scope != null);
return lastClassScope;
}
public final MethodScope outerMostMethodScope() {
MethodScope lastMethodScope = null;
Scope scope = this;
do {
if (scope instanceof MethodScope)
lastMethodScope = (MethodScope) scope;
scope = scope.parent;
} while (scope != null);
return lastMethodScope;
}
public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments, InvocationSite site) {
if (method.problemId() == ProblemReasons.InvocationTypeInferenceFailure) {
method = ((ProblemMethodBinding)method).closestMatch;
if (method == null)
return NOT_COMPATIBLE;
}
if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8 && method instanceof ParameterizedGenericMethodBinding) {
int inferenceKind = InferenceContext18.CHECK_UNKNOWN;
InferenceContext18 context = null;
if (site instanceof Invocation) {
Invocation invocation = (Invocation) site;
context = invocation.getInferenceContext((ParameterizedGenericMethodBinding) method);
if (context != null)
inferenceKind = context.inferenceKind;
} else if (site instanceof ReferenceExpression) {
ReferenceExpression referenceExpression = (ReferenceExpression) site;
context = referenceExpression.getInferenceContext((ParameterizedGenericMethodBinding) method);
if (context != null)
inferenceKind = context.inferenceKind;
}
if (site instanceof Invocation && context != null && context.stepCompleted >= InferenceContext18.TYPE_INFERRED) {
for (int i = 0, length = arguments.length; i < length; i++) {
TypeBinding argument = arguments[i];
if (!argument.isFunctionalType())
continue;
TypeBinding parameter = InferenceContext18.getParameter(method.parameters, i, context.isVarArgs());
if (!argument.isCompatibleWith(parameter, this)) {
if (argument.isPolyType()) {
parameter = InferenceContext18.getParameter(method.original().parameters, i, context.isVarArgs());
if (!((PolyTypeBinding)argument).expression.isPertinentToApplicability(parameter, method))
continue;
}
return NOT_COMPATIBLE;
}
}
}
switch (inferenceKind) {
case InferenceContext18.CHECK_STRICT:
return COMPATIBLE;
case InferenceContext18.CHECK_LOOSE:
return AUTOBOX_COMPATIBLE;
case InferenceContext18.CHECK_VARARG:
return VARARGS_COMPATIBLE;
default:
break;
}
}
return parameterCompatibilityLevel(method, arguments, false);
}
public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments) {
return parameterCompatibilityLevel(method, arguments, false);
}
public int parameterCompatibilityLevel(MethodBinding method, TypeBinding[] arguments, boolean tiebreakingVarargsMethods) {
TypeBinding[] parameters = method.parameters;
int paramLength = parameters.length;
int argLength = arguments.length;
CompilerOptions compilerOptions = compilerOptions();
if (compilerOptions.sourceLevel < ClassFileConstants.JDK1_5) {
if (paramLength != argLength)
return NOT_COMPATIBLE;
for (int i = 0; i < argLength; i++) {
TypeBinding param = parameters[i];
TypeBinding arg = arguments[i];
if (TypeBinding.notEquals(arg, param) && !arg.isCompatibleWith(param.erasure(), this))
return NOT_COMPATIBLE;
}
return COMPATIBLE;
}
if (tiebreakingVarargsMethods) {
if (CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation && compilerOptions.complianceLevel < ClassFileConstants.JDK1_7) {
tiebreakingVarargsMethods = false;
}
}
int level = COMPATIBLE;
int lastIndex = argLength;
LookupEnvironment env = environment();
if (method.isVarargs()) {
lastIndex = paramLength - 1;
if (paramLength == argLength) {
TypeBinding param = parameters[lastIndex];
TypeBinding arg = arguments[lastIndex];
if (TypeBinding.notEquals(param, arg)) {
level = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method);
if (level == NOT_COMPATIBLE) {
param = ((ArrayBinding) param).elementsType();
if (tiebreakingVarargsMethods) {
arg = ((ArrayBinding) arg).elementsType();
}
if (parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method) == NOT_COMPATIBLE)
return NOT_COMPATIBLE;
level = VARARGS_COMPATIBLE;
}
}
} else {
if (paramLength < argLength) {
TypeBinding param = ((ArrayBinding) parameters[lastIndex]).elementsType();
for (int i = lastIndex; i < argLength; i++) {
TypeBinding arg = (tiebreakingVarargsMethods && (i == (argLength - 1))) ? ((ArrayBinding)arguments[i]).elementsType() : arguments[i];
if (TypeBinding.notEquals(param, arg) && parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method) == NOT_COMPATIBLE)
return NOT_COMPATIBLE;
}
} else if (lastIndex != argLength) {
return NOT_COMPATIBLE;
}
level = VARARGS_COMPATIBLE;
}
} else if (paramLength != argLength) {
return NOT_COMPATIBLE;
}
for (int i = 0; i < lastIndex; i++) {
TypeBinding param = parameters[i];
TypeBinding arg = (tiebreakingVarargsMethods && (i == (argLength - 1))) ? ((ArrayBinding)arguments[i]).elementsType() : arguments[i];
if (TypeBinding.notEquals(arg,param)) {
int newLevel = parameterCompatibilityLevel(arg, param, env, tiebreakingVarargsMethods, method);
if (newLevel == NOT_COMPATIBLE)
return NOT_COMPATIBLE;
if (newLevel > level)
level = newLevel;
}
}
return level;
}
public int parameterCompatibilityLevel(TypeBinding arg, TypeBinding param) {
if (TypeBinding.equalsEquals(arg, param))
return COMPATIBLE;
if (arg == null || param == null)
return NOT_COMPATIBLE;
if (arg.isCompatibleWith(param, this))
return COMPATIBLE;
if (arg.kind() == Binding.POLY_TYPE || (arg.isBaseType() != param.isBaseType())) {
TypeBinding convertedType = environment().computeBoxingType(arg);
if (TypeBinding.equalsEquals(convertedType, param) || convertedType.isCompatibleWith(param, this))
return AUTOBOX_COMPATIBLE;
}
return NOT_COMPATIBLE;
}
private int parameterCompatibilityLevel(TypeBinding arg, TypeBinding param, LookupEnvironment env, boolean tieBreakingVarargsMethods, MethodBinding method) {
if (arg == null || param == null)
return NOT_COMPATIBLE;
if (arg instanceof PolyTypeBinding && !((PolyTypeBinding) arg).expression.isPertinentToApplicability(param, method)) {
if (arg.isPotentiallyCompatibleWith(param, this))
return COMPATIBLE;
} else if (arg.isCompatibleWith(param, this)) {
return COMPATIBLE;
}
if (tieBreakingVarargsMethods && (this.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_7 || !CompilerOptions.tolerateIllegalAmbiguousVarargsInvocation)) {
return NOT_COMPATIBLE;
}
if (arg.kind() == Binding.POLY_TYPE || (arg.isBaseType() != param.isBaseType())) {
TypeBinding convertedType = env.computeBoxingType(arg);
if (TypeBinding.equalsEquals(convertedType, param) || convertedType.isCompatibleWith(param, this))
return AUTOBOX_COMPATIBLE;
}
return NOT_COMPATIBLE;
}
public abstract ProblemReporter problemReporter();
public final CompilationUnitDeclaration referenceCompilationUnit() {
Scope scope, unitScope = this;
while ((scope = unitScope.parent) != null)
unitScope = scope;
return ((CompilationUnitScope) unitScope).referenceContext;
}
public ReferenceContext referenceContext() {
Scope current = this;
do {
switch(current.kind) {
case METHOD_SCOPE :
return ((MethodScope) current).referenceContext;
case CLASS_SCOPE :
return ((ClassScope) current).referenceContext;
case COMPILATION_UNIT_SCOPE :
return ((CompilationUnitScope) current).referenceContext;
}
} while ((current = current.parent) != null);
return null;
}
public ReferenceContext originalReferenceContext() {
Scope current = this;
do {
switch(current.kind) {
case METHOD_SCOPE :
ReferenceContext context = ((MethodScope) current).referenceContext;
if (context instanceof LambdaExpression) {
LambdaExpression expression = (LambdaExpression) context;
while (expression != expression.original)
expression = expression.original;
return expression;
}
return context;
case CLASS_SCOPE :
return ((ClassScope) current).referenceContext;
case COMPILATION_UNIT_SCOPE :
return ((CompilationUnitScope) current).referenceContext;
}
} while ((current = current.parent) != null);
return null;
}
public boolean deferCheck(Runnable check) {
if (this.parent != null)
return this.parent.deferCheck(check);
return false;
}
public void deferBoundCheck(TypeReference typeRef) {
if (this.kind == CLASS_SCOPE) {
ClassScope classScope = (ClassScope) this;
if (classScope.deferredBoundChecks == null) {
classScope.deferredBoundChecks = new ArrayList(3);
classScope.deferredBoundChecks.add(typeRef);
} else if (!classScope.deferredBoundChecks.contains(typeRef)) {
classScope.deferredBoundChecks.add(typeRef);
}
}
}
int startIndex() {
return 0;
}
public MethodBinding getStaticFactory (ParameterizedTypeBinding allocationType, ReferenceBinding originalEnclosingType, TypeBinding[] argumentTypes, final InvocationSite allocationSite) {
int classTypeVariablesArity = 0;
TypeVariableBinding[] classTypeVariables = Binding.NO_TYPE_VARIABLES;
ReferenceBinding genericType = allocationType.genericType();
ReferenceBinding currentType = genericType;
while (currentType != null) {
TypeVariableBinding[] typeVariables = currentType.typeVariables();
int length = typeVariables == null ? 0 : typeVariables.length;
if (length > 0) {
System.arraycopy(classTypeVariables, 0, classTypeVariables = new TypeVariableBinding[classTypeVariablesArity + length], 0, classTypeVariablesArity);
System.arraycopy(typeVariables, 0, classTypeVariables, classTypeVariablesArity, length);
classTypeVariablesArity += length;
}
if (currentType.isStatic())
break;
currentType = currentType.enclosingType();
}
boolean isInterface = allocationType.isInterface();
ReferenceBinding typeToSearch = isInterface ? getJavaLangObject() : allocationType;
MethodBinding[] methods = typeToSearch.getMethods(TypeConstants.INIT, argumentTypes.length);
MethodBinding [] staticFactories = new MethodBinding[methods.length];
int sfi = 0;
for (int i = 0, length = methods.length; i < length; i++) {
MethodBinding method = methods[i];
if (!method.canBeSeenBy(allocationSite, this))
continue;
int paramLength = method.parameters.length;
boolean isVarArgs = method.isVarargs();
if (argumentTypes.length != paramLength)
if (!isVarArgs || argumentTypes.length < paramLength - 1)
continue;
TypeVariableBinding[] methodTypeVariables = method.typeVariables();
int methodTypeVariablesArity = methodTypeVariables.length;
final int factoryArity = classTypeVariablesArity + methodTypeVariablesArity;
final LookupEnvironment environment = environment();
MethodBinding targetMethod = isInterface ? new MethodBinding(method.original(), genericType) : method.original();
MethodBinding staticFactory = new SyntheticFactoryMethodBinding(targetMethod, environment, originalEnclosingType);
staticFactory.typeVariables = new TypeVariableBinding[factoryArity];
final SimpleLookupTable map = new SimpleLookupTable(factoryArity);
String prime = "";
Binding declaringElement = null;
for (int j = 0; j < classTypeVariablesArity; j++) {
TypeVariableBinding original;
original = classTypeVariables[j];
if (original.declaringElement != declaringElement) {
declaringElement = original.declaringElement;
prime += "'";
}
map.put(original.unannotated(), staticFactory.typeVariables[j] = new TypeVariableBinding(CharOperation.concat(original.sourceName, prime.toCharArray()),
staticFactory, j, environment));
}
prime += "'";
for (int j = classTypeVariablesArity, k = 0; j < factoryArity; j++, k++) {
map.put(methodTypeVariables[k].unannotated(),
(staticFactory.typeVariables[j] = new TypeVariableBinding(CharOperation.concat(methodTypeVariables[k].sourceName, prime.toCharArray()),
staticFactory, j, environment)));
}
final Scope scope = this;
Substitution substitution = new Substitution() {
@Override
public LookupEnvironment environment() {
return scope.environment();
}
@Override
public boolean isRawSubstitution() {
return false;
}
@Override
public TypeBinding substitute(TypeVariableBinding typeVariable) {
TypeBinding retVal = (TypeBinding) map.get(typeVariable.unannotated());
return retVal == null ? typeVariable : typeVariable.hasTypeAnnotations() ? environment().createAnnotatedType(retVal, typeVariable.getTypeAnnotations()) : retVal;
}
};
for (int j = 0; j < factoryArity; j++) {
TypeVariableBinding originalVariable = j < classTypeVariablesArity ? classTypeVariables[j] : methodTypeVariables[j - classTypeVariablesArity];
TypeVariableBinding substitutedVariable = (TypeVariableBinding) map.get(originalVariable.unannotated());
TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
if (originalVariable.firstBound != null) {
TypeBinding firstBound;
firstBound = TypeBinding.equalsEquals(originalVariable.firstBound, originalVariable.superclass)
? substitutedSuperclass
: substitutedInterfaces[0];
substitutedVariable.setFirstBound(firstBound);
}
switch (substitutedSuperclass.kind()) {
case Binding.ARRAY_TYPE :
substitutedVariable.setSuperClass(environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null));
substitutedVariable.setSuperInterfaces(substitutedInterfaces);
break;
default:
if (substitutedSuperclass.isInterface()) {
substitutedVariable.setSuperClass(environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null));
int interfaceCount = substitutedInterfaces.length;
System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount);
substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
substitutedVariable.setSuperInterfaces(substitutedInterfaces);
} else {
substitutedVariable.setSuperClass((ReferenceBinding) substitutedSuperclass);
substitutedVariable.setSuperInterfaces(substitutedInterfaces);
}
}
}
staticFactory.returnType = environment.createParameterizedType(genericType, Scope.substitute(substitution, genericType.typeVariables()), originalEnclosingType);
staticFactory.parameters = Scope.substitute(substitution, method.parameters);
staticFactory.thrownExceptions = Scope.substitute(substitution, method.thrownExceptions);
if (staticFactory.thrownExceptions == null) {
staticFactory.thrownExceptions = Binding.NO_EXCEPTIONS;
}
staticFactories[sfi++] = new ParameterizedMethodBinding((ParameterizedTypeBinding) environment.convertToParameterizedType(isInterface ? allocationType : staticFactory.declaringClass),
staticFactory);
}
if (sfi == 0)
return null;
if (sfi != methods.length) {
System.arraycopy(staticFactories, 0, staticFactories = new MethodBinding[sfi], 0, sfi);
}
MethodBinding[] compatible = new MethodBinding[sfi];
int compatibleIndex = 0;
for (int i = 0; i < sfi; i++) {
MethodBinding compatibleMethod = computeCompatibleMethod(staticFactories[i], argumentTypes, allocationSite);
if (compatibleMethod != null) {
if (compatibleMethod.isValidBinding())
compatible[compatibleIndex++] = compatibleMethod;
}
}
if (compatibleIndex == 0) {
return null;
}
return compatibleIndex == 1 ? compatible[0] : mostSpecificMethodBinding(compatible, compatibleIndex, argumentTypes, allocationSite, allocationType);
}
public boolean validateNullAnnotation(long tagBits, TypeReference typeRef, Annotation[] annotations) {
if (typeRef == null || typeRef.resolvedType == null)
return true;
TypeBinding type = typeRef.resolvedType;
boolean usesNullTypeAnnotations = this.environment().usesNullTypeAnnotations();
long nullAnnotationTagBit;
if (usesNullTypeAnnotations) {
type = type.leafComponentType();
nullAnnotationTagBit = type.tagBits & TagBits.AnnotationNullMASK;
} else {
nullAnnotationTagBit = tagBits & (TagBits.AnnotationNullMASK);
}
if (nullAnnotationTagBit != 0) {
if (type != null && type.isBaseType()) {
if (!(typeRef.resolvedType.id == TypeIds.T_void && usesNullTypeAnnotations))
problemReporter().illegalAnnotationForBaseType(typeRef, annotations, nullAnnotationTagBit);
return false;
}
}
return true;
}
public boolean recordNonNullByDefault(Binding target, int value, Annotation annotation, int scopeStart, int scopeEnd) {
ReferenceContext context = referenceContext();
if (context instanceof LambdaExpression && context != ((LambdaExpression) context).original)
return false;
if (this.nullDefaultRanges == null) {
this.nullDefaultRanges=new ArrayList<>(3);
}
for (NullDefaultRange nullDefaultRange : this.nullDefaultRanges) {
if (nullDefaultRange.start== scopeStart && nullDefaultRange.end==scopeEnd) {
if (nullDefaultRange.contains(annotation)) {
return false;
} else {
nullDefaultRange.merge(value, annotation, target);
return true;
}
}
}
this.nullDefaultRanges.add(new NullDefaultRange(value, annotation, scopeStart, scopeEnd, target));
return true;
}
public Binding checkRedundantDefaultNullness(int nullBits, int sourceStart) {
Binding target = localCheckRedundantDefaultNullness(nullBits, sourceStart);
if (target != null) {
return target;
}
return this.parent.checkRedundantDefaultNullness(nullBits, sourceStart);
}
public boolean hasDefaultNullnessFor(int location, int sourceStart) {
int nonNullByDefaultValue = localNonNullByDefaultValue(sourceStart);
if (nonNullByDefaultValue != 0) {
return (nonNullByDefaultValue & location) != 0;
}
return this.parent.hasDefaultNullnessFor(location, sourceStart);
}
public final int localNonNullByDefaultValue(int start) {
NullDefaultRange nullDefaultRange = nullDefaultRangeForPosition(start);
return nullDefaultRange != null ? nullDefaultRange.value : 0;
}
final protected Binding localCheckRedundantDefaultNullness(int nullBits, int position) {
NullDefaultRange nullDefaultRange = nullDefaultRangeForPosition(position);
if (nullDefaultRange != null)
return (nullBits == nullDefaultRange.value) ? nullDefaultRange.target : NOT_REDUNDANT;
return null;
}
private NullDefaultRange nullDefaultRangeForPosition(int start) {
if (this.nullDefaultRanges != null) {
for (NullDefaultRange nullDefaultRange : this.nullDefaultRanges) {
if (start >= nullDefaultRange.start && start < nullDefaultRange.end) {
return nullDefaultRange;
}
}
}
return null;
}
public static BlockScope typeAnnotationsResolutionScope(Scope scope) {
BlockScope resolutionScope = null;
switch(scope.kind) {
case Scope.CLASS_SCOPE:
resolutionScope = ((ClassScope) scope).referenceContext.staticInitializerScope;
break;
case Scope.BLOCK_SCOPE :
case Scope.METHOD_SCOPE :
resolutionScope = (BlockScope) scope;
break;
}
return resolutionScope;
}
public void tagAsAccessingEnclosingInstanceStateOf(ReferenceBinding enclosingType, boolean typeVariableAccess) {
MethodScope methodScope = methodScope();
if (methodScope != null && methodScope.referenceContext instanceof TypeDeclaration) {
if (!methodScope.enclosingReceiverType().isCompatibleWith(enclosingType)) {
methodScope = methodScope.enclosingMethodScope();
}
}
MethodBinding enclosingMethod = enclosingType != null ? enclosingType.enclosingMethod() : null;
while (methodScope != null) {
while (methodScope != null && methodScope.referenceContext instanceof LambdaExpression) {
LambdaExpression lambda = (LambdaExpression) methodScope.referenceContext;
if (!typeVariableAccess && !lambda.scope.isStatic)
lambda.shouldCaptureInstance = true;
methodScope = methodScope.enclosingMethodScope();
}
if (methodScope != null) {
if (methodScope.referenceContext instanceof MethodDeclaration) {
MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext;
if (methodDeclaration.binding == enclosingMethod)
break;
methodDeclaration.bits &= ~ASTNode.CanBeStatic;
}
ClassScope enclosingClassScope = methodScope.enclosingClassScope();
if (enclosingClassScope != null) {
TypeDeclaration type = enclosingClassScope.referenceContext;
if (type != null && type.binding != null && enclosingType != null && !type.binding.isCompatibleWith(enclosingType.original())) {
methodScope = enclosingClassScope.enclosingMethodScope();
continue;
}
}
break;
}
}
}
}