Sealed sub-class -> object: handle equals, suggest "add equals"

Before this commit, sealed sub-class without state was considered
a style issue.
After this commit, sealed sub-class without state AND custom equals
is considered a probable bug,
because comparison of its instances is very fragile.
Alternative fix (generate equals & hashCode by identity) is added.
This commit is contained in:
Mikhail Glukhikh
2018-06-13 18:05:46 +03:00
parent ecd2709a11
commit 9ef89447b3
27 changed files with 222 additions and 51 deletions
@@ -0,0 +1,18 @@
// PROBLEM: none
abstract class Base {
open val prop: Int
get() = 13
override fun equals(other: Any?): Boolean {
if (other !is Base) return false
return prop == other.prop
}
}
sealed class SC : Base() {
<caret>class U : SC()
override val prop: Int
get() = 42
}
@@ -1,3 +1,5 @@
// FIX: Convert sealed sub-class to object
sealed class Sealed
private <caret>class SubSealed : Sealed()
@@ -1,3 +1,5 @@
// FIX: Convert sealed sub-class to object
sealed class Sealed
private object SubSealed : Sealed()
@@ -1,3 +1,5 @@
// FIX: Convert sealed sub-class to object
sealed class Sealed
<caret>class SubSealed() : Sealed()
@@ -1,3 +1,5 @@
// FIX: Convert sealed sub-class to object
sealed class Sealed
object SubSealed : Sealed()
@@ -1,3 +1,5 @@
// FIX: Convert sealed sub-class to object
sealed class Sealed
<caret>class SubSealed : Sealed()
@@ -1,3 +1,5 @@
// FIX: Convert sealed sub-class to object
sealed class Sealed
object SubSealed : Sealed()
@@ -1,3 +1,4 @@
// FIX: Convert sealed sub-class to object
// WITH_RUNTIME
abstract class Base {
@@ -1,3 +1,4 @@
// FIX: Convert sealed sub-class to object
// WITH_RUNTIME
abstract class Base {
@@ -0,0 +1,13 @@
// FIX: Generate equals & hashCode by identity
abstract class Base {
open val prop: Int
get() = 13
}
sealed class SC : Base() {
<caret>class U : SC()
override val prop: Int
get() = 42
}
@@ -0,0 +1,21 @@
// FIX: Generate equals & hashCode by identity
abstract class Base {
open val prop: Int
get() = 13
}
sealed class SC : Base() {
class U : SC() {
override fun equals(other: Any?): Boolean {
return this === other
}
override fun hashCode(): Int {
return System.identityHashCode(this)
}
}
override val prop: Int
get() = 42
}
@@ -0,0 +1,9 @@
// PROBLEM: none
sealed class SC {
<caret>class U : SC() {
override fun equals(other: Any?): Boolean {
return this === other
}
}
}
@@ -0,0 +1,12 @@
// PROBLEM: none
sealed class SC {
<caret>class U : SC()
fun foo() = 42
override fun equals(other: Any?): Boolean {
if (other !is SC) return false
return foo() == other.foo()
}
}