⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sourcelineannotation.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * 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 org.apache.bcel.classfile.Code;import org.apache.bcel.classfile.JavaClass;import org.apache.bcel.classfile.LineNumber;import org.apache.bcel.classfile.LineNumberTable;import org.apache.bcel.classfile.Method;import org.apache.bcel.generic.InstructionHandle;import org.apache.bcel.generic.MethodGen;import edu.umd.cs.findbugs.annotations.CheckForNull;import edu.umd.cs.findbugs.annotations.NonNull;import edu.umd.cs.findbugs.ba.AnalysisContext;import edu.umd.cs.findbugs.ba.ClassContext;import edu.umd.cs.findbugs.ba.Hierarchy;import edu.umd.cs.findbugs.ba.JavaClassAndMethod;import edu.umd.cs.findbugs.ba.Location;import edu.umd.cs.findbugs.ba.SourceInfoMap;import edu.umd.cs.findbugs.ba.XMethod;import edu.umd.cs.findbugs.visitclass.PreorderVisitor;import edu.umd.cs.findbugs.xml.XMLAttributeList;import edu.umd.cs.findbugs.xml.XMLOutput;/** * A BugAnnotation that records a range of source lines * in a class. * * @author David Hovemeyer * @see BugAnnotation */public class SourceLineAnnotation implements BugAnnotation {	private static final long serialVersionUID = 1L;	public static final String DEFAULT_ROLE = "SOURCE_LINE_DEFAULT";	public static final String DEFAULT_ROLE_UNKNOWN_LINE = "SOURCE_LINE_DEFAULT_UNKNOWN_LINE";	public static final String ROLE_ANOTHER_INSTANCE = "SOURCE_LINE_ANOTHER_INSTANCE";	/**	 * String returned if the source file is unknown.	 * This must match what BCEL uses when the source file is unknown.	 */	public static final String UNKNOWN_SOURCE_FILE = "<Unknown>";	private String description;	final private String className;	private String sourceFile;	final private int startLine;	final private int endLine;	final private int startBytecode;	final private int endBytecode;	private boolean synthetic;	/**	 * Constructor.	 *	 * @param className     the class to which the line number(s) refer	 * @param sourceFile    the name of the source file	 * @param startLine     the first line (inclusive)	 * @param endLine       the ending line (inclusive)	 * @param startBytecode the first bytecode offset (inclusive)	 * @param endBytecode   the end bytecode offset (inclusive)	 */	public SourceLineAnnotation(@NonNull String className, @NonNull String sourceFile, int startLine, int endLine,								int startBytecode, int endBytecode) {		if (className == null) throw new IllegalArgumentException("class name is null");		if (sourceFile == null) throw new IllegalArgumentException("source file is null");		this.description = DEFAULT_ROLE;		this.className = className;		this.sourceFile = sourceFile;		this.startLine = startLine;		this.endLine = endLine;		this.startBytecode = startBytecode;		this.endBytecode = endBytecode;	}	@Override	public Object clone() {		try {			return super.clone();		} catch (CloneNotSupportedException e) {			throw new AssertionError(e);		}	}	/**	 * Factory method to create an unknown source line annotation.	 *	 * @param className the class name	 * @param sourceFile the source file name	 * @return the SourceLineAnnotation	 */	public static SourceLineAnnotation createUnknown(String className, String sourceFile) {		return createUnknown(className, sourceFile, -1, -1);	}	/**	 * Factory method to create an unknown source line annotation.	 * This variant looks up the source filename automatically	 * based on the class using best effort.	 *	 * @param className the class name	 * @return the SourceLineAnnotation	 */	public static SourceLineAnnotation createUnknown(String className) {		return createUnknown(				className,				AnalysisContext.currentAnalysisContext().lookupSourceFile(className),				-1,				-1);	}	/**	 * Factory method to create an unknown source line annotation.	 * This doesn't use the analysis context.	 *	 * @param className the class name	 * @return the SourceLineAnnotation	 */	public static SourceLineAnnotation createReallyUnknown(String className) {		return createUnknown(				className,				SourceLineAnnotation.UNKNOWN_SOURCE_FILE,				-1,				-1);	}	/**	 * Factory method to create an unknown source line annotation.	 * This variant is used when bytecode offsets are known,	 * but not source lines.	 *	 * @param className the class name	 * @param sourceFile the source file name	 * @return the SourceLineAnnotation	 */	public static SourceLineAnnotation createUnknown(String className, String sourceFile, int startBytecode, int endBytecode) {		SourceLineAnnotation result = new SourceLineAnnotation(className, sourceFile, -1, -1, startBytecode, endBytecode);		// result.setDescription("SOURCE_LINE_UNKNOWN");		return result;	}	/**	 * Factory method for creating a source line annotation describing	 * an entire method.	 *	 * @param visitor a BetterVisitor which is visiting the method	 * @return the SourceLineAnnotation	 */	public static SourceLineAnnotation fromVisitedMethod(PreorderVisitor visitor) {		SourceLineAnnotation sourceLines = getSourceAnnotationForMethod(				visitor.getDottedClassName(), visitor.getMethodName(), visitor.getMethodSig());		return sourceLines;	}	/**	 * Factory method for creating a source line annotation describing an entire	 * method.	 * 	 * @param methodGen	 *            the method being visited	 * @return the SourceLineAnnotation, or null if we do not have line number	 *         information for the method	 */	public static SourceLineAnnotation fromVisitedMethod(MethodGen methodGen, String sourceFile) {		LineNumberTable lineNumberTable = methodGen.getLineNumberTable(methodGen.getConstantPool());		String className = methodGen.getClassName();		int codeSize = methodGen.getInstructionList().getLength();		if (lineNumberTable == null)			return createUnknown(className, sourceFile, 0, codeSize - 1);		return forEntireMethod(className, sourceFile, lineNumberTable, codeSize);	}	/**	 * Create a SourceLineAnnotation covering an entire method.	 * 	 * @param className       name of the class the method is in	 * @param sourceFile      source file containing the method	 * @param lineNumberTable the method's LineNumberTable	 * @param codeSize        size in bytes of the method's code	 * @return a SourceLineAnnotation covering the entire method	 */	public static SourceLineAnnotation forEntireMethod(String className, String sourceFile,														LineNumberTable lineNumberTable, int codeSize) {		LineNumber[] table = lineNumberTable.getLineNumberTable();		if (table != null && table.length > 0) {			LineNumber first = table[0];			LineNumber last = table[table.length - 1];			return new SourceLineAnnotation(className, sourceFile, first.getLineNumber(), last.getLineNumber(),					0, codeSize - 1);		} else {			return createUnknown(className, sourceFile, 0, codeSize - 1);		}	}	/**	 * Create a SourceLineAnnotation covering an entire method.	 * 	 * @param javaClass JavaClass containing the method	 * @param method    the method	 * @return a SourceLineAnnotation for the entire method	 */	public static SourceLineAnnotation forEntireMethod(JavaClass javaClass, @CheckForNull Method method) {		String sourceFile = javaClass.getSourceFileName();		if (method == null) 			return createUnknown(javaClass.getClassName(), sourceFile);		Code code = method.getCode();		LineNumberTable lineNumberTable = method.getLineNumberTable();		if (code == null || lineNumberTable == null) {			return createUnknown(javaClass.getClassName(), sourceFile);		}		return forEntireMethod(javaClass.getClassName(), sourceFile, lineNumberTable, code.getLength());	}	/**	 * Create a SourceLineAnnotation covering an entire method.	 * 	 * @param javaClass JavaClass containing the method	 * @param xmethod    the method	 * @return a SourceLineAnnotation for the entire method	 */	public static SourceLineAnnotation forEntireMethod(JavaClass javaClass, XMethod xmethod) {		JavaClassAndMethod m = Hierarchy.findMethod(javaClass, xmethod.getName(), xmethod.getSignature());		if (m == null) {			return createUnknown(javaClass.getClassName(), javaClass.getSourceFileName());		} else {			return forEntireMethod(javaClass, m.getMethod());		}	}	/**	 * Factory method for creating a source line annotation describing the	 * source line number for the instruction being visited by given visitor.	 *	 * @param visitor a BetterVisitor which is visiting the method	 * @param pc      the bytecode offset of the instruction in the method	 * @return the SourceLineAnnotation, or null if we do not have line number information	 *         for the instruction	 */	public static SourceLineAnnotation fromVisitedInstruction(BytecodeScanningDetector visitor, int pc) {		return fromVisitedInstructionRange(visitor.getClassContext(), visitor, pc, pc);	}	/**	 * Factory method for creating a source line annotation describing the	 * source line number for the instruction being visited by given visitor.	 *	 * @param classContext the ClassContext	 * @param visitor a BetterVisitor which is visiting the method	 * @param pc      the bytecode offset of the instruction in the method	 * @return the SourceLineAnnotation, or null if we do not have line number information	 *         for the instruction	 */	public static SourceLineAnnotation fromVisitedInstruction(ClassContext classContext, PreorderVisitor visitor, int pc) {		return fromVisitedInstructionRange(classContext, visitor, pc, pc);	}	/**	 * Create from Method and Location in a visited class.	 * 	 * @param classContext ClassContext of visited class	 * @param method       Method in visited class	 * @param loc          Location in visited class	 * @return SourceLineAnnotation describing visited Location	 */	public static SourceLineAnnotation fromVisitedInstruction(ClassContext classContext, Method method, Location loc) {		return fromVisitedInstruction(classContext, method, loc.getHandle());	}	/**	 * Create from Method and InstructionHandle in a visited class.	 * 	 * @param classContext ClassContext of visited class	 * @param method       Method in visited class	 * @param handle       InstructionHandle in visited class	 * @return SourceLineAnnotation describing visited instruction	 */	public static SourceLineAnnotation fromVisitedInstruction(ClassContext classContext, Method method, InstructionHandle handle) {		return fromVisitedInstruction(classContext, method, handle.getPosition());	}	/**	 * Create from Method and bytecode offset in a visited class.	 * 	 * @param classContext ClassContext of visited class	 * @param method       Method in visited class	 * @param pc           bytecode offset in visited method	 * @return SourceLineAnnotation describing visited instruction	 */	public static SourceLineAnnotation fromVisitedInstruction(ClassContext classContext, Method method, int pc) {		LineNumberTable lineNumberTable = method.getCode().getLineNumberTable();		String className = classContext.getJavaClass().getClassName();		String sourceFile = classContext.getJavaClass().getSourceFileName();		if (lineNumberTable == null)			return createUnknown(className, sourceFile, pc, pc);		int startLine = lineNumberTable.getSourceLine(pc);		return new SourceLineAnnotation(className, sourceFile, startLine, startLine, pc, pc).addInstructionContext(classContext, method);	}	/**	 * Factory method for creating a source line annotation describing the	 * source line numbers for a range of instructions in the method being	 * visited by the given visitor.	 *	 * @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 the SourceLineAnnotation, or null if we do not have line number information	 *         for the instruction	 */	public static SourceLineAnnotation fromVisitedInstructionRange(			BytecodeScanningDetector visitor, int startPC, int endPC) {		LineNumberTable lineNumberTable = getLineNumberTable(visitor);		String className = visitor.getDottedClassName();		String sourceFile = visitor.getSourceFile();		if (lineNumberTable == null)			return createUnknown(className, sourceFile, startPC, endPC);		int startLine = lineNumberTable.getSourceLine(startPC);		int endLine = lineNumberTable.getSourceLine(endPC);		return new SourceLineAnnotation(className, sourceFile, startLine, endLine, startPC, endPC)				.addInstructionContext(visitor.getClassContext(), visitor.getMethod());	}	/**	 * Factory method for creating a source line annotation describing the	 * source line numbers for a range of instructions in the method being	 * visited by the given visitor.	 *	 * @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 the SourceLineAnnotation, or null if we do not have line number information	 *         for the instruction	 */	public static SourceLineAnnotation fromVisitedInstructionRange(			ClassContext classContext, PreorderVisitor visitor, int startPC, int endPC) {		LineNumberTable lineNumberTable = getLineNumberTable(visitor);		String className = visitor.getDottedClassName();		String sourceFile = visitor.getSourceFile();		if (lineNumberTable == null)			return createUnknown(className, sourceFile, startPC, endPC);		int startLine = lineNumberTable.getSourceLine(startPC);		int endLine = lineNumberTable.getSourceLine(endPC);		return new SourceLineAnnotation(className, sourceFile, startLine, endLine, startPC, endPC)				.addInstructionContext(classContext, visitor.getMethod());	}	public static SourceLineAnnotation fromRawData(String className, String sourceFile, int startLine, int endLine, int startPC, int endPC) {		if (startLine == -1)			return createUnknown(className, sourceFile, startPC, endPC);		return new SourceLineAnnotation(className, sourceFile, startLine, endLine, startPC, endPC)				.addInstructionContext(null, null); // throw exception if we ever start using this	}	/**	 * Factory method for creating a source line annotation describing the	 * source line number for the instruction being visited by given visitor.	 *	 * @param visitor a DismantleBytecode visitor which is visiting the method	 * @return the SourceLineAnnotation, or null if we do not have line number information	 *         for the instruction	 */	public static SourceLineAnnotation fromVisitedInstruction(BytecodeScanningDetector visitor) {		return fromVisitedInstruction(visitor.getClassContext(), visitor, visitor.getPC());	}	/**	 * Factory method for creating a source line annotation describing the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -