8009138: javac, equals-hashCode warning tuning

Thu, 07 Mar 2013 10:04:28 +0000

author
vromero
date
Thu, 07 Mar 2013 10:04:28 +0000
changeset 1620
3806171b52d8
parent 1619
c98b3e96c726
child 1621
823fb9229724

8009138: javac, equals-hashCode warning tuning
Reviewed-by: mcimadamore

src/share/classes/com/sun/tools/javac/code/Symbol.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Symtab.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Check.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/resources/compiler.properties file | annotate | diff | comparison | revisions
test/tools/javac/6563143/EqualsHashCodeWarningTest.java file | annotate | diff | comparison | revisions
test/tools/javac/6563143/EqualsHashCodeWarningTest.out file | annotate | diff | comparison | revisions
test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.java file | annotate | diff | comparison | revisions
test/tools/javac/6563143/OverridesEqualsButNotHashCodeTest.out file | annotate | diff | comparison | revisions
     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

mercurial