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

📄 methodannotation.java

📁 A static analysis tool to find bugs in Java programs
💻 JAVA
字号:
/* * 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.Constants;import edu.umd.cs.findbugs.ba.SignatureConverter;import edu.umd.cs.findbugs.ba.XFactory;import edu.umd.cs.findbugs.ba.XMethod;import edu.umd.cs.findbugs.classfile.MethodDescriptor;import edu.umd.cs.findbugs.util.ClassName;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;/** * A BugAnnotation specifying a particular method in a particular class. * A MethodAnnotation may (optionally) have a SourceLineAnnotation directly * embedded inside it to indicate the range of source lines where the * method is defined. * * @author David Hovemeyer * @see BugAnnotation */public class MethodAnnotation extends PackageMemberAnnotation {	private static final long serialVersionUID = 1L;	private static final boolean UGLY_METHODS = SystemProperties.getBoolean("ma.ugly");	private static final String DEFAULT_ROLE = "METHOD_DEFAULT";	private String methodName;	private String methodSig;	private String fullMethod;	private boolean isStatic;	public static final String METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL = "METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL";	public static final String METHOD_DANGEROUS_TARGET = "METHOD_DANGEROUS_TARGET";	public static final String METHOD_SAFE_TARGET = "METHOD_SAFE_TARGET";	/**	 * Constructor.	 *	 * @param className  the name of the class containing the method	 * @param methodName the name of the method	 * @param methodSig  the Java type signature of the method	 * @param isStatic   true if the method is static, false if not	 */	public MethodAnnotation(String className, String methodName, String methodSig, boolean isStatic) {		super(className, DEFAULT_ROLE);		this.methodName = methodName;		if (methodSig.indexOf(".") >= 0) {			assert false : "signatures should not be dotted: " + methodSig;			methodSig = methodSig.replace('.','/');		}		this.methodSig = methodSig;		this.isStatic = isStatic;		fullMethod = null;		sourceLines = null;	}	/**	 * Factory method to create a MethodAnnotation from the method the	 * given visitor is currently visiting.	 *	 * @param visitor the BetterVisitor currently visiting the method	 */	public static MethodAnnotation fromVisitedMethod(PreorderVisitor visitor) {		String className = visitor.getDottedClassName();		MethodAnnotation result = new MethodAnnotation(				className,				visitor.getMethodName(),				visitor.getMethodSig(),				visitor.getMethod().isStatic());		// Try to find the source lines for the method		SourceLineAnnotation srcLines = SourceLineAnnotation.fromVisitedMethod(visitor);		result.setSourceLines(srcLines);		return result;	}	/**	 * Factory method to create a MethodAnnotation from a method	 * called by the instruction the given visitor is currently visiting.	 * 	 * @param visitor the visitor	 * @return the MethodAnnotation representing the called method	 */	public static MethodAnnotation fromCalledMethod(DismantleBytecode visitor) {		String className = visitor.getDottedClassConstantOperand();		String methodName = visitor.getNameConstantOperand();		String methodSig = visitor.getSigConstantOperand();		return fromCalledMethod(className, methodName, methodSig,				visitor.getOpcode() == Constants.INVOKESTATIC);	}	/**	 * Factory method to create the MethodAnnotation from	 * the classname, method name, signature, etc.	 * The method tries to look up source line information for	 * the method.	 * 	 * @param className  name of the class containing the method	 * @param methodName name of the method	 * @param methodSig  signature of the method	 * @param isStatic   true if the method is static, false otherwise	 * @return the MethodAnnotation	 */	public static MethodAnnotation fromForeignMethod(			String className, String methodName, String methodSig, int accessFlags) {		// FIXME: would be nice to do this without using BCEL		 className = ClassName.toDottedClassName(className);		// Create MethodAnnotation.		// It won't have source lines yet.		MethodAnnotation methodAnnotation =			new MethodAnnotation(className, methodName, methodSig, (accessFlags & Constants.ACC_STATIC) != 0);		SourceLineAnnotation sourceLines = SourceLineAnnotation.getSourceAnnotationForMethod(				className, methodName, methodSig);		methodAnnotation.setSourceLines(sourceLines);		return methodAnnotation;	}	/**	 * Factory method to create the MethodAnnotation from	 * the classname, method name, signature, etc.	 * The method tries to look up source line information for	 * the method.	 * 	 * @param className  name of the class containing the method	 * @param methodName name of the method	 * @param methodSig  signature of the method	 * @param isStatic   true if the method is static, false otherwise	 * @return the MethodAnnotation	 */	public static MethodAnnotation fromForeignMethod(			String className, String methodName, String methodSig, boolean isStatic) {		// FIXME: would be nice to do this without using BCEL		 className = ClassName.toDottedClassName(className);		// Create MethodAnnotation.		// It won't have source lines yet.		MethodAnnotation methodAnnotation =			new MethodAnnotation(className, methodName, methodSig, isStatic);		SourceLineAnnotation sourceLines = SourceLineAnnotation.getSourceAnnotationForMethod(				className, methodName, methodSig);		methodAnnotation.setSourceLines(sourceLines);		return methodAnnotation;	}	/**	 * Create a MethodAnnotation from a method that is not	 * directly accessible.  We will use the repository to	 * try to find its class in order to populate the information	 * as fully as possible.	 * 	 * @param className  class containing called method	 * @param methodName name of called method	 * @param methodSig  signature of called method	 * @param isStatic   true if called method is static	 * @return the MethodAnnotation for the called method	 */	public static MethodAnnotation fromCalledMethod(			String className, String methodName, String methodSig, boolean isStatic) {		MethodAnnotation methodAnnotation =			fromForeignMethod(className, methodName, methodSig, isStatic);		methodAnnotation.setDescription("METHOD_CALLED");		return methodAnnotation;	}	/**	 * Create a MethodAnnotation from an XMethod.	 * 	 * @param xmethod the XMethod	 * @return the MethodAnnotation	 */	public static MethodAnnotation fromXMethod(XMethod xmethod) {		return fromForeignMethod(				xmethod.getClassName(),				xmethod.getName(),				xmethod.getSignature(),				xmethod.isStatic());	}	/**	 * Create a MethodAnnotation from a MethodDescriptor.	 * 	 * @param methodDescriptor the MethodDescriptor	 * @return the MethodAnnotation	 */	public static BugAnnotation fromMethodDescriptor(MethodDescriptor methodDescriptor) {		return fromForeignMethod(				methodDescriptor.getClassName(),				methodDescriptor.getName(),				methodDescriptor.getSignature(),				methodDescriptor.isStatic());	}	/**	 * Get the method name.	 */	public String getMethodName() {		return methodName;	}	public String getJavaSourceMethodName() {		if (methodName.equals("<clinit>")) return "<static initializer>";		if (methodName.equals("<init>")) {			String result = getClassName();			int pos = Math.max(result.lastIndexOf('$'),result.lastIndexOf('.'));			return className.substring(pos+1);		}		return methodName;	}	/**	 * Get the method type signature.	 */	public String getMethodSignature() {		return methodSig;	}	/**	 * Return whether or not the method is static.	 * 	 * @return true if the method is static, false otherwise	 */	public boolean isStatic() {		return isStatic;	}	/**	 * Convert to an XMethod.	 * 	 * @return an XMethod specifying the same method as this MethodAnnotation	 */	public XMethod toXMethod() {		return XFactory.createXMethod(className, methodName, methodSig, isStatic);	}	public void accept(BugAnnotationVisitor visitor) {		visitor.visitMethodAnnotation(this);	}	@Override	protected String formatPackageMember(String key, ClassAnnotation primaryClass) {		if (key.equals(""))			return UGLY_METHODS ? getUglyMethod() : getFullMethod(primaryClass);		else if (key.equals("givenClass")) {			if (className.equals(primaryClass.getClassName())) return getNameInClass(primaryClass);			else return shorten(primaryClass.getPackageName(), className) + "." + getNameInClass(primaryClass);		}		else if (key.equals("shortMethod") )			return className + "." + methodName + "(...)";		else if (key.equals("hash")){				String tmp= getNameInClass(false, true, true);				return className + "." + tmp;		}		else if (key.equals("returnType")) {			int i = methodSig.indexOf(')');			String returnType = methodSig.substring(i+1);			String pkgName = primaryClass == null ? "" : primaryClass.getPackageName();			SignatureConverter converter = new SignatureConverter(returnType);			return shorten(pkgName, converter.parseNext());		}	else			throw new IllegalArgumentException("unknown key " + key);	}	/**	 * Get the "full" method name.	 * This is a format which looks sort of like a method signature	 * that would appear in Java source code.	 * @param primaryClass TODO	 */	public String getNameInClass(ClassAnnotation primaryClass) {		return  getNameInClass(true, false, false);	}	/**	 * Get the "full" method name.	 * This is a format which looks sort of like a method signature	 * that would appear in Java source code.	 * 	 * note: If shortenPackeges==true, this will return the same	 * value as getNameInClass(), except that method caches the	 * result and this one does not. Calling this one may be slow.	 * 	 * @param shortenPackages whether to shorten package names	 * if they are in java or in the same package as this method.	 * @param useJVMMethodName TODO	 * @param hash TODO	 */	public String getNameInClass(boolean shortenPackages, boolean useJVMMethodName, boolean hash) {		// Convert to "nice" representation		StringBuffer result = new StringBuffer();		if (useJVMMethodName)			result.append(getMethodName());		else result.append(getJavaSourceMethodName());		result.append('(');		// append args		SignatureConverter converter = new SignatureConverter(methodSig);		if (converter.getFirst() != '(')			throw new IllegalStateException("bad method signature " + methodSig);		converter.skip();		boolean needsComma = false;		while (converter.getFirst() != ')') {			if (needsComma)				if (hash) result.append(",");				else result.append(", ");			if (shortenPackages)				result.append(removePackageName(converter.parseNext()));			else				result.append(converter.parseNext());			needsComma = true;		}		converter.skip();		result.append(')');		return result.toString();	}	/**	 * Get the "full" method name.	 * This is a format which looks sort of like a method signature	 * that would appear in Java source code.	 * @param primaryClass TODO	 */	public String getFullMethod(ClassAnnotation primaryClass) {		if (fullMethod == null) {			fullMethod = className + "." + getNameInClass(primaryClass);		}		return fullMethod;	}	private String getUglyMethod() {		return className + "." + methodName + " : " + methodSig.replace('/', '.');	}	@Override	public int hashCode() {		return className.hashCode() + methodName.hashCode() + methodSig.hashCode();	}	@Override	public boolean equals(Object o) {		if (!(o instanceof MethodAnnotation))			return false;		MethodAnnotation other = (MethodAnnotation) o;		return className.equals(other.className)				&& methodName.equals(other.methodName)				&& methodSig.equals(other.methodSig);	}	public int compareTo(BugAnnotation o) {		if (!(o instanceof MethodAnnotation)) // BugAnnotations must be Comparable with any type of BugAnnotation			return this.getClass().getName().compareTo(o.getClass().getName());		MethodAnnotation other = (MethodAnnotation) o;		int cmp;		cmp = className.compareTo(other.className);		if (cmp != 0)			return cmp;		cmp = methodName.compareTo(other.methodName);		if (cmp != 0)			return cmp;		return methodSig.compareTo(other.methodSig);	}	/* ----------------------------------------------------------------------	 * XML Conversion support	 * ---------------------------------------------------------------------- */	private static final String ELEMENT_NAME = "Method";	public void writeXML(XMLOutput xmlOutput) throws IOException {	}	public void writeXML(XMLOutput xmlOutput, boolean addMessages) throws IOException {		XMLAttributeList attributeList = new XMLAttributeList()			.addAttribute("classname", getClassName())			.addAttribute("name", getMethodName())			.addAttribute("signature", getMethodSignature())			.addAttribute("isStatic", String.valueOf(isStatic()));		String role = getDescription();		if (!role.equals(DEFAULT_ROLE))			attributeList.addAttribute("role", role);		if (sourceLines == null && !addMessages) {			xmlOutput.openCloseTag(ELEMENT_NAME, attributeList);		} else {			xmlOutput.openTag(ELEMENT_NAME, attributeList);			if (sourceLines != null) {				sourceLines.writeXML(xmlOutput);			}			if (addMessages) {				xmlOutput.openTag(MESSAGE_TAG);				xmlOutput.writeText(this.toString());				xmlOutput.closeTag(MESSAGE_TAG);			}			xmlOutput.closeTag(ELEMENT_NAME);		}	}		@Override	public boolean isSignificant() {		String role = getDescription();		if (METHOD_DANGEROUS_TARGET.equals(role) 				|| METHOD_DANGEROUS_TARGET_ACTUAL_GUARANTEED_NULL.equals(role) 				|| METHOD_SAFE_TARGET.equals(role)) return false;		return true;	}}// vim:ts=4

⌨️ 快捷键说明

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