package org.eclipse.jdt.internal.compiler.lookup;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants.BoundCheckStatus;
public class ParameterizedTypeBinding extends ReferenceBinding implements Substitution {
protected ReferenceBinding type;
public TypeBinding[] arguments;
public LookupEnvironment environment;
public char[] genericTypeSignature;
public ReferenceBinding superclass;
public ReferenceBinding[] superInterfaces;
public FieldBinding[] fields;
public ReferenceBinding[] memberTypes;
public MethodBinding[] methods;
protected ReferenceBinding enclosingType;
public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments, ReferenceBinding enclosingType, LookupEnvironment environment){
this.environment = environment;
this.enclosingType = enclosingType;
if (!type.hasEnclosingInstanceContext() && arguments == null && !(this instanceof RawTypeBinding))
throw new IllegalStateException();
initialize(type, arguments);
if (type instanceof UnresolvedReferenceBinding)
((UnresolvedReferenceBinding) type).addWrapper(this, environment);
if (arguments != null) {
for (int i = 0, l = arguments.length; i < l; i++) {
if (arguments[i] instanceof UnresolvedReferenceBinding)
((UnresolvedReferenceBinding) arguments[i]).addWrapper(this, environment);
if (arguments[i].hasNullTypeAnnotations())
this.tagBits |= TagBits.HasNullTypeAnnotation;
}
}
if (enclosingType != null && enclosingType.hasNullTypeAnnotations())
this.tagBits |= TagBits.HasNullTypeAnnotation;
this.tagBits |= TagBits.HasUnresolvedTypeVariables;
this.typeBits = type.typeBits;
}
@Override
public ReferenceBinding actualType() {
return this.type;
}
@Override
public boolean isParameterizedType() {
return true;
}
public void boundCheck(Scope scope, TypeReference[] argumentReferences) {
if ((this.tagBits & TagBits.PassedBoundCheck) == 0) {
boolean hasErrors = false;
TypeVariableBinding[] typeVariables = this.type.typeVariables();
if (this.arguments != null && typeVariables != null) {
for (int i = 0, length = typeVariables.length; i < length; i++) {
BoundCheckStatus checkStatus = typeVariables[i].boundCheck(this, this.arguments[i], scope, argumentReferences[i]);
hasErrors |= checkStatus != BoundCheckStatus.OK;
if (!checkStatus.isOKbyJLS() && (this.arguments[i].tagBits & TagBits.HasMissingType) == 0) {
scope.problemReporter().typeMismatchError(this.arguments[i], typeVariables[i], this.type, argumentReferences[i]);
}
}
}
if (!hasErrors) this.tagBits |= TagBits.PassedBoundCheck;
}
}
@Override
public boolean canBeInstantiated() {
return ((this.tagBits & TagBits.HasDirectWildcard) == 0) && super.canBeInstantiated();
}
@Override
public ParameterizedTypeBinding capture(Scope scope, int start, int end) {
if ((this.tagBits & TagBits.HasDirectWildcard) == 0)
return this;
TypeBinding[] originalArguments = this.arguments;
int length = originalArguments.length;
TypeBinding[] capturedArguments = new TypeBinding[length];
ReferenceBinding contextType = scope.enclosingSourceType();
if (contextType != null) contextType = contextType.outermostEnclosingType();
CompilationUnitScope compilationUnitScope = scope.compilationUnitScope();
ASTNode cud = compilationUnitScope.referenceContext;
long sourceLevel = this.environment.globalOptions.sourceLevel;
final boolean needUniqueCapture = sourceLevel >= ClassFileConstants.JDK1_8;
for (int i = 0; i < length; i++) {
TypeBinding argument = originalArguments[i];
if (argument.kind() == Binding.WILDCARD_TYPE) {
final WildcardBinding wildcard = (WildcardBinding) argument;
if (wildcard.boundKind == Wildcard.SUPER && wildcard.bound.id == TypeIds.T_JavaLangObject)
capturedArguments[i] = wildcard.bound;
else if (needUniqueCapture)
capturedArguments[i] = this.environment.createCapturedWildcard(wildcard, contextType, start, end, cud, compilationUnitScope.nextCaptureID());
else
capturedArguments[i] = new CaptureBinding(wildcard, contextType, start, end, cud, compilationUnitScope.nextCaptureID());
} else {
capturedArguments[i] = argument;
}
}
ParameterizedTypeBinding capturedParameterizedType = this.environment.createParameterizedType(this.type, capturedArguments, enclosingType(), this.typeAnnotations);
for (int i = 0; i < length; i++) {
TypeBinding argument = capturedArguments[i];
if (argument.isCapture()) {
((CaptureBinding)argument).initializeBounds(scope, capturedParameterizedType);
}
}
return capturedParameterizedType;
}
@Override
public TypeBinding uncapture(Scope scope) {
if ((this.tagBits & TagBits.HasCapturedWildcard) == 0)
return this;
int length = this.arguments == null ? 0 : this.arguments.length;
TypeBinding[] freeTypes = new TypeBinding[length];
for (int i = 0; i < length; i++) {
freeTypes[i] = this.arguments[i].uncapture(scope);
}
return scope.environment().createParameterizedType(this.type, freeTypes, (ReferenceBinding) (this.enclosingType != null ? this.enclosingType.uncapture(scope) : null), this.typeAnnotations);
}
@Override
public List<TypeBinding> collectMissingTypes(List<TypeBinding> missingTypes) {
if ((this.tagBits & TagBits.HasMissingType) != 0) {
if (this.enclosingType != null) {
missingTypes = this.enclosingType.collectMissingTypes(missingTypes);
}
missingTypes = genericType().collectMissingTypes(missingTypes);
if (this.arguments != null) {
for (int i = 0, max = this.arguments.length; i < max; i++) {
missingTypes = this.arguments[i].collectMissingTypes(missingTypes);
}
}
}
return missingTypes;
}
@Override
public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {
if ((this.tagBits & TagBits.HasTypeVariable) == 0) {
TypeBinding actualEquivalent = actualType.findSuperTypeOriginatingFrom(this.type);
if (actualEquivalent != null && actualEquivalent.isRawType()) {
inferenceContext.isUnchecked = true;
}
return;
}
if (actualType == TypeBinding.NULL || actualType.kind() == POLY_TYPE) return;
if (!(actualType instanceof ReferenceBinding)) return;
TypeBinding formalEquivalent, actualEquivalent;
switch (constraint) {
case TypeConstants.CONSTRAINT_EQUAL :
case TypeConstants.CONSTRAINT_EXTENDS :
formalEquivalent = this;
actualEquivalent = actualType.findSuperTypeOriginatingFrom(this.type);
if (actualEquivalent == null) return;
break;
case TypeConstants.CONSTRAINT_SUPER :
default:
formalEquivalent = this.findSuperTypeOriginatingFrom(actualType);
if (formalEquivalent == null) return;
actualEquivalent = actualType;
break;
}
ReferenceBinding formalEnclosingType = formalEquivalent.enclosingType();
if (formalEnclosingType != null) {
formalEnclosingType.collectSubstitutes(scope, actualEquivalent.enclosingType(), inferenceContext, constraint);
}
if (this.arguments == null) return;
TypeBinding[] formalArguments;
switch (formalEquivalent.kind()) {
case Binding.GENERIC_TYPE :
formalArguments = formalEquivalent.typeVariables();
break;
case Binding.PARAMETERIZED_TYPE :
formalArguments = ((ParameterizedTypeBinding)formalEquivalent).arguments;
break;
case Binding.RAW_TYPE :
if (inferenceContext.depth > 0) {
inferenceContext.status = InferenceContext.FAILED;
}
return;
default :
return;
}
TypeBinding[] actualArguments;
switch (actualEquivalent.kind()) {
case Binding.GENERIC_TYPE :
actualArguments = actualEquivalent.typeVariables();
break;
case Binding.PARAMETERIZED_TYPE :
actualArguments = ((ParameterizedTypeBinding)actualEquivalent).arguments;
break;
case Binding.RAW_TYPE :
if (inferenceContext.depth > 0) {
inferenceContext.status = InferenceContext.FAILED;
} else {
inferenceContext.isUnchecked = true;
}
return;
default :
return;
}
inferenceContext.depth++;
for (int i = 0, length = formalArguments.length; i < length; i++) {
TypeBinding formalArgument = formalArguments[i];
TypeBinding actualArgument = actualArguments[i];
if (formalArgument.isWildcard()) {
formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, constraint);
continue;
} else if (actualArgument.isWildcard()){
WildcardBinding actualWildcardArgument = (WildcardBinding) actualArgument;
if (actualWildcardArgument.otherBounds == null) {
if (constraint == TypeConstants.CONSTRAINT_SUPER) {
switch(actualWildcardArgument.boundKind) {
case Wildcard.EXTENDS :
formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_SUPER);
continue;
case Wildcard.SUPER :
formalArgument.collectSubstitutes(scope, actualWildcardArgument.bound, inferenceContext, TypeConstants.CONSTRAINT_EXTENDS);
continue;
default :
continue;
}
} else {
continue;
}
}
}
formalArgument.collectSubstitutes(scope, actualArgument, inferenceContext, TypeConstants.CONSTRAINT_EQUAL);
}
inferenceContext.depth--;
}
@Override
public void computeId() {
this.id = TypeIds.NoId;
}
@Override
public char[] computeUniqueKey(boolean isLeaf) {
StringBuffer sig = new StringBuffer(10);
ReferenceBinding enclosing;
if (isMemberType() && ((enclosing = enclosingType()).isParameterizedType() || enclosing.isRawType())) {
char[] typeSig = enclosing.computeUniqueKey(false);
sig.append(typeSig, 0, typeSig.length-1);
sig.append('.').append(sourceName());
} else if(this.type.isLocalType()){
LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.type;
enclosing = localTypeBinding.enclosingType();
ReferenceBinding temp;
while ((temp = enclosing.enclosingType()) != null)
enclosing = temp;
char[] typeSig = enclosing.computeUniqueKey(false);
sig.append(typeSig, 0, typeSig.length-1);
sig.append('$');
sig.append(localTypeBinding.sourceStart);
} else {
char[] typeSig = this.type.computeUniqueKey(false);
sig.append(typeSig, 0, typeSig.length-1);
}
ReferenceBinding captureSourceType = null;
if (this.arguments != null) {
sig.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
TypeBinding typeBinding = this.arguments[i];
sig.append(typeBinding.computeUniqueKey(false));
if (typeBinding instanceof CaptureBinding)
captureSourceType = ((CaptureBinding) typeBinding).sourceType;
}
sig.append('>');
}
sig.append(';');
if (captureSourceType != null && TypeBinding.notEquals(captureSourceType, this.type)) {
sig.insert(0, "&");
sig.insert(0, captureSourceType.computeUniqueKey(false));
}
int sigLength = sig.length();
char[] uniqueKey = new char[sigLength];
sig.getChars(0, sigLength, uniqueKey, 0);
return uniqueKey;
}
@Override
public char[] constantPoolName() {
return this.type.constantPoolName();
}
@Override
public TypeBinding clone(TypeBinding outerType) {
return new ParameterizedTypeBinding(this.type, this.arguments, (ReferenceBinding) outerType, this.environment);
}
public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
return new ParameterizedMethodBinding(this, originalMethod);
}
@Override
public String debugName() {
if (this.hasTypeAnnotations())
return annotatedDebugName();
StringBuffer nameBuffer = new StringBuffer(10);
if (this.type instanceof UnresolvedReferenceBinding) {
nameBuffer.append(this.type);
} else {
nameBuffer.append(this.type.sourceName());
}
if (this.arguments != null && this.arguments.length > 0) {
nameBuffer.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
if (i > 0) nameBuffer.append(',');
nameBuffer.append(this.arguments[i].debugName());
}
nameBuffer.append('>');
}
return nameBuffer.toString();
}
@Override
public String annotatedDebugName() {
StringBuffer nameBuffer = new StringBuffer(super.annotatedDebugName());
if (this.arguments != null && this.arguments.length > 0) {
nameBuffer.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
if (i > 0) nameBuffer.append(',');
nameBuffer.append(this.arguments[i].annotatedDebugName());
}
nameBuffer.append('>');
}
return nameBuffer.toString();
}
@Override
public ReferenceBinding enclosingType() {
if (this.type instanceof UnresolvedReferenceBinding && ((UnresolvedReferenceBinding) this.type).depth() > 0) {
((UnresolvedReferenceBinding) this.type).resolve(this.environment, false);
}
return this.enclosingType;
}
@Override
public LookupEnvironment environment() {
return this.environment;
}
@Override
public TypeBinding erasure() {
return this.type.erasure();
}
@Override
public ReferenceBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
TypeBinding[] typeVariables = this.arguments;
if (typeVariables == null) return this;
TypeBinding[] a_i_primes = new TypeBinding[typeVariables.length];
for (int i = 0, length = typeVariables.length; i < length; i++) {
TypeBinding a_i = typeVariables[i];
int typeVariableKind = a_i.kind();
if (! a_i.mentionsAny(mentionedTypeVariables, -1)) {
a_i_primes[i] = a_i;
} else if (typeVariableKind != Binding.WILDCARD_TYPE) {
TypeBinding u = a_i.upwardsProjection(scope, mentionedTypeVariables);
TypeVariableBinding[] g_vars = this.type.typeVariables();
if (g_vars == null || g_vars.length == 0) return this;
TypeBinding b_i = g_vars[i].upperBound();
if (u.id != TypeIds.T_JavaLangObject
&& (b_i.mentionsAny(typeVariables, -1) || !b_i.isSubtypeOf(u, false))) {
a_i_primes[i] = this.environment().createWildcard(genericType(), i, u, null, Wildcard.EXTENDS);
} else {
TypeBinding l = a_i.downwardsProjection(scope, mentionedTypeVariables);
if (l != null) {
a_i_primes[i] = this.environment().createWildcard(genericType(), i, l, null, Wildcard.SUPER);
} else {
a_i_primes[i] = this.environment().createWildcard(genericType(), i, null, null, Wildcard.UNBOUND);
}
}
} else {
WildcardBinding wildcard = (WildcardBinding)a_i;
if (wildcard.boundKind() == Wildcard.EXTENDS) {
TypeBinding u = wildcard.bound().upwardsProjection(scope, mentionedTypeVariables);
a_i_primes[i] = this.environment().createWildcard(null, 0, u, null, Wildcard.EXTENDS);
} else if (wildcard.boundKind() == Wildcard.SUPER) {
TypeBinding l = wildcard.bound().downwardsProjection(scope, mentionedTypeVariables);
if (l != null) {
a_i_primes[i] = this.environment().createWildcard(null, 0, l, null, Wildcard.SUPER);
} else {
a_i_primes[i] = this.environment().createWildcard(null, 0, null, null, Wildcard.UNBOUND);
}
}
}
}
return this.environment.createParameterizedType(this.type, a_i_primes, this.enclosingType);
}
@Override
public ReferenceBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
TypeBinding[] typeVariables = this.arguments;
if (typeVariables == null) return this;
TypeBinding[] a_i_primes = new TypeBinding[typeVariables.length];
for (int i = 0, length = typeVariables.length; i < length; i++) {
TypeBinding a_i = typeVariables[i];
int typeVariableKind = a_i.kind();
if (! a_i.mentionsAny(mentionedTypeVariables, -1)) {
a_i_primes[i] = a_i;
} else if (typeVariableKind != Binding.WILDCARD_TYPE) {
return null;
} else {
WildcardBinding wildcard = (WildcardBinding)a_i;
if (wildcard.boundKind() == Wildcard.EXTENDS) {
TypeBinding u = wildcard.bound().downwardsProjection(scope, mentionedTypeVariables);
if (u != null) {
a_i_primes[i] = this.environment().createWildcard(null, 0, u, null, Wildcard.EXTENDS);
} else {
return null;
}
} else if (wildcard.boundKind() == Wildcard.SUPER) {
TypeBinding l = wildcard.bound().upwardsProjection(scope, mentionedTypeVariables);
a_i_primes[i] = this.environment().createWildcard(null, 0, l, null, Wildcard.SUPER);
} else {
return null;
}
}
}
return this.environment.createParameterizedType(this.type, a_i_primes, this.enclosingType);
}
@Override
public int fieldCount() {
return this.type.fieldCount();
}
@Override
public FieldBinding[] fields() {
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return this.fields;
try {
FieldBinding[] originalFields = this.type.fields();
int length = originalFields.length;
FieldBinding[] parameterizedFields = new FieldBinding[length];
for (int i = 0; i < length; i++)
parameterizedFields[i] = new ParameterizedFieldBinding(this, originalFields[i]);
this.fields = parameterizedFields;
} finally {
if (this.fields == null)
this.fields = Binding.NO_FIELDS;
this.tagBits |= TagBits.AreFieldsComplete;
}
return this.fields;
}
public ReferenceBinding genericType() {
if (this.type instanceof UnresolvedReferenceBinding)
((UnresolvedReferenceBinding) this.type).resolve(this.environment, false);
return this.type;
}
@Override
public char[] genericTypeSignature() {
if (this.genericTypeSignature == null) {
if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) {
this.genericTypeSignature = this.type.signature();
} else {
StringBuffer sig = new StringBuffer(10);
if (isMemberType() && !isStatic()) {
ReferenceBinding enclosing = enclosingType();
char[] typeSig = enclosing.genericTypeSignature();
sig.append(typeSig, 0, typeSig.length-1);
if ((enclosing.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
sig.append('.');
} else {
sig.append('$');
}
sig.append(sourceName());
} else {
char[] typeSig = this.type.signature();
sig.append(typeSig, 0, typeSig.length-1);
}
if (this.arguments != null) {
sig.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
sig.append(this.arguments[i].genericTypeSignature());
}
sig.append('>');
}
sig.append(';');
int sigLength = sig.length();
this.genericTypeSignature = new char[sigLength];
sig.getChars(0, sigLength, this.genericTypeSignature, 0);
}
}
return this.genericTypeSignature;
}
@Override
public long getAnnotationTagBits() {
return this.type.getAnnotationTagBits();
}
@Override
public int getEnclosingInstancesSlotSize() {
return genericType().getEnclosingInstancesSlotSize();
}
@Override
public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
int argCount = argumentTypes.length;
MethodBinding match = null;
if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
long range;
if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) {
nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
MethodBinding method = this.methods[imethod];
if (method.parameters.length == argCount) {
TypeBinding[] toMatch = method.parameters;
for (int iarg = 0; iarg < argCount; iarg++)
if (TypeBinding.notEquals(toMatch[iarg], argumentTypes[iarg]))
continue nextMethod;
if (match != null) return null;
match = method;
}
}
}
} else {
MethodBinding[] matchingMethods = getMethods(TypeConstants.INIT);
nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
MethodBinding method = matchingMethods[m];
TypeBinding[] toMatch = method.parameters;
if (toMatch.length == argCount) {
for (int p = 0; p < argCount; p++)
if (TypeBinding.notEquals(toMatch[p], argumentTypes[p]))
continue nextMethod;
if (match != null) return null;
match = method;
}
}
}
return match;
}
@Override
public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
int argCount = argumentTypes.length;
boolean foundNothing = true;
MethodBinding match = null;
if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
long range;
if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
MethodBinding method = this.methods[imethod];
foundNothing = false;
if (method.parameters.length == argCount) {
TypeBinding[] toMatch = method.parameters;
for (int iarg = 0; iarg < argCount; iarg++)
if (TypeBinding.notEquals(toMatch[iarg], argumentTypes[iarg]))
continue nextMethod;
if (match != null) return null;
match = method;
}
}
}
} else {
MethodBinding[] matchingMethods = getMethods(selector);
foundNothing = matchingMethods == Binding.NO_METHODS;
nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
MethodBinding method = matchingMethods[m];
TypeBinding[] toMatch = method.parameters;
if (toMatch.length == argCount) {
for (int p = 0; p < argCount; p++)
if (TypeBinding.notEquals(toMatch[p], argumentTypes[p]))
continue nextMethod;
if (match != null) return null;
match = method;
}
}
}
if (match != null) {
if (match.hasSubstitutedParameters()) return null;
return match;
}
if (foundNothing && (this.arguments == null || this.arguments.length <= 1)) {
if (isInterface()) {
if (superInterfaces().length == 1) {
if (refScope != null)
refScope.recordTypeReference(this.superInterfaces[0]);
return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
}
} else if (superclass() != null) {
if (refScope != null)
refScope.recordTypeReference(this.superclass);
return this.superclass.getExactMethod(selector, argumentTypes, refScope);
}
}
return null;
}
@Override
public FieldBinding getField(char[] fieldName, boolean needResolve) {
if (((this.tagBits & TagBits.AreFieldsComplete) == 0) && ((this.type.tagBits & TagBits.AreFieldsSorted) != 0)) {
FieldBinding originalField = ReferenceBinding.binarySearch(fieldName, this.type.unResolvedFields());
if (originalField == null)
return null;
}
fields();
return ReferenceBinding.binarySearch(fieldName, this.fields);
}
@Override
public MethodBinding[] getMethods(char[] selector) {
if (this.methods != null) {
long range;
if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
int start = (int) range;
int length = (int) (range >> 32) - start + 1;
MethodBinding[] result;
System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
return result;
}
}
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return Binding.NO_METHODS;
MethodBinding[] parameterizedMethods = null;
try {
MethodBinding[] originalMethods = this.type.getMethods(selector);
int length = originalMethods.length;
if (length == 0) return Binding.NO_METHODS;
parameterizedMethods = new MethodBinding[length];
boolean useNullTypeAnnotations = this.environment.usesNullTypeAnnotations();
for (int i = 0; i < length; i++) {
parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
if (useNullTypeAnnotations)
parameterizedMethods[i] = NullAnnotationMatching.checkForContradictions(parameterizedMethods[i], null, null);
}
if (this.methods == null) {
MethodBinding[] temp = new MethodBinding[length];
System.arraycopy(parameterizedMethods, 0, temp, 0, length);
this.methods = temp;
} else {
int total = length + this.methods.length;
MethodBinding[] temp = new MethodBinding[total];
System.arraycopy(parameterizedMethods, 0, temp, 0, length);
System.arraycopy(this.methods, 0, temp, length, this.methods.length);
if (total > 1)
ReferenceBinding.sortMethods(temp, 0, total);
this.methods = temp;
}
return parameterizedMethods;
} finally {
if (parameterizedMethods == null)
this.methods = parameterizedMethods = Binding.NO_METHODS;
}
}
@Override
public int getOuterLocalVariablesSlotSize() {
return genericType().getOuterLocalVariablesSlotSize();
}
@Override
public boolean hasMemberTypes() {
return this.type.hasMemberTypes();
}
@Override
public boolean hasTypeBit(int bit) {
TypeBinding erasure = erasure();
if (erasure instanceof ReferenceBinding)
return ((ReferenceBinding) erasure).hasTypeBit(bit);
return false;
}
@Override
public boolean implementsMethod(MethodBinding method) {
return this.type.implementsMethod(method);
}
void initialize(ReferenceBinding someType, TypeBinding[] someArguments) {
this.type = someType;
this.sourceName = someType.sourceName;
this.compoundName = someType.compoundName;
this.fPackage = someType.fPackage;
this.fileName = someType.fileName;
this.modifiers = someType.modifiers & ~ExtraCompilerModifiers.AccGenericSignature;
if (someArguments != null) {
this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
} else if (this.enclosingType != null) {
this.modifiers |= (this.enclosingType.modifiers & ExtraCompilerModifiers.AccGenericSignature);
this.tagBits |= this.enclosingType.tagBits & (TagBits.HasTypeVariable | TagBits.HasMissingType | TagBits.HasCapturedWildcard);
}
if (someArguments != null) {
this.arguments = someArguments;
for (int i = 0, length = someArguments.length; i < length; i++) {
TypeBinding someArgument = someArguments[i];
switch (someArgument.kind()) {
case Binding.WILDCARD_TYPE :
this.tagBits |= TagBits.HasDirectWildcard;
if (((WildcardBinding) someArgument).boundKind != Wildcard.UNBOUND) {
this.tagBits |= TagBits.IsBoundParameterizedType;
}
break;
case Binding.INTERSECTION_TYPE :
this.tagBits |= TagBits.HasDirectWildcard | TagBits.IsBoundParameterizedType;
break;
default :
this.tagBits |= TagBits.IsBoundParameterizedType;
break;
}
this.tagBits |= someArgument.tagBits & (TagBits.HasTypeVariable | TagBits.HasMissingType | TagBits.ContainsNestedTypeReferences | TagBits.HasCapturedWildcard);
}
}
this.tagBits |= someType.tagBits & (TagBits.IsLocalType| TagBits.IsMemberType | TagBits.IsNestedType | TagBits.ContainsNestedTypeReferences
| TagBits.HasMissingType | TagBits.AnnotationNullMASK | TagBits.HasCapturedWildcard);
this.tagBits &= ~(TagBits.AreFieldsComplete|TagBits.AreMethodsComplete);
}
protected void initializeArguments() {
}
@Override
void initializeForStaticImports() {
this.type.initializeForStaticImports();
}
@Override
public boolean isBoundParameterizedType() {
return (this.tagBits & TagBits.IsBoundParameterizedType) != 0;
}
@Override
public boolean isEquivalentTo(TypeBinding otherType) {
if (equalsEquals(this, otherType))
return true;
if (otherType == null)
return false;
switch(otherType.kind()) {
case Binding.WILDCARD_TYPE :
case Binding.INTERSECTION_TYPE:
return ((WildcardBinding) otherType).boundCheck(this);
case Binding.PARAMETERIZED_TYPE :
ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
if (TypeBinding.notEquals(this.type, otherParamType.type))
return false;
if (!isStatic()) {
ReferenceBinding enclosing = enclosingType();
if (enclosing != null) {
ReferenceBinding otherEnclosing = otherParamType.enclosingType();
if (otherEnclosing == null) return false;
if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
if (TypeBinding.notEquals(enclosing, otherEnclosing)) return false;
} else {
if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false;
}
}
}
if (this.arguments != ParameterizedSingleTypeReference.DIAMOND_TYPE_ARGUMENTS) {
if (this.arguments == null) {
return otherParamType.arguments == null;
}
int length = this.arguments.length;
TypeBinding[] otherArguments = otherParamType.arguments;
if (otherArguments == null || otherArguments.length != length) return false;
for (int i = 0; i < length; i++) {
if (!this.arguments[i].isTypeArgumentContainedBy(otherArguments[i]))
return false;
}
}
return true;
case Binding.RAW_TYPE :
return TypeBinding.equalsEquals(erasure(), otherType.erasure());
}
if (TypeBinding.equalsEquals(erasure(), otherType)) {
return true;
}
return false;
}
@Override
public boolean isHierarchyConnected() {
return this.superclass != null && this.superInterfaces != null;
}
@Override
public boolean isProperType(boolean admitCapture18) {
if (this.arguments != null) {
for (int i = 0; i < this.arguments.length; i++)
if (!this.arguments[i].isProperType(admitCapture18))
return false;
}
return super.isProperType(admitCapture18);
}
@Override
TypeBinding substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType) {
ReferenceBinding newEnclosing = this.enclosingType;
if (!isStatic() && this.enclosingType != null) {
newEnclosing = (ReferenceBinding) this.enclosingType.substituteInferenceVariable(var, substituteType);
}
if (this.arguments != null) {
TypeBinding[] newArgs = null;
int length = this.arguments.length;
for (int i = 0; i < length; i++) {
TypeBinding oldArg = this.arguments[i];
TypeBinding newArg = oldArg.substituteInferenceVariable(var, substituteType);
if (TypeBinding.notEquals(newArg, oldArg)) {
if (newArgs == null)
System.arraycopy(this.arguments, 0, newArgs = new TypeBinding[length], 0, length);
newArgs[i] = newArg;
}
}
if (newArgs != null)
return this.environment.createParameterizedType(this.type, newArgs, newEnclosing);
} else if (TypeBinding.notEquals(newEnclosing, this.enclosingType)) {
return this.environment.createParameterizedType(this.type, this.arguments, newEnclosing);
}
return this;
}
@Override
public boolean isRawSubstitution() {
return isRawType();
}
@Override
public TypeBinding unannotated() {
return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this;
}
@Override
public TypeBinding withoutToplevelNullAnnotation() {
if (!hasNullTypeAnnotations())
return this;
ReferenceBinding unannotatedGenericType = (ReferenceBinding) this.environment.getUnannotatedType(this.type);
AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations);
return this.environment.createParameterizedType(unannotatedGenericType, this.arguments, this.enclosingType, newAnnotations);
}
@Override
public int kind() {
return PARAMETERIZED_TYPE;
}
@Override
public ReferenceBinding[] memberTypes() {
if (this.memberTypes == null) {
try {
ReferenceBinding[] originalMemberTypes = this.type.memberTypes();
int length = originalMemberTypes.length;
ReferenceBinding[] parameterizedMemberTypes = new ReferenceBinding[length];
for (int i = 0; i < length; i++) {
parameterizedMemberTypes[i] = originalMemberTypes[i].isStatic()
? originalMemberTypes[i]
: this.environment.createParameterizedType(originalMemberTypes[i], null, this);
}
this.memberTypes = parameterizedMemberTypes;
} finally {
if (this.memberTypes == null)
this.memberTypes = Binding.NO_MEMBER_TYPES;
}
}
return this.memberTypes;
}
@Override
public boolean mentionsAny(TypeBinding[] parameters, int idx) {
if (super.mentionsAny(parameters, idx))
return true;
if (this.arguments != null) {
int len = this.arguments.length;
for (int i = 0; i < len; i++) {
if (TypeBinding.notEquals(this.arguments[i], this) && this.arguments[i].mentionsAny(parameters, idx))
return true;
}
}
return false;
}
@Override
void collectInferenceVariables(Set<InferenceVariable> variables) {
if (this.arguments != null) {
int len = this.arguments.length;
for (int i = 0; i < len; i++) {
if (TypeBinding.notEquals(this.arguments[i], this))
this.arguments[i].collectInferenceVariables(variables);
}
}
if (!isStatic() && this.enclosingType != null) {
this.enclosingType.collectInferenceVariables(variables);
}
}
@Override
public MethodBinding[] methods() {
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return this.methods;
try {
MethodBinding[] originalMethods = this.type.methods();
int length = originalMethods.length;
MethodBinding[] parameterizedMethods = new MethodBinding[length];
boolean useNullTypeAnnotations = this.environment.usesNullTypeAnnotations();
for (int i = 0; i < length; i++) {
parameterizedMethods[i] = createParameterizedMethod(originalMethods[i]);
if (useNullTypeAnnotations)
parameterizedMethods[i] = NullAnnotationMatching.checkForContradictions(parameterizedMethods[i], null, null);
}
this.methods = parameterizedMethods;
} finally {
if (this.methods == null)
this.methods = Binding.NO_METHODS;
this.tagBits |= TagBits.AreMethodsComplete;
}
return this.methods;
}
@Override
public int problemId() {
return this.type.problemId();
}
@Override
public char[] qualifiedPackageName() {
return this.type.qualifiedPackageName();
}
@Override
public char[] qualifiedSourceName() {
return this.type.qualifiedSourceName();
}
@Override
public char[] readableName() {
return readableName(true);
}
@Override
public char[] readableName(boolean showGenerics) {
StringBuffer nameBuffer = new StringBuffer(10);
if (isMemberType()) {
nameBuffer.append(CharOperation.concat(enclosingType().readableName(showGenerics && !isStatic()), this.sourceName, '.'));
} else {
nameBuffer.append(CharOperation.concatWith(this.type.compoundName, '.'));
}
if (showGenerics) {
if (this.arguments != null && this.arguments.length > 0) {
nameBuffer.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
if (i > 0) nameBuffer.append(',');
nameBuffer.append(this.arguments[i].readableName());
}
nameBuffer.append('>');
}
}
int nameLength = nameBuffer.length();
char[] readableName = new char[nameLength];
nameBuffer.getChars(0, nameLength, readableName, 0);
return readableName;
}
ReferenceBinding resolve() {
if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
return this;
this.tagBits &= ~TagBits.HasUnresolvedTypeVariables;
ReferenceBinding resolvedType = (ReferenceBinding) BinaryTypeBinding.resolveType(this.type, this.environment, false );
this.tagBits |= resolvedType.tagBits & TagBits.ContainsNestedTypeReferences;
if (this.arguments != null) {
int argLength = this.arguments.length;
if ((this.type.tagBits & TagBits.HasMissingType) == 0) {
this.tagBits &= ~TagBits.HasMissingType;
if (this.enclosingType != null)
this.tagBits |= this.enclosingType.tagBits & TagBits.HasMissingType;
}
for (int i = 0; i < argLength; i++) {
TypeBinding resolveType = BinaryTypeBinding.resolveType(this.arguments[i], this.environment, true );
this.arguments[i] = resolveType;
this.tagBits |= resolveType.tagBits & (TagBits.ContainsNestedTypeReferences | TagBits.HasMissingType);
}
}
return this;
}
@Override
public char[] shortReadableName() {
return shortReadableName(true);
}
@Override
public char[] shortReadableName(boolean showGenerics) {
StringBuffer nameBuffer = new StringBuffer(10);
if (isMemberType()) {
nameBuffer.append(CharOperation.concat(enclosingType().shortReadableName(showGenerics && !isStatic()), this.sourceName, '.'));
} else {
nameBuffer.append(this.type.sourceName);
}
if (showGenerics) {
if (this.arguments != null && this.arguments.length > 0) {
nameBuffer.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
if (i > 0) nameBuffer.append(',');
nameBuffer.append(this.arguments[i].shortReadableName());
}
nameBuffer.append('>');
}
}
int nameLength = nameBuffer.length();
char[] shortReadableName = new char[nameLength];
nameBuffer.getChars(0, nameLength, shortReadableName, 0);
return shortReadableName;
}
@Override
public char[] nullAnnotatedReadableName(CompilerOptions options, boolean shortNames) {
if (shortNames)
return nullAnnotatedShortReadableName(options);
return nullAnnotatedReadableName(options);
}
@Override
char[] nullAnnotatedReadableName(CompilerOptions options) {
StringBuffer nameBuffer = new StringBuffer(10);
if (isMemberType()) {
nameBuffer.append(enclosingType().nullAnnotatedReadableName(options, false));
nameBuffer.append('.');
appendNullAnnotation(nameBuffer, options);
nameBuffer.append(this.sourceName);
} else if (this.type.compoundName != null) {
int i;
int l=this.type.compoundName.length;
for (i=0; i<l-1; i++) {
nameBuffer.append(this.type.compoundName[i]);
nameBuffer.append('.');
}
appendNullAnnotation(nameBuffer, options);
nameBuffer.append(this.type.compoundName[i]);
} else {
appendNullAnnotation(nameBuffer, options);
if (this.type.sourceName != null)
nameBuffer.append(this.type.sourceName);
else
nameBuffer.append(this.type.readableName());
}
if (this.arguments != null && this.arguments.length > 0 && !isRawType()) {
nameBuffer.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
if (i > 0) nameBuffer.append(',');
nameBuffer.append(this.arguments[i].nullAnnotatedReadableName(options, false));
}
nameBuffer.append('>');
}
int nameLength = nameBuffer.length();
char[] readableName = new char[nameLength];
nameBuffer.getChars(0, nameLength, readableName, 0);
return readableName;
}
@Override
char[] nullAnnotatedShortReadableName(CompilerOptions options) {
StringBuffer nameBuffer = new StringBuffer(10);
if (isMemberType()) {
nameBuffer.append(enclosingType().nullAnnotatedReadableName(options, true));
nameBuffer.append('.');
appendNullAnnotation(nameBuffer, options);
nameBuffer.append(this.sourceName);
} else {
appendNullAnnotation(nameBuffer, options);
if (this.type.sourceName != null)
nameBuffer.append(this.type.sourceName);
else
nameBuffer.append(this.type.shortReadableName());
}
if (this.arguments != null && this.arguments.length > 0 && !isRawType()) {
nameBuffer.append('<');
for (int i = 0, length = this.arguments.length; i < length; i++) {
if (i > 0) nameBuffer.append(',');
nameBuffer.append(this.arguments[i].nullAnnotatedReadableName(options, true));
}
nameBuffer.append('>');
}
int nameLength = nameBuffer.length();
char[] shortReadableName = new char[nameLength];
nameBuffer.getChars(0, nameLength, shortReadableName, 0);
return shortReadableName;
}
@Override
public char[] signature() {
if (this.signature == null) {
this.signature = this.type.signature();
}
return this.signature;
}
@Override
public char[] sourceName() {
return this.type.sourceName();
}
@Override
public TypeBinding substitute(TypeVariableBinding originalVariable) {
ParameterizedTypeBinding currentType = this;
while (true) {
TypeVariableBinding[] typeVariables = currentType.type.typeVariables();
int length = typeVariables.length;
if (originalVariable.rank < length && TypeBinding.equalsEquals(typeVariables[originalVariable.rank], originalVariable)) {
if (currentType.arguments == null)
currentType.initializeArguments();
if (currentType.arguments != null) {
if (currentType.arguments.length == 0) {
return originalVariable;
}
TypeBinding substitute = currentType.arguments[originalVariable.rank];
return originalVariable.combineTypeAnnotations(substitute);
}
}
if (currentType.isStatic()) break;
ReferenceBinding enclosing = currentType.enclosingType();
if (!(enclosing instanceof ParameterizedTypeBinding))
break;
currentType = (ParameterizedTypeBinding) enclosing;
}
return originalVariable;
}
@Override
public ReferenceBinding superclass() {
if (this.superclass == null) {
ReferenceBinding genericSuperclass = this.type.superclass();
if (genericSuperclass == null) return null;
this.superclass = (ReferenceBinding) Scope.substitute(this, genericSuperclass);
this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
this.typeBits |= applyCloseableClassWhitelists();
}
return this.superclass;
}
@Override
public ReferenceBinding[] superInterfaces() {
if (this.superInterfaces == null) {
if (this.type.isHierarchyBeingConnected())
return Binding.NO_SUPERINTERFACES;
this.superInterfaces = Scope.substitute(this, this.type.superInterfaces());
if (this.superInterfaces != null) {
for (int i = this.superInterfaces.length; --i >= 0;) {
this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
this.typeBits |= applyCloseableInterfaceWhitelists();
}
}
}
return this.superInterfaces;
}
@Override
public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
boolean update = false;
if (this.type == unresolvedType) {
this.type = resolvedType;
update = true;
ReferenceBinding enclosing = resolvedType.enclosingType();
if (enclosing != null) {
this.enclosingType = resolvedType.isStatic() ? enclosing : (ReferenceBinding) env.convertUnresolvedBinaryToRawType(enclosing);
}
}
if (this.arguments != null) {
for (int i = 0, l = this.arguments.length; i < l; i++) {
if (this.arguments[i] == unresolvedType) {
this.arguments[i] = env.convertUnresolvedBinaryToRawType(resolvedType);
update = true;
}
}
}
if (update)
initialize(this.type, this.arguments);
}
@Override
public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
return genericType().syntheticEnclosingInstanceTypes();
}
@Override
public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
return genericType().syntheticOuterLocalVariables();
}
@Override
public String toString() {
if (this.hasTypeAnnotations()) {
return annotatedDebugName();
}
StringBuffer buffer = new StringBuffer(30);
if (this.type instanceof UnresolvedReferenceBinding) {
buffer.append(debugName());
} else {
if (isDeprecated()) buffer.append("deprecated ");
if (isPublic()) buffer.append("public ");
if (isProtected()) buffer.append("protected ");
if (isPrivate()) buffer.append("private ");
if (isAbstract() && isClass()) buffer.append("abstract ");
if (isStatic() && isNestedType()) buffer.append("static ");
if (isFinal()) buffer.append("final ");
if (isEnum()) buffer.append("enum ");
else if (isAnnotationType()) buffer.append("@interface ");
else if (isClass()) buffer.append("class ");
else buffer.append("interface ");
buffer.append(debugName());
buffer.append("\n\textends ");
buffer.append((this.superclass != null) ? this.superclass.debugName() : "NULL TYPE");
if (this.superInterfaces != null) {
if (this.superInterfaces != Binding.NO_SUPERINTERFACES) {
buffer.append("\n\timplements : ");
for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
if (i > 0)
buffer.append(", ");
buffer.append((this.superInterfaces[i] != null) ? this.superInterfaces[i].debugName() : "NULL TYPE");
}
}
} else {
buffer.append("NULL SUPERINTERFACES");
}
if (enclosingType() != null) {
buffer.append("\n\tenclosing type : ");
buffer.append(enclosingType().debugName());
}
if (this.fields != null) {
if (this.fields != Binding.NO_FIELDS) {
buffer.append("\n/* fields */");
for (int i = 0, length = this.fields.length; i < length; i++)
buffer.append('\n').append((this.fields[i] != null) ? this.fields[i].toString() : "NULL FIELD");
}
} else {
buffer.append("NULL FIELDS");
}
if (this.methods != null) {
if (this.methods != Binding.NO_METHODS) {
buffer.append("\n/* methods */");
for (int i = 0, length = this.methods.length; i < length; i++)
buffer.append('\n').append((this.methods[i] != null) ? this.methods[i].toString() : "NULL METHOD");
}
} else {
buffer.append("NULL METHODS");
}
buffer.append("\n\n");
}
return buffer.toString();
}
@Override
public TypeVariableBinding[] typeVariables() {
if (this.arguments == null) {
return this.type.typeVariables();
}
return Binding.NO_TYPE_VARIABLES;
}
@Override
public TypeBinding[] typeArguments() {
return this.arguments;
}
@Override
public FieldBinding[] unResolvedFields() {
return this.fields;
}
@Override
protected MethodBinding[] getInterfaceAbstractContracts(Scope scope, boolean replaceWildcards, boolean filterDefaultMethods) throws InvalidInputException {
if (replaceWildcards) {
TypeBinding[] types = getNonWildcardParameterization(scope);
if (types == null)
return new MethodBinding[] { new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.NotAWellFormedParameterizedType) };
for (int i = 0; i < types.length; i++) {
if (TypeBinding.notEquals(types[i], this.arguments[i])) {
ParameterizedTypeBinding declaringType = scope.environment().createParameterizedType(this.type, types, this.type.enclosingType());
TypeVariableBinding [] typeParameters = this.type.typeVariables();
for (int j = 0, length = typeParameters.length; j < length; j++) {
if (!typeParameters[j].boundCheck(declaringType, types[j], scope, null).isOKbyJLS())
return new MethodBinding[] { new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.NotAWellFormedParameterizedType) };
}
return declaringType.getInterfaceAbstractContracts(scope, replaceWildcards, filterDefaultMethods);
}
}
}
return super.getInterfaceAbstractContracts(scope, replaceWildcards, filterDefaultMethods);
}
@Override
public MethodBinding getSingleAbstractMethod(final Scope scope, boolean replaceWildcards) {
return getSingleAbstractMethod(scope, replaceWildcards, -1, -1 );
}
public MethodBinding getSingleAbstractMethod(final Scope scope, boolean replaceWildcards, int start, int end) {
int index = replaceWildcards ? end < 0 ? 0 : 1 : 2;
if (this.singleAbstractMethod != null) {
if (this.singleAbstractMethod[index] != null)
return this.singleAbstractMethod[index];
} else {
this.singleAbstractMethod = new MethodBinding[3];
}
if (!isValidBinding())
return null;
final ReferenceBinding genericType = genericType();
MethodBinding theAbstractMethod = genericType.getSingleAbstractMethod(scope, replaceWildcards);
if (theAbstractMethod == null || !theAbstractMethod.isValidBinding())
return this.singleAbstractMethod[index] = theAbstractMethod;
ParameterizedTypeBinding declaringType = null;
TypeBinding [] types = this.arguments;
if (replaceWildcards) {
types = getNonWildcardParameterization(scope);
if (types == null)
return this.singleAbstractMethod[index] = new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.NotAWellFormedParameterizedType);
} else if (types == null) {
types = NO_TYPES;
}
if (end >= 0) {
for (int i = 0, length = types.length; i < length; i++) {
types[i] = types[i].capture(scope, start, end);
}
}
declaringType = scope.environment().createParameterizedType(genericType, types, genericType.enclosingType());
TypeVariableBinding [] typeParameters = genericType.typeVariables();
for (int i = 0, length = typeParameters.length; i < length; i++) {
if (!typeParameters[i].boundCheck(declaringType, types[i], scope, null).isOKbyJLS())
return this.singleAbstractMethod[index] = new ProblemMethodBinding(TypeConstants.ANONYMOUS_METHOD, null, ProblemReasons.NotAWellFormedParameterizedType);
}
ReferenceBinding substitutedDeclaringType = (ReferenceBinding) declaringType.findSuperTypeOriginatingFrom(theAbstractMethod.declaringClass);
MethodBinding [] choices = substitutedDeclaringType.getMethods(theAbstractMethod.selector);
for (int i = 0, length = choices.length; i < length; i++) {
MethodBinding method = choices[i];
if (!method.isAbstract() || method.redeclaresPublicObjectMethod(scope)) continue;
if (method.problemId() == ProblemReasons.ContradictoryNullAnnotations)
method = ((ProblemMethodBinding) method).closestMatch;
this.singleAbstractMethod[index] = method;
break;
}
return this.singleAbstractMethod[index];
}
public TypeBinding[] getNonWildcardParameterization(Scope scope) {
TypeBinding[] typeArguments = this.arguments;
if (typeArguments == null)
return NO_TYPES;
TypeVariableBinding[] typeParameters = genericType().typeVariables();
TypeBinding[] types = new TypeBinding[typeArguments.length];
for (int i = 0, length = typeArguments.length; i < length; i++) {
TypeBinding typeArgument = typeArguments[i];
if (typeArgument.kind() == Binding.WILDCARD_TYPE) {
if (typeParameters[i].mentionsAny(typeParameters, i))
return null;
WildcardBinding wildcard = (WildcardBinding) typeArgument;
switch(wildcard.boundKind) {
case Wildcard.EXTENDS :
TypeBinding[] otherUBounds = wildcard.otherBounds;
TypeBinding[] otherBBounds = typeParameters[i].otherUpperBounds();
int len = 1 + (otherUBounds != null ? otherUBounds.length : 0) + otherBBounds.length;
if (typeParameters[i].firstBound != null)
len++;
TypeBinding[] allBounds = new TypeBinding[len];
int idx = 0;
allBounds[idx++] = wildcard.bound;
if (otherUBounds != null)
for (int j = 0; j < otherUBounds.length; j++)
allBounds[idx++] = otherUBounds[j];
if (typeParameters[i].firstBound != null)
allBounds[idx++] = typeParameters[i].firstBound;
for (int j = 0; j < otherBBounds.length; j++)
allBounds[idx++] = otherBBounds[j];
TypeBinding[] glb = Scope.greaterLowerBound(allBounds, null, this.environment);
if (glb == null || glb.length == 0) {
return null;
} else if (glb.length == 1) {
types[i] = glb[0];
} else {
try {
ReferenceBinding[] refs = new ReferenceBinding[glb.length];
System.arraycopy(glb, 0, refs, 0, glb.length);
types[i] = this.environment.createIntersectionType18(refs);
} catch (ArrayStoreException ase) {
scope.problemReporter().genericInferenceError("Cannot compute glb of "+Arrays.toString(glb), null);
return null;
}
}
break;
case Wildcard.SUPER :
types[i] = wildcard.bound;
break;
case Wildcard.UNBOUND :
types[i] = typeParameters[i].firstBound;
if (types[i] == null)
types[i] = typeParameters[i].superclass;
break;
}
} else {
types[i] = typeArgument;
}
}
return types;
}
@Override
public long updateTagBits() {
if (this.arguments != null)
for (TypeBinding argument : this.arguments)
this.tagBits |= argument.updateTagBits();
return super.updateTagBits();
}
}