[Fb-contrib-commit] SF.net SVN: fb-contrib: [932] trunk/fb-contrib/src/com/mebigfatguy/ fbcontrib/d
Brought to you by:
dbrosius
From: <dbr...@us...> - 2007-10-11 06:38:00
|
Revision: 932 http://fb-contrib.svn.sourceforge.net/fb-contrib/?rev=932&view=rev Author: dbrosius Date: 2007-10-10 23:38:02 -0700 (Wed, 10 Oct 2007) Log Message: ----------- check for member collections now as well Modified Paths: -------------- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseAddAll.java Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseAddAll.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseAddAll.java 2007-10-11 05:57:21 UTC (rev 931) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseAddAll.java 2007-10-11 06:38:02 UTC (rev 932) @@ -33,6 +33,7 @@ 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.XField; /** * looks for loops that transfers the contents of one collection to another. These collection sources @@ -54,10 +55,11 @@ private BugReporter bugReporter; private OpcodeStack stack; - /** register to alias register */ - private Map<Integer, Integer> userValues; + /** register/field to alias register/field */ + private Map<Comparable, Comparable> userValues; /** alias register to loop info */ - private Map<Integer, LoopInfo> loops; + private Map<Comparable, LoopInfo> loops; + private boolean isInstanceMethod; /** * constructs a UTA detector given the reporter to report bugs on @@ -99,8 +101,9 @@ public void visitCode(Code obj) { try { stack.resetForMethodEntry(this); - userValues = new HashMap<Integer, Integer>(); - loops = new HashMap<Integer, LoopInfo>(); + userValues = new HashMap<Comparable, Comparable>(); + loops = new HashMap<Comparable, LoopInfo>(); + isInstanceMethod = !getMethod().isStatic(); super.visitCode(obj); } finally { userValues = null; @@ -115,8 +118,8 @@ */ @Override public void sawOpcode(int seen) { - int reg = -1; - Integer uValue = null; + Comparable regOrField = null; + Comparable uValue = null; boolean sawAlias = false; boolean sawLoad = false; @@ -127,26 +130,41 @@ if ("get".equals(methodName) && "(I)Ljava/lang/Object;".equals(signature)) { if (stack.getStackDepth() > 1) { OpcodeStack.Item itm = stack.getStackItem(1); - reg = isLocalCollection(itm); + int reg = isLocalCollection(itm); if (reg >= 0) { + regOrField = Integer14.valueOf(reg); sawAlias = true; + } else { + String field = isFieldCollection(itm); + if (field != null) { + regOrField = field; + sawAlias = true; + } } } } else if ("keySet".equals(methodName) || "values".equals(methodName) || "iterator".equals(methodName) || "next".equals(methodName) || "hasNext".equals(methodName)) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); - reg = isLocalCollection(itm); + int reg = isLocalCollection(itm); if (reg >= 0) { + regOrField = Integer14.valueOf(reg); sawAlias = true; + } else { + String field = isFieldCollection(itm); + if (field != null) { + regOrField = field; + sawAlias = true; + } } } } else if ("add".equals(methodName) && "(Ljava/lang/Object;)Z".equals(signature)) { if (stack.getStackDepth() > 1) { OpcodeStack.Item colItem = stack.getStackItem(1); OpcodeStack.Item valueItem = stack.getStackItem(0); - reg = isLocalCollection(colItem); + int reg = isLocalCollection(colItem); if (reg >= 0) { - uValue = (Integer)valueItem.getUserValue(); + regOrField = Integer14.valueOf(reg); + uValue = (Comparable)valueItem.getUserValue(); if (uValue != null) { LoopInfo loop = loops.get(uValue); if ((loop != null) && loop.isInLoop(getPC(), false)) { @@ -156,13 +174,28 @@ .addSourceLine(this)); } } + } else { + String field = isFieldCollection(colItem); + if (field != null) { + regOrField = field; + uValue = (Comparable)valueItem.getUserValue(); + if (uValue != null) { + LoopInfo loop = loops.get(uValue); + if ((loop != null) && loop.isInLoop(getPC(), false)) { + bugReporter.reportBug(new BugInstance(this, "UAA_USE_ADD_ALL", NORMAL_PRIORITY) + .addClass(this) + .addMethod(this) + .addSourceLine(this)); + } + } + } } } } } else if (((seen == ISTORE) || ((seen >= ISTORE_0) && (seen <= ISTORE_3))) || ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3)))) { if (stack.getStackDepth() > 0) { - uValue = (Integer)stack.getStackItem(0).getUserValue(); + uValue = (Comparable)stack.getStackItem(0).getUserValue(); userValues.put(Integer14.valueOf(RegisterUtils.getStoreReg(this, seen)), uValue); } } else if (((seen == ILOAD) || ((seen >= ILOAD_0) && (seen <= ILOAD_3))) @@ -181,7 +214,7 @@ gotoPos += brOffset; if (gotoPos < getPC()) { OpcodeStack.Item itm = stack.getStackItem(0); - uValue = (Integer)itm.getUserValue(); + uValue = (Comparable)itm.getUserValue(); if (uValue != null) { loops.put(uValue, new LoopInfo(getPC(), getBranchTarget())); } @@ -198,6 +231,22 @@ } } } + } else if (isInstanceMethod && (seen == PUTFIELD)) { + if (stack.getStackDepth() > 1) { + OpcodeStack.Item item = stack.getStackItem(1); + if (item.getRegisterNumber() == 0) { + uValue = (Comparable)stack.getStackItem(0).getUserValue(); + userValues.put(getNameConstantOperand(), uValue); + } + } + } else if (isInstanceMethod && (seen == GETFIELD)) { + if (stack.getStackDepth() > 0) { + OpcodeStack.Item item = stack.getStackItem(0); + if (item.getRegisterNumber() == 0) { + uValue = userValues.get(getNameConstantOperand()); + sawLoad = true; + } + } } else if (((seen > IFEQ) && (seen <= GOTO)) || (seen == IFNULL) || (seen == IFNONNULL)) { LoopInfo loop = findLoop(getPC(), true); if (loop != null) { @@ -206,29 +255,37 @@ } else if (seen == CHECKCAST) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); - uValue = (Integer)itm.getUserValue(); + uValue = (Comparable)itm.getUserValue(); if (uValue != null) { - reg = ((Integer)uValue).intValue(); + regOrField = uValue; sawAlias = true; } } } } catch (ClassNotFoundException cnfe) { bugReporter.reportMissingClass(cnfe); + } catch (Exception e) { + e.printStackTrace(); } finally { stack.sawOpcode(this, seen); if (sawAlias) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); - itm.setUserValue(Integer14.valueOf(reg)); + itm.setUserValue(regOrField); } } else if (sawLoad) { if (stack.getStackDepth() > 0) { OpcodeStack.Item itm = stack.getStackItem(0); - reg = itm.getRegisterNumber(); + int reg = itm.getRegisterNumber(); if (reg >= 0) { uValue = userValues.get(Integer14.valueOf(reg)); itm.setUserValue(uValue); + } else { + XField xField = itm.getXField(); + if (xField != null) { + uValue = userValues.get(xField.getName()); + itm.setUserValue(uValue); + } } } } @@ -244,9 +301,9 @@ * @throws ClassNotFoundException if the items class cannot be found */ private int isLocalCollection(OpcodeStack.Item item) throws ClassNotFoundException { - Integer aliasReg = (Integer)item.getUserValue(); - if (aliasReg != null) - return aliasReg.intValue(); + Comparable aliasReg = (Comparable)item.getUserValue(); + if (aliasReg instanceof Integer) + return ((Integer)aliasReg).intValue(); int reg = item.getRegisterNumber(); if (reg < 0) @@ -259,6 +316,30 @@ return -1; } + /** + * determines if the stack item refers to a collection that is stored in a field + * + * param item the stack item to check + * + * @return the field name of the collection, or null + * @throws ClassNotFoundException if the items class cannot be found + */ + private String isFieldCollection(OpcodeStack.Item item) throws ClassNotFoundException { + Comparable aliasReg = (Comparable)item.getUserValue(); + if (aliasReg instanceof String) + return (String)aliasReg; + + XField field = item.getXField(); + if (field == null) + return null; + + JavaClass cls = item.getJavaClass(); + if ((cls != null) && cls.implementationOf(collectionClass)) + return field.getName(); + + return null; + } + private LoopInfo findLoop(int pc, boolean ignoreConditionals) { for (LoopInfo loop : loops.values()) { if (loop.isInLoop(pc, ignoreConditionals)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |