edu.umd.cs.findbugs.ClassAnnotation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spotbugs Show documentation
Show all versions of spotbugs Show documentation
SpotBugs: Because it's easy!
/*
* FindBugs - Find bugs in Java programs
* Copyright (C) 2003-2005, University of Maryland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.umd.cs.findbugs;
import java.io.IOException;
import java.util.stream.Collectors;
import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.SourceInfoMap;
import edu.umd.cs.findbugs.classfile.ClassDescriptor;
import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
import edu.umd.cs.findbugs.util.ClassName;
import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;
/**
* A BugAnnotation object specifying a Java class involved in the bug.
*
* @author David Hovemeyer
* @see BugAnnotation
* @see BugInstance
*/
public class ClassAnnotation extends PackageMemberAnnotation {
private static final long serialVersionUID = 1L;
private static final String DEFAULT_ROLE = "CLASS_DEFAULT";
public static final String SUBCLASS_ROLE = "CLASS_SUBCLASS";
public static final String SUPERCLASS_ROLE = "CLASS_SUPERCLASS";
public static final String ANONYMOUS_ROLE = "CLASS_ANONYMOUS";
public static final String RECOMMENDED_SUPERCLASS_ROLE = "CLASS_RECOMMENDED_SUPERCLASS";
public static final String IMPLEMENTED_INTERFACE_ROLE = "CLASS_IMPLEMENTED_INTERFACE";
public static final String INTERFACE_ROLE = "INTERFACE_TYPE";
public static final String ANNOTATION_ROLE = "CLASS_ANNOTATION";
public static final String TYPE_QUALIFIER_ROLE = "CLASS_TYPE_QUALIFIER";
/**
* Constructor.
*
* @param className
* the name of the class
*/
public ClassAnnotation(@DottedClassName String className) {
super(className, DEFAULT_ROLE);
}
public ClassAnnotation(@DottedClassName String className, String sourceFileName) {
super(className, DEFAULT_ROLE, sourceFileName);
}
@Override
public boolean isSignificant() {
return !SUBCLASS_ROLE.equals(description);
}
/**
* Factory method to create a ClassAnnotation from a ClassDescriptor.
*
* @param classDescriptor
* the ClassDescriptor
* @return the ClassAnnotation
*/
public static ClassAnnotation fromClassDescriptor(ClassDescriptor classDescriptor) {
return new ClassAnnotation(classDescriptor.toDottedClassName());
}
@Override
public void accept(BugAnnotationVisitor visitor) {
visitor.visitClassAnnotation(this);
}
@Override
protected String formatPackageMember(String key, ClassAnnotation primaryClass) {
if ("".equals(key) || "hash".equals(key)) {
return className;
} else if ("givenClass".equals(key)) {
return shorten(primaryClass.getPackageName(), className);
} else if ("excludingPackage".equals(key)) {
return shorten(getPackageName(), className);
} else if ("simpleClass".equals(key) || "simpleName".equals(key)) {
return ClassName.extractSimpleName(className);
} else {
throw new IllegalArgumentException("unknown key " + key);
}
}
@Override
public int hashCode() {
return className.hashCode();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ClassAnnotation)) {
return false;
}
ClassAnnotation other = (ClassAnnotation) o;
return className.equals(other.className);
}
public boolean contains(ClassAnnotation other) {
return other.className.startsWith(className);
}
public ClassAnnotation getTopLevelClass() {
int firstDollar = className.indexOf('$');
if (firstDollar <= 0) {
return this;
}
return new ClassAnnotation(className.substring(0, firstDollar));
}
@Override
public int compareTo(BugAnnotation o) {
if (!(o instanceof ClassAnnotation)) {
// Comparable with any type of
// BugAnnotation
return this.getClass().getName().compareTo(o.getClass().getName());
}
ClassAnnotation other = (ClassAnnotation) o;
return className.compareTo(other.className);
}
/*
* (non-Javadoc)
*
* @see edu.umd.cs.findbugs.PackageMemberAnnotation#getSourceLines()
*/
@Override
public SourceLineAnnotation getSourceLines() {
if (sourceLines == null) {
this.sourceLines = getSourceLinesForClass(className, sourceFileName);
}
return sourceLines;
}
public static SourceLineAnnotation getSourceLinesForClass(@DottedClassName String className, String sourceFileName) {
// Create source line annotation for class on demand
AnalysisContext currentAnalysisContext = AnalysisContext.currentAnalysisContext();
if (currentAnalysisContext == null) {
return new SourceLineAnnotation(className, sourceFileName, -1, -1, -1, -1);
}
SourceInfoMap.SourceLineRange classLine = currentAnalysisContext.getSourceInfoMap().getClassLine(className);
if (classLine == null) {
return SourceLineAnnotation.getSourceAnnotationForClass(className, sourceFileName);
} else {
return new SourceLineAnnotation(className, sourceFileName, classLine.getStart(), classLine.getEnd(), -1, -1);
}
}
/*
* ----------------------------------------------------------------------
* XML Conversion support
* ----------------------------------------------------------------------
*/
private static final String ELEMENT_NAME = "Class";
@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("classname", getClassName());
if (isPrimary) {
attributeList.addAttribute("primary", "true");
}
if (!getJavaAnnotationNames().isEmpty()) {
attributeList.addAttribute("classAnnotationNames",
getJavaAnnotationNames().stream().collect(Collectors.joining(",")));
}
String role = getDescription();
if (!DEFAULT_ROLE.equals(role)) {
attributeList.addAttribute("role", role);
}
xmlOutput.openTag(ELEMENT_NAME, attributeList);
getSourceLines().writeXML(xmlOutput, addMessages, false);
if (addMessages) {
xmlOutput.openTag(BugAnnotation.MESSAGE_TAG);
xmlOutput.writeText(this.toString());
xmlOutput.closeTag(BugAnnotation.MESSAGE_TAG);
}
xmlOutput.closeTag(ELEMENT_NAME);
}
}