langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
changeset 16301 b6fd735ea78e
parent 16292 3be2cdacb3b3
child 16316 1150b1b2f5c2
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Feb 15 18:40:38 2013 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Feb 18 14:33:25 2013 +0000
@@ -1588,6 +1588,7 @@
                    (other.flags() & STATIC) == 0) {
             log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.static",
                       cannotOverride(m, other));
+            m.flags_field |= BAD_OVERRIDE;
             return;
         }
 
@@ -1599,6 +1600,7 @@
             log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth",
                       cannotOverride(m, other),
                       asFlagSet(other.flags() & (FINAL | STATIC)));
+            m.flags_field |= BAD_OVERRIDE;
             return;
         }
 
@@ -1615,6 +1617,7 @@
                       other.flags() == 0 ?
                           Flag.PACKAGE :
                           asFlagSet(other.flags() & AccessFlags));
+            m.flags_field |= BAD_OVERRIDE;
             return;
         }
 
@@ -1642,6 +1645,7 @@
                           "override.incompatible.ret",
                           cannotOverride(m, other),
                           mtres, otres);
+                m.flags_field |= BAD_OVERRIDE;
                 return;
             }
         } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
@@ -1661,6 +1665,7 @@
                       "override.meth.doesnt.throw",
                       cannotOverride(m, other),
                       unhandledUnerased.head);
+            m.flags_field |= BAD_OVERRIDE;
             return;
         }
         else if (unhandledUnerased.nonEmpty()) {
@@ -1956,6 +1961,33 @@
         }
     }
 
+    public void checkClassOverrideEqualsAndHash(ClassSymbol someClass) {
+        if (lint.isEnabled(LintCategory.OVERRIDES)) {
+            boolean hasEquals = false;
+            boolean hasHashCode = false;
+
+            Scope.Entry equalsAtObject = syms.objectType.tsym.members().lookup(names.equals);
+            Scope.Entry hashCodeAtObject = syms.objectType.tsym.members().lookup(names.hashCode);
+            for (Symbol s: someClass.members().getElements(new Filter<Symbol>() {
+                    public boolean accepts(Symbol s) {
+                        return s.kind == Kinds.MTH &&
+                                (s.flags() & BAD_OVERRIDE) == 0;
+                    }
+                })) {
+                MethodSymbol m = (MethodSymbol)s;
+                hasEquals |= m.name.equals(names.equals) &&
+                        m.overrides(equalsAtObject.sym, someClass, types, false);
+
+                hasHashCode |= m.name.equals(names.hashCode) &&
+                        m.overrides(hashCodeAtObject.sym, someClass, types, false);
+            }
+            if (hasEquals && !hasHashCode) {
+                log.warning(LintCategory.OVERRIDES, (DiagnosticPosition) null,
+                        "override.equals.but.not.hashcode", someClass.fullname);
+            }
+        }
+    }
+
     private boolean checkNameClash(ClassSymbol origin, Symbol s1, Symbol s2) {
         ClashFilter cf = new ClashFilter(origin.type);
         return (cf.accepts(s1) &&