Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2013 Dave Brosius
   * 
   * 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 com.mebigfatguy.fbcontrib.detect;
 
 import  org.apache.bcel.classfile.Code;
 import  org.apache.bcel.classfile.Constant;
 import  org.apache.bcel.classfile.ConstantString;
 
 
 import  edu.umd.cs.findbugs.BugInstance;
 import  edu.umd.cs.findbugs.BugReporter;
 import  edu.umd.cs.findbugs.BytecodeScanningDetector;
 import  edu.umd.cs.findbugs.OpcodeStack;
 import  edu.umd.cs.findbugs.ba.ClassContext;

looks for appending strings inside of calls to StringBuffer or StringBuilder append.
 
 public class InefficientStringBuffering extends BytecodeScanningDetector
 {
 	private BugReporter bugReporter;
 	private OpcodeStack stack;
 	private boolean sawLDCEmpty;

constructs a ISB detector given the reporter to report bugs on

Parameters:
bugReporter the sync of bug reports
 
 	public InefficientStringBuffering(final BugReporter bugReporter) {
 		this. = bugReporter;
 	}

implements the visitor to create an clear the stack

Parameters:
classContext the context object of the currently parsed class
 
 	public void visitClassContext(ClassContext classContext) {
 		try {
 			 = new OpcodeStack();
 			super.visitClassContext(classContext);
 		} finally {
 			 = null;
 		}
 	}
    
implements the visitor to create and clear the stack

Parameters:
obj the context object of the currently parsed code block
 
 	public void visitCode(final Code obj) {
 		if (obj.getCode() != null) {
             .resetForMethodEntry(this);
              = false;
 			super.visitCode(obj);
 		}
 	}
 	
 	public void sawOpcode(final int seen) {
 		Boolean nestedSB = null;
 		try {
 			.mergeJumps(this);
 			
 			if (seen == INVOKESPECIAL) {
 				String calledClass = getClassConstantOperand();
 				String signature = getSigConstantOperand();
 				if (("java/lang/StringBuffer".equals(calledClass)
 				||  "java/lang/StringBuilder".equals(calledClass))
 				&&  "<init>".equals(getNameConstantOperand())) {
 					if ("()V".equals(signature)) {
 						OpcodeStack.Item itm = getStringBufferItemAt(2);
 						if (itm != null) {
 							nestedSB = .;
 						}
 					} else if ("(Ljava/lang/String;)V".equals(signature)) {
 						if (.getStackDepth() > 0) {
 							OpcodeStack.Item itm = .getStackItem(0);
 							nestedSB = (Boolean)itm.getUserValue();
 							if ((nestedSB != null) && nestedSB.booleanValue()) {
								.reportBug( 
										new BugInstance(this"ISB_INEFFICIENT_STRING_BUFFERING", NORMAL_PRIORITY)
												.addClass(this)
												.addMethod(this)
												.addSourceLine(this));
							}
						}
					}
				}
else if (seen == INVOKEVIRTUAL) {
				if () {
					String calledClass = getClassConstantOperand();
					if (("java/lang/StringBuffer".equals(calledClass)
					||  "java/lang/StringBuilder".equals(calledClass))
					&&  getSigConstantOperand().startsWith("(Ljava/lang/String;)")) {
						if (.getStackDepth() > 1) {
                            OpcodeStack.Item sbItm = .getStackItem(1);
                            if ((sbItm != null) && (sbItm.getUserValue() == null))
                            {
    							OpcodeStack.Item itm = .getStackItem(0);
    							Object cons = itm.getConstant();
    							if ((cons instanceof String) && (itm.getRegisterNumber() < 0)) {
    								if (((String)cons).length() == 0) {
    									.reportBug(
    										new BugInstance(this"ISB_EMPTY_STRING_APPENDING", NORMAL_PRIORITY)
    											.addClass(this)
    											.addMethod(this)
    											.addSourceLine(this));
    								}
    							}
                            }
						}
					}
				}
				String calledClass = getClassConstantOperand();
				if (("java/lang/StringBuffer".equals(calledClass)
				||  "java/lang/StringBuilder".equals(calledClass))) {
					String methodName = getNameConstantOperand();
					if ("append".equals(methodName)) {
						OpcodeStack.Item itm = getStringBufferItemAt(1);
						nestedSB = (itm == null) ? null : (Boolean)itm.getUserValue();
						if (.getStackDepth() > 0) {
							itm = .getStackItem(0);
							Boolean uValue = (Boolean)itm.getUserValue();
							if ((uValue != null) && uValue.booleanValue()) {
								.reportBug( 
										new BugInstance(this"ISB_INEFFICIENT_STRING_BUFFERING""toString".equals(getMethodName()) ? LOW_PRIORITY : NORMAL_PRIORITY)
												.addClass(this)
												.addMethod(this)
												.addSourceLine(this));
							}
						}
else if ("toString".equals(methodName)) {
						OpcodeStack.Item itm = getStringBufferItemAt(0);
						nestedSB = (itm == null) ? null : (Boolean)itm.getUserValue();
					}
				}
else if ((seen == GOTO) || (seen == GOTO_W)) {
				int depth = .getStackDepth();
				for (int i = 0; i < depthi++) {
					OpcodeStack.Item itm = .getStackItem(i);
					itm.setUserValue(.);
				}
else if ((seen == LDC) || (seen == LDC_W)) {
				Constant c = getConstantRefOperand();
				if (c instanceof ConstantString) {
					String s = ((ConstantString) c).getBytes(getConstantPool());
					if (s.length() == 0)
						 = true;
				}
			}
finally {
			TernaryPatcher.pre(seen);
			.sawOpcode(thisseen);
			TernaryPatcher.post(seen);
			if (nestedSB != null) {
				if (.getStackDepth() > 0) {
					OpcodeStack.Item itm = .getStackItem(0);
					itm.setUserValue(nestedSB);
				}
			}
		}
	}
	private OpcodeStack.Item getStringBufferItemAt(int depth) {
		if (.getStackDepth() > depth) {
			OpcodeStack.Item itm = .getStackItem(depth);
			String signature = itm.getSignature();
			if ("Ljava/lang/StringBuffer;".equals(signature)
			||  "Ljava/lang/StringBuilder;".equals(signature)) {
				return itm;
			}
		}
		return null;
	}
New to GrepCode? Check out our FAQ X