📄 buginstance.java
字号:
if (sourceLineAnnotation != null) add(sourceLineAnnotation); return this; } /** * Add a source line annotation describing the * source line numbers for a range of instructions in the method being * visited by the given visitor. * Note that if the method does not have line number information, then * no source line annotation will be added. * * @param classContext the ClassContext * @param visitor a BetterVisitor which is visiting the method * @param startPC the bytecode offset of the start instruction in the range * @param endPC the bytecode offset of the end instruction in the range * @return this object */ public BugInstance addSourceLineRange(ClassContext classContext, PreorderVisitor visitor, int startPC, int endPC) { SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstructionRange(classContext, visitor, startPC, endPC); if (sourceLineAnnotation != null) add(sourceLineAnnotation); return this; } /** * Add a source line annotation for instruction currently being visited * by given visitor. * Note that if the method does not have line number information, then * no source line annotation will be added. * * @param visitor a BytecodeScanningDetector visitor that is currently visiting the instruction * @return this object */ public BugInstance addSourceLine(BytecodeScanningDetector visitor) { SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(visitor); if (sourceLineAnnotation != null) add(sourceLineAnnotation); return this; } /** * Add a non-specific source line annotation. * This will result in the entire source file being displayed. * * @param className the class name * @param sourceFile the source file name * @return this object */ public BugInstance addUnknownSourceLine(String className, String sourceFile) { SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.createUnknown(className, sourceFile); if (sourceLineAnnotation != null) add(sourceLineAnnotation); return this; } /* ---------------------------------------------------------------------- * Formatting support * ---------------------------------------------------------------------- */ /** * Format a string describing this bug instance. * * @return the description */ public String getMessageWithoutPrefix() { BugPattern bugPattern = getBugPattern(); String pattern, shortPattern; pattern = getLongDescription(); shortPattern = bugPattern.getShortDescription(); try { FindBugsMessageFormat format = new FindBugsMessageFormat(pattern); return format.format(annotationList.toArray(new BugAnnotation[annotationList.size()]), getPrimaryClass()); } catch (RuntimeException e) { AnalysisContext.logError("Error generating bug msg ", e); return shortPattern + " [Error generating customized description]"; } } String getLongDescription() { return getBugPattern().getLongDescription().replaceAll("BUG_PATTERN", type); } public String getAbridgedMessage() { BugPattern bugPattern = getBugPattern(); String pattern, shortPattern; if (bugPattern == null) shortPattern = pattern = "Error2: missing bug pattern for key " + type; else { pattern = getLongDescription().replaceAll(" in \\{1\\}", ""); shortPattern = bugPattern.getShortDescription(); } try { FindBugsMessageFormat format = new FindBugsMessageFormat(pattern); return format.format(annotationList.toArray(new BugAnnotation[annotationList.size()]), getPrimaryClass()); } catch (RuntimeException e) { AnalysisContext.logError("Error generating bug msg ", e); return shortPattern + " [Error3 generating customized description]"; } } /** * Format a string describing this bug instance. * * @return the description */ public String getMessage() { BugPattern bugPattern = getBugPattern(); String pattern = bugPattern.getAbbrev() + ": " + getLongDescription(); FindBugsMessageFormat format = new FindBugsMessageFormat(pattern); try { return format.format(annotationList.toArray(new BugAnnotation[annotationList.size()]), getPrimaryClass()); } catch (RuntimeException e) { AnalysisContext.logError("Error generating bug msg ", e); if (bugPattern == null) return "Error4: missing bug pattern for key " + type; return bugPattern.getShortDescription() + " [Error generating customized description]"; } } /** * Format a string describing this bug pattern, with the priority and type at the beginning. * e.g. "(High Priority Correctness) Guaranteed null pointer dereference..." */ public String getMessageWithPriorityType() { return "(" + this.getPriorityTypeString() + ") " + this.getMessage(); } public String getMessageWithPriorityTypeAbbreviation() { return this.getPriorityTypeAbbreviation() + " "+ this.getMessage(); } /** * Add a description to the most recently added bug annotation. * * @param description the description to add * @return this object */ public BugInstance describe(String description) { annotationList.get(annotationList.size() - 1).setDescription(description); return this; } /** * Convert to String. * This method returns the "short" message describing the bug, * as opposed to the longer format returned by getMessage(). * The short format is appropriate for the tree view in a GUI, * where the annotations are listed separately as part of the overall * bug instance. */ @Override public String toString() { return I18N.instance().getShortMessage(type); } /* ---------------------------------------------------------------------- * XML Conversion support * ---------------------------------------------------------------------- */ public void writeXML(XMLOutput xmlOutput) throws IOException { writeXML(xmlOutput, false); } public void writeXML(XMLOutput xmlOutput, boolean addMessages) throws IOException { XMLAttributeList attributeList = new XMLAttributeList() .addAttribute("type", type) .addAttribute("priority", String.valueOf(priority)); BugPattern pattern = getBugPattern(); if (pattern != null) { // The bug abbreviation and pattern category are // emitted into the XML for informational purposes only. // (The information is redundant, but might be useful // for processing tools that want to make sense of // bug instances without looking at the plugin descriptor.) attributeList.addAttribute("abbrev", pattern.getAbbrev()); attributeList.addAttribute("category", pattern.getCategory()); } if (addMessages) { // Add a uid attribute, if we have a unique id. if (getUniqueId() != null) { attributeList.addAttribute("uid", getUniqueId()); } attributeList.addAttribute("instanceHash", getInstanceHash()); attributeList.addAttribute("instanceOccurrenceNum", Integer.toString(getInstanceOccurrenceNum())); attributeList.addAttribute("instanceOccurrenceMax", Integer.toString(getInstanceOccurrenceMax())); } if (firstVersion > 0) attributeList.addAttribute("first", Long.toString(firstVersion)); if (lastVersion >= 0) attributeList.addAttribute("last", Long.toString(lastVersion)); if (introducedByChangeOfExistingClass) attributeList.addAttribute("introducedByChange", "true"); if (removedByChangeOfPersistingClass) attributeList.addAttribute("removedByChange", "true"); xmlOutput.openTag(ELEMENT_NAME, attributeList); if (userDesignation != null) { userDesignation.writeXML(xmlOutput); } if (addMessages) { BugPattern bugPattern = getBugPattern(); xmlOutput.openTag("ShortMessage"); xmlOutput.writeText(bugPattern != null ? bugPattern.getShortDescription() : this.toString()); xmlOutput.closeTag("ShortMessage"); xmlOutput.openTag("LongMessage"); if (FindBugsDisplayFeatures.isAbridgedMessages()) xmlOutput.writeText(this.getAbridgedMessage()); else xmlOutput.writeText(this.getMessageWithoutPrefix()); xmlOutput.closeTag("LongMessage"); } boolean foundSourceAnnotation = false; for (BugAnnotation annotation : annotationList) { if (annotation instanceof SourceLineAnnotation) foundSourceAnnotation = true; annotation.writeXML(xmlOutput, addMessages); } if (!foundSourceAnnotation && addMessages) { SourceLineAnnotation synth = getPrimarySourceLineAnnotation(); if (synth != null) { synth.setSynthetic(true); synth.writeXML(xmlOutput, addMessages); } } if (propertyListHead != null) { BugProperty prop = propertyListHead; while (prop != null) { prop.writeXML(xmlOutput); prop = prop.getNext(); } } xmlOutput.closeTag(ELEMENT_NAME); } private static final String ELEMENT_NAME = "BugInstance"; private static final String USER_ANNOTATION_ELEMENT_NAME = "UserAnnotation"; /* ---------------------------------------------------------------------- * Implementation * ---------------------------------------------------------------------- */ public BugInstance addOptionalAnnotation(@CheckForNull BugAnnotation annotation) { if (annotation == null) return this; return add(annotation); } public BugInstance add(BugAnnotation annotation) { if (annotation == null) throw new IllegalStateException("Missing BugAnnotation!"); // Add to list annotationList.add(annotation); // This object is being modified, so the cached hashcode // must be invalidated cachedHashCode = INVALID_HASH_CODE; return this; } private void addSourceLinesForMethod(MethodAnnotation methodAnnotation, SourceLineAnnotation sourceLineAnnotation) { if (sourceLineAnnotation != null) { // Note: we don't add the source line annotation directly to // the bug instance. Instead, we stash it in the MethodAnnotation. // It is much more useful there, and it would just be distracting // if it were displayed in the UI, since it would compete for attention // with the actual bug location source line annotation (which is much // more important and interesting). methodAnnotation.setSourceLines(sourceLineAnnotation); } } @Override public int hashCode() { if (cachedHashCode == INVALID_HASH_CODE) { int hashcode = type.hashCode() + priority; Iterator<BugAnnotation> i = annotationIterator(); while (i.hasNext()) hashcode += i.next().hashCode(); if (hashcode == INVALID_HASH_CODE) hashcode = INVALID_HASH_CODE+1; cachedHashCode = hashcode; } return cachedHashCode; } @Override public boolean equals(Object o) { if (!(o instanceof BugInstance)) return false; BugInstance other = (BugInstance) o; if (!type.equals(other.type) || priority != other.priority) return false; if (annotationList.size() != other.annotationList.size()) return false; int numAnnotations = annotationList.size(); for (int i = 0; i < numAnnotations; ++i) { BugAnnotation lhs = annotationList.get(i); BugAnnotation rhs = other.annotationList.get(i); if (!lhs.equals(rhs)) return false; } return true; } public int compareTo(BugInstance other) { int cmp; cmp = type.compareTo(other.type); if (cmp != 0) return cmp; cmp = priority - other.priority; if (cmp != 0) return cmp; // Compare BugAnnotations lexicographically int pfxLen = Math.min(annotationList.size(), other.annotationList.size()); for (int i = 0; i < pfxLen; ++i) { BugAnnotation lhs = annotationList.get(i); BugAnnotation rhs = other.annotationList.get(i); cmp = lhs.compareTo(rhs); if (cmp != 0) return cmp; } // All elements in prefix were the same, // so use number of elements to decide return annotationList.size() - other.annotationList.size(); } /** * @param firstVersion The firstVersion to set. */ public void setFirstVersion(long firstVersion) { this.firstVersion = firstVersion; if (lastVersion >= 0 && firstVersion > lastVersion) throw new IllegalArgumentException( firstVersion + ".." + lastVersion); } /** * @return Returns the firstVersion. */ public long getFirstVersion() { return firstVersion; } /** * @param lastVersion The lastVersion to set. */ public void setLastVersion(long lastVersion) { if (lastVersion >= 0 && firstVersion > lastVersion) throw new IllegalArgumentException( firstVersion + ".." + lastVersion); this.lastVersion = lastVersion; } /** * @return Returns the lastVersion. */ public long getLastVersion() { return lastVersion; } /** * @param introducedByChangeOfExistingClass The introducedByChangeOfExistingClass to set. */ public void setIntroducedByChangeOfExistingClass(boolean introducedByChangeOfExistingClass) { this.introducedByChangeOfExistingClass = introducedByChangeOfExistingClass; } /** * @return Returns the introducedByChangeOfExistingClass. */ public boolean isIntroducedByChangeOfExistingClass() { return introducedByChangeOfExistingClass; } /** * @param removedByChangeOfPersistingClass The removedByChangeOfPersistingClass to set. */ public void setRemovedByChangeOfPersistingClass(boolean removedByChangeOfPersistingClass) { this.removedByChangeOfPersistingClass = removedByChangeOfPersistingClass; } /** * @return Returns the removedByChangeOfPersistingClass. */ public boolean isRemovedByChangeOfPersistingClass() { return removedByChangeOfPersistingClass; } /** * @param instanceHash The instanceHash to set. */ public void setInstanceHash(String instanceHash) { this.instanceHash = instanceHash; } /** * @param oldInstanceHash The oldInstanceHash to set. */ public void setOldInstanceHash(String oldInstanceHash) { this.oldInstanceHash = oldInstanceHash; } private static final boolean DONT_HASH = SystemProperties.getBoolean("findbugs.dontHash"); /** * @return Returns the instanceHash. */ public String getInstanceHash() { if (instanceHash != null) return instanceHash; MessageDigest digest = null; try { digest = MessageDigest.getInstance("MD5"); } catch (Exception e2) { // OK, we won't digest } instanceHash = getInstanceKey(); if (digest != null && !DONT_HASH) { byte [] data = digest.digest(instanceHash.getBytes()); String tmp = new BigInteger(1,data).toString(16); instanceHash = tmp; } return instanceHash; } public boolean isInstanceHashConsistent() { return oldInstanceHash == null || instanceHash.equals(oldInstanceHash); } /** * @param instanceOccurrenceNum The instanceOccurrenceNum to set. */ public void setInstanceOccurrenceNum(int instanceOccurrenceNum) { this.instanceOccurrenceNum = instanceOccurrenceNum; } /** * @return Returns the instanceOccurrenceNum. */ public int getInstanceOccurrenceNum() { return instanceOccurrenceNum; } /** * @param instanceOccurrenceMax The instanceOccurrenceMax to set. */ public void setInstanceOccurrenceMax(int instanceOccurrenceMax) { this.instanceOccurrenceMax = instanceOccurrenceMax; } /** * @return Returns the instanceOccurrenceMax. */ public int getInstanceOccurrenceMax() { return instanceOccurrenceMax; }}// vim:ts=4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -