8008436: javac should not issue a warning for overriding equals without hasCode if hashCode has been overriden by a superclass
Reviewed-by: jjg, mcimadamore
This commit is contained in:
parent
63fe735683
commit
9f2721bfb1
@ -1305,7 +1305,7 @@ public abstract class Symbol implements Element {
|
|||||||
return implementation(origin, types, checkResult, implementation_filter);
|
return implementation(origin, types, checkResult, implementation_filter);
|
||||||
}
|
}
|
||||||
// where
|
// where
|
||||||
private static final Filter<Symbol> implementation_filter = new Filter<Symbol>() {
|
public static final Filter<Symbol> implementation_filter = new Filter<Symbol>() {
|
||||||
public boolean accepts(Symbol s) {
|
public boolean accepts(Symbol s) {
|
||||||
return s.kind == Kinds.MTH &&
|
return s.kind == Kinds.MTH &&
|
||||||
(s.flags() & SYNTHETIC) == 0;
|
(s.flags() & SYNTHETIC) == 0;
|
||||||
|
@ -3992,7 +3992,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
attribClassBody(env, c);
|
attribClassBody(env, c);
|
||||||
|
|
||||||
chk.checkDeprecatedAnnotation(env.tree.pos(), c);
|
chk.checkDeprecatedAnnotation(env.tree.pos(), c);
|
||||||
chk.checkClassOverrideEqualsAndHash(c);
|
chk.checkClassOverrideEqualsAndHash(env.tree.pos(), c);
|
||||||
} finally {
|
} finally {
|
||||||
env.info.returnResult = prevReturnRes;
|
env.info.returnResult = prevReturnRes;
|
||||||
log.useSource(prev);
|
log.useSource(prev);
|
||||||
|
@ -1964,28 +1964,29 @@ public class Check {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkClassOverrideEqualsAndHash(ClassSymbol someClass) {
|
private Filter<Symbol> equalsHasCodeFilter = new Filter<Symbol>() {
|
||||||
|
public boolean accepts(Symbol s) {
|
||||||
|
return MethodSymbol.implementation_filter.accepts(s) &&
|
||||||
|
(s.flags() & BAD_OVERRIDE) == 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void checkClassOverrideEqualsAndHash(DiagnosticPosition pos,
|
||||||
|
ClassSymbol someClass) {
|
||||||
if (lint.isEnabled(LintCategory.OVERRIDES)) {
|
if (lint.isEnabled(LintCategory.OVERRIDES)) {
|
||||||
boolean hasEquals = false;
|
MethodSymbol equalsAtObject = (MethodSymbol)syms.objectType
|
||||||
boolean hasHashCode = false;
|
.tsym.members().lookup(names.equals).sym;
|
||||||
|
MethodSymbol hashCodeAtObject = (MethodSymbol)syms.objectType
|
||||||
|
.tsym.members().lookup(names.hashCode).sym;
|
||||||
|
|
||||||
Scope.Entry equalsAtObject = syms.objectType.tsym.members().lookup(names.equals);
|
boolean overridesEquals = types.implementation(equalsAtObject,
|
||||||
Scope.Entry hashCodeAtObject = syms.objectType.tsym.members().lookup(names.hashCode);
|
someClass, false, equalsHasCodeFilter).owner == someClass;
|
||||||
for (Symbol s: someClass.members().getElements(new Filter<Symbol>() {
|
boolean overridesHashCode = types.implementation(hashCodeAtObject,
|
||||||
public boolean accepts(Symbol s) {
|
someClass, false, equalsHasCodeFilter) != hashCodeAtObject;
|
||||||
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) &&
|
if (overridesEquals && !overridesHashCode) {
|
||||||
m.overrides(hashCodeAtObject.sym, someClass, types, false);
|
log.warning(LintCategory.OVERRIDES, pos,
|
||||||
}
|
|
||||||
if (hasEquals && !hasHashCode) {
|
|
||||||
log.warning(LintCategory.OVERRIDES, (DiagnosticPosition) null,
|
|
||||||
"override.equals.but.not.hashcode", someClass.fullname);
|
"override.equals.but.not.hashcode", someClass.fullname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2071,8 +2071,7 @@ compiler.warn.override.unchecked.thrown=\
|
|||||||
|
|
||||||
# 0: class name
|
# 0: class name
|
||||||
compiler.warn.override.equals.but.not.hashcode=\
|
compiler.warn.override.equals.but.not.hashcode=\
|
||||||
Class {0}\n\
|
Class {0} overrides equals, but neither it nor any superclass overrides hashCode method
|
||||||
overrides method equals but does not overrides method hashCode from Object
|
|
||||||
|
|
||||||
## The following are all possible strings for the first argument ({0}) of the
|
## The following are all possible strings for the first argument ({0}) of the
|
||||||
## above strings.
|
## above strings.
|
||||||
|
@ -1,22 +1,42 @@
|
|||||||
/*
|
/*
|
||||||
* @test /nodynamiccopyright/
|
* @test /nodynamiccopyright/
|
||||||
* @bug 6563143
|
* @bug 6563143 8008436
|
||||||
* @summary javac should issue a warning for overriding equals without hashCode
|
* @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
|
* @compile/ref=OverridesEqualsButNotHashCodeTest.out -Xlint:overrides -XDrawDiagnostics OverridesEqualsButNotHashCodeTest.java
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@SuppressWarnings("overrides")
|
|
||||||
public class OverridesEqualsButNotHashCodeTest {
|
public class OverridesEqualsButNotHashCodeTest {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return o == this;
|
return o == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Other {
|
class SubClass extends OverridesEqualsButNotHashCodeTest {
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return o == this;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
- compiler.warn.override.equals.but.not.hashcode: Other
|
OverridesEqualsButNotHashCodeTest.java:37:1: compiler.warn.override.equals.but.not.hashcode: DoWarnMe
|
||||||
1 warning
|
1 warning
|
||||||
|
Loading…
x
Reference in New Issue
Block a user