Thu, 07 Mar 2013 10:04:28 +0000
8009138: javac, equals-hashCode warning tuning
Reviewed-by: mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Mar 06 15:33:39 2013 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Mar 07 10:04:28 2013 +0000 1.3 @@ -237,7 +237,7 @@ 1.4 } 1.5 1.6 /** Has this symbol an empty name? This includes anonymous 1.7 - * inner classses. 1.8 + * inner classes. 1.9 */ 1.10 public boolean isAnonymous() { 1.11 return name.isEmpty();
2.1 --- a/src/share/classes/com/sun/tools/javac/code/Symtab.java Wed Mar 06 15:33:39 2013 +0000 2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java Thu Mar 07 10:04:28 2013 +0000 2.3 @@ -148,6 +148,7 @@ 2.4 public final Type listType; 2.5 public final Type collectionsType; 2.6 public final Type comparableType; 2.7 + public final Type comparatorType; 2.8 public final Type arraysType; 2.9 public final Type iterableType; 2.10 public final Type iteratorType; 2.11 @@ -502,6 +503,7 @@ 2.12 listType = enterClass("java.util.List"); 2.13 collectionsType = enterClass("java.util.Collections"); 2.14 comparableType = enterClass("java.lang.Comparable"); 2.15 + comparatorType = enterClass("java.util.Comparator"); 2.16 arraysType = enterClass("java.util.Arrays"); 2.17 iterableType = target.hasIterable() 2.18 ? enterClass("java.lang.Iterable")
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Mar 06 15:33:39 2013 +0000 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Mar 07 10:04:28 2013 +0000 3.3 @@ -4016,7 +4016,7 @@ 3.4 attribClassBody(env, c); 3.5 3.6 chk.checkDeprecatedAnnotation(env.tree.pos(), c); 3.7 - chk.checkClassOverrideEqualsAndHash(env.tree.pos(), c); 3.8 + chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c); 3.9 } finally { 3.10 env.info.returnResult = prevReturnRes; 3.11 log.useSource(prev);
4.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Mar 06 15:33:39 2013 +0000 4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Thu Mar 07 10:04:28 2013 +0000 4.3 @@ -1972,14 +1972,32 @@ 4.4 } 4.5 }; 4.6 4.7 - public void checkClassOverrideEqualsAndHash(DiagnosticPosition pos, 4.8 + public void checkClassOverrideEqualsAndHashIfNeeded(DiagnosticPosition pos, 4.9 + ClassSymbol someClass) { 4.10 + /* At present, annotations cannot possibly have a method that is override 4.11 + * equivalent with Object.equals(Object) but in any case the condition is 4.12 + * fine for completeness. 4.13 + */ 4.14 + if (someClass == (ClassSymbol)syms.objectType.tsym || 4.15 + someClass.isInterface() || someClass.isEnum() || 4.16 + (someClass.flags() & ANNOTATION) != 0 || 4.17 + (someClass.flags() & ABSTRACT) != 0) return; 4.18 + //anonymous inner classes implementing interfaces need especial treatment 4.19 + if (someClass.isAnonymous()) { 4.20 + List<Type> interfaces = types.interfaces(someClass.type); 4.21 + if (interfaces != null && !interfaces.isEmpty() && 4.22 + interfaces.head.tsym == syms.comparatorType.tsym) return; 4.23 + } 4.24 + checkClassOverrideEqualsAndHash(pos, someClass); 4.25 + } 4.26 + 4.27 + private void checkClassOverrideEqualsAndHash(DiagnosticPosition pos, 4.28 ClassSymbol someClass) { 4.29 if (lint.isEnabled(LintCategory.OVERRIDES)) { 4.30 MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType 4.31 .tsym.members().lookup(names.equals).sym; 4.32 MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType 4.33 .tsym.members().lookup(names.hashCode).sym; 4.34 - 4.35 boolean overridesEquals = types.implementation(equalsAtObject, 4.36 someClass, false, equalsHasCodeFilter).owner == someClass; 4.37 boolean overridesHashCode = types.implementation(hashCodeAtObject, 4.38 @@ -1987,7 +2005,7 @@ 4.39 4.40 if (overridesEquals && !overridesHashCode) { 4.41 log.warning(LintCategory.OVERRIDES, pos, 4.42 - "override.equals.but.not.hashcode", someClass.fullname); 4.43 + "override.equals.but.not.hashcode", someClass); 4.44 } 4.45 } 4.46 }
5.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Wed Mar 06 15:33:39 2013 +0000 5.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Mar 07 10:04:28 2013 +0000 5.3 @@ -2077,7 +2077,7 @@ 5.4 {0}\n\ 5.5 overridden method does not throw {1} 5.6 5.7 -# 0: class name 5.8 +# 0: symbol 5.9 compiler.warn.override.equals.but.not.hashcode=\ 5.10 Class {0} overrides equals, but neither it nor any superclass overrides hashCode method 5.11
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/6563143/EqualsHashCodeWarningTest.java Thu Mar 07 10:04:28 2013 +0000 6.3 @@ -0,0 +1,71 @@ 6.4 +/* 6.5 + * @test /nodynamiccopyright/ 6.6 + * @bug 6563143 8008436 8009138 6.7 + * @summary javac should issue a warning for overriding equals without hashCode 6.8 + * @summary javac should not issue a warning for overriding equals without hasCode 6.9 + * @summary javac, equals-hashCode warning tuning 6.10 + * if hashCode has been overriden by a superclass 6.11 + * @compile/ref=EqualsHashCodeWarningTest.out -Xlint:overrides -XDrawDiagnostics EqualsHashCodeWarningTest.java 6.12 + */ 6.13 + 6.14 +import java.util.Comparator; 6.15 + 6.16 +public class EqualsHashCodeWarningTest { 6.17 + @Override 6.18 + public boolean equals(Object o) { 6.19 + return o == this; 6.20 + } 6.21 + 6.22 + @Override 6.23 + public int hashCode() { 6.24 + return 0; 6.25 + } 6.26 + 6.27 + public Comparator m() { 6.28 + return new Comparator() { 6.29 + @Override 6.30 + public boolean equals(Object o) {return true;} 6.31 + 6.32 + @Override 6.33 + public int compare(Object o1, Object o2) { 6.34 + return 0; 6.35 + } 6.36 + }; 6.37 + } 6.38 +} 6.39 + 6.40 +class SubClass extends EqualsHashCodeWarningTest { 6.41 + @Override 6.42 + public boolean equals(Object o) { 6.43 + return true; 6.44 + } 6.45 +} 6.46 + 6.47 +@SuppressWarnings("overrides") 6.48 +class DontWarnMe { 6.49 + @Override 6.50 + public boolean equals(Object o) { 6.51 + return true; 6.52 + } 6.53 +} 6.54 + 6.55 +class DoWarnMe { 6.56 + @Override 6.57 + public boolean equals(Object o) { 6.58 + return o == this; 6.59 + } 6.60 +} 6.61 + 6.62 +abstract class IamAbstractGetMeOutOfHere { 6.63 + public boolean equals(Object o){return true;} 6.64 +} 6.65 + 6.66 +interface I { 6.67 + public boolean equals(Object o); 6.68 +} 6.69 + 6.70 +enum E { 6.71 + A, B 6.72 +} 6.73 + 6.74 +@interface anno {}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/6563143/EqualsHashCodeWarningTest.out Thu Mar 07 10:04:28 2013 +0000 7.3 @@ -0,0 +1,2 @@ 7.4 +EqualsHashCodeWarningTest.java:52:1: compiler.warn.override.equals.but.not.hashcode: DoWarnMe 7.5 +1 warning
8.1 --- a/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.java Wed Mar 06 15:33:39 2013 +0000 8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 8.3 @@ -1,42 +0,0 @@ 8.4 -/* 8.5 - * @test /nodynamiccopyright/ 8.6 - * @bug 6563143 8008436 8.7 - * @summary javac should issue a warning for overriding equals without hashCode 8.8 - * @summary javac should not issue a warning for overriding equals without hasCode 8.9 - * if hashCode has been overriden by a superclass 8.10 - * @compile/ref=OverridesEqualsButNotHashCodeTest.out -Xlint:overrides -XDrawDiagnostics OverridesEqualsButNotHashCodeTest.java 8.11 - */ 8.12 - 8.13 -public class OverridesEqualsButNotHashCodeTest { 8.14 - @Override 8.15 - public boolean equals(Object o) { 8.16 - return o == this; 8.17 - } 8.18 - 8.19 - @Override 8.20 - public int hashCode() { 8.21 - return 0; 8.22 - } 8.23 -} 8.24 - 8.25 -class SubClass extends OverridesEqualsButNotHashCodeTest { 8.26 - @Override 8.27 - public boolean equals(Object o) { 8.28 - return o == this; 8.29 - } 8.30 -} 8.31 - 8.32 -@SuppressWarnings("overrides") 8.33 -class NoWarning { 8.34 - @Override 8.35 - public boolean equals(Object o) { 8.36 - return o == this; 8.37 - } 8.38 -} 8.39 - 8.40 -class DoWarnMe { 8.41 - @Override 8.42 - public boolean equals(Object o) { 8.43 - return o == this; 8.44 - } 8.45 -}
9.1 --- a/test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.out Wed Mar 06 15:33:39 2013 +0000 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,2 +0,0 @@ 9.4 -OverridesEqualsButNotHashCodeTest.java:37:1: compiler.warn.override.equals.but.not.hashcode: DoWarnMe 9.5 -1 warning