[Fb-contrib-commit] SF.net SVN: fb-contrib:[1794] trunk/fb-contrib
Brought to you by:
dbrosius
From: <dbr...@us...> - 2016-08-17 00:36:41
|
Revision: 1794 http://sourceforge.net/p/fb-contrib/code/1794 Author: dbrosius Date: 2016-08-17 00:36:37 +0000 (Wed, 17 Aug 2016) Log Message: ----------- sync from github Modified Paths: -------------- trunk/fb-contrib/build.xml trunk/fb-contrib/etc/findbugs.xml trunk/fb-contrib/htdocs/index.shtml trunk/fb-contrib/htdocs/repository.html trunk/fb-contrib/pom.xml trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/collect/CollectStatistics.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/AbnormalFinallyBlockReturn.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BloatedAssignmentScope.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BogusExceptionDeclaration.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CommonsEqualsBuilderToEquals.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CompareClassNameEquals.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConfusingFunctionSemantics.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CyclomaticComplexity.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DeletingWhileIterating.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DubiousMapCollection.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ExceptionSoftening.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FieldCouldBeLocal.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FinalParameters.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FindCircularDependencies.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FloatingPointLoops.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/HangingExecutors.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/MethodReturnsConstant.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ModifyingUnmodifiableCollection.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/NeedlessMemberCollectionSynchronization.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/NonRecycleableTaglibs.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/OverlyConcreteParameter.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/PartiallyConstructedObjectAccess.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/PoorMansEnum.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/PossibleMemoryBloat.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/PossiblyRedundantMethodCalls.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/SluggishGui.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/SuspiciousComparatorReturnValues.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/TristateBooleanPattern.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnitTestAssertionOddities.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnrelatedCollectionContents.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnrelatedReturnValues.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UnusedParameter.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseAddAll.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseEnumCollections.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/UseToArray.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/utils/BugType.java trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/utils/QMethod.java Added Paths: ----------- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/utils/StopOpcodeParsingException.java Modified: trunk/fb-contrib/build.xml =================================================================== --- trunk/fb-contrib/build.xml 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/build.xml 2016-08-17 00:36:37 UTC (rev 1794) @@ -28,7 +28,7 @@ <property name="javac.deprecation" value="on" /> <property name="javac.debug" value="on" /> - <property name="fb-contrib.version" value="6.7.0-SNAPSHOT" /> + <property name="fb-contrib.version" value="6.6.2" /> <property name="sonatype.dir" value="${user.home}/.fb-contrib-${fb-contrib.version}-sonatype" /> @@ -198,12 +198,13 @@ <include name="**/*.txt" /> <include name="**/*.md" /> <include name="**/*.xls" /> + <include name="**/*.example" /> </fileset> </zip> </target> <target name="javadoc" depends="-init" description="build the javadoc for the project"> - <javadoc packagenames="com.mebigfatguy.*" sourcepath="${src.dir}" classpathref="fb-contrib.classpath" destdir="${javadoc.dir}" windowtitle="fb-contrib api"> + <javadoc packagenames="com.mebigfatguy.*" sourcepath="${src.dir}" classpathref="fb-contrib.classpath" destdir="${javadoc.dir}" windowtitle="fb-contrib api" access="private"> <doctitle><![CDATA[<h1>fb-contrib javadoc</h1>]]></doctitle> <bottom><![CDATA[<i>Copyright © 2005-2016 MeBigFatGuy.com. All Rights Reserved.</i>]]></bottom> </javadoc> Modified: trunk/fb-contrib/etc/findbugs.xml =================================================================== --- trunk/fb-contrib/etc/findbugs.xml 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/etc/findbugs.xml 2016-08-17 00:36:37 UTC (rev 1794) @@ -20,7 +20,7 @@ <!-- Detectors --> -<!-- COMMENT OUT FOR RELEASE --> +<!-- COMMENT OUT FOR RELEASE <Detector class="com.mebigfatguy.fbcontrib.debug.OCSDebugger" speed="fast"/> @@ -30,7 +30,7 @@ <Detector class="com.mebigfatguy.fbcontrib.detect.BloatedAssignmentScope" speed="fast" reports="BAS_BLOATED_ASSIGNMENT_SCOPE" hidden="true" /> -<!-- COMMENT OUT FOR RELEASE --> + COMMENT OUT FOR RELEASE --> <Detector class="com.mebigfatguy.fbcontrib.collect.CollectStatistics" speed="fast" reports="" hidden="true" /> @@ -297,13 +297,13 @@ <Detector class="com.mebigfatguy.fbcontrib.detect.IOIssues" speed="fast" reports="IOI_DOUBLE_BUFFER_COPY,IOI_COPY_WITH_READER"/> - <!-- COMMENT OUT FOR POINT RELEASE --> + <!-- COMMENT OUT FOR POINT RELEASE <Detector class="com.mebigfatguy.fbcontrib.detect.DubiousMapCollection" speed="fast" reports="DMC_DUBIOUS_MAP_COLLECTION"/> <Detector class="com.mebigfatguy.fbcontrib.detect.BuryingLogic" speed="fast" reports="BL_BURYING_LOGIC"/> - <!-- COMMENT OUT FOR POINT RELEASE --> + COMMENT OUT FOR POINT RELEASE --> <!-- BugPattern --> Modified: trunk/fb-contrib/htdocs/index.shtml =================================================================== --- trunk/fb-contrib/htdocs/index.shtml 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/htdocs/index.shtml 2016-08-17 00:36:37 UTC (rev 1794) @@ -68,7 +68,7 @@ </li> </ul> </p> - <p style="font-weight: bold;">The latest version of fb-contrib is 6.6.1 available for download + <p style="font-weight: bold;">The latest version of fb-contrib is 6.6.2 available for download <a href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22fb-contrib%22">here</a>.</p> <p style="font-weight: bold;">This version requires FindBugs 3.0.1 or better</p> <p style="font-weight: bold;">Please note that active development for this project is now done on Modified: trunk/fb-contrib/htdocs/repository.html =================================================================== --- trunk/fb-contrib/htdocs/repository.html 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/htdocs/repository.html 2016-08-17 00:36:37 UTC (rev 1794) @@ -22,7 +22,7 @@ <table style="margin-left: 40px; background-color: #A0A0FF; padding: 20px; border-width: 1px; border-style: outset; border-color: #000000;"> <tr><td><b>GroupId:</b></td><td>com.mebigfatguy.fb-contrib</td></tr> <tr><td><b>ArtifactId:</b></td><td>fb-contrib</td></tr> - <tr><td><b>Version:</b></td><td>6.6.1</td></tr> + <tr><td><b>Version:</b></td><td>6.6.2</td></tr> </table> </div> Modified: trunk/fb-contrib/pom.xml =================================================================== --- trunk/fb-contrib/pom.xml 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/pom.xml 2016-08-17 00:36:37 UTC (rev 1794) @@ -8,7 +8,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>com.mebigfatguy.fb-contrib</groupId> <artifactId>fb-contrib</artifactId> - <version>6.7.0-SNAPSHOT</version> + <version>6.6.2</version> <prerequisites> <maven>2.2.1</maven> @@ -77,6 +77,9 @@ <contributor> <name>Richard Fearn</name> </contributor> + <contributor> + <name>Mikkel Kjeldsen</name> + </contributor> </contributors> <licenses> Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/collect/CollectStatistics.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/collect/CollectStatistics.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/collect/CollectStatistics.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -18,6 +18,10 @@ */ package com.mebigfatguy.fbcontrib.collect; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; import java.util.Set; import org.apache.bcel.Constants; @@ -25,12 +29,15 @@ import org.apache.bcel.classfile.Code; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; +import org.objectweb.asm.Type; +import com.mebigfatguy.fbcontrib.utils.QMethod; import com.mebigfatguy.fbcontrib.utils.UnmodifiableSet; import edu.umd.cs.findbugs.BugReporter; import edu.umd.cs.findbugs.BytecodeScanningDetector; import edu.umd.cs.findbugs.NonReportingDetector; +import edu.umd.cs.findbugs.OpcodeStack; import edu.umd.cs.findbugs.ba.ClassContext; public class CollectStatistics extends BytecodeScanningDetector implements NonReportingDetector { @@ -48,6 +55,9 @@ private int numMethodCalls; private boolean modifiesState; private boolean classHasAnnotation; + private OpcodeStack stack; + private Map<QMethod, Set<CalledMethod>> selfCallTree; + private QMethod curMethod; public CollectStatistics(@SuppressWarnings("unused") BugReporter bugReporter) { Statistics.getStatistics().clear(); @@ -55,10 +65,21 @@ @Override public void visitClassContext(ClassContext classContext) { - JavaClass cls = classContext.getJavaClass(); - AnnotationEntry[] annotations = cls.getAnnotationEntries(); - classHasAnnotation = (annotations != null) && (annotations.length > 0); - super.visitClassContext(classContext); + try { + JavaClass cls = classContext.getJavaClass(); + AnnotationEntry[] annotations = cls.getAnnotationEntries(); + classHasAnnotation = (annotations != null) && (annotations.length > 0); + stack = new OpcodeStack(); + selfCallTree = new HashMap<>(); + super.visitClassContext(classContext); + + performModifyStateClosure(classContext.getJavaClass()); + + } finally { + stack = null; + selfCallTree = null; + curMethod = null; + } } @Override @@ -69,6 +90,8 @@ byte[] code = obj.getCode(); if (code != null) { + stack.resetForMethodEntry(this); + curMethod = null; super.visitCode(obj); String clsName = getClassName(); Method method = getMethod(); @@ -97,25 +120,104 @@ @Override public void sawOpcode(int seen) { - switch (seen) { - case INVOKEVIRTUAL: - case INVOKEINTERFACE: - case INVOKESPECIAL: - case INVOKESTATIC: - case INVOKEDYNAMIC: - numMethodCalls++; - break; + try { + switch (seen) { + case INVOKEVIRTUAL: + case INVOKEINTERFACE: + case INVOKESPECIAL: + case INVOKESTATIC: + case INVOKEDYNAMIC: + numMethodCalls++; - case PUTSTATIC: - case PUTFIELD: - modifiesState = true; - break; + if (seen != INVOKESTATIC) { + int numParms = Type.getArgumentTypes(getSigConstantOperand()).length; + if (stack.getStackDepth() > numParms) { + OpcodeStack.Item itm = stack.getStackItem(numParms); + if (itm.getRegisterNumber() == 0) { + Set<CalledMethod> calledMethods; - default: - break; + if (curMethod == null) { + curMethod = new QMethod(getMethodName(), getMethodSig()); + calledMethods = new HashSet<>(); + selfCallTree.put(curMethod, calledMethods); + } else { + calledMethods = selfCallTree.get(curMethod); + } + + calledMethods.add(new CalledMethod(new QMethod(getNameConstantOperand(), getSigConstantOperand()), seen == INVOKESPECIAL)); + } + } + } + break; + + case PUTSTATIC: + case PUTFIELD: + modifiesState = true; + break; + + default: + break; + } + } finally { + stack.sawOpcode(this, seen); } } + private void performModifyStateClosure(JavaClass cls) { + boolean foundNewCall = true; + Statistics statistics = Statistics.getStatistics(); + + String clsName = cls.getClassName(); + while (foundNewCall && !selfCallTree.isEmpty()) { + foundNewCall = false; + + Iterator<Map.Entry<QMethod, Set<CalledMethod>>> callerIt = selfCallTree.entrySet().iterator(); + while (callerIt.hasNext()) { + Map.Entry<QMethod, Set<CalledMethod>> callerEntry = callerIt.next(); + QMethod caller = callerEntry.getKey(); + + MethodInfo callerMi = statistics.getMethodStatistics(clsName, caller.getMethodName(), caller.getSignature()); + if (callerMi == null) { + // odd, shouldn't happen + foundNewCall = true; + } else if (callerMi.getModifiesState()) { + foundNewCall = true; + } else { + + for (CalledMethod calledMethod : callerEntry.getValue()) { + + if (calledMethod.isSuper) { + callerMi.setModifiesState(true); + foundNewCall = true; + break; + } else { + MethodInfo calleeMi = statistics.getMethodStatistics(clsName, calledMethod.callee.getMethodName(), + calledMethod.callee.getSignature()); + if (calleeMi == null) { + // a super or sub class probably implements this method so just assume it modifies state + callerMi.setModifiesState(true); + foundNewCall = true; + break; + } + + if (calleeMi.getModifiesState()) { + callerMi.setModifiesState(true); + foundNewCall = true; + break; + } + } + } + } + + if (foundNewCall) { + callerIt.remove(); + } + } + } + + selfCallTree.clear(); + } + private boolean isAssociationedWithAnnotations(Method m) { if (classHasAnnotation) { return true; @@ -124,4 +226,30 @@ AnnotationEntry[] annotations = m.getAnnotationEntries(); return (annotations != null) && (annotations.length > 0); } + + static class CalledMethod { + private QMethod callee; + private boolean isSuper; + + public CalledMethod(QMethod c, boolean s) { + callee = c; + isSuper = s; + } + + @Override + public int hashCode() { + return callee.hashCode() & (isSuper ? 0 : 1); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof CalledMethod)) { + return false; + } + + CalledMethod that = (CalledMethod) obj; + + return (isSuper == that.isSuper) && callee.equals(that.callee); + } + } } Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/AbnormalFinallyBlockReturn.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/AbnormalFinallyBlockReturn.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/AbnormalFinallyBlockReturn.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -31,6 +31,7 @@ import com.mebigfatguy.fbcontrib.utils.BugType; import com.mebigfatguy.fbcontrib.utils.OpcodeUtils; import com.mebigfatguy.fbcontrib.utils.RegisterUtils; +import com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException; import com.mebigfatguy.fbcontrib.utils.ToString; import edu.umd.cs.findbugs.BugInstance; @@ -73,7 +74,7 @@ try { int majorVersion = classContext.getJavaClass().getMajor(); if (majorVersion >= MAJOR_1_4) { - fbInfo = new ArrayList<FinallyBlockInfo>(); + fbInfo = new ArrayList<>(); super.visitClassContext(classContext); } } finally { @@ -102,7 +103,11 @@ } if (!fbInfo.isEmpty()) { - super.visitCode(obj); + try { + super.visitCode(obj); + } catch (StopOpcodeParsingException e) { + // no more finally blocks to check + } } } @@ -114,9 +119,6 @@ */ @Override public void sawOpcode(int seen) { - if (fbInfo.isEmpty()) { - return; - } FinallyBlockInfo fbi = fbInfo.get(0); @@ -128,7 +130,7 @@ if (OpcodeUtils.isAStore(seen)) { fbi.exReg = RegisterUtils.getAStoreReg(this, seen); } else { - fbInfo.remove(0); + removeEarliestFinallyBlock(); sawOpcode(seen); return; } @@ -140,14 +142,14 @@ } else if (seen == MONITOREXIT) { fbi.monitorCount--; if (fbi.monitorCount < 0) { - fbInfo.remove(0); + removeEarliestFinallyBlock(); sawOpcode(seen); return; } } if ((seen == ATHROW) && (loadedReg == fbi.exReg)) { - fbInfo.remove(0); + removeEarliestFinallyBlock(); sawOpcode(seen); return; } else if (OpcodeUtils.isALoad(seen)) { @@ -159,7 +161,7 @@ if (OpcodeUtils.isReturn(seen) || (seen == ATHROW)) { bugReporter.reportBug(new BugInstance(this, BugType.AFBR_ABNORMAL_FINALLY_BLOCK_RETURN.name(), NORMAL_PRIORITY).addClass(this).addMethod(this) .addSourceLine(this)); - fbInfo.remove(0); + removeEarliestFinallyBlock(); } else if (OpcodeUtils.isInvoke(seen)) { try { JavaClass cls = Repository.lookupClass(getClassConstantOperand()); @@ -169,7 +171,7 @@ if ((et != null) && (et.getLength() > 0) && !catchBlockInFinally(fbi)) { bugReporter.reportBug(new BugInstance(this, BugType.AFBR_ABNORMAL_FINALLY_BLOCK_RETURN.name(), LOW_PRIORITY).addClass(this) .addMethod(this).addSourceLine(this)); - fbInfo.remove(0); + removeEarliestFinallyBlock(); } } } catch (ClassNotFoundException cnfe) { @@ -179,6 +181,16 @@ } /** + * removes the earliest finally block, as we've just concluded checking it, and if it's the last one then throw back to visitCode + */ + private void removeEarliestFinallyBlock() { + fbInfo.remove(0); + if (fbInfo.isEmpty()) { + throw new StopOpcodeParsingException(); + } + } + + /** * finds the method in specified class by name and signature * * @param cls Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BloatedAssignmentScope.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BloatedAssignmentScope.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BloatedAssignmentScope.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -642,6 +642,8 @@ * * @param sb * the scope block to start with + * @param start + * the current pc * @param target * the target to look for * @@ -697,6 +699,10 @@ /** * finds the scope block that is the active synchronized block * + * @param sb + * the parent scope block to start with + * @param monitorEnterPC + * the pc where the current synchronized block starts * @return the scope block */ private ScopeBlock findSynchronizedScopeBlock(ScopeBlock sb, int monitorEnterPC) { @@ -933,6 +939,8 @@ * the register that was stored * @param pc * the instruction that did the store + * @param assocObject + * the the object that is associated with this store, usually the field from which this came */ public void addStore(int reg, int pc, UserObject assocObject) { if (stores == null) { @@ -1035,7 +1043,7 @@ if (assocs != null) { for (Map.Entry<UserObject, Integer> entry : assocs.entrySet()) { UserObject uo = entry.getKey(); - if ((uo.fieldFromReg == fieldFromReg) || ((uo.caller instanceof Integer) && (((Integer) uo.caller) == fieldFromReg))) { + if ((uo.fieldFromReg == fieldFromReg) || ((uo.caller instanceof Integer) && (((Integer) uo.caller).intValue() == fieldFromReg))) { Integer preWrittenFromField = entry.getValue(); if (preWrittenFromField != null) { if (stores != null) { @@ -1049,6 +1057,9 @@ /** * report stores that occur at scopes higher than associated loads that are not involved with loops + * + * @param parentUsedRegs + * the set of registers that where used by the parent scope block */ public void findBugs(Set<Integer> parentUsedRegs) { if (isLoop) { Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BogusExceptionDeclaration.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BogusExceptionDeclaration.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BogusExceptionDeclaration.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -30,6 +30,7 @@ import com.mebigfatguy.fbcontrib.utils.BugType; import com.mebigfatguy.fbcontrib.utils.OpcodeUtils; import com.mebigfatguy.fbcontrib.utils.SignatureUtils; +import com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException; import com.mebigfatguy.fbcontrib.utils.UnmodifiableSet; import com.mebigfatguy.fbcontrib.utils.Values; @@ -139,14 +140,18 @@ } } if (!declaredCheckedExceptions.isEmpty()) { - super.visitCode(obj); - if (!declaredCheckedExceptions.isEmpty()) { - BugInstance bi = new BugInstance(this, BugType.BED_BOGUS_EXCEPTION_DECLARATION.name(), NORMAL_PRIORITY).addClass(this).addMethod(this) - .addSourceLine(this, 0); - for (String ex : declaredCheckedExceptions) { - bi.addString(ex.replaceAll("/", ".")); + try { + super.visitCode(obj); + if (!declaredCheckedExceptions.isEmpty()) { + BugInstance bi = new BugInstance(this, BugType.BED_BOGUS_EXCEPTION_DECLARATION.name(), NORMAL_PRIORITY).addClass(this) + .addMethod(this).addSourceLine(this, 0); + for (String ex : declaredCheckedExceptions) { + bi.addString(ex.replaceAll("/", ".")); + } + bugReporter.reportBug(bi); } - bugReporter.reportBug(bi); + } catch (StopOpcodeParsingException e) { + // no exceptions left } } } @@ -213,10 +218,6 @@ */ @Override public void sawOpcode(int seen) { - if (declaredCheckedExceptions.isEmpty()) { - return; - } - try { stack.precomputation(this); @@ -245,14 +246,14 @@ } if (!found) { - declaredCheckedExceptions.clear(); + clearExceptions(); } } catch (ClassNotFoundException cnfe) { bugReporter.reportMissingClass(cnfe); - declaredCheckedExceptions.clear(); + clearExceptions(); } } else if ("wait".equals(getNameConstantOperand())) { - declaredCheckedExceptions.remove("java.lang.InterruptedException"); + removeException("java.lang.InterruptedException"); } } else if (seen == ATHROW) { if (stack.getStackDepth() > 0) { @@ -261,7 +262,7 @@ String thrownException = SignatureUtils.stripSignature(exSig); removeThrownExceptionHierarchy(thrownException); } else { - declaredCheckedExceptions.clear(); + clearExceptions(); } } } finally { @@ -280,9 +281,9 @@ try { if (Values.DOTTED_JAVA_LANG_EXCEPTION.equals(thrownException)) { // Exception can be thrown even tho the method isn't declared to throw Exception in the case of templated Exceptions - declaredCheckedExceptions.clear(); + clearExceptions(); } else { - declaredCheckedExceptions.remove(thrownException); + removeException(thrownException); JavaClass exCls = Repository.lookupClass(thrownException); String clsName; @@ -292,13 +293,35 @@ break; } clsName = exCls.getClassName(); - declaredCheckedExceptions.remove(clsName); + removeException(clsName); } while (!declaredCheckedExceptions.isEmpty() && !Values.DOTTED_JAVA_LANG_EXCEPTION.equals(clsName) && !Values.DOTTED_JAVA_LANG_ERROR.equals(clsName)); } + } catch (ClassNotFoundException cnfe) { bugReporter.reportMissingClass(cnfe); - declaredCheckedExceptions.clear(); + clearExceptions(); } } + + /** + * removes the declared checked exception, and if that was the last declared exception, stops opcode parsing by throwing exception + * + * @param clsName + * the name of the exception to remove + */ + private void removeException(String clsName) { + declaredCheckedExceptions.remove(clsName); + if (declaredCheckedExceptions.isEmpty()) { + throw new StopOpcodeParsingException(); + } + } + + /** + * clears all declared checked exceptions and throws an exception to stop opcode parsing + */ + private void clearExceptions() { + declaredCheckedExceptions.clear(); + throw new StopOpcodeParsingException(); + } } Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/BuryingLogic.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -29,6 +29,7 @@ import org.apache.bcel.generic.Type; import com.mebigfatguy.fbcontrib.utils.BugType; +import com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException; import com.mebigfatguy.fbcontrib.utils.ToString; import edu.umd.cs.findbugs.BugInstance; @@ -53,7 +54,6 @@ private OpcodeStack stack; private Deque<IfBlock> ifBlocks; private IfBlock activeUnconditional; - private boolean isReported; private double lowBugRatioLimit; private double normalBugRatioLimit; private BitSet catchPCs; @@ -72,7 +72,7 @@ lowBugRatioLimit = LOW_BUG_RATIO_LIMIT; } } - } catch (Exception e) { + } catch (NumberFormatException e) { lowBugRatioLimit = LOW_BUG_RATIO_LIMIT; } @@ -86,7 +86,7 @@ normalBugRatioLimit = NORMAL_BUG_RATIO_LIMIT; } } - } catch (Exception e) { + } catch (NumberFormatException e) { normalBugRatioLimit = NORMAL_BUG_RATIO_LIMIT; } } @@ -116,7 +116,6 @@ stack.resetForMethodEntry(this); ifBlocks.clear(); activeUnconditional = null; - isReported = false; CodeException[] ces = obj.getExceptionTable(); if ((ces == null) || (ces.length == 0)) { @@ -128,14 +127,15 @@ } } gotoBranchPCs.clear(); - super.visitCode(obj); + try { + super.visitCode(obj); + } catch (StopOpcodeParsingException e) { + // reported an issue, so get out + } } @Override public void sawOpcode(int seen) { - if (isReported) { - return; - } try { @@ -181,7 +181,7 @@ bugReporter .reportBug(new BugInstance(this, BugType.BL_BURYING_LOGIC.name(), ratio > normalBugRatioLimit ? NORMAL_PRIORITY : LOW_PRIORITY) .addClass(this).addMethod(this).addSourceLineRange(this, activeUnconditional.getStart(), activeUnconditional.getEnd())); - isReported = true; + throw new StopOpcodeParsingException(); } } else if (!ifBlocks.isEmpty() && (getNextPC() == ifBlocks.getFirst().getEnd())) { activeUnconditional = ifBlocks.getFirst(); Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CommonsEqualsBuilderToEquals.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CommonsEqualsBuilderToEquals.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CommonsEqualsBuilderToEquals.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -30,8 +30,7 @@ import edu.umd.cs.findbugs.OpcodeStack; /** - * Find usage of EqualsBuilder from Apache commons, where the code invoke - * equals() on the constructed object rather than isEquals() + * Find usage of EqualsBuilder from Apache commons, where the code invoke equals() on the constructed object rather than isEquals() * * <pre> * new EqualsBuilder().append(this.name, other.name).equals(other); @@ -56,10 +55,8 @@ } /** - * implements the visitor to pass through constructors and static - * initializers to the byte code scanning code. These methods are not - * reported, but are used to build SourceLineAnnotations for fields, if - * accessed. + * implements the visitor to pass through constructors and static initializers to the byte code scanning code. These methods are not reported, but are used + * to build SourceLineAnnotations for fields, if accessed. * * @param obj * the context object of the currently parsed code attribute @@ -75,17 +72,20 @@ @Override public void sawOpcode(int seen) { - if (seen == INVOKEVIRTUAL) { - String methodName = getNameConstantOperand(); - if ("equals".equals(methodName) && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand()) && (stack.getStackDepth() > 1)) { - String calledClass = stack.getStackItem(1).getSignature(); - if (LANG3_EQUALS_BUILDER.equals(calledClass) || LANG_EQUALS_BUILDER.equals(calledClass)) { - bugReporter.reportBug(new BugInstance(this, BugType.CEBE_COMMONS_EQUALS_BUILDER_ISEQUALS.name(), HIGH_PRIORITY).addClass(this) - .addMethod(this).addSourceLine(this)); + try { + if (seen == INVOKEVIRTUAL) { + String methodName = getNameConstantOperand(); + if ("equals".equals(methodName) && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand()) && (stack.getStackDepth() > 1)) { + String calledClass = stack.getStackItem(1).getSignature(); + if (LANG3_EQUALS_BUILDER.equals(calledClass) || LANG_EQUALS_BUILDER.equals(calledClass)) { + bugReporter.reportBug(new BugInstance(this, BugType.CEBE_COMMONS_EQUALS_BUILDER_ISEQUALS.name(), HIGH_PRIORITY).addClass(this) + .addMethod(this).addSourceLine(this)); + } } } + } finally { + super.sawOpcode(seen); + stack.sawOpcode(this, seen); } - super.sawOpcode(seen); - stack.sawOpcode(this, seen); } } Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CompareClassNameEquals.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CompareClassNameEquals.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CompareClassNameEquals.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -60,7 +60,7 @@ @Override public void afterOpcode(int seen) { super.afterOpcode(seen); - if (flag == true) { + if (flag) { stack.getStackItem(0).setUserValue(Boolean.TRUE); flag = false; } @@ -84,6 +84,5 @@ } } } - // stack.sawOpcode(this, seen); } } Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConfusingFunctionSemantics.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConfusingFunctionSemantics.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ConfusingFunctionSemantics.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -34,6 +34,7 @@ import com.mebigfatguy.fbcontrib.utils.OpcodeUtils; import com.mebigfatguy.fbcontrib.utils.RegisterUtils; import com.mebigfatguy.fbcontrib.utils.SignatureUtils; +import com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException; import com.mebigfatguy.fbcontrib.utils.ToString; import edu.umd.cs.findbugs.BugInstance; @@ -51,7 +52,7 @@ private static final Set<String> knownImmutables; static { - Set<String> ki = new HashSet<String>(); + Set<String> ki = new HashSet<>(); ki.add("Ljava/lang/String;"); ki.add("Ljava/lang/Byte;"); ki.add("Ljava/lang/Character;"); @@ -89,7 +90,7 @@ public void visitClassContext(ClassContext classContext) { try { stack = new OpcodeStack(); - possibleParmRegs = new HashMap<Integer, ParmUsage>(10); + possibleParmRegs = new HashMap<>(10); super.visitClassContext(classContext); } finally { stack = null; @@ -130,14 +131,18 @@ } } - if (possibleParmRegs.size() > 0) { - stack.resetForMethodEntry(this); - super.visitCode(obj); - for (ParmUsage pu : possibleParmRegs.values()) { - if ((pu.returnPC >= 0) && (pu.alteredPC >= 0)) { - bugReporter.reportBug(new BugInstance(this, BugType.CFS_CONFUSING_FUNCTION_SEMANTICS.name(), NORMAL_PRIORITY).addClass(this) - .addMethod(this).addSourceLine(this, pu.returnPC).addSourceLine(this, pu.alteredPC)); + if (!possibleParmRegs.isEmpty()) { + try { + stack.resetForMethodEntry(this); + super.visitCode(obj); + for (ParmUsage pu : possibleParmRegs.values()) { + if ((pu.returnPC >= 0) && (pu.alteredPC >= 0)) { + bugReporter.reportBug(new BugInstance(this, BugType.CFS_CONFUSING_FUNCTION_SEMANTICS.name(), NORMAL_PRIORITY).addClass(this) + .addMethod(this).addSourceLine(this, pu.returnPC).addSourceLine(this, pu.alteredPC)); + } } + } catch (StopOpcodeParsingException e) { + // no parm regs left } } } @@ -148,10 +153,6 @@ @Override public void sawOpcode(int seen) { - if (possibleParmRegs.isEmpty()) { - return; - } - try { stack.precomputation(this); @@ -176,6 +177,9 @@ } else if (OpcodeUtils.isAStore(seen)) { int reg = RegisterUtils.getAStoreReg(this, seen); possibleParmRegs.remove(Integer.valueOf(reg)); + if (possibleParmRegs.isEmpty()) { + throw new StopOpcodeParsingException(); + } } else if ((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) { processInvoke(); } Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CopiedOverriddenMethod.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -38,6 +38,7 @@ import com.mebigfatguy.fbcontrib.utils.BugType; import com.mebigfatguy.fbcontrib.utils.SignatureUtils; +import com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException; import com.mebigfatguy.fbcontrib.utils.ToString; import com.mebigfatguy.fbcontrib.utils.Values; @@ -61,7 +62,6 @@ private int nextParmOffset; private boolean sawAload0; private boolean sawParentCall; - private boolean ignore; /** * constructs a COM detector given the reporter to report bugs on @@ -86,7 +86,7 @@ String superName = cls.getSuperclassName(); if (!Values.DOTTED_JAVA_LANG_OBJECT.equals(superName)) { this.classContext = clsContext; - superclassCode = new HashMap<String, CodeInfo>(); + superclassCode = new HashMap<>(); JavaClass superCls = cls.getSuperClass(); childPoolGen = new ConstantPoolGen(cls.getConstantPool()); parentPoolGen = new ConstantPoolGen(superCls.getConstantPool()); @@ -130,26 +130,29 @@ */ @Override public void visitCode(Code obj) { - Method m = getMethod(); - if ((!m.isPublic() && !m.isProtected()) || m.isAbstract() || m.isSynthetic()) { - return; - } - - CodeInfo superCode = superclassCode.remove(curMethodInfo); - if (superCode != null) { - if (sameAccess(getMethod().getAccessFlags(), superCode.getAccess()) && codeEquals(obj, superCode.getCode())) { - bugReporter.reportBug(new BugInstance(this, BugType.COM_COPIED_OVERRIDDEN_METHOD.name(), NORMAL_PRIORITY).addClass(this).addMethod(this) - .addSourceLine(classContext, this, getPC())); + try { + Method m = getMethod(); + if ((!m.isPublic() && !m.isProtected()) || m.isAbstract() || m.isSynthetic()) { return; } - parmTypes = getMethod().getArgumentTypes(); - ignore = false; - nextParmIndex = 0; - nextParmOffset = getMethod().isStatic() ? 0 : 1; - sawAload0 = nextParmOffset == 0; - sawParentCall = false; - super.visitCode(obj); + CodeInfo superCode = superclassCode.remove(curMethodInfo); + if (superCode != null) { + if (sameAccess(getMethod().getAccessFlags(), superCode.getAccess()) && codeEquals(obj, superCode.getCode())) { + bugReporter.reportBug(new BugInstance(this, BugType.COM_COPIED_OVERRIDDEN_METHOD.name(), NORMAL_PRIORITY).addClass(this).addMethod(this) + .addSourceLine(classContext, this, getPC())); + return; + } + + parmTypes = getMethod().getArgumentTypes(); + nextParmIndex = 0; + nextParmOffset = getMethod().isStatic() ? 0 : 1; + sawAload0 = nextParmOffset == 0; + sawParentCall = false; + super.visitCode(obj); + } + } catch (StopOpcodeParsingException e) { + // method is unique } } @@ -163,22 +166,19 @@ */ @Override public void sawOpcode(int seen) { - if (ignore) { - return; - } if (!sawAload0) { if (seen == ALOAD_0) { sawAload0 = true; } else { - ignore = true; + throw new StopOpcodeParsingException(); } } else if (nextParmIndex < parmTypes.length) { if (isExpectedParmInstruction(seen, nextParmOffset, parmTypes[nextParmIndex])) { nextParmOffset += SignatureUtils.getSignatureSize(parmTypes[nextParmIndex].getSignature()); nextParmIndex++; } else { - ignore = true; + throw new StopOpcodeParsingException(); } } else if (!sawParentCall) { @@ -187,7 +187,7 @@ && getSigConstantOperand().equals(getMethod().getSignature())) { sawParentCall = true; } else { - ignore = true; + throw new StopOpcodeParsingException(); } } else { int expectedInstruction = getExpectedReturnInstruction(getMethod().getReturnType()); @@ -195,7 +195,7 @@ bugReporter.reportBug( new BugInstance(this, BugType.COM_PARENT_DELEGATED_CALL.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this)); } else { - ignore = true; + throw new StopOpcodeParsingException(); } } } @@ -242,7 +242,9 @@ * determines if two access flags contain the same access modifiers * * @param parentAccess + * the access flags of the parent method * @param childAccess + * the access flats of the child method * @return whether the access modifiers are the same */ private static boolean sameAccess(int parentAccess, int childAccess) { Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CyclomaticComplexity.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CyclomaticComplexity.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/CyclomaticComplexity.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -120,6 +120,7 @@ while (bbi.hasNext()) { BasicBlock bb = bbi.next(); Iterator<Edge> iei = cfg.outgoingEdgeIterator(bb); + int lastSwitchTargetBlockLabel = Integer.MIN_VALUE; while (iei.hasNext()) { Edge e = iei.next(); int edgeType = e.getType(); @@ -130,6 +131,12 @@ exceptionNodeTargets.set(nodeTarget); branches++; } + } else if ((edgeType == EdgeTypes.SWITCH_EDGE) || (edgeType == EdgeTypes.SWITCH_DEFAULT_EDGE)) { + int nodeTarget = e.getTarget().getLabel(); + if (nodeTarget != lastSwitchTargetBlockLabel) { + branches++; + } + lastSwitchTargetBlockLabel = nodeTarget; } else { branches++; } Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DeletingWhileIterating.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DeletingWhileIterating.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DeletingWhileIterating.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -76,7 +76,7 @@ } try { - exceptionClasses = new HashSet<JavaClass>(2); + exceptionClasses = new HashSet<>(2); exceptionClasses.add(Repository.lookupClass("java/util/concurrent/CopyOnWriteArrayList")); exceptionClasses.add(Repository.lookupClass("java/util/concurrent/CopyOnWriteArraySet")); } catch (ClassNotFoundException cnfe) { @@ -90,7 +90,7 @@ private static final Map<QMethod, Integer> modifyingMethods; static { - Map<QMethod, Integer> mm = new HashMap<QMethod, Integer>(); + Map<QMethod, Integer> mm = new HashMap<>(); mm.put(new QMethod("add", "(Ljava/lang/Object;)Z"), Values.ONE); mm.put(new QMethod("addAll", "(Ljava/util/Collection;)Z"), Values.ONE); mm.put(new QMethod("addAll", "(ILjava/util/Collection;)Z"), Values.TWO); @@ -136,9 +136,9 @@ try { stack = new OpcodeStack(); - collectionGroups = new ArrayList<GroupPair>(); - groupToIterator = new HashMap<Integer, Integer>(); - loops = new HashMap<Integer, Loop>(10); + collectionGroups = new ArrayList<>(); + groupToIterator = new HashMap<>(); + loops = new HashMap<>(10); super.visitClassContext(classContext); } finally { stack = null; @@ -383,6 +383,8 @@ * * @param couldSeePop * if the preceding instruction returns a value, and thus might need to be popped + * + * @return when a following instruction issues some sort of return */ private boolean returnFollows(boolean couldSeePop) { @@ -491,7 +493,7 @@ } private void buildVariableEndScopeMap() { - endOfScopes = new HashMap<Integer, BitSet>(); + endOfScopes = new HashMap<>(); LocalVariableTable lvt = getMethod().getLocalVariableTable(); if (lvt != null) { @@ -570,7 +572,7 @@ private final String colClass; public GroupPair(Comparable<?> member, String cls) { - groupMembers = new HashSet<Comparable<?>>(); + groupMembers = new HashSet<>(); groupMembers.add(member); colClass = cls; } Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DubiousMapCollection.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DubiousMapCollection.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/DubiousMapCollection.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -30,6 +30,7 @@ import com.mebigfatguy.fbcontrib.utils.BugType; import com.mebigfatguy.fbcontrib.utils.OpcodeUtils; +import com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException; import com.mebigfatguy.fbcontrib.utils.UnmodifiableSet; import com.mebigfatguy.fbcontrib.utils.Values; @@ -70,7 +71,6 @@ // @formatter:on ); - private BugReporter bugReporter; private JavaClass mapClass; private OpcodeStack stack; @@ -114,15 +114,15 @@ public void visitCode(Code obj) { isInSpecial = SPECIAL_METHODS.contains(getMethod().getName()); stack.resetForMethodEntry(this); - super.visitCode(obj); + try { + super.visitCode(obj); + } catch (StopOpcodeParsingException e) { + // no more unaccounted for map fields + } } @Override public void sawOpcode(int seen) { - if (mapFields.isEmpty()) { - return; - } - try { if ((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL)) { @@ -136,6 +136,9 @@ XField xf = item.getXField(); if (xf != null) { mapFields.remove(xf.getName()); + if (mapFields.isEmpty()) { + throw new StopOpcodeParsingException(); + } } } } else if ((seen == PUTFIELD) || (seen == PUTSTATIC)) { @@ -143,6 +146,7 @@ if (xf != null) { if (!isInSpecial) { mapFields.remove(xf.getName()); + } else { if (stack.getStackDepth() > 0) { OpcodeStack.Item item = stack.getStackItem(0); @@ -151,6 +155,10 @@ } } } + if (mapFields.isEmpty()) { + throw new StopOpcodeParsingException(); + } + } } @@ -180,6 +188,10 @@ String mName = getNameConstantOperand(); if (MAP_METHODS.contains(mName)) { mapFields.remove(fName); + if (mapFields.isEmpty()) { + throw new StopOpcodeParsingException(); + } + return; } @@ -190,6 +202,10 @@ if (MODIFYING_METHODS.contains(mName)) { mapFields.remove(fName); + if (mapFields.isEmpty()) { + throw new StopOpcodeParsingException(); + } + return; } } @@ -207,6 +223,10 @@ XField xf = item.getXField(); if (xf != null) { mapFields.remove(xf.getName()); + if (mapFields.isEmpty()) { + throw new StopOpcodeParsingException(); + } + } } else { return; Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ExceptionSoftening.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ExceptionSoftening.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/ExceptionSoftening.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -320,6 +320,8 @@ * the list of active catch blocks * @param pc * the current pc + * @param seen + * the currently parsed opcode */ private void updateEndPCsOnCatchRegScope(List<CatchInfo> infos, int pc, int seen) { if (lvt != null) { @@ -363,9 +365,14 @@ /** * finds the super class or interface that constrains the types of exceptions that can be thrown from the given method * + * @param cls + * the currently parsed class * @param m * the method to check * @return a map containing the class name to a set of exceptions that constrain this method + * + * @throws ClassNotFoundException + * if a super class or super interface can't be loaded from the repository */ private Map<String, Set<String>> getConstrainingInfo(JavaClass cls, Method m) throws ClassNotFoundException { String methodName = m.getName(); @@ -436,6 +443,9 @@ * @param m * the method to add exceptions from * @return a map with one entry of a class name to a set of exceptions that constrain what can be thrown. + * + * @throws ClassNotFoundException + * if an exception class can't be loaded from the repository */ private Map<String, Set<String>> buildConstrainingInfo(JavaClass cls, Method m) throws ClassNotFoundException { Map<String, Set<String>> constraintInfo = new HashMap<>(); Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FieldCouldBeLocal.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FieldCouldBeLocal.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FieldCouldBeLocal.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -96,7 +96,7 @@ @Override public void visitClassContext(ClassContext classContext) { try { - localizableFields = new HashMap<String, FieldInfo>(); + localizableFields = new HashMap<>(); visitedBlocks = new BitSet(); clsContext = classContext; clsName = clsContext.getJavaClass().getClassName(); @@ -158,7 +158,7 @@ cfg = clsContext.getCFG(obj); cpg = cfg.getMethodGen().getConstantPool(); BasicBlock bb = cfg.getEntry(); - Set<String> uncheckedFields = new HashSet<String>(localizableFields.keySet()); + Set<String> uncheckedFields = new HashSet<>(localizableFields.keySet()); visitedBlocks.clear(); checkBlock(bb, uncheckedFields); } catch (CFGBuilderException cbe) { @@ -228,7 +228,7 @@ * the list of fields to look for */ private void checkBlock(BasicBlock bb, Set<String> uncheckedFields) { - Deque<BlockState> toBeProcessed = new ArrayDeque<BlockState>(); + Deque<BlockState> toBeProcessed = new ArrayDeque<>(); toBeProcessed.addLast(new BlockState(bb, uncheckedFields)); visitedBlocks.set(bb.getLabel()); @@ -270,8 +270,11 @@ INVOKESPECIAL is = (INVOKESPECIAL) ins; ReferenceType rt = is.getReferenceType(cpg); - if (Values.CONSTRUCTOR.equals(is.getMethodName(cpg)) - && ((rt instanceof ObjectType) && ((ObjectType) rt).getClassName().startsWith(clsContext.getJavaClass().getClassName() + '$'))) { + if (Values.CONSTRUCTOR.equals(is.getMethodName(cpg))) { + if ((rt instanceof ObjectType) && ((ObjectType) rt).getClassName().startsWith(clsContext.getJavaClass().getClassName() + '$')) { + localizableFields.clear(); + } + } else { localizableFields.clear(); } } else if (ins instanceof INVOKEVIRTUAL) { @@ -441,6 +444,9 @@ /** * return the field from the set of unchecked fields if this occurs make a copy of the set on write to reduce memory usage * + * @param field + * the field to be removed + * * @return whether the object was removed. */ public boolean removeUncheckedField(String field) { @@ -455,7 +461,7 @@ } if (fieldsAreSharedWithParent) { - uncheckedFields = new HashSet<String>(uncheckedFields); + uncheckedFields = new HashSet<>(uncheckedFields); fieldsAreSharedWithParent = false; uncheckedFields.remove(field); } else { @@ -473,15 +479,15 @@ private static class FieldModifier extends BytecodeScanningDetector { - private final Map<String, Set<String>> methodCallChain = new HashMap<String, Set<String>>(); - private final Map<String, Set<String>> mfModifiers = new HashMap<String, Set<String>>(); + private final Map<String, Set<String>> methodCallChain = new HashMap<>(); + private final Map<String, Set<String>> mfModifiers = new HashMap<>(); private String clsName; public Map<String, Set<String>> getMethodFieldModifiers() { - Map<String, Set<String>> modifiers = new HashMap<String, Set<String>>(mfModifiers.size()); + Map<String, Set<String>> modifiers = new HashMap<>(mfModifiers.size()); modifiers.putAll(mfModifiers); for (Entry<String, Set<String>> method : modifiers.entrySet()) { - modifiers.put(method.getKey(), new HashSet<String>(method.getValue())); + modifiers.put(method.getKey(), new HashSet<>(method.getValue())); } boolean modified = true; @@ -496,7 +502,7 @@ if (fields != null) { Set<String> flds = modifiers.get(methodDesc); if (flds == null) { - flds = new HashSet<String>(); + flds = new HashSet<>(); modifiers.put(methodDesc, flds); } if (flds.addAll(fields)) { @@ -523,7 +529,7 @@ String methodDesc = getMethodName() + getMethodSig(); Set<String> fields = mfModifiers.get(methodDesc); if (fields == null) { - fields = new HashSet<String>(); + fields = new HashSet<>(); mfModifiers.put(methodDesc, fields); } fields.add(getNameConstantOperand()); @@ -532,7 +538,7 @@ String methodDesc = getMethodName() + getMethodSig(); Set<String> methods = methodCallChain.get(methodDesc); if (methods == null) { - methods = new HashSet<String>(); + methods = new HashSet<>(); methodCallChain.put(methodDesc, methods); } methods.add(getNameConstantOperand() + getSigConstantOperand()); Modified: trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FinalParameters.java =================================================================== --- trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FinalParameters.java 2016-07-24 19:20:39 UTC (rev 1793) +++ trunk/fb-contrib/src/com/mebigfatguy/fbcontrib/detect/FinalParameters.java 2016-08-17 00:36:37 UTC (rev 1794) @@ -33,6 +33,7 @@ import org.apache.bcel.generic.Type; import com.mebigfatguy.fbcontrib.utils.BugType; +import com.mebigfatguy.fbc... [truncated message content] |