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);