Skip to content

Commit

Permalink
Removed UnnecessaryAbstractClass if it inherits from a abstract class (
Browse files Browse the repository at this point in the history
…#5009)

* Removed UnnecessaryAbstractClass if it inherits from an interface or abstract class that has concrete members

Removed deprecated annotations

Revert "Removed deprecated annotations"

This reverts commit 326a356

fix return count rule violation

* Removed UnnecessaryAbstractClass if it inherits from an interface or abstract class that has concrete members

Removed deprecated annotations

Revert "Removed deprecated annotations"

This reverts commit 326a356

fix return count rule violation

* Handle corner case of multiple inheritance in UnnecessaryAbstractClass rule

Co-authored-by: Amit Dash <amitdash291@gmail.com>
  • Loading branch information
gouri-panda and amitdash291 committed Jul 10, 2022
1 parent fe98c45 commit 1b330e9
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
Expand Up @@ -22,6 +22,8 @@ import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.isAbstract
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassMemberScope
import org.jetbrains.kotlin.types.typeUtil.isInterface

/**
* This rule inspects `abstract` classes. In case an `abstract class` does not have any concrete members it should be
Expand Down Expand Up @@ -86,6 +88,7 @@ class UnnecessaryAbstractClass(config: Config = Config.empty) : Rule(config) {
val members = members()
when {
members.isNotEmpty() -> checkMembers(members, nameIdentifier)
hasInheritedMember(true) && isAnyParentAbstract() -> return
!hasConstructorParameter() ->
report(CodeSmell(issue, Entity.from(nameIdentifier), noConcreteMember))
else ->
Expand Down Expand Up @@ -125,4 +128,9 @@ class UnnecessaryAbstractClass(config: Config = Config.empty) : Rule(config) {
}
}
}

private fun KtClass.isAnyParentAbstract() =
(bindingContext[BindingContext.CLASS, this]?.unsubstitutedMemberScope as? LazyClassMemberScope)
?.supertypes
?.all { it.isInterface() } == false
}
Expand Up @@ -86,8 +86,37 @@ class UnnecessaryAbstractClassSpec(val env: KotlinCoreEnvironment) {
}
abstract class B : A()
"""
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}

@Test
fun `does not report abstract class that inherits from an abstract class and an interface 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: A(), I
"""
val findings = subject.compileAndLintWithContext(env, code)
assertFindingMessage(findings, message)
assertThat(findings).isEmpty()
}

@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()
}
}

Expand Down

0 comments on commit 1b330e9

Please sign in to comment.