📄 sourcelineannotation.java
字号:
* source line number for a visited instruction. * * @param classContext the ClassContext * @param methodGen the MethodGen object representing the method * @param handle the InstructionHandle containing the visited instruction * @return the SourceLineAnnotation, or null if we do not have line number information * for the instruction */ public static SourceLineAnnotation fromVisitedInstruction(ClassContext classContext, MethodGen methodGen, String sourceFile, @NonNull InstructionHandle handle) { LineNumberTable table = methodGen.getLineNumberTable(methodGen.getConstantPool()); String className = methodGen.getClassName(); int bytecodeOffset = handle.getPosition(); if (table == null) return createUnknown(className, sourceFile, bytecodeOffset, bytecodeOffset); int lineNumber = table.getSourceLine(handle.getPosition()); return new SourceLineAnnotation( className, sourceFile, lineNumber, lineNumber, bytecodeOffset, bytecodeOffset) .addInstructionContext(classContext, classContext.getMethod(methodGen)); } /** * Factory method for creating a source line annotation describing * the source line numbers for a range of instruction in a method. * * @param classContext theClassContext * @param methodGen the method * @param start the start instruction * @param end the end instruction (inclusive) */ public static SourceLineAnnotation fromVisitedInstructionRange( ClassContext classContext, MethodGen methodGen, String sourceFile, InstructionHandle start, InstructionHandle end) { LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool()); String className = methodGen.getClassName(); if (lineNumberTable == null) return createUnknown(className, sourceFile, start.getPosition(), end.getPosition()); int startLine = lineNumberTable.getSourceLine(start.getPosition()); int endLine = lineNumberTable.getSourceLine(end.getPosition()); return new SourceLineAnnotation( className, sourceFile, startLine, endLine, start.getPosition(), end.getPosition()) .addInstructionContext(classContext, classContext.getMethod(methodGen)); } private static LineNumberTable getLineNumberTable(PreorderVisitor visitor) { Code code = visitor.getMethod().getCode(); if (code == null) return null; return code.getLineNumberTable(); } private static final int NUM_CONTEXT_OPCODES = 5; /** * Fill in context information about surrounding opcodes. * * @param classContext the ClassContext * @param method the method */ private SourceLineAnnotation addInstructionContext(ClassContext classContext, Method method) { // For now, do nothing. return this; } /** * Get the class name. */ public String getClassName() { return className; } /** * Get the source file name. */ public String getSourceFile() { return sourceFile; } /** * Is the source file known? */ public boolean isSourceFileKnown() { return !sourceFile.equals(UNKNOWN_SOURCE_FILE); } /** * Set the source file name. * * @param sourceFile the source file name */ public void setSourceFile(String sourceFile) { this.sourceFile = sourceFile; } /** * Get the simple class name (the part of the name after the dot) */ public String getSimpleClassName() { int lastDot = className.lastIndexOf('.'); return className.substring(lastDot+1); } /** * Get the package name. */ public String getPackageName() { int lastDot = className.lastIndexOf('.'); if (lastDot < 0) return ""; else return className.substring(0, lastDot); } /** * Get the start line (inclusive). */ public int getStartLine() { return startLine; } /** * Get the ending line (inclusive). */ public int getEndLine() { return endLine; } /** * Get start bytecode (inclusive). */ public int getStartBytecode() { return startBytecode; } /** * Get end bytecode (inclusive). */ public int getEndBytecode() { return endBytecode; } /** * Is this an unknown source line annotation? */ public boolean isUnknown() { return startLine < 0 || endLine < 0; } public void accept(BugAnnotationVisitor visitor) { visitor.visitSourceLineAnnotation(this); } public String format(String key, ClassAnnotation primaryClass) { if (key.equals("hash")) return ""; if (key.equals("")) { StringBuffer buf = new StringBuffer(); buf.append(sourceFile); appendLines(buf); return buf.toString(); } else if (key.equals("lineNumber")) { StringBuffer buf = new StringBuffer(); appendLinesRaw(buf); return buf.toString(); } else if (key.equals("full")) { StringBuffer buf = new StringBuffer(); String pkgName = getPackageName(); if (!pkgName.equals("")) { buf.append(pkgName.replace('.', '/')); buf.append('/'); } buf.append(sourceFile); appendLines(buf); return buf.toString(); } else throw new IllegalArgumentException("Unknown format key " + key); } private void appendLines(StringBuffer buf) { if (isUnknown()) return; buf.append(":["); appendLinesRaw(buf); buf.append(']'); } private void appendLinesRaw(StringBuffer buf) { if (isUnknown()) return; if (startLine == endLine) { buf.append("line "); buf.append(startLine); } else { buf.append("lines "); buf.append(startLine); buf.append('-'); buf.append(endLine); } } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { String desc = description; if (desc.equals(DEFAULT_ROLE) && isUnknown()) desc = DEFAULT_ROLE_UNKNOWN_LINE; String pattern = I18N.instance().getAnnotationDescription(desc); FindBugsMessageFormat format = new FindBugsMessageFormat(pattern); return format.format(new BugAnnotation[]{this}, null); } public int compareTo(BugAnnotation o) { if (!(o instanceof SourceLineAnnotation)) // All BugAnnotations must be comparable return this.getClass().getName().compareTo(o.getClass().getName()); SourceLineAnnotation other = (SourceLineAnnotation) o; int cmp = className.compareTo(other.className); if (cmp != 0) return cmp; cmp = startLine - other.startLine; if (cmp != 0) return cmp; return endLine - other.endLine; } @Override public int hashCode() { return className.hashCode() + startLine + 3 * endLine; } @Override public boolean equals(Object o) { if (!(o instanceof SourceLineAnnotation)) return false; SourceLineAnnotation other = (SourceLineAnnotation) o; return className.equals(other.className) && startLine == other.startLine && endLine == other.endLine; } /* ---------------------------------------------------------------------- * XML Conversion support * ---------------------------------------------------------------------- */ private static final String ELEMENT_NAME = "SourceLine"; public void writeXML(XMLOutput xmlOutput) throws IOException { writeXML(xmlOutput, false); } public void writeXML(XMLOutput xmlOutput, boolean addMessages) throws IOException { String classname = getClassName(); String packageName = ""; if (classname.indexOf('.') > 0) packageName = classname.substring(0,1+classname.lastIndexOf('.')); XMLAttributeList attributeList = new XMLAttributeList() .addAttribute("classname", classname); int n = getStartLine(); // start/end are now optional (were too many "-1"s in the xml) if (n >= 0) attributeList.addAttribute("start", String.valueOf(n)); n = getEndLine(); if (n >= 0) attributeList.addAttribute("end", String.valueOf(n)); n = getStartBytecode(); // startBytecode/endBytecode haven't been set for a while now if (n >= 0) attributeList.addAttribute("startBytecode", String.valueOf(n)); n = getEndBytecode(); if (n >= 0) attributeList.addAttribute("endBytecode", String.valueOf(n)); if (isSourceFileKnown()) { attributeList.addAttribute("sourcefile", sourceFile); attributeList.addAttribute("sourcepath", packageName.replace('.', '/')+sourceFile); } String role = getDescription(); if (!role.equals(DEFAULT_ROLE)) attributeList.addAttribute("role", getDescription()); if (synthetic) attributeList.addAttribute("synthetic", "true"); if (addMessages) { xmlOutput.openTag(ELEMENT_NAME, attributeList); xmlOutput.openTag("Message"); xmlOutput.writeText(this.toString()); xmlOutput.closeTag("Message"); xmlOutput.closeTag(ELEMENT_NAME); } else { xmlOutput.openCloseTag(ELEMENT_NAME, attributeList); } } /** * @param synthetic The synthetic to set. */ public void setSynthetic(boolean synthetic) { this.synthetic = synthetic; } /** * @return Returns the synthetic. */ public boolean isSynthetic() { return synthetic; } public boolean isSignificant() { return false; } /** * @param className * @param methodName * @param methodSig * @return */ static SourceLineAnnotation getSourceAnnotationForMethod( String className, String methodName, String methodSig) { JavaClassAndMethod targetMethod = null; Code code = null; try { JavaClass targetClass = AnalysisContext.currentAnalysisContext().lookupClass(className); targetMethod = Hierarchy.findMethod(targetClass, methodName, methodSig); if (targetMethod != null) { Method method = targetMethod.getMethod(); if (method != null) code = method.getCode(); } } catch (ClassNotFoundException e) { AnalysisContext.reportMissingClass(e); } SourceInfoMap sourceInfoMap = AnalysisContext.currentAnalysisContext().getSourceInfoMap(); SourceInfoMap.SourceLineRange range = sourceInfoMap.getMethodLine(className, methodName, methodSig); if (range != null) return new SourceLineAnnotation( className, AnalysisContext.currentAnalysisContext().lookupSourceFile(className), range.getStart(), range.getEnd(), 0, code == null ? -1 : code.getLength()); if (sourceInfoMap.fallBackToClassfile() && targetMethod != null) return forEntireMethod( targetMethod.getJavaClass(), targetMethod.getMethod()); // If we couldn't find the source lines, // create an unknown source line annotation referencing // the class and source file. return createUnknown(className); }/** * @param className * @return */ static SourceLineAnnotation getSourceAnnotationForClass(String className, String sourceFileName) { int lastLine = -1; int firstLine = Integer.MAX_VALUE; try { JavaClass targetClass = AnalysisContext.currentAnalysisContext().lookupClass(className); for (Method m : targetClass.getMethods()) { Code c = m.getCode(); if (c != null) { LineNumberTable table = c.getLineNumberTable(); if (table != null) for (LineNumber line : table.getLineNumberTable()) { lastLine = Math.max(lastLine, line.getLineNumber()); firstLine = Math.min(firstLine, line.getLineNumber()); } } } } catch (ClassNotFoundException e) { AnalysisContext.reportMissingClass(e); } if (firstLine < Integer.MAX_VALUE) return new SourceLineAnnotation(className, sourceFileName, firstLine, lastLine, -1, -1); return SourceLineAnnotation.createUnknown(className, sourceFileName); }}// vim:ts=4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -