Removed UnnecessaryAbstractClass if it inherits from a abstract class#5009
Conversation
| """ | ||
| val findings = subject.compileAndLintWithContext(env, code) | ||
| assertFindingMessage(findings, message) | ||
| assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() |
There was a problem hiding this comment.
This test shouldn't change, right?
There was a problem hiding this comment.
@BraisGabin If we don't change it, the tests will fail. I don't understand your question.
There was a problem hiding this comment.
But this one was right. An abstract class that only extends an interface is an unnecessary abstract class. The only one that should change is the case where an abstract class extend another abstract class because there you can't use an interface. (maybe I'm missing something here)
There was a problem hiding this comment.
Should I revert that?
There was a problem hiding this comment.
Yes. This test shouldn't change.
schalkms
left a comment
There was a problem hiding this comment.
Thanks for the fix - appreciate it!
|
@gouri-panda please try to rebase this branch and fix the following rule violation. Then this PR is good to go. 👍
|
| report(CodeSmell(issue, Entity.from(nameIdentifier), noConcreteMember)) | ||
| } | ||
| } | ||
| hasInheritedMember(true) -> return |
There was a problem hiding this comment.
The following enhancement to this logic will ensure the rule still fails for interface super types (as discussed in @BraisGabin's comment):
hasInheritedMember(true) && !isParentInterface() -> return
private fun KtClass.isParentInterface() =
(bindingContext[BindingContext.CLASS, this]?.unsubstitutedMemberScope as? LazyClassMemberScope)
?.supertypes?.firstOrNull()?.isInterface() == true
There was a problem hiding this comment.
@amitdash291 Thanks for advice and code :)
There was a problem hiding this comment.
I think there's a corner case to test here. What if the class implements an interface and inherits from an abstract class in that order. For eg the following may fail the rule whereas it's expected to pass:
interface I
abstract class A
// some abstract fields here
abstract class B: I, A()
There was a problem hiding this comment.
Is that even valid Kotlin code? Shouldn't the class be defined the first one? I can't check right now. Anyway, a test extending both, a class and an interface seems like a really good case to have a test. @guori-panda, can you add such test?
There was a problem hiding this comment.
@BraisGabin yes interestingly this is valid Kotlin code, given below is the test case (that compiles):
@Test
fun `does not report abstract class that inherits from an interface and an abstract class in that order`() {
val code = """
interface I
@Deprecated("We don't care about this first class")
abstract class A {
abstract val i: Int
}
abstract class B: I, A()
"""
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}
…abstract class that has concrete members Removed deprecated annotations Revert "Removed deprecated annotations" This reverts commit 326a356 fix return count rule violation
amitd291
left a comment
There was a problem hiding this comment.
Refer reply to the code suggestion earlier.
|
@gouri-panda sorry for all the changes. Can you fix the conflicts and add the tests that @amitdash291 point out here: #5009 (comment) ? After that (and if that test passes) I think that this is ready to merge. |
|
@BraisGabin @amitdash291 Sure :) |
…abstract class that has concrete members Removed deprecated annotations Revert "Removed deprecated annotations" This reverts commit 326a356 fix return count rule violation
# Conflicts: # detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt
| abstract class A { | ||
| abstract val i: Int | ||
| } | ||
| abstract class B: A(), I |
There was a problem hiding this comment.
| abstract class B: A(), I | |
| abstract class B: A(), I | |
| abstract class C: I, A() |
We should check both cases.
There was a problem hiding this comment.
Sure! Let me add another test case as well!
There was a problem hiding this comment.
@gouri-panda I have an idea to solve this in a generic manner. If you're okay I can raise a PR on your fork branch gouri-panda:fix-4753?
There was a problem hiding this comment.
I was thinking if we check one of the parent is abstract, then we can return. But go for it :)
There was a problem hiding this comment.
@gouri-panda
I have pushed my changes as a PR to your fork's branch here
In summary I have checked if not all the parents are interfaces, which is equivalent of the fact that at least one parent is abstract.
Please refer to this commit (there are a few other merge commits)
Handle corner case of multiple inheritance in UnnecessaryAbstractClass rule
|
Thanks for the fix @gouri-panda and @amitdash291 |
closes: #4753
Removed UnnecessaryAbstractClass if it inherits from abstract class an interface or that has concrete members.