package org.eclipse.jdt.internal.compiler.lookup;
import java.util.ArrayList;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.classfmt.AnnotationInfo;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider.IMethodAnnotationWalker;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfoWithAnnotations;
import org.eclipse.jdt.internal.compiler.classfmt.NonNullDefaultAwareTypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.classfmt.TypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.env.ClassSignature;
import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;
@SuppressWarnings({ "rawtypes", "unchecked" })
public class BinaryTypeBinding extends ReferenceBinding {
public static final char[] TYPE_QUALIFIER_DEFAULT = "TypeQualifierDefault".toCharArray();
private static final IBinaryMethod[] NO_BINARY_METHODS = new IBinaryMethod[0];
protected ReferenceBinding superclass;
protected ReferenceBinding enclosingType;
protected ReferenceBinding[] superInterfaces;
protected FieldBinding[] fields;
protected MethodBinding[] methods;
protected ReferenceBinding[] memberTypes;
protected TypeVariableBinding[] typeVariables;
protected ModuleBinding module;
private BinaryTypeBinding prototype;
protected LookupEnvironment environment;
protected SimpleLookupTable storedAnnotations = null;
private ReferenceBinding containerAnnotationType;
int defaultNullness = 0;
boolean memberTypesSorted = false;
public enum ExternalAnnotationStatus {
FROM_SOURCE,
NOT_EEA_CONFIGURED,
NO_EEA_FILE,
TYPE_IS_ANNOTATED;
public boolean isPotentiallyUnannotatedLib() {
switch (this) {
case FROM_SOURCE:
case TYPE_IS_ANNOTATED:
return false;
default:
return true;
}
}
}
public ExternalAnnotationStatus externalAnnotationStatus = ExternalAnnotationStatus.NOT_EEA_CONFIGURED;
static Object convertMemberValue(Object binaryValue, LookupEnvironment env, char[][][] missingTypeNames, boolean resolveEnumConstants) {
if (binaryValue == null) return null;
if (binaryValue instanceof Constant)
return binaryValue;
if (binaryValue instanceof ClassSignature)
return env.getTypeFromSignature(((ClassSignature) binaryValue).getTypeName(), 0, -1, false, null, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
if (binaryValue instanceof IBinaryAnnotation)
return createAnnotation((IBinaryAnnotation) binaryValue, env, missingTypeNames);
if (binaryValue instanceof EnumConstantSignature) {
EnumConstantSignature ref = (EnumConstantSignature) binaryValue;
ReferenceBinding enumType = (ReferenceBinding) env.getTypeFromSignature(ref.getTypeName(), 0, -1, false, null, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
if (enumType.isUnresolvedType() && !resolveEnumConstants)
return new ElementValuePair.UnresolvedEnumConstant(enumType, env, ref.getEnumConstantName());
enumType = (ReferenceBinding) resolveType(enumType, env, false );
return enumType.getField(ref.getEnumConstantName(), false);
}
if (binaryValue instanceof Object[]) {
Object[] objects = (Object[]) binaryValue;
int length = objects.length;
if (length == 0) return objects;
Object[] values = new Object[length];
for (int i = 0; i < length; i++)
values[i] = convertMemberValue(objects[i], env, missingTypeNames, resolveEnumConstants);
return values;
}
throw new IllegalStateException();
}
@Override
public TypeBinding clone(TypeBinding outerType) {
BinaryTypeBinding copy = new BinaryTypeBinding(this);
copy.enclosingType = (ReferenceBinding) outerType;
if (copy.enclosingType != null)
copy.tagBits |= TagBits.HasUnresolvedEnclosingType;
else
copy.tagBits &= ~TagBits.HasUnresolvedEnclosingType;
copy.tagBits |= TagBits.HasUnresolvedMemberTypes;
return copy;
}
static AnnotationBinding createAnnotation(IBinaryAnnotation annotationInfo, LookupEnvironment env, char[][][] missingTypeNames) {
if (annotationInfo instanceof AnnotationInfo) {
RuntimeException ex = ((AnnotationInfo) annotationInfo).exceptionDuringDecode;
if (ex != null)
new IllegalStateException("Accessing annotation with decode error", ex).printStackTrace();
}
IBinaryElementValuePair[] binaryPairs = annotationInfo.getElementValuePairs();
int length = binaryPairs == null ? 0 : binaryPairs.length;
ElementValuePair[] pairs = length == 0 ? Binding.NO_ELEMENT_VALUE_PAIRS : new ElementValuePair[length];
for (int i = 0; i < length; i++)
pairs[i] = new ElementValuePair(binaryPairs[i].getName(), convertMemberValue(binaryPairs[i].getValue(), env, missingTypeNames, false), null);
char[] typeName = annotationInfo.getTypeName();
LookupEnvironment env2 = annotationInfo.isExternalAnnotation() ? env.root : env;
ReferenceBinding annotationType = env2.getTypeFromConstantPoolName(typeName, 1, typeName.length - 1, false,
missingTypeNames);
return env2.createUnresolvedAnnotation(annotationType, pairs);
}
public static AnnotationBinding[] createAnnotations(IBinaryAnnotation[] annotationInfos, LookupEnvironment env, char[][][] missingTypeNames) {
int length = annotationInfos == null ? 0 : annotationInfos.length;
AnnotationBinding[] result = length == 0 ? Binding.NO_ANNOTATIONS : new AnnotationBinding[length];
for (int i = 0; i < length; i++)
result[i] = createAnnotation(annotationInfos[i], env, missingTypeNames);
return result;
}
public static TypeBinding resolveType(TypeBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
switch (type.kind()) {
case Binding.PARAMETERIZED_TYPE :
((ParameterizedTypeBinding) type).resolve();
break;
case Binding.WILDCARD_TYPE :
case Binding.INTERSECTION_TYPE :
return ((WildcardBinding) type).resolve();
case Binding.ARRAY_TYPE :
ArrayBinding arrayBinding = (ArrayBinding) type;
TypeBinding leafComponentType = arrayBinding.leafComponentType;
resolveType(leafComponentType, environment, convertGenericToRawType);
if (leafComponentType.hasNullTypeAnnotations() && environment.usesNullTypeAnnotations()) {
if (arrayBinding.nullTagBitsPerDimension == null)
arrayBinding.nullTagBitsPerDimension = new long[arrayBinding.dimensions+1];
arrayBinding.nullTagBitsPerDimension[arrayBinding.dimensions] = leafComponentType.tagBits & TagBits.AnnotationNullMASK;
}
break;
case Binding.TYPE_PARAMETER :
((TypeVariableBinding) type).resolve();
break;
case Binding.GENERIC_TYPE :
if (convertGenericToRawType)
return environment.convertUnresolvedBinaryToRawType(type);
break;
default:
if (type instanceof UnresolvedReferenceBinding)
return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
if (convertGenericToRawType)
return environment.convertUnresolvedBinaryToRawType(type);
break;
}
return type;
}
protected BinaryTypeBinding() {
this.prototype = this;
}
public BinaryTypeBinding(BinaryTypeBinding prototype) {
super(prototype);
this.superclass = prototype.superclass;
this.enclosingType = prototype.enclosingType;
this.superInterfaces = prototype.superInterfaces;
this.fields = prototype.fields;
this.methods = prototype.methods;
this.memberTypes = prototype.memberTypes;
this.typeVariables = prototype.typeVariables;
this.prototype = prototype.prototype;
this.environment = prototype.environment;
this.storedAnnotations = prototype.storedAnnotations;
}
public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) {
this(packageBinding, binaryType, environment, false);
}
public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment, boolean needFieldsAndMethods) {
this.prototype = this;
this.compoundName = CharOperation.splitOn('/', binaryType.getName());
computeId();
this.tagBits |= TagBits.IsBinaryBinding;
this.environment = environment;
this.fPackage = packageBinding;
this.fileName = binaryType.getFileName();
char[] typeSignature = binaryType.getGenericSignature();
this.typeVariables = typeSignature != null && typeSignature.length > 0 && typeSignature[0] == Util.C_GENERIC_START
? null
: Binding.NO_TYPE_VARIABLES;
this.sourceName = binaryType.getSourceName();
this.modifiers = binaryType.getModifiers();
if ((binaryType.getTagBits() & TagBits.HierarchyHasProblems) != 0)
this.tagBits |= TagBits.HierarchyHasProblems;
if (binaryType.isAnonymous()) {
this.tagBits |= TagBits.AnonymousTypeMask;
} else if (binaryType.isLocal()) {
this.tagBits |= TagBits.LocalTypeMask;
} else if (binaryType.isMember()) {
this.tagBits |= TagBits.MemberTypeMask;
}
char[] enclosingTypeName = binaryType.getEnclosingTypeName();
if (enclosingTypeName != null) {
this.enclosingType = environment.getTypeFromConstantPoolName(enclosingTypeName, 0, -1, true, null );
this.tagBits |= TagBits.MemberTypeMask;
this.tagBits |= TagBits.HasUnresolvedEnclosingType;
if (enclosingType().isStrictfp())
this.modifiers |= ClassFileConstants.AccStrictfp;
if (enclosingType().isDeprecated())
this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
}
if (needFieldsAndMethods)
cachePartsFrom(binaryType, true);
}
@Override
public boolean canBeSeenBy(Scope sco) {
ModuleBinding mod = sco.module();
return mod.canAccess(this.fPackage) && super.canBeSeenBy(sco);
}
@Override
public FieldBinding[] availableFields() {
if (!isPrototype()) {
return this.prototype.availableFields();
}
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return this.fields;
if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
int length = this.fields.length;
if (length > 1)
ReferenceBinding.sortFields(this.fields, 0, length);
this.tagBits |= TagBits.AreFieldsSorted;
}
FieldBinding[] availableFields = new FieldBinding[this.fields.length];
int count = 0;
for (int i = 0; i < this.fields.length; i++) {
try {
availableFields[count] = resolveTypeFor(this.fields[i]);
count++;
} catch (AbortCompilation a){
}
}
if (count < availableFields.length)
System.arraycopy(availableFields, 0, availableFields = new FieldBinding[count], 0, count);
return availableFields;
}
private TypeVariableBinding[] addMethodTypeVariables(TypeVariableBinding[] methodTypeVars) {
if (!isPrototype()) throw new IllegalStateException();
if (this.typeVariables == null || this.typeVariables == Binding.NO_TYPE_VARIABLES) {
return methodTypeVars;
}
if (methodTypeVars == null || methodTypeVars == Binding.NO_TYPE_VARIABLES) {
return this.typeVariables;
}
int total = this.typeVariables.length + methodTypeVars.length;
TypeVariableBinding[] combinedTypeVars = new TypeVariableBinding[total];
System.arraycopy(this.typeVariables, 0, combinedTypeVars, 0, this.typeVariables.length);
int size = this.typeVariables.length;
loop: for (int i = 0, len = methodTypeVars.length; i < len; i++) {
for (int j = this.typeVariables.length -1 ; j >= 0; j--) {
if (CharOperation.equals(methodTypeVars[i].sourceName, this.typeVariables[j].sourceName))
continue loop;
}
combinedTypeVars[size++] = methodTypeVars[i];
}
if (size != total) {
System.arraycopy(combinedTypeVars, 0, combinedTypeVars = new TypeVariableBinding[size], 0, size);
}
return combinedTypeVars;
}
@Override
public MethodBinding[] availableMethods() {
if (!isPrototype()) {
return this.prototype.availableMethods();
}
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return this.methods;
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
int length = this.methods.length;
if (length > 1)
ReferenceBinding.sortMethods(this.methods, 0, length);
this.tagBits |= TagBits.AreMethodsSorted;
}
MethodBinding[] availableMethods = new MethodBinding[this.methods.length];
int count = 0;
for (int i = 0; i < this.methods.length; i++) {
try {
availableMethods[count] = resolveTypesFor(this.methods[i]);
count++;
} catch (AbortCompilation a){
}
}
if (count < availableMethods.length)
System.arraycopy(availableMethods, 0, availableMethods = new MethodBinding[count], 0, count);
return availableMethods;
}
void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
if (!isPrototype()) throw new IllegalStateException();
try {
this.typeVariables = Binding.NO_TYPE_VARIABLES;
this.superInterfaces = Binding.NO_SUPERINTERFACES;
this.memberTypes = Binding.NO_MEMBER_TYPES;
IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
if (memberTypeStructures != null) {
int size = memberTypeStructures.length;
if (size > 0) {
this.memberTypes = new ReferenceBinding[size];
for (int i = 0; i < size; i++) {
this.memberTypes[i] = this.environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false, null );
}
this.tagBits |= TagBits.HasUnresolvedMemberTypes;
}
}
CompilerOptions globalOptions = this.environment.globalOptions;
long sourceLevel = globalOptions.originalSourceLevel;
if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
scanTypeForNullDefaultAnnotation(binaryType, this.fPackage);
}
ITypeAnnotationWalker walker = getTypeAnnotationWalker(binaryType.getTypeAnnotations(), Binding.NO_NULL_DEFAULT);
ITypeAnnotationWalker toplevelWalker = binaryType.enrichWithExternalAnnotationsFor(walker, null, this.environment);
this.externalAnnotationStatus = binaryType.getExternalAnnotationStatus();
if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && this.defaultNullness != 0) {
this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
}
char[] typeSignature = binaryType.getGenericSignature();
this.tagBits |= binaryType.getTagBits();
if (this.environment.globalOptions.complianceLevel < ClassFileConstants.JDK1_8)
this.tagBits &= ~TagBits.AnnotationForTypeUse;
char[][][] missingTypeNames = binaryType.getMissingTypeNames();
SignatureWrapper wrapper = null;
if (typeSignature != null) {
wrapper = new SignatureWrapper(typeSignature);
if (wrapper.signature[wrapper.start] == Util.C_GENERIC_START) {
wrapper.start++;
this.typeVariables = createTypeVariables(wrapper, true, missingTypeNames, toplevelWalker, true);
wrapper.start++;
this.tagBits |= TagBits.HasUnresolvedTypeVariables;
this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
}
}
TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES;
char[] methodDescriptor = binaryType.getEnclosingMethod();
if (methodDescriptor != null) {
MethodBinding enclosingMethod = findMethod(methodDescriptor, missingTypeNames);
if (enclosingMethod != null) {
typeVars = enclosingMethod.typeVariables;
this.typeVariables = addMethodTypeVariables(typeVars);
}
}
if (typeSignature == null) {
char[] superclassName = binaryType.getSuperclassName();
if (superclassName != null) {
this.superclass = this.environment.getTypeFromConstantPoolName(superclassName, 0, -1, false, missingTypeNames, toplevelWalker.toSupertype((short) -1, superclassName));
this.tagBits |= TagBits.HasUnresolvedSuperclass;
}
this.superInterfaces = Binding.NO_SUPERINTERFACES;
char[][] interfaceNames = binaryType.getInterfaceNames();
if (interfaceNames != null) {
int size = interfaceNames.length;
if (size > 0) {
this.superInterfaces = new ReferenceBinding[size];
for (short i = 0; i < size; i++)
this.superInterfaces[i] = this.environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false, missingTypeNames, toplevelWalker.toSupertype(i, superclassName));
this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
}
}
} else {
this.superclass = (ReferenceBinding) this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames,
toplevelWalker.toSupertype((short) -1, wrapper.peekFullType()));
this.tagBits |= TagBits.HasUnresolvedSuperclass;
this.superInterfaces = Binding.NO_SUPERINTERFACES;
if (!wrapper.atEnd()) {
java.util.ArrayList types = new java.util.ArrayList(2);
short rank = 0;
do {
types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, toplevelWalker.toSupertype(rank++, wrapper.peekFullType())));
} while (!wrapper.atEnd());
this.superInterfaces = new ReferenceBinding[types.size()];
types.toArray(this.superInterfaces);
this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
}
}
boolean canUseNullTypeAnnotations = this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled && this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8;
if (canUseNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
if (this.superclass != null && this.superclass.hasNullTypeAnnotations()) {
this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
} else {
for (TypeBinding ifc : this.superInterfaces) {
if (ifc.hasNullTypeAnnotations()) {
this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
break;
}
}
}
}
if (needFieldsAndMethods) {
IBinaryField[] iFields = binaryType.getFields();
createFields(iFields, binaryType, sourceLevel, missingTypeNames);
IBinaryMethod[] iMethods = createMethods(binaryType.getMethods(), binaryType, sourceLevel, missingTypeNames);
boolean isViewedAsDeprecated = isViewedAsDeprecated();
if (isViewedAsDeprecated) {
for (int i = 0, max = this.fields.length; i < max; i++) {
FieldBinding field = this.fields[i];
if (!field.isDeprecated()) {
field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
}
}
for (int i = 0, max = this.methods.length; i < max; i++) {
MethodBinding method = this.methods[i];
if (!method.isDeprecated()) {
method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
}
}
}
if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
if (iFields != null) {
for (int i = 0; i < iFields.length; i++) {
ITypeAnnotationWalker fieldWalker = ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
if (sourceLevel < ClassFileConstants.JDK1_8)
fieldWalker = binaryType.enrichWithExternalAnnotationsFor(walker, iFields[i], this.environment);
scanFieldForNullAnnotation(iFields[i], this.fields[i], this.isEnum(), fieldWalker);
}
}
if (iMethods != null) {
for (int i = 0; i < iMethods.length; i++) {
ITypeAnnotationWalker methodWalker = ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
if (sourceLevel < ClassFileConstants.JDK1_8)
methodWalker = binaryType.enrichWithExternalAnnotationsFor(methodWalker, iMethods[i], this.environment);
scanMethodForNullAnnotation(iMethods[i], this.methods[i], methodWalker, canUseNullTypeAnnotations);
}
}
}
}
if (this.environment.globalOptions.storeAnnotations) {
setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames), false);
} else if (sourceLevel >= ClassFileConstants.JDK9 && isDeprecated() && binaryType.getAnnotations() != null) {
for (IBinaryAnnotation annotation : binaryType.getAnnotations()) {
if (annotation.isDeprecatedAnnotation()) {
AnnotationBinding[] annotationBindings = createAnnotations(new IBinaryAnnotation[] { annotation }, this.environment, missingTypeNames);
setAnnotations(annotationBindings, true);
for (ElementValuePair elementValuePair : annotationBindings[0].getElementValuePairs()) {
if (CharOperation.equals(elementValuePair.name, TypeConstants.FOR_REMOVAL)) {
if (elementValuePair.value instanceof BooleanConstant && ((BooleanConstant) elementValuePair.value).booleanValue()) {
this.tagBits |= TagBits.AnnotationTerminallyDeprecated;
markImplicitTerminalDeprecation(this);
}
}
}
break;
}
}
}
if (this.isAnnotationType())
scanTypeForContainerAnnotation(binaryType, missingTypeNames);
} finally {
if (this.fields == null)
this.fields = Binding.NO_FIELDS;
if (this.methods == null)
this.methods = Binding.NO_METHODS;
}
}
void markImplicitTerminalDeprecation(ReferenceBinding type) {
for (ReferenceBinding member : type.memberTypes()) {
member.tagBits |= TagBits.AnnotationTerminallyDeprecated;
markImplicitTerminalDeprecation(member);
}
MethodBinding[] methodsOfType = type.unResolvedMethods();
if (methodsOfType != null)
for (MethodBinding methodBinding : methodsOfType)
methodBinding.tagBits |= TagBits.AnnotationTerminallyDeprecated;
FieldBinding[] fieldsOfType = type.unResolvedFields();
if (fieldsOfType != null)
for (FieldBinding fieldBinding : fieldsOfType)
fieldBinding.tagBits |= TagBits.AnnotationTerminallyDeprecated;
}
private ITypeAnnotationWalker getTypeAnnotationWalker(IBinaryTypeAnnotation[] annotations, int nullness) {
if (!isPrototype()) throw new IllegalStateException();
if (annotations == null || annotations.length == 0 || !this.environment.usesAnnotatedTypeSystem()) {
if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
if (nullness == Binding.NO_NULL_DEFAULT)
nullness = getNullDefault();
if (nullness > Binding.NULL_UNSPECIFIED_BY_DEFAULT)
return new NonNullDefaultAwareTypeAnnotationWalker(nullness, this.environment);
}
return ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
}
if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
if (nullness == Binding.NO_NULL_DEFAULT)
nullness = getNullDefault();
if (nullness > Binding.NULL_UNSPECIFIED_BY_DEFAULT)
return new NonNullDefaultAwareTypeAnnotationWalker(annotations, nullness, this.environment);
}
return new TypeAnnotationWalker(annotations);
}
private int getNullDefaultFrom(IBinaryAnnotation[] declAnnotations) {
int result = 0;
if (declAnnotations != null) {
for (IBinaryAnnotation annotation : declAnnotations) {
char[][] typeName = signature2qualifiedTypeName(annotation.getTypeName());
if (this.environment.getNullAnnotationBit(typeName) == TypeIds.BitNonNullByDefaultAnnotation)
result |= getNonNullByDefaultValue(annotation, this.environment);
}
}
return result;
}
private void createFields(IBinaryField[] iFields, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames) {
if (!isPrototype()) throw new IllegalStateException();
boolean save = this.environment.mayTolerateMissingType;
this.environment.mayTolerateMissingType = true;
try {
this.fields = Binding.NO_FIELDS;
if (iFields != null) {
int size = iFields.length;
if (size > 0) {
FieldBinding[] fields1 = new FieldBinding[size];
boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
boolean hasRestrictedAccess = hasRestrictedAccess();
int firstAnnotatedFieldIndex = -1;
for (int i = 0; i < size; i++) {
IBinaryField binaryField = iFields[i];
char[] fieldSignature = use15specifics ? binaryField.getGenericSignature() : null;
ITypeAnnotationWalker walker = getTypeAnnotationWalker(binaryField.getTypeAnnotations(), getNullDefaultFrom(binaryField.getAnnotations()));
if (sourceLevel >= ClassFileConstants.JDK1_8) {
walker = binaryType.enrichWithExternalAnnotationsFor(walker, iFields[i], this.environment);
}
walker = walker.toField();
TypeBinding type = fieldSignature == null
? this.environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this, missingTypeNames, walker)
: this.environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), Binding.NO_TYPE_VARIABLES, this, missingTypeNames, walker);
FieldBinding field =
new FieldBinding(
binaryField.getName(),
type,
binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved,
this,
binaryField.getConstant());
boolean forceStoreAnnotations = !this.environment.globalOptions.storeAnnotations
&& (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK9
&& binaryField.getAnnotations() != null
&& (binaryField.getTagBits() & TagBits.AnnotationDeprecated) != 0);
if (firstAnnotatedFieldIndex < 0
&& (this.environment.globalOptions.storeAnnotations || forceStoreAnnotations)
&& binaryField.getAnnotations() != null) {
firstAnnotatedFieldIndex = i;
if (forceStoreAnnotations)
storedAnnotations(true, true);
}
field.id = i;
if (use15specifics)
field.tagBits |= binaryField.getTagBits();
if (hasRestrictedAccess)
field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
if (fieldSignature != null)
field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
fields1[i] = field;
}
this.fields = fields1;
if (firstAnnotatedFieldIndex >= 0) {
for (int i = firstAnnotatedFieldIndex; i <size; i++) {
IBinaryField binaryField = iFields[i];
this.fields[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames), false);
}
}
}
}
} finally {
this.environment.mayTolerateMissingType = save;
}
}
private MethodBinding createMethod(IBinaryMethod method, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames) {
if (!isPrototype()) throw new IllegalStateException();
int methodModifiers = method.getModifiers() | ExtraCompilerModifiers.AccUnresolved;
if (sourceLevel < ClassFileConstants.JDK1_5)
methodModifiers &= ~ClassFileConstants.AccVarargs;
if (isInterface() && (methodModifiers & ClassFileConstants.AccAbstract) == 0) {
if (((methodModifiers & ClassFileConstants.AccStatic) == 0
&& (methodModifiers & ClassFileConstants.AccPrivate) == 0)) {
methodModifiers |= ExtraCompilerModifiers.AccDefaultMethod;
}
}
ReferenceBinding[] exceptions = Binding.NO_EXCEPTIONS;
TypeBinding[] parameters = Binding.NO_PARAMETERS;
TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES;
AnnotationBinding[][] paramAnnotations = null;
TypeBinding returnType = null;
char[][] argumentNames = method.getArgumentNames();
final boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
ITypeAnnotationWalker walker = getTypeAnnotationWalker(method.getTypeAnnotations(), getNullDefaultFrom(method.getAnnotations()));
char[] methodSignature = method.getGenericSignature();
if (methodSignature == null) {
char[] methodDescriptor = method.getMethodDescriptor();
if (sourceLevel >= ClassFileConstants.JDK1_8) {
walker = binaryType.enrichWithExternalAnnotationsFor(walker, method, this.environment);
}
int numOfParams = 0;
char nextChar;
int index = 0;
while ((nextChar = methodDescriptor[++index]) != Util.C_PARAM_END) {
if (nextChar != Util.C_ARRAY) {
numOfParams++;
if (nextChar == Util.C_RESOLVED)
while ((nextChar = methodDescriptor[++index]) != Util.C_NAME_END){}
}
}
int startIndex = 0;
if (method.isConstructor()) {
if (isMemberType() && !isStatic()) {
startIndex++;
}
if (isEnum()) {
startIndex += 2;
}
}
int size = numOfParams - startIndex;
if (size > 0) {
parameters = new TypeBinding[size];
if (this.environment.globalOptions.storeAnnotations)
paramAnnotations = new AnnotationBinding[size][];
index = 1;
short visibleIdx = 0;
int end = 0;
for (int i = 0; i < numOfParams; i++) {
while ((nextChar = methodDescriptor[++end]) == Util.C_ARRAY){}
if (nextChar == Util.C_RESOLVED)
while ((nextChar = methodDescriptor[++end]) != Util.C_NAME_END){}
if (i >= startIndex) {
parameters[i - startIndex] = this.environment.getTypeFromSignature(methodDescriptor, index, end, false, this, missingTypeNames, walker.toMethodParameter(visibleIdx++));
if (paramAnnotations != null)
paramAnnotations[i - startIndex] = createAnnotations(method.getParameterAnnotations(i - startIndex, this.fileName), this.environment, missingTypeNames);
}
index = end + 1;
}
}
char[][] exceptionTypes = method.getExceptionTypeNames();
if (exceptionTypes != null) {
size = exceptionTypes.length;
if (size > 0) {
exceptions = new ReferenceBinding[size];
for (int i = 0; i < size; i++)
exceptions[i] = this.environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false, missingTypeNames, walker.toThrows(i));
}
}
if (!method.isConstructor())
returnType = this.environment.getTypeFromSignature(methodDescriptor, index + 1, -1, false, this, missingTypeNames, walker.toMethodReturn());
final int argumentNamesLength = argumentNames == null ? 0 : argumentNames.length;
if (startIndex > 0 && argumentNamesLength > 0) {
if (startIndex >= argumentNamesLength) {
argumentNames = Binding.NO_PARAMETER_NAMES;
} else {
char[][] slicedArgumentNames = new char[argumentNamesLength - startIndex][];
System.arraycopy(argumentNames, startIndex, slicedArgumentNames, 0, argumentNamesLength - startIndex);
argumentNames = slicedArgumentNames;
}
}
} else {
if (sourceLevel >= ClassFileConstants.JDK1_8) {
walker = binaryType.enrichWithExternalAnnotationsFor(walker, method, this.environment);
}
methodModifiers |= ExtraCompilerModifiers.AccGenericSignature;
SignatureWrapper wrapper = new SignatureWrapper(methodSignature, use15specifics);
if (wrapper.signature[wrapper.start] == Util.C_GENERIC_START) {
wrapper.start++;
typeVars = createTypeVariables(wrapper, false, missingTypeNames, walker, false);
wrapper.start++;
}
if (wrapper.signature[wrapper.start] == Util.C_PARAM_START) {
wrapper.start++;
if (wrapper.signature[wrapper.start] == Util.C_PARAM_END) {
wrapper.start++;
} else {
java.util.ArrayList types = new java.util.ArrayList(2);
short rank = 0;
while (wrapper.signature[wrapper.start] != Util.C_PARAM_END) {
IBinaryAnnotation[] binaryParameterAnnotations = method.getParameterAnnotations(rank, this.fileName);
ITypeAnnotationWalker updatedWalker = NonNullDefaultAwareTypeAnnotationWalker.updateWalkerForParamNonNullDefault(walker, getNullDefaultFrom(binaryParameterAnnotations), this.environment);
types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, updatedWalker.toMethodParameter(rank)));
rank++;
}
wrapper.start++;
int numParam = types.size();
parameters = new TypeBinding[numParam];
types.toArray(parameters);
if (this.environment.globalOptions.storeAnnotations) {
paramAnnotations = new AnnotationBinding[numParam][];
for (int i = 0; i < numParam; i++)
paramAnnotations[i] = createAnnotations(method.getParameterAnnotations(i, this.fileName), this.environment, missingTypeNames);
}
}
}
returnType = this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, walker.toMethodReturn());
if (!wrapper.atEnd() && wrapper.signature[wrapper.start] == Util.C_EXCEPTION_START) {
java.util.ArrayList types = new java.util.ArrayList(2);
int excRank = 0;
do {
wrapper.start++;
types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames,
walker.toThrows(excRank++)));
} while (!wrapper.atEnd() && wrapper.signature[wrapper.start] == Util.C_EXCEPTION_START);
exceptions = new ReferenceBinding[types.size()];
types.toArray(exceptions);
} else {
char[][] exceptionTypes = method.getExceptionTypeNames();
if (exceptionTypes != null) {
int size = exceptionTypes.length;
if (size > 0) {
exceptions = new ReferenceBinding[size];
for (int i = 0; i < size; i++)
exceptions[i] = this.environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false, missingTypeNames, walker.toThrows(i));
}
}
}
}
MethodBinding result = method.isConstructor()
? new MethodBinding(methodModifiers, parameters, exceptions, this)
: new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
IBinaryAnnotation[] receiverAnnotations = walker.toReceiver().getAnnotationsAtCursor(this.id, false);
if (receiverAnnotations != null && receiverAnnotations.length > 0) {
result.receiver = this.environment.createAnnotatedType(this, createAnnotations(receiverAnnotations, this.environment, missingTypeNames));
}
boolean forceStoreAnnotations = !this.environment.globalOptions.storeAnnotations
&& (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK9
&& method instanceof MethodInfoWithAnnotations
&& (method.getTagBits() & TagBits.AnnotationDeprecated) != 0);
if (this.environment.globalOptions.storeAnnotations || forceStoreAnnotations) {
if (forceStoreAnnotations)
storedAnnotations(true, true);
IBinaryAnnotation[] annotations = method.getAnnotations();
if (method.isConstructor()) {
IBinaryAnnotation[] tAnnotations = walker.toMethodReturn().getAnnotationsAtCursor(this.id, false);
result.setTypeAnnotations(createAnnotations(tAnnotations, this.environment, missingTypeNames));
}
result.setAnnotations(
createAnnotations(annotations, this.environment, missingTypeNames),
paramAnnotations,
isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames, true) : null,
this.environment);
}
if (argumentNames != null) result.parameterNames = argumentNames;
if (use15specifics)
result.tagBits |= method.getTagBits();
result.typeVariables = typeVars;
for (int i = 0, length = typeVars.length; i < length; i++)
this.environment.typeSystem.fixTypeVariableDeclaringElement(typeVars[i], result);
return result;
}
private IBinaryMethod[] createMethods(IBinaryMethod[] iMethods, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames) {
if (!isPrototype()) throw new IllegalStateException();
boolean save = this.environment.mayTolerateMissingType;
this.environment.mayTolerateMissingType = true;
try {
int total = 0, initialTotal = 0, iClinit = -1;
int[] toSkip = null;
if (iMethods != null) {
total = initialTotal = iMethods.length;
boolean keepBridgeMethods = sourceLevel < ClassFileConstants.JDK1_5;
for (int i = total; --i >= 0;) {
IBinaryMethod method = iMethods[i];
if ((method.getModifiers() & ClassFileConstants.AccSynthetic) != 0) {
if (keepBridgeMethods && (method.getModifiers() & ClassFileConstants.AccBridge) != 0)
continue;
if (toSkip == null) toSkip = new int[iMethods.length];
toSkip[i] = -1;
total--;
} else if (iClinit == -1) {
char[] methodName = method.getSelector();
if (methodName.length == 8 && methodName[0] == Util.C_GENERIC_START) {
iClinit = i;
total--;
}
}
}
}
if (total == 0) {
this.methods = Binding.NO_METHODS;
return NO_BINARY_METHODS;
}
boolean hasRestrictedAccess = hasRestrictedAccess();
MethodBinding[] methods1 = new MethodBinding[total];
if (total == initialTotal) {
for (int i = 0; i < initialTotal; i++) {
MethodBinding method = createMethod(iMethods[i], binaryType, sourceLevel, missingTypeNames);
if (hasRestrictedAccess)
method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
methods1[i] = method;
}
this.methods = methods1;
return iMethods;
} else {
IBinaryMethod[] mappedBinaryMethods = new IBinaryMethod[total];
for (int i = 0, index = 0; i < initialTotal; i++) {
if (iClinit != i && (toSkip == null || toSkip[i] != -1)) {
MethodBinding method = createMethod(iMethods[i], binaryType, sourceLevel, missingTypeNames);
if (hasRestrictedAccess)
method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
mappedBinaryMethods[index] = iMethods[i];
methods1[index++] = method;
}
}
this.methods = methods1;
return mappedBinaryMethods;
}
} finally {
this.environment.mayTolerateMissingType = save;
}
}
private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, boolean assignVariables, char[][][] missingTypeNames,
ITypeAnnotationWalker walker, boolean isClassTypeParameter)
{
if (!isPrototype()) throw new IllegalStateException();
char[] typeSignature = wrapper.signature;
int depth = 0, length = typeSignature.length;
int rank = 0;
ArrayList variables = new ArrayList(1);
depth = 0;
boolean pendingVariable = true;
createVariables: {
for (int i = 1; i < length; i++) {
switch(typeSignature[i]) {
case Util.C_GENERIC_START :
depth++;
break;
case Util.C_GENERIC_END :
if (--depth < 0)
break createVariables;
break;
case Util.C_NAME_END :
if ((depth == 0) && (i +1 < length) && (typeSignature[i+1] != Util.C_COLON))
pendingVariable = true;
break;
default:
if (pendingVariable) {
pendingVariable = false;
int colon = CharOperation.indexOf(Util.C_COLON, typeSignature, i);
char[] variableName = CharOperation.subarray(typeSignature, i, colon);
TypeVariableBinding typeVariable = new TypeVariableBinding(variableName, this, rank, this.environment);
AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.toTypeParameter(isClassTypeParameter, rank++).getAnnotationsAtCursor(0, false),
this.environment, missingTypeNames);
if (annotations != null && annotations != Binding.NO_ANNOTATIONS)
typeVariable.setTypeAnnotations(annotations, this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
variables.add(typeVariable);
}
}
}
}
TypeVariableBinding[] result;
variables.toArray(result = new TypeVariableBinding[rank]);
if (assignVariables)
this.typeVariables = result;
for (int i = 0; i < rank; i++) {
initializeTypeVariable(result[i], result, wrapper, missingTypeNames, walker.toTypeParameterBounds(isClassTypeParameter, i));
if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && result[i].hasNullTypeAnnotations())
this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
}
return result;
}
@Override
public ReferenceBinding enclosingType() {
if ((this.tagBits & TagBits.HasUnresolvedEnclosingType) == 0)
return this.enclosingType;
this.enclosingType = (ReferenceBinding) resolveType(this.enclosingType, this.environment, false );
this.tagBits &= ~TagBits.HasUnresolvedEnclosingType;
return this.enclosingType;
}
@Override
public FieldBinding[] fields() {
if (!isPrototype()) {
return this.fields = this.prototype.fields();
}
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return this.fields;
if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
int length = this.fields.length;
if (length > 1)
ReferenceBinding.sortFields(this.fields, 0, length);
this.tagBits |= TagBits.AreFieldsSorted;
}
for (int i = this.fields.length; --i >= 0;)
resolveTypeFor(this.fields[i]);
this.tagBits |= TagBits.AreFieldsComplete;
return this.fields;
}
private MethodBinding findMethod(char[] methodDescriptor, char[][][] missingTypeNames) {
if (!isPrototype()) throw new IllegalStateException();
int index = -1;
while (methodDescriptor[++index] != Util.C_PARAM_START) {
}
char[] selector = new char[index];
System.arraycopy(methodDescriptor, 0, selector, 0, index);
TypeBinding[] parameters = Binding.NO_PARAMETERS;
int numOfParams = 0;
char nextChar;
int paramStart = index;
while ((nextChar = methodDescriptor[++index]) != Util.C_PARAM_END) {
if (nextChar != Util.C_ARRAY) {
numOfParams++;
if (nextChar == Util.C_RESOLVED)
while ((nextChar = methodDescriptor[++index]) != Util.C_NAME_END){}
}
}
if (numOfParams > 0) {
parameters = new TypeBinding[numOfParams];
index = paramStart + 1;
int end = paramStart;
for (int i = 0; i < numOfParams; i++) {
while ((nextChar = methodDescriptor[++end]) == Util.C_ARRAY){}
if (nextChar == Util.C_RESOLVED)
while ((nextChar = methodDescriptor[++end]) != Util.C_NAME_END){}
TypeBinding param = this.environment.getTypeFromSignature(methodDescriptor, index, end, false, this, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
if (param instanceof UnresolvedReferenceBinding) {
param = resolveType(param, this.environment, true );
}
parameters[i] = param;
index = end + 1;
}
}
int parameterLength = parameters.length;
MethodBinding[] methods2 = this.enclosingType.getMethods(selector, parameterLength);
loop: for (int i = 0, max = methods2.length; i < max; i++) {
MethodBinding currentMethod = methods2[i];
TypeBinding[] parameters2 = currentMethod.parameters;
int currentMethodParameterLength = parameters2.length;
if (parameterLength == currentMethodParameterLength) {
for (int j = 0; j < currentMethodParameterLength; j++) {
if (TypeBinding.notEquals(parameters[j], parameters2[j]) && TypeBinding.notEquals(parameters[j].erasure(), parameters2[j].erasure())) {
continue loop;
}
}
return currentMethod;
}
}
return null;
}
@Override
public char[] genericTypeSignature() {
if (!isPrototype())
return this.prototype.computeGenericTypeSignature(this.typeVariables);
return computeGenericTypeSignature(this.typeVariables);
}
@Override
public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
if (!isPrototype())
return this.prototype.getExactConstructor(argumentTypes);
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
int length = this.methods.length;
if (length > 1)
ReferenceBinding.sortMethods(this.methods, 0, length);
this.tagBits |= TagBits.AreMethodsSorted;
}
int argCount = argumentTypes.length;
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) {
resolveTypesFor(method);
TypeBinding[] toMatch = method.parameters;
for (int iarg = 0; iarg < argCount; iarg++)
if (TypeBinding.notEquals(toMatch[iarg], argumentTypes[iarg]))
continue nextMethod;
return method;
}
}
}
return null;
}
@Override
public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
if (!isPrototype())
return this.prototype.getExactMethod(selector, argumentTypes, refScope);
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
int length = this.methods.length;
if (length > 1)
ReferenceBinding.sortMethods(this.methods, 0, length);
this.tagBits |= TagBits.AreMethodsSorted;
}
int argCount = argumentTypes.length;
boolean foundNothing = true;
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) {
resolveTypesFor(method);
TypeBinding[] toMatch = method.parameters;
for (int iarg = 0; iarg < argCount; iarg++)
if (TypeBinding.notEquals(toMatch[iarg], argumentTypes[iarg]))
continue nextMethod;
return method;
}
}
}
if (foundNothing) {
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 (!isPrototype())
return this.prototype.getField(fieldName, needResolve);
if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
int length = this.fields.length;
if (length > 1)
ReferenceBinding.sortFields(this.fields, 0, length);
this.tagBits |= TagBits.AreFieldsSorted;
}
FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields);
return needResolve && field != null ? resolveTypeFor(field) : field;
}
@Override
public ReferenceBinding getMemberType(char[] typeName) {
if (!isPrototype()) {
ReferenceBinding memberType = this.prototype.getMemberType(typeName);
return memberType == null ? null : this.environment.createMemberType(memberType, this);
}
ReferenceBinding[] members = maybeSortedMemberTypes();
if (!this.memberTypesSorted) {
for (int i = members.length; --i >= 0;) {
ReferenceBinding memberType = members[i];
if (memberType instanceof UnresolvedReferenceBinding) {
char[] name = memberType.sourceName;
int prefixLength = this.compoundName[this.compoundName.length - 1].length + 1;
if (name.length == (prefixLength + typeName.length))
if (CharOperation.fragmentEquals(typeName, name, prefixLength, true))
return members[i] = (ReferenceBinding) resolveType(memberType, this.environment, false );
} else if (CharOperation.equals(typeName, memberType.sourceName)) {
return memberType;
}
}
return null;
}
int memberTypeIndex = ReferenceBinding.binarySearch(typeName, members);
if (memberTypeIndex >= 0) {
return members[memberTypeIndex];
}
return null;
}
@Override
public MethodBinding[] getMethods(char[] selector) {
if (!isPrototype())
return this.prototype.getMethods(selector);
if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
long range;
if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
int start = (int) range, end = (int) (range >> 32);
int length = end - start + 1;
if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
MethodBinding[] result;
System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
return result;
}
}
return Binding.NO_METHODS;
}
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
int length = this.methods.length;
if (length > 1)
ReferenceBinding.sortMethods(this.methods, 0, length);
this.tagBits |= TagBits.AreMethodsSorted;
}
long range;
if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
int start = (int) range, end = (int) (range >> 32);
int length = end - start + 1;
MethodBinding[] result = new MethodBinding[length];
for (int i = start, index = 0; i <= end; i++, index++)
result[index] = resolveTypesFor(this.methods[i]);
return result;
}
return Binding.NO_METHODS;
}
@Override
public MethodBinding[] getMethods(char[] selector, int suggestedParameterLength) {
if (!isPrototype())
return this.prototype.getMethods(selector, suggestedParameterLength);
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return getMethods(selector);
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
int length = this.methods.length;
if (length > 1)
ReferenceBinding.sortMethods(this.methods, 0, length);
this.tagBits |= TagBits.AreMethodsSorted;
}
long range;
if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
int start = (int) range, end = (int) (range >> 32);
int length = end - start + 1;
int count = 0;
for (int i = start; i <= end; i++) {
if (this.methods[i].doesParameterLengthMatch(suggestedParameterLength))
count++;
}
if (count == 0) {
MethodBinding[] result = new MethodBinding[length];
for (int i = start, index = 0; i <= end; i++)
result[index++] = resolveTypesFor(this.methods[i]);
return result;
} else {
MethodBinding[] result = new MethodBinding[count];
for (int i = start, index = 0; i <= end; i++) {
if (this.methods[i].doesParameterLengthMatch(suggestedParameterLength))
result[index++] = resolveTypesFor(this.methods[i]);
}
return result;
}
}
return Binding.NO_METHODS;
}
@Override
public boolean hasMemberTypes() {
if (!isPrototype())
return this.prototype.hasMemberTypes();
return this.memberTypes.length > 0;
}
@Override
public TypeVariableBinding getTypeVariable(char[] variableName) {
if (!isPrototype())
return this.prototype.getTypeVariable(variableName);
TypeVariableBinding variable = super.getTypeVariable(variableName);
variable.resolve();
return variable;
}
@Override
public boolean hasTypeBit(int bit) {
if (!isPrototype())
return this.prototype.hasTypeBit(bit);
boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
this.environment.mayTolerateMissingType = true;
try {
superclass();
superInterfaces();
} finally {
this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
}
return (this.typeBits & bit) != 0;
}
private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames, ITypeAnnotationWalker walker) {
if (!isPrototype()) throw new IllegalStateException();
int colon = CharOperation.indexOf(Util.C_COLON, wrapper.signature, wrapper.start);
wrapper.start = colon + 1;
ReferenceBinding type, firstBound = null;
short rank = 0;
if (wrapper.signature[wrapper.start] == Util.C_COLON) {
type = this.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null);
rank++;
} else {
TypeBinding typeFromTypeSignature = this.environment.getTypeFromTypeSignature(wrapper, existingVariables, this, missingTypeNames, walker.toTypeBound(rank++));
if (typeFromTypeSignature instanceof ReferenceBinding) {
type = (ReferenceBinding) typeFromTypeSignature;
} else {
type = this.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null);
}
firstBound = type;
}
variable.modifiers |= ExtraCompilerModifiers.AccUnresolved;
variable.setSuperClass(type);
ReferenceBinding[] bounds = null;
if (wrapper.signature[wrapper.start] == Util.C_COLON) {
java.util.ArrayList types = new java.util.ArrayList(2);
do {
wrapper.start++;
types.add(this.environment.getTypeFromTypeSignature(wrapper, existingVariables, this, missingTypeNames, walker.toTypeBound(rank++)));
} while (wrapper.signature[wrapper.start] == Util.C_COLON);
bounds = new ReferenceBinding[types.size()];
types.toArray(bounds);
}
variable.setSuperInterfaces(bounds == null ? Binding.NO_SUPERINTERFACES : bounds);
if (firstBound == null) {
firstBound = variable.superInterfaces.length == 0 ? null : variable.superInterfaces[0];
}
variable.setFirstBound(firstBound);
}
@Override
public boolean isEquivalentTo(TypeBinding otherType) {
if (TypeBinding.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:
case Binding.RAW_TYPE :
return TypeBinding.equalsEquals(otherType.erasure(), this);
}
return false;
}
@Override
public boolean isGenericType() {
if (!isPrototype())
return this.prototype.isGenericType();
return this.typeVariables != Binding.NO_TYPE_VARIABLES;
}
@Override
public boolean isHierarchyConnected() {
if (!isPrototype())
return this.prototype.isHierarchyConnected();
return (this.tagBits & (TagBits.HasUnresolvedSuperclass | TagBits.HasUnresolvedSuperinterfaces)) == 0;
}
@Override
public boolean isRepeatableAnnotationType() {
if (!isPrototype()) throw new IllegalStateException();
return this.containerAnnotationType != null;
}
@Override
public int kind() {
if (!isPrototype())
return this.prototype.kind();
if (this.typeVariables != Binding.NO_TYPE_VARIABLES)
return Binding.GENERIC_TYPE;
return Binding.TYPE;
}
@Override
public ReferenceBinding[] memberTypes() {
if (!isPrototype()) {
if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
return this.memberTypes;
ReferenceBinding [] members = this.prototype.memberTypes();
int memberTypesLength = members == null ? 0 : members.length;
if (memberTypesLength > 0) {
this.memberTypes = new ReferenceBinding[memberTypesLength];
for (int i = 0; i < memberTypesLength; i++)
this.memberTypes[i] = this.environment.createMemberType(members[i], this);
}
this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
this.memberTypesSorted = true;
return this.memberTypes;
}
if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0) {
return maybeSortedMemberTypes();
}
for (int i = this.memberTypes.length; --i >= 0;)
this.memberTypes[i] = (ReferenceBinding) resolveType(this.memberTypes[i], this.environment, false );
this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
return maybeSortedMemberTypes();
}
private ReferenceBinding[] maybeSortedMemberTypes() {
if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) != 0) {
return this.memberTypes;
}
if (!this.memberTypesSorted) {
int length = this.memberTypes.length;
if (length > 1)
sortMemberTypes(this.memberTypes, 0, length);
this.memberTypesSorted = true;
}
return this.memberTypes;
}
@Override
public MethodBinding[] methods() {
if (!isPrototype()) {
return this.methods = this.prototype.methods();
}
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return this.methods;
if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
int length = this.methods.length;
if (length > 1)
ReferenceBinding.sortMethods(this.methods, 0, length);
this.tagBits |= TagBits.AreMethodsSorted;
}
for (int i = this.methods.length; --i >= 0;)
resolveTypesFor(this.methods[i]);
this.tagBits |= TagBits.AreMethodsComplete;
return this.methods;
}
@Override
public void setHierarchyCheckDone() {
this.tagBits |= TagBits.BeginHierarchyCheck | TagBits.EndHierarchyCheck;
}
@Override
public TypeBinding prototype() {
return this.prototype;
}
private boolean isPrototype() {
return this == this.prototype;
}
@Override
public ReferenceBinding containerAnnotationType() {
if (!isPrototype()) throw new IllegalStateException();
if (this.containerAnnotationType instanceof UnresolvedReferenceBinding) {
this.containerAnnotationType = (ReferenceBinding) BinaryTypeBinding.resolveType(this.containerAnnotationType, this.environment, false);
}
return this.containerAnnotationType;
}
private FieldBinding resolveTypeFor(FieldBinding field) {
if (!isPrototype())
return this.prototype.resolveTypeFor(field);
if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
return field;
TypeBinding resolvedType = resolveType(field.type, this.environment, true );
field.type = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
field.tagBits |= TagBits.HasMissingType;
}
field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
return field;
}
MethodBinding resolveTypesFor(MethodBinding method) {
if (!isPrototype())
return this.prototype.resolveTypesFor(method);
if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
return method;
if (!method.isConstructor()) {
TypeBinding resolvedType = resolveType(method.returnType, this.environment, true );
method.returnType = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
}
}
for (int i = method.parameters.length; --i >= 0;) {
TypeBinding resolvedType = resolveType(method.parameters[i], this.environment, true );
method.parameters[i] = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
}
}
for (int i = method.thrownExceptions.length; --i >= 0;) {
ReferenceBinding resolvedType = (ReferenceBinding) resolveType(method.thrownExceptions[i], this.environment, true );
method.thrownExceptions[i] = resolvedType;
if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
}
}
for (int i = method.typeVariables.length; --i >= 0;) {
method.typeVariables[i].resolve();
}
method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
return method;
}
@Override
AnnotationBinding[] retrieveAnnotations(Binding binding) {
if (!isPrototype())
return this.prototype.retrieveAnnotations(binding);
return AnnotationBinding.addStandardAnnotations(super.retrieveAnnotations(binding), binding.getAnnotationTagBits(), this.environment);
}
@Override
public void setContainerAnnotationType(ReferenceBinding value) {
if (!isPrototype()) throw new IllegalStateException();
this.containerAnnotationType = value;
}
@Override
public void tagAsHavingDefectiveContainerType() {
if (!isPrototype()) throw new IllegalStateException();
if (this.containerAnnotationType != null && this.containerAnnotationType.isValidBinding())
this.containerAnnotationType = new ProblemReferenceBinding(this.containerAnnotationType.compoundName, this.containerAnnotationType, ProblemReasons.DefectiveContainerAnnotationType);
}
@Override
SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) {
if (!isPrototype())
return this.prototype.storedAnnotations(forceInitialize, forceStore);
if (forceInitialize && this.storedAnnotations == null) {
if (!this.environment.globalOptions.storeAnnotations && !forceStore)
return null;
this.storedAnnotations = new SimpleLookupTable(3);
}
return this.storedAnnotations;
}
private void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBinding, boolean isEnum, ITypeAnnotationWalker externalAnnotationWalker) {
if (!isPrototype()) throw new IllegalStateException();
if (isEnum && (field.getModifiers() & ClassFileConstants.AccEnum) != 0) {
fieldBinding.tagBits |= TagBits.AnnotationNonNull;
return;
}
if (!CharOperation.equals(this.fPackage.compoundName, TypeConstants.JAVA_LANG_ANNOTATION)
&& this.environment.usesNullTypeAnnotations()) {
TypeBinding fieldType = fieldBinding.type;
if (fieldType != null
&& !fieldType.isBaseType()
&& (fieldType.tagBits & TagBits.AnnotationNullMASK) == 0
&& fieldType.acceptsNonNullDefault()) {
int nullDefaultFromField = getNullDefaultFrom(field.getAnnotations());
if (nullDefaultFromField == Binding.NO_NULL_DEFAULT
? hasNonNullDefaultFor(DefaultLocationField, -1)
: (nullDefaultFromField & DefaultLocationField) != 0) {
fieldBinding.type = this.environment.createAnnotatedType(fieldType,
new AnnotationBinding[] { this.environment.getNonNullAnnotation() });
}
}
return;
}
if (fieldBinding.type == null || fieldBinding.type.isBaseType())
return;
boolean explicitNullness = false;
IBinaryAnnotation[] annotations = externalAnnotationWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER
? externalAnnotationWalker.getAnnotationsAtCursor(fieldBinding.type.id, false)
: field.getAnnotations();
if (annotations != null) {
for (int i = 0; i < annotations.length; i++) {
char[] annotationTypeName = annotations[i].getTypeName();
if (annotationTypeName[0] != Util.C_RESOLVED)
continue;
int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
if (typeBit == TypeIds.BitNonNullAnnotation) {
fieldBinding.tagBits |= TagBits.AnnotationNonNull;
explicitNullness = true;
break;
}
if (typeBit == TypeIds.BitNullableAnnotation) {
fieldBinding.tagBits |= TagBits.AnnotationNullable;
explicitNullness = true;
break;
}
}
}
if (explicitNullness && this.externalAnnotationStatus.isPotentiallyUnannotatedLib())
this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
if (!explicitNullness) {
int nullDefaultFromField = getNullDefaultFrom(field.getAnnotations());
if (nullDefaultFromField == Binding.NO_NULL_DEFAULT ? hasNonNullDefaultFor(DefaultLocationField, -1)
: (nullDefaultFromField & DefaultLocationField) != 0) {
fieldBinding.tagBits |= TagBits.AnnotationNonNull;
}
}
}
private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding, ITypeAnnotationWalker externalAnnotationWalker, boolean useNullTypeAnnotations) {
if (!isPrototype()) throw new IllegalStateException();
if (isEnum()) {
int purpose = 0;
if (CharOperation.equals(TypeConstants.VALUEOF, method.getSelector())
&& methodBinding.parameters.length == 1
&& methodBinding.parameters[0].id == TypeIds.T_JavaLangString)
{
purpose = SyntheticMethodBinding.EnumValueOf;
} else if (CharOperation.equals(TypeConstants.VALUES, method.getSelector())
&& methodBinding.parameters == Binding.NO_PARAMETERS) {
purpose = SyntheticMethodBinding.EnumValues;
}
if (purpose != 0) {
boolean needToDefer = this.environment.globalOptions.useNullTypeAnnotations == null;
if (needToDefer)
this.environment.deferredEnumMethods.add(methodBinding);
else
SyntheticMethodBinding.markNonNull(methodBinding, purpose, this.environment);
return;
}
}
ITypeAnnotationWalker returnWalker = externalAnnotationWalker.toMethodReturn();
IBinaryAnnotation[] annotations = returnWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER
? returnWalker.getAnnotationsAtCursor(methodBinding.returnType.id, false)
: method.getAnnotations();
if (annotations != null) {
int methodDefaultNullness = NO_NULL_DEFAULT;
for (int i = 0; i < annotations.length; i++) {
char[] annotationTypeName = annotations[i].getTypeName();
if (annotationTypeName[0] != Util.C_RESOLVED)
continue;
int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
if (typeBit == TypeIds.BitNonNullByDefaultAnnotation) {
methodDefaultNullness |= getNonNullByDefaultValue(annotations[i], this.environment);
} else if (typeBit == TypeIds.BitNonNullAnnotation) {
methodBinding.tagBits |= TagBits.AnnotationNonNull;
if (this.environment.usesNullTypeAnnotations()) {
if (methodBinding.returnType != null && !methodBinding.returnType.hasNullTypeAnnotations()) {
methodBinding.returnType = this.environment.createAnnotatedType(methodBinding.returnType,
new AnnotationBinding[] { this.environment.getNonNullAnnotation() });
}
}
} else if (typeBit == TypeIds.BitNullableAnnotation) {
methodBinding.tagBits |= TagBits.AnnotationNullable;
if (this.environment.usesNullTypeAnnotations()) {
if (methodBinding.returnType != null && !methodBinding.returnType.hasNullTypeAnnotations()) {
methodBinding.returnType = this.environment.createAnnotatedType(methodBinding.returnType,
new AnnotationBinding[] { this.environment.getNullableAnnotation() });
}
}
}
}
methodBinding.defaultNullness = methodDefaultNullness;
}
TypeBinding[] parameters = methodBinding.parameters;
int numVisibleParams = parameters.length;
int numParamAnnotations = externalAnnotationWalker instanceof IMethodAnnotationWalker
? ((IMethodAnnotationWalker) externalAnnotationWalker).getParameterCount()
: method.getAnnotatedParametersCount();
if (numParamAnnotations > 0) {
for (int j = 0; j < numVisibleParams; j++) {
if (numParamAnnotations > 0) {
int startIndex = numParamAnnotations - numVisibleParams;
ITypeAnnotationWalker parameterWalker = externalAnnotationWalker.toMethodParameter((short) (j+startIndex));
IBinaryAnnotation[] paramAnnotations = parameterWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER
? parameterWalker.getAnnotationsAtCursor(parameters[j].id, false)
: method.getParameterAnnotations(j+startIndex, this.fileName);
if (paramAnnotations != null) {
for (int i = 0; i < paramAnnotations.length; i++) {
char[] annotationTypeName = paramAnnotations[i].getTypeName();
if (annotationTypeName[0] != Util.C_RESOLVED)
continue;
int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
if (typeBit == TypeIds.BitNonNullAnnotation) {
if (methodBinding.parameterNonNullness == null)
methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
methodBinding.parameterNonNullness[j] = Boolean.TRUE;
if (this.environment.usesNullTypeAnnotations()) {
if (methodBinding.parameters[j] != null
&& !methodBinding.parameters[j].hasNullTypeAnnotations()) {
methodBinding.parameters[j] = this.environment.createAnnotatedType(
methodBinding.parameters[j],
new AnnotationBinding[] { this.environment.getNonNullAnnotation() });
}
}
break;
} else if (typeBit == TypeIds.BitNullableAnnotation) {
if (methodBinding.parameterNonNullness == null)
methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
methodBinding.parameterNonNullness[j] = Boolean.FALSE;
if (this.environment.usesNullTypeAnnotations()) {
if (methodBinding.parameters[j] != null
&& !methodBinding.parameters[j].hasNullTypeAnnotations()) {
methodBinding.parameters[j] = this.environment.createAnnotatedType(
methodBinding.parameters[j],
new AnnotationBinding[] { this.environment.getNullableAnnotation() });
}
}
break;
}
}
}
}
}
}
if (useNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
if (methodBinding.returnType.hasNullTypeAnnotations()
|| (methodBinding.tagBits & TagBits.AnnotationNullMASK) != 0
|| methodBinding.parameterNonNullness != null) {
this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
} else {
for (TypeBinding parameter : parameters) {
if (parameter.hasNullTypeAnnotations()) {
this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
break;
}
}
}
}
}
private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBinding packageBinding) {
if (!isPrototype()) throw new IllegalStateException();
char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
if (nonNullByDefaultAnnotationName == null)
return;
if (CharOperation.equals(CharOperation.splitOn('/', binaryType.getName()), nonNullByDefaultAnnotationName))
return;
for (String name : this.environment.globalOptions.nonNullByDefaultAnnotationSecondaryNames)
if (CharOperation.toString(this.compoundName).equals(name))
return;
IBinaryAnnotation[] annotations = binaryType.getAnnotations();
boolean isPackageInfo = CharOperation.equals(sourceName(), TypeConstants.PACKAGE_INFO_NAME);
if (annotations != null) {
int nullness = NO_NULL_DEFAULT;
int length = annotations.length;
for (int i = 0; i < length; i++) {
char[] annotationTypeName = annotations[i].getTypeName();
if (annotationTypeName[0] != Util.C_RESOLVED)
continue;
int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
if (typeBit == TypeIds.BitNonNullByDefaultAnnotation) {
nullness |= getNonNullByDefaultValue(annotations[i], this.environment);
}
}
this.defaultNullness = nullness;
if (nullness != NO_NULL_DEFAULT) {
if (isPackageInfo)
packageBinding.setDefaultNullness(nullness);
return;
}
}
if (isPackageInfo) {
packageBinding.setDefaultNullness(Binding.NO_NULL_DEFAULT);
return;
}
ReferenceBinding enclosingTypeBinding = this.enclosingType;
if (enclosingTypeBinding != null) {
if (setNullDefault(enclosingTypeBinding.getNullDefault()))
return;
}
if (packageBinding.getDefaultNullness() == Binding.NO_NULL_DEFAULT && !isPackageInfo
&& ((this.typeBits & (TypeIds.BitAnyNullAnnotation)) == 0))
{
ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME, packageBinding.enclosingModule);
if (packageInfo == null) {
packageBinding.setDefaultNullness(Binding.NO_NULL_DEFAULT);
}
}
setNullDefault(packageBinding.getDefaultNullness());
}
boolean setNullDefault(int newNullDefault) {
this.defaultNullness = newNullDefault;
if (newNullDefault != Binding.NO_NULL_DEFAULT) {
return true;
}
return false;
}
static int getNonNullByDefaultValue(IBinaryAnnotation annotation, LookupEnvironment environment) {
char[] annotationTypeName = annotation.getTypeName();
char[][] typeName = signature2qualifiedTypeName(annotationTypeName);
IBinaryElementValuePair[] elementValuePairs = annotation.getElementValuePairs();
if (elementValuePairs == null || elementValuePairs.length == 0 ) {
ReferenceBinding annotationType = environment.getType(typeName, environment.UnNamedModule);
if (annotationType == null) return 0;
if (annotationType.isUnresolvedType())
annotationType = ((UnresolvedReferenceBinding) annotationType).resolve(environment, false);
int nullness = evaluateTypeQualifierDefault(annotationType);
if (nullness != 0)
return nullness;
MethodBinding[] annotationMethods = annotationType.methods();
if (annotationMethods != null && annotationMethods.length == 1) {
Object value = annotationMethods[0].getDefaultValue();
return Annotation.nullLocationBitsFromAnnotationValue(value);
}
return DefaultLocationsForTrueValue;
} else if (elementValuePairs.length > 0) {
int nullness = 0;
for (int i = 0; i < elementValuePairs.length; i++)
nullness |= Annotation.nullLocationBitsFromAnnotationValue(elementValuePairs[i].getValue());
return nullness;
} else {
return NULL_UNSPECIFIED_BY_DEFAULT;
}
}
public static int evaluateTypeQualifierDefault(ReferenceBinding annotationType) {
for (AnnotationBinding annotationOnAnnotation : annotationType.getAnnotations()) {
if(CharOperation.equals(annotationOnAnnotation.getAnnotationType().compoundName[annotationOnAnnotation.type.compoundName.length-1], TYPE_QUALIFIER_DEFAULT)) {
ElementValuePair[] pairs2 = annotationOnAnnotation.getElementValuePairs();
if(pairs2 != null) {
for (ElementValuePair elementValuePair : pairs2) {
char[] name = elementValuePair.getName();
if(CharOperation.equals(name, TypeConstants.VALUE)) {
int nullness = 0;
Object value = elementValuePair.getValue();
if(value instanceof Object[]) {
Object[] values = (Object[]) value;
for (Object value1 : values)
nullness |= Annotation.nullLocationBitsFromElementTypeAnnotationValue(value1);
} else {
nullness |= Annotation.nullLocationBitsFromElementTypeAnnotationValue(value);
}
return nullness;
}
}
}
}
}
return 0;
}
static char[][] signature2qualifiedTypeName(char[] typeSignature) {
return CharOperation.splitOn('/', typeSignature, 1, typeSignature.length-1);
}
@Override
int getNullDefault() {
return this.defaultNullness;
}
private void scanTypeForContainerAnnotation(IBinaryType binaryType, char[][][] missingTypeNames) {
if (!isPrototype()) throw new IllegalStateException();
IBinaryAnnotation[] annotations = binaryType.getAnnotations();
if (annotations != null) {
int length = annotations.length;
for (int i = 0; i < length; i++) {
char[] annotationTypeName = annotations[i].getTypeName();
if (CharOperation.equals(annotationTypeName, ConstantPool.JAVA_LANG_ANNOTATION_REPEATABLE)) {
IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs();
if (elementValuePairs != null && elementValuePairs.length == 1) {
Object value = elementValuePairs[0].getValue();
if (value instanceof ClassSignature) {
this.containerAnnotationType = (ReferenceBinding) this.environment.getTypeFromSignature(((ClassSignature)value).getTypeName(), 0, -1, false, null, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
}
}
break;
}
}
}
}
@Override
public ReferenceBinding superclass() {
if (!isPrototype()) {
return this.superclass = this.prototype.superclass();
}
if ((this.tagBits & TagBits.HasUnresolvedSuperclass) == 0)
return this.superclass;
this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true );
this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
if (this.superclass.problemId() == ProblemReasons.NotFound) {
this.tagBits |= TagBits.HierarchyHasProblems;
} else {
boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
this.environment.mayTolerateMissingType = true;
try {
this.superclass.superclass();
this.superclass.superInterfaces();
} finally {
this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
}
}
this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
this.typeBits |= applyCloseableClassWhitelists();
detectCircularHierarchy();
return this.superclass;
}
private void breakLoop() {
ReferenceBinding currentSuper = this.superclass;
ReferenceBinding prevSuper = null;
while (currentSuper != null) {
if ((currentSuper.tagBits & TagBits.EndHierarchyCheck) != 0 && prevSuper instanceof BinaryTypeBinding) {
((BinaryTypeBinding)prevSuper).superclass = this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
break;
}
currentSuper.tagBits |= TagBits.EndHierarchyCheck;
prevSuper = currentSuper;
currentSuper = currentSuper.superclass();
}
}
private void detectCircularHierarchy() {
ReferenceBinding currentSuper = this.superclass;
ReferenceBinding tempSuper = null;
int count = 0;
int skipCount = 20;
while (currentSuper != null) {
if (currentSuper.hasHierarchyCheckStarted())
break;
if (TypeBinding.equalsEquals(currentSuper, this) || TypeBinding.equalsEquals(currentSuper, tempSuper)) {
currentSuper.tagBits |= TagBits.HierarchyHasProblems;
if (currentSuper.isBinaryBinding())
breakLoop();
return;
}
if (count == skipCount) {
tempSuper = currentSuper;
skipCount *= 2;
count = 0;
}
if (!currentSuper.isHierarchyConnected())
return;
currentSuper = currentSuper.superclass();
count++;
}
tempSuper = this;
while (TypeBinding.notEquals(currentSuper, tempSuper)) {
tempSuper.setHierarchyCheckDone();
tempSuper=tempSuper.superclass();
}
}
@Override
public ReferenceBinding[] superInterfaces() {
if (!isPrototype()) {
return this.superInterfaces = this.prototype.superInterfaces();
}
if ((this.tagBits & TagBits.HasUnresolvedSuperinterfaces) == 0)
return this.superInterfaces;
for (int i = this.superInterfaces.length; --i >= 0;) {
this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true );
if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) {
this.tagBits |= TagBits.HierarchyHasProblems;
} else {
boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
this.environment.mayTolerateMissingType = true;
try {
this.superInterfaces[i].superclass();
if (this.superInterfaces[i].isParameterizedType()) {
ReferenceBinding superType = this.superInterfaces[i].actualType();
if (TypeBinding.equalsEquals(superType, this)) {
this.tagBits |= TagBits.HierarchyHasProblems;
continue;
}
}
this.superInterfaces[i].superInterfaces();
} finally {
this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
}
}
this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
this.typeBits |= applyCloseableInterfaceWhitelists();
}
this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
return this.superInterfaces;
}
@Override
public TypeVariableBinding[] typeVariables() {
if (!isPrototype()) {
return this.typeVariables = this.prototype.typeVariables();
}
if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
return this.typeVariables;
for (int i = this.typeVariables.length; --i >= 0;)
this.typeVariables[i].resolve();
this.tagBits &= ~TagBits.HasUnresolvedTypeVariables;
return this.typeVariables;
}
@Override
public String toString() {
if (this.hasTypeAnnotations())
return annotatedDebugName();
StringBuffer buffer = new StringBuffer();
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((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED TYPE");
if (this.typeVariables == null) {
buffer.append("<NULL TYPE VARIABLES>");
} else if (this.typeVariables != Binding.NO_TYPE_VARIABLES) {
buffer.append("<");
for (int i = 0, length = this.typeVariables.length; i < length; i++) {
if (i > 0) buffer.append(", ");
if (this.typeVariables[i] == null) {
buffer.append("NULL TYPE VARIABLE");
continue;
}
char[] varChars = this.typeVariables[i].toString().toCharArray();
buffer.append(varChars, 1, varChars.length - 2);
}
buffer.append(">");
}
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 (this.enclosingType != null) {
buffer.append("\n\tenclosing type : ");
buffer.append(this.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((this.fields[i] != null) ? "\n" + this.fields[i].toString() : "\nNULL 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((this.methods[i] != null) ? "\n" + this.methods[i].toString() : "\nNULL METHOD");
}
} else {
buffer.append("NULL METHODS");
}
if (this.memberTypes != null) {
if (this.memberTypes != Binding.NO_MEMBER_TYPES) {
buffer.append("\n/* members */");
for (int i = 0, length = this.memberTypes.length; i < length; i++)
buffer.append((this.memberTypes[i] != null) ? "\n" + this.memberTypes[i].toString() : "\nNULL TYPE");
}
} else {
buffer.append("NULL MEMBER TYPES");
}
buffer.append("\n\n\n");
return buffer.toString();
}
@Override
public TypeBinding unannotated() {
return this.prototype;
}
@Override
public TypeBinding withoutToplevelNullAnnotation() {
if (!hasNullTypeAnnotations())
return this;
AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations);
if (newAnnotations.length > 0)
return this.environment.createAnnotatedType(this.prototype, newAnnotations);
return this.prototype;
}
@Override
MethodBinding[] unResolvedMethods() {
if (!isPrototype())
return this.prototype.unResolvedMethods();
return this.methods;
}
@Override
public FieldBinding[] unResolvedFields() {
if (!isPrototype())
return this.prototype.unResolvedFields();
return this.fields;
}
@Override
public ModuleBinding module() {
if (!isPrototype())
return this.prototype.module;
return this.module;
}
}