for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) {
Location location = i.next();
InstructionHandle handle = location.getHandle();
Instruction ins = handle.getInstruction();
if (ins.getOpcode() == Constants.INVOKEVIRTUAL) {
INVOKEVIRTUAL iv = (INVOKEVIRTUAL) ins;
String methodName = iv.getMethodName(cpg);
String methodSig = iv.getSignature(cpg);
if (methodName.equals("wait")
&& (methodSig.equals("()V") || methodSig.equals("(J)V") || methodSig.equals("(JI)V"))
|| (methodName.equals("notify") || methodName.equals("notifyAll")) && methodSig.equals("()V")) {
try {
TypeFrame frame = typeDataflow.getFactAtLocation(location);
if (!frame.isValid()) {
continue;
}
Type type = frame.getInstance(ins, cpg);
if (!(type instanceof ReferenceType)) {
// Something is deeply wrong if a non-reference type
// is used for a method invocation. But, that's
// really a
// verification problem.
continue;
}
ClassDescriptor classDescriptor = DescriptorFactory.createClassDescriptorFromSignature(type
.getSignature());
if (classDescriptor.equals(classContext.getClassDescriptor())) {
continue;
}
if (!classDescriptor.getClassName().startsWith("java/util/concurrent")) {
continue;
}
XClass c = Lookup.getXClass(classDescriptor);
XMethod m;
int priority = NORMAL_PRIORITY;
if (methodName.equals("wait")) {
m = c.findMethod("await", "()V", false);
priority = HIGH_PRIORITY;
} else if (methodName.equals("notify")) {
m = c.findMethod("signal", "()V", false);
if (m == null) {
m = c.findMethod("countDown", "()V", false);
}
} else if (methodName.equals("notifyAll")) {
m = c.findMethod("signalAll", "()V", false);
if (m == null) {
m = c.findMethod("countDown", "()V", false);
}
} else {
throw new IllegalStateException("Unexpected methodName: " + methodName);
}
if (m != null && m.isPublic() && c.isPublic()) {
bugReporter.reportBug(new BugInstance(this, "JML_JSR166_CALLING_WAIT_RATHER_THAN_AWAIT", priority)
.addClassAndMethod(classContext.getJavaClass(), method).addCalledMethod(cpg, iv).addMethod(m)
.describe(MethodAnnotation.METHOD_ALTERNATIVE_TARGET).addType(classDescriptor)
.describe(TypeAnnotation.FOUND_ROLE).addSourceLine(classContext, method, location));
}
} catch (CheckedAnalysisException e) {
AnalysisContext.logError("Coult not get Type dataflow", e);
continue;
}
}
}
if (ins.getOpcode() != Constants.MONITORENTER) {
continue;
}
Type type;
try {
TypeFrame frame = typeDataflow.getFactAtLocation(location);