if (lhsDescriptor.equals(rhsDescriptor)) {
return SEEMS_OK;
}
AnalysisContext analysisContext = AnalysisContext.currentAnalysisContext();
Subtypes2 subtypes2 = analysisContext.getSubtypes2();
IAnalysisCache cache = Global.getAnalysisCache();
XClass lhs = cache.getClassAnalysis(XClass.class, lhsDescriptor);
XClass rhs = cache.getClassAnalysis(XClass.class, rhsDescriptor);
// Look up the classes
XMethod lhsEquals = getInvokedMethod(lhs, "equals", "(Ljava/lang/Object;)Z", false);
XMethod rhsEquals = getInvokedMethod(rhs, "equals", "(Ljava/lang/Object;)Z", false);
String lhsClassName = lhsEquals.getClassName();
if (lhsEquals.equals(rhsEquals)) {
if (lhsClassName.equals("java.lang.Enum")) {
return INCOMPATIBLE_CLASSES;
}
if (!pointerEquality && !lhsClassName.equals("java.lang.Object")) {
return SEEMS_OK;
}
}
if ((subtypes2.isSubtype(lhsDescriptor, SET_DESCRIPTOR) && subtypes2.isSubtype(rhsDescriptor, SET_DESCRIPTOR)
|| subtypes2.isSubtype(lhsDescriptor, MAP_DESCRIPTOR) && subtypes2.isSubtype(rhsDescriptor, MAP_DESCRIPTOR) || subtypes2
.isSubtype(lhsDescriptor, LIST_DESCRIPTOR) && subtypes2.isSubtype(rhsDescriptor, LIST_DESCRIPTOR))) {
return SEEMS_OK;
}
if (!lhs.isInterface() && !rhs.isInterface()) {
// Both are class types, and therefore there is no possible
// way
// the compared objects can have the same runtime type.
return INCOMPATIBLE_CLASSES;
} else {
// Look up the common subtypes of the two types. If the
// intersection does not contain at least one
// class,
// then issue a warning of the appropriate type.
Set<ClassDescriptor> commonSubtypes = subtypes2.getTransitiveCommonSubtypes(lhsDescriptor, rhsDescriptor);
if (commonSubtypes.isEmpty()) {
if (lhs.isInterface() && rhs.isInterface()) {
if (!subtypes2.hasKnownSubclasses(lhsDescriptor) || !subtypes2.hasKnownSubclasses(rhsDescriptor)) {
return UNRELATED_INTERFACES_WITHOUT_IMPLEMENTATIONS;
}
return UNRELATED_INTERFACES;
}
if (lhs.isFinal() || rhs.isFinal()) {