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 java.util.Set;
 
 import  org.apache.bcel.Repository;
 import  org.apache.bcel.classfile.Constant;
 import  org.apache.bcel.classfile.ConstantInteger;
 import  org.apache.bcel.classfile.JavaClass;
 import  org.apache.bcel.classfile.Method;
 
 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;
 import  edu.umd.cs.findbugs.ba.XMethod;

looks for methods that access arrays or classes that implement java.util.List using a constant integer for the index. This is often a typo intented to be a loop variable, but if specific indices mean certain things, perhaps a first class object would be a better choice for a container.
 
 public class ConstantListIndex extends BytecodeScanningDetector
 {
 	enum State {SAW_NOTHING, SAW_CONSTANT_0, SAW_CONSTANT}
 	
 	private static final String MAX_ICONST0_LOOP_DISTANCE_PROPERTY = "fb-contrib.cli.maxloopdistance";
 	private static final Set<StringubiquitousMethods = new HashSet<String>(2);
 	private static JavaClass INVOCATIONHANDLER_CLASS;
 	static {
 		.add("java.lang.String.split(Ljava/lang/String;)[Ljava/lang/String;");
 		
 		try {
 		     = Repository.lookupClass("java.lang.reflect.InvocationHandler");
 		} catch (ClassNotFoundException cnfe) {
 		     = null;
 		}
 	}
 	
 	
 	private final BugReporter bugReporter;
 	private State state;
 	private BitSet iConst0Looped;
 	private final int max_iConst0LoopDistance;
 	private OpcodeStack stack;

constructs a CLI detector given the reporter to report bugs on

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

implements the visitor to create and clear the const0loop set

Parameters:
classContext the context object of the currently parsed class
 
 	public void visitClassContext(ClassContext classContext) {
 		try {
 		    if ( != null) {
 		        if (classContext.getJavaClass().implementationOf()) {
 		            return;
 		        }
 		    }
 			 = new BitSet();
 			 = new OpcodeStack();
 			super.visitClassContext(classContext);
 		} catch (ClassNotFoundException cnfe) {
 		    .reportMissingClass(cnfe);
 		} finally {
 			 = null;
 			 = null;
 		}
 	}

implements the visitor to reset the state

Parameters:
obj the context object for the currently parsed code block
	public void visitMethod(Method obj) {
		.resetForMethodEntry(this);
	}

implements the visitor to find accesses to lists or arrays using constants

Parameters:
seen the currently visitor opcode
	public void sawOpcode(int seen) {
		try {
	        .precomputation(this);
	        
			switch () {
					if (seen == ICONST_0)
					else if ((seen >= ICONST_1) && (seen <= ICONST_5))
					else if ((seen == LDC) || (seen == LDC_W)) {
						Constant c = getConstantRefOperand();
						if (c instanceof ConstantInteger)
					}
				break;
					switch (seen) {
						case AALOAD:
							if ("main".equals(this.getMethodName()))
								break;
							//$FALL-THROUGH$
						case IALOAD:
						case LALOAD:
						case FALOAD:
						case DALOAD:
						//case BALOAD: byte and char indexing seems prevalent, and 
						//case CALOAD: usually harmless so ignore
						case SALOAD:
							else {
								if (.getStackDepth() > 1) {
									OpcodeStack.Item item = .getStackItem(1);
									if (!isArrayFromUbiquitousMethod(item)) {
										.reportBug(new BugInstance(this"CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY)
													.addClass(this)
													.addMethod(this)
													.addSourceLine(this));
									}
								}
							}
						break;
						case INVOKEVIRTUAL:
							if ("java/util/List".equals(getClassConstantOperand())) {
								String methodName = getNameConstantOperand();
								if ("get".equals(methodName)) {
									else {
										.reportBug(new BugInstance(this"CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY)
																.addClass(this)
																.addMethod(this)
																.addSourceLine(this));
									}
								}
							}
						break;
					}
				break;
			}
			if (((seen >= IFEQ) && (seen <= GOTO)) || (seen == GOTO_W)) {
				int branchTarget = this.getBranchTarget();
				for (int bugPC = .nextSetBit(0); bugPC >= 0; bugPC = .nextSetBit(bugPC+1)) {
					if (branchTarget < bugPC) {
						if ((bugPC - branchTarget) < ) {
							.reportBug(new BugInstance(this"CLI_CONSTANT_LIST_INDEX", NORMAL_PRIORITY)
													.addClass(this)
													.addMethod(this)
													.addSourceLine(thisbugPC));
						}
					}
				}
			}
finally {
			.sawOpcode(thisseen);
		}
	}

returns whether the array item was returned from a common method that the user can't do anything about and so don't report CLI in this case.

Parameters:
item the stack item representing the array
Returns:
if the array was returned from a common method
	private boolean isArrayFromUbiquitousMethod(OpcodeStack.Item item) {
		XMethod method = item.getReturnValueOf();
		if (method == null)
			return false;
		String methodDesc = method.getClassName() + '.' + method.getName() + method.getSignature();
		return .contains(methodDesc);
	}
New to GrepCode? Check out our FAQ X