# HG changeset patch # User vromero # Date 1362650668 0 # Node ID 3806171b52d8ca7ab1bb4335b3017a196926675e # Parent c98b3e96c7269224ebe35daf9f5b51642eb6db56 8009138: javac, equals-hashCode warning tuning Reviewed-by: mcimadamore diff -r c98b3e96c726 -r 3806171b52d8 src/share/classes/com/sun/tools/javac/code/Symbol.java --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Mar 06 15:33:39 2013 +0000 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Mar 07 10:04:28 2013 +0000 @@ -237,7 +237,7 @@ } /** Has this symbol an empty name? This includes anonymous - * inner classses. + * inner classes. */ public boolean isAnonymous() { return name.isEmpty(); diff -r c98b3e96c726 -r 3806171b52d8 src/share/classes/com/sun/tools/javac/code/Symtab.java --- a/src/share/classes/com/sun/tools/javac/code/Symtab.java Wed Mar 06 15:33:39 2013 +0000 +++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java Thu Mar 07 10:04:28 2013 +0000 @@ -148,6 +148,7 @@ public final Type listType; public final Type collectionsType; public final Type comparableType; + public final Type comparatorType; public final Type arraysType; public final Type iterableType; public final Type iteratorType; @@ -502,6 +503,7 @@ listType = enterClass("java.util.List"); collectionsType = enterClass("java.util.Collections"); comparableType = enterClass("java.lang.Comparable"); + comparatorType = enterClass("java.util.Comparator"); arraysType = enterClass("java.util.Arrays"); iterableType = target.hasIterable() ? enterClass("java.lang.Iterable") diff -r c98b3e96c726 -r 3806171b52d8 src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Mar 06 15:33:39 2013 +0000 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Mar 07 10:04:28 2013 +0000 @@ -4016,7 +4016,7 @@ attribClassBody(env, c); chk.checkDeprecatedAnnotation(env.tree.pos(), c); - chk.checkClassOverrideEqualsAndHash(env.tree.pos(), c); + chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c); } finally { env.info.returnResult = prevReturnRes; log.useSource(prev); diff -r c98b3e96c726 -r 3806171b52d8 src/share/classes/com/sun/tools/javac/comp/Check.java --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Mar 06 15:33:39 2013 +0000 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Mar 07 10:04:28 2013 +0000 @@ -1972,14 +1972,32 @@ } }; - public void checkClassOverrideEqualsAndHash(DiagnosticPosition pos, + public void checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos, + ClassSymbol someClass) { + /* At present, annotations cannot possibly have a method that is override + * equivalent with Object.equals(Object) but in any case the condition is + * fine for completeness. + */ + if (someClass == (ClassSymbol)syms.objectType.tsym || + someClass.isInterface() || someClass.isEnum() || + (someClass.flags() & ANNOTATION) != 0 || + (someClass.flags() & ABSTRACT) != 0) return; + //anonymous inner classes implementing interfaces need especial treatment + if (someClass.isAnonymous()) { + List interfaces = types.interfaces(someClass.type); + if (interfaces != null && !interfaces.isEmpty() && + interfaces.head.tsym == syms.comparatorType.tsym) return; + } + checkClassOverrideEqualsAndHash(pos, someClass); + } + + private void checkClassOverrideEqualsAndHash(DiagnosticPosition pos, ClassSymbol someClass) { if (lint.isEnabled(LintCategory.OVERRIDES)) { MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType .tsym.members().lookup(names.equals).sym; MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType .tsym.members().lookup(names.hashCode).sym; - boolean overridesEquals = types.implementation(equalsAtObject, someClass, false, equalsHasCodeFilter).owner == someClass; boolean overridesHashCode = types.implementation(hashCodeAtObject, @@ -1987,7 +2005,7 @@ if (overridesEquals && !overridesHashCode) { log.warning(LintCategory.OVERRIDES, pos, - "override.equals.but.not.hashcode", someClass.fullname); + "override.equals.but.not.hashcode", someClass); } } } diff -r c98b3e96c726 -r 3806171b52d8 src/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Mar 06 15:33:39 2013 +0000 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Mar 07 10:04:28 2013 +0000 @@ -2077,7 +2077,7 @@ {0}\n\ overridden method does not throw {1} -# 0: class name +# 0: symbol compiler.warn.override.equals.but.not.hashcode=\ Class {0} overrides equals, but neither it nor any superclass overrides hashCode method diff -r c98b3e96c726 -r 3806171b52d8 test/tools/javac/6563143/EqualsHashCodeWarningTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6563143/EqualsHashCodeWarningTest.java Thu Mar 07 10:04:28 2013 +0000 @@ -0,0 +1,71 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6563143 8008436 8009138 + * @summary javac should issue a warning for overriding equals without hashCode + * @summary javac should not issue a warning for overriding equals without hasCode + * @summary javac, equals-hashCode warning tuning + * if hashCode has been overriden by a superclass + * @compile/ref=EqualsHashCodeWarningTest.out -Xlint:overrides -XDrawDiagnostics EqualsHashCodeWarningTest.java + */ + +import java.util.Comparator; + +public class EqualsHashCodeWarningTest { + @Override + public boolean equals(Object o) { + return o == this; + } + + @Override + public int hashCode() { + return 0; + } + + public Comparator m() { + return new Comparator() { + @Override + public boolean equals(Object o) {return true;} + + @Override + public int compare(Object o1, Object o2) { + return 0; + } + }; + } +} + +class SubClass extends EqualsHashCodeWarningTest { + @Override + public boolean equals(Object o) { + return true; + } +} + +@SuppressWarnings("overrides") +class DontWarnMe { + @Override + public boolean equals(Object o) { + return true; + } +} + +class DoWarnMe { + @Override + public boolean equals(Object o) { + return o == this; + } +} + +abstract class IamAbstractGetMeOutOfHere { + public boolean equals(Object o){return true;} +} + +interface I { + public boolean equals(Object o); +} + +enum E { + A, B +} + +@interface anno {} diff -r c98b3e96c726 -r 3806171b52d8 test/tools/javac/6563143/EqualsHashCodeWarningTest.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6563143/EqualsHashCodeWarningTest.out Thu Mar 07 10:04:28 2013 +0000 @@ -0,0 +1,2 @@ +EqualsHashCodeWarningTest.java:52:1: compiler.warn.override.equals.but.not.hashcode: DoWarnMe +1 warning diff -r c98b3e96c726 -r 3806171b52d8 test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.java --- a/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.java Wed Mar 06 15:33:39 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 6563143 8008436 - * @summary javac should issue a warning for overriding equals without hashCode - * @summary javac should not issue a warning for overriding equals without hasCode - * if hashCode has been overriden by a superclass - * @compile/ref=OverridesEqualsButNotHashCodeTest.out -Xlint:overrides -XDrawDiagnostics OverridesEqualsButNotHashCodeTest.java - */ - -public class OverridesEqualsButNotHashCodeTest { - @Override - public boolean equals(Object o) { - return o == this; - } - - @Override - public int hashCode() { - return 0; - } -} - -class SubClass extends OverridesEqualsButNotHashCodeTest { - @Override - public boolean equals(Object o) { - return o == this; - } -} - -@SuppressWarnings("overrides") -class NoWarning { - @Override - public boolean equals(Object o) { - return o == this; - } -} - -class DoWarnMe { - @Override - public boolean equals(Object o) { - return o == this; - } -} diff -r c98b3e96c726 -r 3806171b52d8 test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.out --- a/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.out Wed Mar 06 15:33:39 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -OverridesEqualsButNotHashCodeTest.java:37:1: compiler.warn.override.equals.but.not.hashcode: DoWarnMe -1 warning