package edu.umd.cs.findbugs;
import java.io.IOException;
import org.apache.bcel.generic.Type;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.SignatureConverter;
import edu.umd.cs.findbugs.ba.generic.GenericObjectType;
import edu.umd.cs.findbugs.ba.generic.GenericUtilities;
import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;
public class TypeAnnotation extends BugAnnotationWithSourceLines {
private static final long serialVersionUID = 1L;
public static final String DEFAULT_ROLE = "TYPE_DEFAULT";
public static final String EXPECTED_ROLE = "TYPE_EXPECTED";
public static final String FOUND_ROLE = "TYPE_FOUND";
public static final String CLOSEIT_ROLE = "TYPE_CLOSEIT";
public static final String UNHASHABLE_ROLE = "TYPE_UNHASHABLE";
final private String descriptor;
private String roleDescription;
private String typeParameters;
public TypeAnnotation(String typeDescriptor) {
this(typeDescriptor, DEFAULT_ROLE);
}
public TypeAnnotation(Type objectType) {
this(objectType, DEFAULT_ROLE);
}
public TypeAnnotation(Type objectType, String roleDescription) {
this(objectType.getSignature(), roleDescription);
if (objectType instanceof GenericObjectType) {
GenericObjectType genericObjectType = (GenericObjectType) objectType;
if (genericObjectType.getTypeCategory() == GenericUtilities.TypeCategory.PARAMETERIZED) {
typeParameters = genericObjectType.getGenericParametersAsString();
}
}
}
public TypeAnnotation(String typeDescriptor, String roleDescription) {
descriptor = typeDescriptor;
this.roleDescription = roleDescription;
if (descriptor.startsWith("L")) {
String className = typeDescriptor.substring(1, typeDescriptor.length() - 1).replace('/', '.');
AnalysisContext context = AnalysisContext.currentAnalysisContext();
if (context != null) {
this.sourceFileName = context.lookupSourceFile(className);
this.sourceLines = ClassAnnotation.getSourceLinesForClass(className, sourceFileName);
} else {
this.sourceFileName = SourceLineAnnotation.UNKNOWN_SOURCE_FILE;
}
}
}
public String getTypeDescriptor() {
return descriptor;
}
@Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitTypeAnnotation(this);
}
@Override
public String format(String key, ClassAnnotation primaryClass) {
String name = new SignatureConverter(descriptor).parseNext().replace("java.lang.", "");
if ("givenClass".equals(key)) {
name = PackageMemberAnnotation.shorten(primaryClass.getPackageName(), name);
} else if ("excludingPackage".equals(key)) {
name = PackageMemberAnnotation.removePackage(name);
}
if (typeParameters != null && !"hash".equals(key)) {
name = name + typeParameters;
}
return name;
}
@Override
public void setDescription(String roleDescription) {
this.roleDescription = roleDescription.intern();
}
@Override
public String getDescription() {
return roleDescription;
}
public void setTypeParameters(String typeParameters) {
this.typeParameters = typeParameters;
}
public String getTypeParameters() {
return typeParameters;
}
@Override
public int hashCode() {
return descriptor.hashCode();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof TypeAnnotation)) {
return false;
}
return descriptor.equals(((TypeAnnotation) o).descriptor);
}
@Override
public int compareTo(BugAnnotation o) {
if (!(o instanceof TypeAnnotation)) {
return this.getClass().getName().compareTo(o.getClass().getName());
}
return descriptor.compareTo(((TypeAnnotation) o).descriptor);
}
@Override
public String toString() {
String pattern = I18N.instance().getAnnotationDescription(roleDescription);
FindBugsMessageFormat format = new FindBugsMessageFormat(pattern);
return format.format(new BugAnnotation[] { this }, null);
}
private static final String ELEMENT_NAME = "Type";
@Override
public void writeXML(XMLOutput xmlOutput) throws IOException {
writeXML(xmlOutput, false, false);
}
@Override
public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
XMLAttributeList attributeList = new XMLAttributeList().addAttribute("descriptor", descriptor);
String role = getDescription();
if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
}
if (typeParameters != null) {
attributeList.addAttribute("typeParameters", typeParameters);
}
BugAnnotationUtil.writeXML(xmlOutput, ELEMENT_NAME, this, attributeList, addMessages);
}
@Override
public boolean isSignificant() {
return true;
}
}