}
}
*/
if (!hasEqualsObject && !hasEqualsSelf && hasEqualsOther) {
BugInstance bug = new BugInstance(this, usesDefaultEquals ? "EQ_OTHER_USE_OBJECT" : "EQ_OTHER_NO_OBJECT",
NORMAL_PRIORITY).addClass(this).addMethod(equalsOtherMethod).addClass(equalsOtherClass);
bugReporter.reportBug(bug);
}
if (!hasEqualsObject && hasEqualsSelf) {
if (usesDefaultEquals) {
int priority = HIGH_PRIORITY;
if (usesDefaultHashCode || obj.isAbstract()) {
priority++;
}
if (!visibleOutsidePackage) {
priority++;
}
String bugPattern = "EQ_SELF_USE_OBJECT";
BugInstance bug = new BugInstance(this, bugPattern, priority).addClass(getDottedClassName());
if (equalsMethod != null) {
bug.addMethod(equalsMethod);
}
bugReporter.reportBug(bug);
} else {
int priority = NORMAL_PRIORITY;
if (hasFields) {
priority--;
}
if (obj.isAbstract()) {
priority++;
}
String bugPattern = "EQ_SELF_NO_OBJECT";
String superclassName = obj.getSuperclassName();
if (superclassName.equals("java.lang.Enum")) {
bugPattern = "EQ_DONT_DEFINE_EQUALS_FOR_ENUM";
priority = HIGH_PRIORITY;
}
BugInstance bug = new BugInstance(this, bugPattern, priority).addClass(getDottedClassName());
if (equalsMethod != null) {
bug.addMethod(equalsMethod);
}
bugReporter.reportBug(bug);
}
}
// System.out.println("Class " + getDottedClassName());
// System.out.println("usesDefaultEquals: " + usesDefaultEquals);
// System.out.println("hasHashCode: : " + hasHashCode);
// System.out.println("usesDefaultHashCode: " + usesDefaultHashCode);
// System.out.println("hasEquals: : " + hasEqualsObject);
// System.out.println("hasCompareToObject: : " + hasCompareToObject);
// System.out.println("hasCompareToSelf: : " + hasCompareToSelf);
if ((hasCompareToObject || hasCompareToSelf) && usesDefaultEquals) {
BugInstance bug = new BugInstance(this, "EQ_COMPARETO_USE_OBJECT_EQUALS", obj.isAbstract() ? Priorities.LOW_PRIORITY
: Priorities.NORMAL_PRIORITY).addClass(this);
if (compareToSelfMethod != null) {
bug.addMethod(compareToSelfMethod);
} else {
bug.addMethod(compareToObjectMethod);
}
bugReporter.reportBug(bug);
}
if (!hasCompareToObject && !hasCompareToBridgeMethod && hasCompareToSelf) {
if (!extendsObject) {
bugReporter.reportBug(new BugInstance(this, "CO_SELF_NO_OBJECT", NORMAL_PRIORITY).addClass(getDottedClassName())
.addMethod(compareToMethod));
}
}
// if (!hasFields) return;
if (hasHashCode && !hashCodeIsAbstract && !(hasEqualsObject || hasEqualsSelf)) {
int priority = LOW_PRIORITY;
if (usesDefaultEquals) {
bugReporter.reportBug(new BugInstance(this, "HE_HASHCODE_USE_OBJECT_EQUALS", priority).addClass(
getDottedClassName()).addMethod(hashCodeMethod));
} else if (!inheritedEqualsIsFinal) {
bugReporter.reportBug(new BugInstance(this, "HE_HASHCODE_NO_EQUALS", priority).addClass(getDottedClassName())
.addMethod(hashCodeMethod));
}
}
if (equalsObjectIsAbstract) {
// no errors reported
} else if (!hasHashCode && (hasEqualsObject || hasEqualsSelf)) {
EqualsKindSummary.KindOfEquals equalsKind = AnalysisContext.currentAnalysisContext().getEqualsKindSummary()
.get(new ClassAnnotation(obj.getClassName()));
if (equalsKind == EqualsKindSummary.KindOfEquals.ALWAYS_FALSE) {
return;
}
if (usesDefaultHashCode) {
int priority = HIGH_PRIORITY;
if (equalsMethodIsInstanceOfEquals) {
priority += 2;
} else if (obj.isAbstract() || !hasEqualsObject) {
priority++;
}
if (priority == HIGH_PRIORITY) {
nonHashableClasses.add(getDottedClassName());
}
if (!visibleOutsidePackage) {
priority++;
}
BugInstance bug = new BugInstance(this, "HE_EQUALS_USE_HASHCODE", priority).addClass(getDottedClassName());
if (equalsMethod != null) {
bug.addMethod(equalsMethod);
}
bugReporter.reportBug(bug);
} else if (!inheritedHashCodeIsFinal && !whereHashCode.startsWith("java.util.Abstract")) {
int priority = LOW_PRIORITY;
if (hasEqualsObject && inheritedEqualsIsAbstract) {
priority++;
}
if (hasFields) {
priority--;
}
if (equalsMethodIsInstanceOfEquals || !hasEqualsObject) {
priority += 2;
} else if (obj.isAbstract()) {
priority++;
}
BugInstance bug = new BugInstance(this, "HE_EQUALS_NO_HASHCODE", priority).addClass(getDottedClassName());
if (equalsMethod != null) {
bug.addMethod(equalsMethod);
}
bugReporter.reportBug(bug);
}
}
if (!hasHashCode && !hasEqualsObject && !hasEqualsSelf && !usesDefaultEquals && usesDefaultHashCode && !obj.isAbstract()
&& inheritedEqualsFromAbstractClass) {
BugInstance bug = new BugInstance(this, "HE_INHERITS_EQUALS_USE_HASHCODE", NORMAL_PRIORITY)
.addClass(getDottedClassName());
if (equalsMethod != null) {
bug.addMethod(equalsMethod);
}
bugReporter.reportBug(bug);
}
if (!hasEqualsObject && !hasEqualsSelf && !usesDefaultEquals && !obj.isAbstract() && hasFields && inheritedEquals != null
&& !inheritedEqualsIsFinal && !inheritedEqualsFromAbstractClass
&& !inheritedEquals.getClassDescriptor().getSimpleName().contains("Abstract")
&& !inheritedEquals.getClassDescriptor().getClassName().equals("java/lang/Enum")) {
BugInstance bug = new BugInstance(this, "EQ_DOESNT_OVERRIDE_EQUALS", NORMAL_PRIORITY);
// create annotation pointing to this class source line 1, otherwise the primary annotation shows parent class
SourceLineAnnotation sourceLine = new SourceLineAnnotation(getDottedClassName(), obj.getSourceFileName(), 1, 1, 0, 0);
bug.addClass(getDottedClassName()).add(sourceLine);
bug.addMethod(inheritedEquals).describe(MethodAnnotation.METHOD_DID_YOU_MEAN_TO_OVERRIDE);
bugReporter.reportBug(bug);
}
}