private void compute() { if (defined == null) { // System.out.println("Computing"); defined = new HashSet<String>(); Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2(); Collection<XClass> allClasses = subtypes2.getXClassCollection(); IAnalysisCache analysisCache = Global.getAnalysisCache(); for (XClass c : allClasses) { try { JavaClass jclass = analysisCache.getClassAnalysis(JavaClass.class, c.getClassDescriptor()); addAllDefinitions(jclass); } catch (MissingClassException e) { bugReporter.reportMissingClass(e.getClassDescriptor()); } catch (CheckedAnalysisException e) { bugReporter.logError( "Could not find class " + c.getClassDescriptor().toDottedClassName(), e); } } // System.out.println("Done Computing: " + // defined.contains("edu.umd.cs.findbugs.ba.IsNullValueAnalysis.UNKNOWN_VALUES_ARE_NSP : Z")); } }
private boolean isPossibleInstanceOfObligationType( Subtypes2 subtypes2, ObjectType type, ObjectType obligationType) throws ClassNotFoundException { // // If we're tracking, e.g., InputStream obligations, // and we see a FileInputStream reference being assigned // to a field (or returned from a method), // then the false-positive supressions heuristic should apply. // return subtypes2.isSubtype(type, obligationType); }
private boolean isGenericCollection(ClassDescriptor operandClass) { String dottedClassName = operandClass.getDottedClassName(); if (baseGenericTypes.contains(dottedClassName)) return true; String found = null; for (String c : baseGenericTypes) { if (Subtypes2.instanceOf(operandClass, c)) { found = c; break; } } if (found == null) return false; if (dottedClassName.startsWith("java.util.") || dottedClassName.startsWith("com.google.common.collect.")) return true; try { XClass xclass = Global.getAnalysisCache().getClassAnalysis(XClass.class, operandClass); String sig = xclass.getSourceSignature(); if (sig == null) return false; String typeParameter = null; List<String> split = GenericUtilities.split(sig, true); if (sig.charAt(0) == '<') { int end = sig.indexOf(':'); if (end > 0) typeParameter = sig.substring(1, end); } if (DEBUG) System.out.println(dottedClassName + " " + typeParameter + " " + split); for (String s : split) { int i = s.indexOf('<'); if (i < 0) continue; if (s.charAt(0) != 'L') throw new IllegalStateException("unexpected non signature: " + s); ClassDescriptor c = DescriptorFactory.createClassDescriptor(s.substring(1, i)); String superTypeParameter = s.substring(i + 1); if (isGenericCollection(c) && (typeParameter == null || superTypeParameter.startsWith("T" + typeParameter))) { if (DEBUG) System.out.println(operandClass + " is a subtype of " + s); return true; } } if (DEBUG) System.out.println("Not a subtype"); } catch (CheckedAnalysisException e1) { AnalysisContext.logError( "Error checking for weird generic parameterization of " + operandClass, e1); } return false; }
@Override public void visit(Field obj) { int flags = obj.getAccessFlags(); if (isEjbImplClass) { ClassDescriptor fieldType = DescriptorFactory.createClassDescriptorFromFieldSignature(obj.getSignature()); if (fieldType != null) { if (Subtypes2.instanceOf(fieldType, "javax.ejb.SessionContext") || Subtypes2.instanceOf(fieldType, "javax.transaction.UserTransaction") || Subtypes2.instanceOf(fieldType, "javax.ejb.EJBHome") || Subtypes2.instanceOf(fieldType, "javax.ejb.EJBObject") || Subtypes2.instanceOf(fieldType, "javax.naming.Context")) { if (obj.isTransient()) bugReporter.reportBug( new BugInstance(this, "UNKNOWN", NORMAL_PRIORITY) .addClass(this) .addVisitedField(this)); return; } } } if (obj.isTransient()) { if (isSerializable && !isExternalizable) { seenTransientField = true; transientFieldsUpdates.put(getXField(), 0); } else if (reportTransientFieldOfNonSerializableClass) { bugReporter.reportBug( new BugInstance(this, "SE_TRANSIENT_FIELD_OF_NONSERIALIZABLE_CLASS", NORMAL_PRIORITY) .addClass(this) .addVisitedField(this)); } } else if (getClassName().indexOf("ObjectStreamClass") == -1 && isSerializable && !isExternalizable && getFieldSig().indexOf("L") >= 0 && !obj.isTransient() && !obj.isStatic()) { if (DEBUG) { System.out.println( "Examining non-transient field with name: " + getFieldName() + ", sig: " + getFieldSig()); } try { double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(getFieldSig()); if (DEBUG) { System.out.println(" isSerializable: " + isSerializable); } if (isSerializable < 1.0) fieldsThatMightBeAProblem.put(obj.getName(), XFactory.createXField(this)); if (isSerializable < 0.9) { // Priority is LOW for GUI classes (unless explicitly marked Serializable), // HIGH if the class directly implements Serializable, // NORMAL otherwise. int priority = computePriority(isSerializable, 0); if (!strongEvidenceForIntendedSerialization()) { if (obj.getName().startsWith("this$")) priority = Math.max(priority, NORMAL_PRIORITY); else if (innerClassHasOuterInstance) { if (isAnonymousInnerClass) priority += 2; else priority += 1; } if (isGUIClass || isEjbImplClass) priority++; } else if (isGUIClass || isEjbImplClass) priority = Math.max(priority, NORMAL_PRIORITY); if (DEBUG) System.out.println( "SE_BAD_FIELD: " + getThisClass().getClassName() + " " + obj.getName() + " " + isSerializable + " " + implementsSerializableDirectly + " " + sawSerialVersionUID + " " + isGUIClass + " " + isEjbImplClass); // Report is queued until after the entire class has been seen. if (obj.getName().equals("this$0")) fieldWarningList.add( new BugInstance(this, "SE_BAD_FIELD_INNER_CLASS", priority) .addClass(getThisClass().getClassName())); else if (isSerializable < 0.9) fieldWarningList.add( new BugInstance(this, "SE_BAD_FIELD", priority) .addClass(getThisClass().getClassName()) .addField(getDottedClassName(), obj.getName(), getFieldSig(), false)); } else if (!isGUIClass && !isEjbImplClass && obj.getName().equals("this$0")) fieldWarningList.add( new BugInstance( this, "SE_INNER_CLASS", implementsSerializableDirectly ? NORMAL_PRIORITY : LOW_PRIORITY) .addClass(getThisClass().getClassName())); } catch (ClassNotFoundException e) { if (DEBUG) { System.out.println("Caught ClassNotFoundException"); } bugReporter.reportMissingClass(e); } } if (!getFieldName().startsWith("this") && isSynthetic(obj)) foundSynthetic = true; if (!getFieldName().equals("serialVersionUID")) return; int mask = ACC_STATIC | ACC_FINAL; if (!getFieldSig().equals("I") && !getFieldSig().equals("J")) return; if ((flags & mask) == mask && getFieldSig().equals("I")) { bugReporter.reportBug( new BugInstance(this, "SE_NONLONG_SERIALVERSIONID", LOW_PRIORITY) .addClass(this) .addVisitedField(this)); sawSerialVersionUID = true; return; } else if ((flags & ACC_STATIC) == 0) { bugReporter.reportBug( new BugInstance(this, "SE_NONSTATIC_SERIALVERSIONID", NORMAL_PRIORITY) .addClass(this) .addVisitedField(this)); return; } else if ((flags & ACC_FINAL) == 0) { bugReporter.reportBug( new BugInstance(this, "SE_NONFINAL_SERIALVERSIONID", NORMAL_PRIORITY) .addClass(this) .addVisitedField(this)); return; } sawSerialVersionUID = true; }
@Override public void visit(JavaClass obj) { String superClassname = obj.getSuperclassName(); // System.out.println("superclass of " + getClassName() + " is " + superClassname); isEnum = superClassname.equals("java.lang.Enum"); if (isEnum) return; int flags = obj.getAccessFlags(); isAbstract = (flags & ACC_ABSTRACT) != 0 || (flags & ACC_INTERFACE) != 0; isAnonymousInnerClass = anonymousInnerClassNamePattern.matcher(getClassName()).matches(); innerClassHasOuterInstance = false; for (Field f : obj.getFields()) { if (f.getName().equals("this$0")) { innerClassHasOuterInstance = true; break; } } sawSerialVersionUID = false; isSerializable = implementsSerializableDirectly = false; isExternalizable = false; directlyImplementsExternalizable = false; isGUIClass = false; isEjbImplClass = false; seenTransientField = false; // boolean isEnum = obj.getSuperclassName().equals("java.lang.Enum"); fieldsThatMightBeAProblem.clear(); transientFieldsUpdates.clear(); transientFieldsSetInConstructor.clear(); transientFieldsSetToDefaultValueInConstructor.clear(); // isRemote = false; // Does this class directly implement Serializable? String[] interface_names = obj.getInterfaceNames(); for (String interface_name : interface_names) { if (interface_name.equals("java.io.Externalizable")) { directlyImplementsExternalizable = true; isExternalizable = true; if (DEBUG) { System.out.println("Directly implements Externalizable: " + getClassName()); } } else if (interface_name.equals("java.io.Serializable")) { implementsSerializableDirectly = true; isSerializable = true; if (DEBUG) { System.out.println("Directly implements Serializable: " + getClassName()); } break; } } // Does this class indirectly implement Serializable? if (!isSerializable) { if (Subtypes2.instanceOf(obj, "java.io.Externalizable")) { isExternalizable = true; if (DEBUG) { System.out.println("Indirectly implements Externalizable: " + getClassName()); } } if (Subtypes2.instanceOf(obj, "java.io.Serializable")) { isSerializable = true; if (DEBUG) { System.out.println("Indirectly implements Serializable: " + getClassName()); } } } hasPublicVoidConstructor = false; superClassHasVoidConstructor = true; superClassHasReadObject = false; superClassImplementsSerializable = isSerializable && !implementsSerializableDirectly; ClassDescriptor superclassDescriptor = getXClass().getSuperclassDescriptor(); if (superclassDescriptor != null) try { XClass superXClass = Global.getAnalysisCache().getClassAnalysis(XClass.class, superclassDescriptor); if (superXClass != null) { superClassImplementsSerializable = AnalysisContext.currentAnalysisContext() .getSubtypes2() .isSubtype( superXClass.getClassDescriptor(), DescriptorFactory.createClassDescriptor(java.io.Serializable.class)); superClassHasVoidConstructor = false; for (XMethod m : superXClass.getXMethods()) { if (m.getName().equals("<init>") && m.getSignature().equals("()V") && !m.isPrivate()) { superClassHasVoidConstructor = true; } if (m.getName().equals("readObject") && m.getSignature().equals("(Ljava/io/ObjectInputStream;)V") && m.isPrivate()) superClassHasReadObject = true; } } } catch (ClassNotFoundException e) { bugReporter.reportMissingClass(e); } catch (CheckedAnalysisException e) { bugReporter.logError("huh", e); } // Is this a GUI or other class that is rarely serialized? isGUIClass = false; isEjbImplClass = false; if (true || !directlyImplementsExternalizable && !implementsSerializableDirectly) { isEjbImplClass = Subtypes2.instanceOf(obj, "javax.ejb.SessionBean"); isGUIClass = (Subtypes2.instanceOf(obj, "java.lang.Throwable") || Subtypes2.instanceOf(obj, "java.awt.Component") || Subtypes2.instanceOf(obj, "java.awt.Component$AccessibleAWTComponent") || Subtypes2.instanceOf(obj, "java.awt.event.ActionListener") || Subtypes2.instanceOf(obj, "java.util.EventListener")); if (!isGUIClass) { JavaClass o = obj; while (o != null) { if (o.getClassName().startsWith("java.awt") || o.getClassName().startsWith("javax.swing")) { isGUIClass = true; break; } try { o = o.getSuperClass(); } catch (ClassNotFoundException e) { break; } } } } foundSynthetic = false; foundSynchronizedMethods = false; writeObjectIsSynchronized = false; sawReadExternal = sawWriteExternal = sawReadObject = sawReadResolve = sawWriteObject = false; if (isSerializable) { for (Method m : obj.getMethods()) { if (m.getName().equals("readObject") && m.getSignature().equals("(Ljava/io/ObjectInputStream;)V")) sawReadObject = true; else if (m.getName().equals("readResolve") && m.getSignature().startsWith("()")) sawReadResolve = true; else if (m.getName().equals("readObjectNoData") && m.getSignature().equals("()V")) sawReadObject = true; else if (m.getName().equals("writeObject") && m.getSignature().equals("(Ljava/io/ObjectOutputStream;)V")) sawWriteObject = true; } for (Field f : obj.getFields()) { if (f.isTransient()) seenTransientField = true; } } }
public static double isDeepSerializable(JavaClass x) throws ClassNotFoundException { if (storedException != null) throw storedException; if (x.getClassName().equals("java.lang.Object")) return 0.4; if (DEBUG) { System.out.println("checking " + x.getClassName()); } double result = Analyze.deepInstanceOf(x, serializable); if (result >= 0.9) { if (DEBUG) { System.out.println("Direct high serializable result: " + result); } return result; } if (x.isFinal()) return result; double collectionResult = Analyze.deepInstanceOf(x, collection); double mapResult = Analyze.deepInstanceOf(x, map); if (x.isInterface() || x.isAbstract()) { result = Math.max(result, Math.max(mapResult, collectionResult) * 0.95); if (result >= 0.9) { return result; } } ClassDescriptor classDescriptor = DescriptorFactory.createClassDescriptor(x); Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2(); Set<ClassDescriptor> directSubtypes = subtypes2.getDirectSubtypes(classDescriptor); directSubtypes.remove(classDescriptor); double confidence = 0.6; if (x.isAbstract() || x.isInterface()) { confidence = 0.8; result = Math.max(result, 0.4); } else if (directSubtypes.isEmpty()) confidence = 0.2; double confidence2 = (1 + confidence) / 2; result = Math.max(result, confidence2 * collectionResult); if (result >= 0.9) { if (DEBUG) { System.out.println("High collection result: " + result); } return result; } result = Math.max(result, confidence2 * mapResult); if (result >= 0.9) { if (DEBUG) { System.out.println("High map result: " + result); } return result; } result = Math.max(result, confidence2 * 0.5 * Analyze.deepInstanceOf(x, comparator)); if (result >= 0.9) { if (DEBUG) { System.out.println("High comparator result: " + result); } return result; } for (ClassDescriptor subtype : directSubtypes) { JavaClass subJavaClass = Repository.lookupClass(subtype.getDottedClassName()); result = Math.max(result, confidence * Analyze.deepInstanceOf(subJavaClass, serializable)); // result = Math.max(result, confidence * isDeepSerializable(subJavaClass)); if (result >= 0.9) { return result; } } if (DEBUG) { System.out.println("No high results; max: " + result); } return result; }
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { if (isSynthetic(method) || !prescreen(classContext, method)) return; XMethod xmethod = XFactory.createXMethod(classContext.getJavaClass(), method); if (xmethod.isSynthetic()) return; BugAccumulator accumulator = new BugAccumulator(bugReporter); CFG cfg = classContext.getCFG(method); TypeDataflow typeDataflow = classContext.getTypeDataflow(method); ValueNumberDataflow vnDataflow = classContext.getValueNumberDataflow(method); ConstantPoolGen cpg = classContext.getConstantPoolGen(); MethodGen methodGen = classContext.getMethodGen(method); if (methodGen == null) return; String fullMethodName = methodGen.getClassName() + "." + methodGen.getName(); String sourceFile = classContext.getJavaClass().getSourceFileName(); if (DEBUG) { System.out.println("\n" + fullMethodName); } // Process each instruction for (Iterator<Location> iter = cfg.locationIterator(); iter.hasNext(); ) { Location location = iter.next(); InstructionHandle handle = location.getHandle(); Instruction ins = handle.getInstruction(); // Only consider invoke instructions if (!(ins instanceof InvokeInstruction)) continue; InvokeInstruction inv = (InvokeInstruction) ins; XMethod invokedMethod = XFactory.createXMethod(inv, cpg); String invokedMethodName = invokedMethod.getName(); String argSignature = invokedMethod.getSignature(); argSignature = argSignature.substring(0, argSignature.indexOf(')') + 1); String call = invokedMethodName + argSignature; SignatureParser sigParser = new SignatureParser(inv.getSignature(cpg)); Collection<Info> collection = callMap.get(call); if (!callMap.containsKey(call)) continue; for (Info info : collection) { Subtypes2 subtypes2 = AnalysisContext.currentAnalysisContext().getSubtypes2(); if (DEBUG) System.out.println( "at " + handle.getPosition() + " Checking call to " + info.interfaceForCall + " : " + invokedMethod); try { if (!subtypes2.isSubtype(invokedMethod.getClassDescriptor(), info.interfaceForCall)) continue; } catch (ClassNotFoundException e) { if (info.interfaceForCall.getClassName().equals("java/util/Collection") && invokedMethod.getClassName().equals("com.google.common.collect.Multiset")) { assert true; // we know this is OK without needing to find definition of Multiset } else { AnalysisContext.reportMissingClass(e); continue; } } boolean allMethod; int typeArgument; if (info.typeIndex >= 0) { allMethod = false; typeArgument = info.typeIndex; } else { allMethod = true; typeArgument = -(1 + info.typeIndex); } int pos = info.argumentIndex; int lhsPos; if (inv instanceof INVOKESTATIC) lhsPos = sigParser.getSlotsFromTopOfStackForParameter(0); else lhsPos = sigParser.getTotalArgumentSize(); int stackPos = sigParser.getSlotsFromTopOfStackForParameter(pos); TypeFrame frame = typeDataflow.getFactAtLocation(location); if (!frame.isValid()) { // This basic block is probably dead continue; } Type operandType = frame.getStackValue(stackPos); if (operandType.equals(TopType.instance())) { // unreachable continue; } if (operandType.equals(NullType.instance())) { // ignore continue; } ValueNumberFrame vnFrame = vnDataflow.getFactAtLocation(location); if (!vnFrame.isValid()) { AnalysisContext.logError("Invalid value number frame in " + xmethod); continue; } ValueNumber objectVN = vnFrame.getStackValue(lhsPos); ValueNumber argVN = vnFrame.getStackValue(stackPos); if (objectVN.equals(argVN)) { String bugPattern = "DMI_COLLECTIONS_SHOULD_NOT_CONTAIN_THEMSELVES"; int priority = HIGH_PRIORITY; if (invokedMethodName.equals("removeAll")) { bugPattern = "DMI_USING_REMOVEALL_TO_CLEAR_COLLECTION"; priority = NORMAL_PRIORITY; } else if (invokedMethodName.endsWith("All")) { bugPattern = "DMI_VACUOUS_SELF_COLLECTION_CALL"; priority = NORMAL_PRIORITY; } if (invokedMethodName.startsWith("contains")) { InstructionHandle next = handle.getNext(); if (next != null) { Instruction nextIns = next.getInstruction(); if (nextIns instanceof InvokeInstruction) { XMethod nextMethod = XFactory.createXMethod((InvokeInstruction) nextIns, cpg); if (nextMethod.getName().equals("assertFalse")) continue; } } } accumulator.accumulateBug( new BugInstance(this, bugPattern, priority) .addClassAndMethod(methodGen, sourceFile) .addCalledMethod(methodGen, (InvokeInstruction) ins) .addOptionalAnnotation( ValueNumberSourceInfo.findAnnotationFromValueNumber( method, location, objectVN, vnFrame, "INVOKED_ON")), SourceLineAnnotation.fromVisitedInstruction( classContext, methodGen, sourceFile, handle)); } // Only consider generic... Type objectType = frame.getStackValue(lhsPos); if (!(objectType instanceof GenericObjectType)) continue; GenericObjectType operand = (GenericObjectType) objectType; int expectedTypeParameters = 1; String simpleName = info.interfaceForCall.getSimpleName(); if (simpleName.toLowerCase().endsWith("map") || simpleName.equals("Hashtable")) expectedTypeParameters = 2; else if (simpleName.equals("Table")) expectedTypeParameters = 3; // ... containers if (!operand.hasParameters()) continue; if (operand.getNumParameters() != expectedTypeParameters) continue; ClassDescriptor operandClass = DescriptorFactory.getClassDescriptor(operand); if (!isGenericCollection(operandClass)) continue; if (expectedTypeParameters == 2 && Subtypes2.instanceOf(operandClass, Map.class) && !TypeFrameModelingVisitor.isStraightGenericMap(operandClass)) continue; Type expectedType; if (allMethod) expectedType = operand; else expectedType = operand.getParameterAt(typeArgument); Type actualType = frame.getStackValue(stackPos); Type equalsType = actualType; if (allMethod) { if (!(actualType instanceof GenericObjectType)) { continue; } equalsType = ((GenericObjectType) actualType).getParameterAt(typeArgument); } IncompatibleTypes matchResult = compareTypes(expectedType, actualType, allMethod); boolean parmIsObject = expectedType.getSignature().equals("Ljava/lang/Object;"); boolean selfOperation = !allMethod && operand.equals(actualType) && !parmIsObject; if (!allMethod && !parmIsObject && actualType instanceof GenericObjectType) { GenericObjectType p2 = (GenericObjectType) actualType; List<? extends ReferenceType> parameters = p2.getParameters(); if (parameters != null && parameters.equals(operand.getParameters())) selfOperation = true; } if (!selfOperation && (matchResult == IncompatibleTypes.SEEMS_OK || matchResult.getPriority() == Priorities.IGNORE_PRIORITY)) continue; if (invokedMethodName.startsWith("contains") || invokedMethodName.equals("remove")) { InstructionHandle next = handle.getNext(); if (next != null) { Instruction nextIns = next.getInstruction(); if (nextIns instanceof InvokeInstruction) { XMethod nextMethod = XFactory.createXMethod((InvokeInstruction) nextIns, cpg); if (nextMethod.getName().equals("assertFalse")) continue; } } } else if (invokedMethodName.equals("get") || invokedMethodName.equals("remove")) { InstructionHandle next = handle.getNext(); if (next != null) { Instruction nextIns = next.getInstruction(); if (nextIns instanceof InvokeInstruction) { XMethod nextMethod = XFactory.createXMethod((InvokeInstruction) nextIns, cpg); if (nextMethod.getName().equals("assertNull")) continue; } } } boolean noisy = false; if (invokedMethodName.equals("get")) { UnconditionalValueDerefDataflow unconditionalValueDerefDataflow = classContext.getUnconditionalValueDerefDataflow(method); UnconditionalValueDerefSet unconditionalDeref = unconditionalValueDerefDataflow.getFactAtLocation(location); ValueNumberFrame vnAfter = vnDataflow.getFactAfterLocation(location); ValueNumber top = vnAfter.getTopValue(); noisy = unconditionalDeref.getValueNumbersThatAreUnconditionallyDereferenced().contains(top); } // Prepare bug report SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction( classContext, methodGen, sourceFile, handle); // Report a bug that mentions each of the failed arguments in // matches if (expectedType instanceof GenericObjectType) expectedType = ((GenericObjectType) expectedType).getUpperBound(); int priority = matchResult.getPriority(); if (!operandClass.getClassName().startsWith("java/util") && priority == Priorities.HIGH_PRIORITY) priority = Math.max(priority, Priorities.NORMAL_PRIORITY); if (TestCaseDetector.likelyTestCase(xmethod)) priority = Math.max(priority, Priorities.NORMAL_PRIORITY); else if (selfOperation) priority = Priorities.HIGH_PRIORITY; ClassDescriptor expectedClassDescriptor = DescriptorFactory.createClassOrObjectDescriptorFromSignature( expectedType.getSignature()); ClassDescriptor actualClassDescriptor = DescriptorFactory.createClassOrObjectDescriptorFromSignature(equalsType.getSignature()); ClassSummary classSummary = AnalysisContext.currentAnalysisContext().getClassSummary(); Set<XMethod> targets = null; try { targets = Hierarchy2.resolveVirtualMethodCallTargets( actualClassDescriptor, "equals", "(Ljava/lang/Object;)Z", false, false); boolean allOk = targets.size() > 0; for (XMethod m2 : targets) if (!classSummary.mightBeEqualTo(m2.getClassDescriptor(), expectedClassDescriptor)) allOk = false; if (allOk) priority += 2; } catch (ClassNotFoundException e) { AnalysisContext.reportMissingClass(e); } String bugPattern = "GC_UNRELATED_TYPES"; BugInstance bug = new BugInstance(this, bugPattern, priority) .addClassAndMethod(methodGen, sourceFile) .addFoundAndExpectedType(actualType, expectedType) .addCalledMethod(methodGen, (InvokeInstruction) ins) .addOptionalAnnotation( ValueNumberSourceInfo.findAnnotationFromValueNumber( method, location, objectVN, vnFrame, "INVOKED_ON")) .addOptionalAnnotation( ValueNumberSourceInfo.findAnnotationFromValueNumber( method, location, argVN, vnFrame, "ARGUMENT")) .addEqualsMethodUsed(targets); if (noisy) { WarningPropertySet<WarningProperty> propertySet = new WarningPropertySet<WarningProperty>(); propertySet.addProperty(GeneralWarningProperty.NOISY_BUG); propertySet.decorateBugInstance(bug); } accumulator.accumulateBug(bug, sourceLineAnnotation); } } accumulator.reportAccumulatedBugs(); }