📄 buginstance.java
字号:
/* * FindBugs - Find bugs in Java programs * Copyright (C) 2003,2004 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.util.*;import java.io.IOException;import edu.umd.cs.findbugs.ba.XField;import edu.umd.cs.findbugs.ba.bcp.FieldVariable;import edu.umd.cs.findbugs.visitclass.DismantleBytecode;import edu.umd.cs.findbugs.visitclass.PreorderVisitor;import edu.umd.cs.findbugs.xml.XMLAttributeList;import edu.umd.cs.findbugs.xml.XMLOutput;import edu.umd.cs.findbugs.xml.XMLOutputUtil;import edu.umd.cs.findbugs.xml.XMLWriteable;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.generic.ConstantPoolGen;import org.apache.bcel.generic.InstructionHandle;import org.apache.bcel.generic.InvokeInstruction;import org.apache.bcel.generic.MethodGen;/** * An instance of a bug pattern. * A BugInstance consists of several parts: * <p/> * <ul> * <li> the type, which is a string indicating what kind of bug it is; * used as a key for the FindBugsMessages resource bundle * <li> the priority; how likely this instance is to actually be a bug * <li> a list of <em>annotations</em> * </ul> * <p/> * The annotations describe classes, methods, fields, source locations, * and other relevant context information about the bug instance. * Every BugInstance must have at least one ClassAnnotation, which * describes the class in which the instance was found. This is the * "primary class annotation". * <p/> * <p> BugInstance objects are built up by calling a string of <code>add</code> * methods. (These methods all "return this", so they can be chained). * Some of the add methods are specialized to get information automatically from * a BetterVisitor or DismantleBytecode object. * * @author David Hovemeyer * @see BugAnnotation */public class BugInstance implements Comparable, XMLWriteable { private String type; private int priority; private ArrayList<BugAnnotation> annotationList; private ClassAnnotation primaryClassAnnotation; private MethodAnnotation primaryMethodAnnotation; private FieldAnnotation primaryFieldAnnotation; private int cachedHashCode; private String annotationText; /** * This value is used to indicate that the cached hashcode * is invalid, and should be recomputed. */ private static final int INVALID_HASH_CODE = 0; /** * This value is used to indicate whether BugInstances should be reprioritized very low, * when the BugPattern is marked as experimental */ private static boolean adjustExperimental = false; /** * Constructor. * * @param type the bug type * @param priority the bug priority */ public BugInstance(String type, int priority) { this.type = type; this.priority = priority < Detector.HIGH_PRIORITY ? Detector.HIGH_PRIORITY : priority; annotationList = new ArrayList<BugAnnotation>(4); primaryClassAnnotation = null; cachedHashCode = INVALID_HASH_CODE; annotationText = ""; if (adjustExperimental && isExperimental()) this.priority = Detector.EXP_PRIORITY; } /** * Create a new BugInstance. * This is the constructor that should be used by Detectors. * * @param detector the Detector that is reporting the BugInstance * @param type the bug type * @param priority the bug priority */ public BugInstance(Detector detector, String type, int priority) { this(type, priority); if (detector != null) { // Adjust priority if required DetectorFactory factory = DetectorFactoryCollection.instance().getFactoryByClassName(detector.getClass().getName()); if (factory != null) { this.priority += factory.getPriorityAdjustment(); if (this.priority < 0) this.priority = 0; } } if (adjustExperimental && isExperimental()) this.priority = Detector.EXP_PRIORITY; } public static void setAdjustExperimental(boolean adjust) { adjustExperimental = adjust; } /* ---------------------------------------------------------------------- * Accessors * ---------------------------------------------------------------------- */ /** * Get the bug type. */ public String getType() { return type; } /** * Get the BugPattern. */ public BugPattern getBugPattern() { return I18N.instance().lookupBugPattern(getType()); } /** * Get the bug priority. */ public int getPriority() { return priority; } /** * Set the bug priority. */ public void setPriority(int p) { priority = p < Detector.HIGH_PRIORITY ? Detector.HIGH_PRIORITY : p; } /** * Is this bug instance the result of an experimental detector? */ public boolean isExperimental() { BugPattern pattern = I18N.instance().lookupBugPattern(type); return (pattern != null) ? pattern.isExperimental() : false; } /** * Get the primary class annotation, which indicates where the bug occurs. */ public ClassAnnotation getPrimaryClass() { return primaryClassAnnotation; } /** * Get the primary method annotation, which indicates where the bug occurs. */ public MethodAnnotation getPrimaryMethod() { return primaryMethodAnnotation; } /** * Get the primary method annotation, which indicates where the bug occurs. */ public FieldAnnotation getPrimaryField() { return primaryFieldAnnotation; } /** * Get the primary source line annotation. * * @return the source line annotation, or null if there is * no source line annotation */ public SourceLineAnnotation getPrimarySourceLineAnnotation() { // Highest priority: return the first top level source line annotation Iterator<BugAnnotation> i = annotationList.iterator(); while (i.hasNext()) { BugAnnotation annotation = i.next(); if (annotation instanceof SourceLineAnnotation) return (SourceLineAnnotation) annotation; } // Second priority: return the source line annotation describing the // primary method if (primaryMethodAnnotation != null) return primaryMethodAnnotation.getSourceLines(); else return null; } /** * Get an Iterator over all bug annotations. */ public Iterator<BugAnnotation> annotationIterator() { return annotationList.iterator(); } /** * Get the abbreviation of this bug instance's BugPattern. * This is the same abbreviation used by the BugCode which * the BugPattern is a particular species of. */ public String getAbbrev() { BugPattern pattern = I18N.instance().lookupBugPattern(getType()); return pattern != null ? pattern.getAbbrev() : "<unknown bug pattern>"; } /** * Set the user annotation text. * * @param annotationText the user annotation text */ public void setAnnotationText(String annotationText) { this.annotationText = annotationText; } /** * Get the user annotation text. * * @return the user annotation text */ public String getAnnotationText() { return annotationText; } /** * Determine whether or not the annotation text contains * the given word. * * @param word the word * @return true if the annotation text contains the word, false otherwise */ public boolean annotationTextContainsWord(String word) { return getTextAnnotationWords().contains(word); } /** * Get set of words in the text annotation. */ public Set<String> getTextAnnotationWords() { HashSet<String> result = new HashSet<String>(); StringTokenizer tok = new StringTokenizer(annotationText, " \t\r\n\f.,:;-"); while (tok.hasMoreTokens()) { result.add(tok.nextToken()); } return result; } /* ---------------------------------------------------------------------- * Combined annotation adders * ---------------------------------------------------------------------- */ /** * Add a class annotation and a method annotation for the class and method * which the given visitor is currently visiting. * * @param visitor the BetterVisitor * @return this object */ public BugInstance addClassAndMethod(PreorderVisitor visitor) { addClass(visitor); addMethod(visitor); return this; } /** * Add class and method annotations for given method. * * @param methodGen the method * @param sourceFile source file the method is defined in * @return this object */ public BugInstance addClassAndMethod(MethodGen methodGen, String sourceFile) { addClass(methodGen.getClassName()); addMethod(methodGen, sourceFile); return this; } /* ---------------------------------------------------------------------- * Class annotation adders * ---------------------------------------------------------------------- */ /** * Add a class annotation. If this is the first class annotation added, * it becomes the primary class annotation. * * @param className the name of the class * @return this object */ public BugInstance addClass(String className) { ClassAnnotation classAnnotation = new ClassAnnotation(className); add(classAnnotation); return this; } /** * Add a class annotation. If this is the first class annotation added, * it becomes the primary class annotation. * * @param jclass the JavaClass object for the class * @return this object */ public BugInstance addClass(JavaClass jclass) { addClass(jclass.getClassName()); return this; } /** * Add a class annotation for the class that the visitor is currently visiting. * * @param visitor the BetterVisitor * @return this object */ public BugInstance addClass(PreorderVisitor visitor) { String className = visitor.getDottedClassName(); addClass(className); return this; } /** * Add a class annotation for the superclass of the class the visitor * is currently visiting. * * @param visitor the BetterVisitor * @return this object */ public BugInstance addSuperclass(PreorderVisitor visitor) { String className = visitor.getSuperclassName(); addClass(className); return this; } /* ---------------------------------------------------------------------- * Field annotation adders * ---------------------------------------------------------------------- */ /** * Add a field annotation. * * @param className name of the class containing the field * @param fieldName the name of the field * @param fieldSig type signature of the field * @param isStatic whether or not the field is static * @return this object */ public BugInstance addField(String className, String fieldName, String fieldSig, boolean isStatic) { addField(new FieldAnnotation(className, fieldName, fieldSig, isStatic)); return this; } /** * Add a field annotation * * @param fieldAnnotation the field annotation * @return this object */ public BugInstance addField(FieldAnnotation fieldAnnotation) { add(fieldAnnotation); return this; } /** * Add a field annotation for a FieldVariable matched in a ByteCodePattern. * * @param field the FieldVariable * @return this object */ public BugInstance addField(FieldVariable field) { return addField(field.getClassName(), field.getFieldName(), field.getFieldSig(), field.isStatic()); } /** * Add a field annotation for an XField. * * @param xfield the XField * @return this object */ public BugInstance addField(XField xfield) { return addField(xfield.getClassName(), xfield.getFieldName(), xfield.getFieldSignature(), xfield.isStatic()); } /** * Add a field annotation for the field which has just been accessed * by the method currently being visited by given visitor. * Assumes that a getfield/putfield or getstatic/putstatic * has just been seen. * * @param visitor the DismantleBytecode object * @return this object */ public BugInstance addReferencedField(DismantleBytecode visitor) { FieldAnnotation f = FieldAnnotation.fromReferencedField(visitor); addField(f); return this; } /** * Add a field annotation for the field referenced by the FieldAnnotation parameter */ public BugInstance addReferencedField(FieldAnnotation fa) { addField(fa);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -