if (!hasHashCode && !hasEqualsObject &&  !hasEqualsSelf && !usesDefaultEquals && usesDefaultHashCode && !obj.isAbstract() && classThatDefinesEqualsIsAbstract) { bugReporter.reportBug(new BugInstance("HE_INHERITS_EQUALS_USE_HASHCODE", NORMAL_PRIORITY ).addClass(getDottedClassName())); }
   public void visitAfter(JavaClass obj) {	if (!obj.isClass()) return;	if (getDottedClassName().equals("java.lang.Object")) return;	int accessFlags = obj.getAccessFlags();	if ((accessFlags & ACC_INTERFACE) != 0) return;  	visibleOutsidePackage = obj.isPublic() || obj.isProtected();	String whereEqual = getDottedClassName();	boolean classThatDefinesEqualsIsAbstract = false;	boolean inheritedHashCodeIsFinal = false;	boolean inheritedEqualsIsFinal = false;	boolean inheritedHashCodeIsAbstract = false;	boolean inheritedEqualsIsAbstract = false;	if (!hasEqualsObject)  {		JavaClass we = Lookup.findSuperImplementor(obj, "equals",					"(Ljava/lang/Object;)Z", bugReporter);		if (we == null) {			whereEqual = "java.lang.Object";		}		else {			whereEqual = we.getClassName();			classThatDefinesEqualsIsAbstract = we.isAbstract();;			Method m = findMethod(we, "equals", "(Ljava/lang/Object;)Z");			if (m != null && m.isFinal()) inheritedEqualsIsFinal = true;			if (m != null && m.isAbstract()) inheritedEqualsIsAbstract = true;			}		}	boolean usesDefaultEquals = whereEqual.equals("java.lang.Object");	String whereHashCode = getDottedClassName();	if (!hasHashCode) {		JavaClass wh = Lookup.findSuperImplementor(obj, "hashCode",					"()I", bugReporter);		if (wh == null) {			whereHashCode = "java.lang.Object";			}		else {			whereHashCode = wh.getClassName();			Method m = findMethod(wh, "hashCode", "()I");			if (m != null && m.isFinal()) inheritedHashCodeIsFinal = true;			if (m != null && m.isAbstract()) inheritedHashCodeIsAbstract = true;			}		}	boolean usesDefaultHashCode = whereHashCode.equals("java.lang.Object");	if (false && (usesDefaultEquals ||  usesDefaultHashCode)) {		try {		  if (Repository.implementationOf(obj, "java/util/Set")		    || Repository.implementationOf(obj, "java/util/List")		    || Repository.implementationOf(obj, "java/util/Map")) {		  // System.out.println(getDottedClassName() + " uses default hashCode or equals");		  }                } catch (ClassNotFoundException e) {			// e.printStackTrace();                }	}	if (!hasEqualsObject &&  hasEqualsSelf) {				if (usesDefaultEquals)  {		  int priority = HIGH_PRIORITY;		  if (usesDefaultHashCode || obj.isAbstract()) 			priority++;		  if (!visibleOutsidePackage)			priority++;		  bugReporter.reportBug(new BugInstance("EQ_SELF_USE_OBJECT", priority).addClass(getDottedClassName()));		   }		else {		  int priority = NORMAL_PRIORITY;		  if (hasFields)			priority--;		  if (obj.isAbstract()) priority++;		  bugReporter.reportBug(new BugInstance("EQ_SELF_NO_OBJECT", priority).addClass(getDottedClassName()));		}		}	/*	System.out.println("Class " + betterClassName);	System.out.println("usesDefaultEquals: " + usesDefaultEquals);	System.out.println("hasHashCode: : " + hasHashCode);	System.out.println("usesDefaultHashCode: " + usesDefaultHashCode);	System.out.println("hasEquals: : " + hasEqualsObject);	*/	if (!hasCompareToObject &&  hasCompareToSelf) {		if (!extendsObject)		  bugReporter.reportBug(new BugInstance("CO_SELF_NO_OBJECT", NORMAL_PRIORITY).addClass(getDottedClassName()));		}	// if (!hasFields) return;	if (hasHashCode && !hashCodeIsAbstract && !(hasEqualsObject ||  hasEqualsSelf))  { 		int priority = LOW_PRIORITY;		if (usesDefaultEquals) 		  bugReporter.reportBug(new BugInstance("HE_HASHCODE_USE_OBJECT_EQUALS", priority).addClass(getDottedClassName()));		else if (!inheritedEqualsIsFinal)		  bugReporter.reportBug(new BugInstance("HE_HASHCODE_NO_EQUALS", priority). addClass(getDottedClassName()));		}	if (!hasHashCode 		&& (hasEqualsObject && !equalsObjectIsAbstract ||  hasEqualsSelf))  {		if (usesDefaultHashCode) {		  int priority = HIGH_PRIORITY;		  if (equalsMethodIsInstanceOfEquals) priority+= 2;		  else if (obj.isAbstract() || !hasEqualsObject) priority++;		  if (!visibleOutsidePackage) {			priority++;			}		  bugReporter.reportBug(new BugInstance("HE_EQUALS_USE_HASHCODE", 				priority ).addClass(getDottedClassName()));		  }		else if (!inheritedHashCodeIsFinal) {		  int priority = LOW_PRIORITY;		  if (hasEqualsObject && inheritedEqualsIsAbstract)			priority++;		  if (hasFields) priority--;		  if (equalsMethodIsInstanceOfEquals || !hasEqualsObject) priority+= 2;		  else if (obj.isAbstract()) priority++;		   bugReporter.reportBug(		    new BugInstance("HE_EQUALS_NO_HASHCODE", 			priority)		    .addClass(getDottedClassName()));		}		}	if (!hasHashCode && !hasEqualsObject &&  !hasEqualsSelf		&& !usesDefaultEquals && usesDefaultHashCode		&& !obj.isAbstract() && classThatDefinesEqualsIsAbstract) {	  bugReporter.reportBug(new BugInstance("HE_INHERITS_EQUALS_USE_HASHCODE", 			NORMAL_PRIORITY ).addClass(getDottedClassName()));	  }	}