package com.puppycrawl.tools.checkstyle.bcel.checks; import java.io.File; import java.util.BitSet; import java.util.Set; import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.LocalVariable; import org.apache.bcel.classfile.LocalVariableTable; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.LoadInstruction; import com.puppycrawl.tools.checkstyle.bcel.AbstractCheckVisitor; import com.puppycrawl.tools.checkstyle.bcel.EmptyClassFileVisitor; import com.puppycrawl.tools.checkstyle.bcel.EmptyDeepVisitor; import com.puppycrawl.tools.checkstyle.bcel.EmptyGenericVisitor; import com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor; /** * Checks for unread variables, i.e. unread formal parameters and local * variables. * Each class file must have a LocalVariableTable. * To generate a LocalVariableTable, compile with debug information, * as with option -g. * @author Rick Giles */ public class UnreadVariableCheck extends AbstractCheckVisitor { private final DeepVisitor mDeepVisitor = new DeepVisitor(); private final org.apache.bcel.classfile.Visitor mClassFileVisitor = new ClassFileVisitor(); private final org.apache.bcel.generic.Visitor mGenericVisitor = new GenericVisitor(); private JavaClass mCurrentJavaClass = null; private Method mCurrentMethod = null; private LocalVariableTable mLocalVariableTable = null; private final BitSet mLocalVariableBitSet = new BitSet(); private class DeepVisitor extends EmptyDeepVisitor { public org.apache.bcel.classfile.Visitor getClassFileVisitor() { return mClassFileVisitor; } public org.apache.bcel.generic.Visitor getGenericVisitor() { return mGenericVisitor; } public void visitObject(Object aObj) { mCurrentJavaClass = (JavaClass) aObj; } public void leaveSet(Set aSet) { checkReferences(); } } private class GenericVisitor extends EmptyGenericVisitor { public void visitLoadInstruction(LoadInstruction aInstruction) { mLocalVariableBitSet.set(aInstruction.getIndex()); } } private class ClassFileVisitor extends EmptyClassFileVisitor { public void visitMethod(Method aMethod) { // check references from previous method checkReferences(); mCurrentMethod = aMethod; // update reference recording mLocalVariableTable = aMethod.getLocalVariableTable(); mLocalVariableBitSet.clear(); } public void visitLocalVariableTable(LocalVariableTable aTable) { } } private void checkReferences() { if (mLocalVariableTable != null) { for (int i = 0; i < mLocalVariableTable.getLength(); i++) { if (!mLocalVariableBitSet.get(i)) { final LocalVariable localVariable = mLocalVariableTable.getLocalVariable(i); if (localVariable != null && !localVariable.getName().equals("this")) { log(0, "unread.variable", new Object[] { mCurrentJavaClass.getClassName(), mCurrentMethod.getName(), localVariable.getName(),}); } } } } } /** @see com.puppycrawl.tools.checkstyle.bcel.AbstractCheckVisitor */ public IDeepVisitor getVisitor() { return mDeepVisitor; } }