From 57072f6fac3be815d791b8bf47653c5f066859f7 Mon Sep 17 00:00:00 2001 From: Gouri Panda Date: Wed, 29 Jun 2022 12:29:21 +0530 Subject: [PATCH] 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 326a356e fix return count rule violation --- .../detekt/rules/style/UnnecessaryAbstractClass.kt | 9 ++++++++- .../detekt/rules/style/UnnecessaryAbstractClassSpec.kt | 10 ++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClass.kt b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClass.kt index 5d4e526a5497..f5c0799efa4d 100644 --- a/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClass.kt +++ b/detekt-rules-style/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClass.kt @@ -21,6 +21,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 @@ -79,7 +81,7 @@ class UnnecessaryAbstractClass(config: Config = Config.empty) : Rule(config) { super.visitClass(klass) } - @Suppress("ComplexMethod") + @Suppress("ComplexMethod", "ReturnCount") private fun KtClass.check() { val nameIdentifier = this.nameIdentifier ?: return if (annotationExcluder.shouldExclude(annotationEntries) || isInterface() || !isAbstract()) return @@ -98,6 +100,8 @@ class UnnecessaryAbstractClass(config: Config = Config.empty) : Rule(config) { report(CodeSmell(issue, Entity.from(nameIdentifier), noConcreteMember)) } } + + hasInheritedMember(true) && !isParentInterface() -> return !hasConstructorParameter() -> report(CodeSmell(issue, Entity.from(nameIdentifier), noConcreteMember)) else -> @@ -122,4 +126,7 @@ class UnnecessaryAbstractClass(config: Config = Config.empty) : Rule(config) { } } } + private fun KtClass.isParentInterface() = + (bindingContext[BindingContext.CLASS, this]?.unsubstitutedMemberScope as? LazyClassMemberScope) + ?.supertypes?.firstOrNull()?.isInterface() == true } diff --git a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt index ba65e69f96ce..9af41be3366e 100644 --- a/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt +++ b/detekt-rules-style/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/style/UnnecessaryAbstractClassSpec.kt @@ -86,6 +86,16 @@ class UnnecessaryAbstractClassSpec(val env: KotlinCoreEnvironment) { } abstract class B : A() """ + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() + } + + @Test + fun `that inherits from another empty abstract class`() { + val code = """ + @Deprecated("We don't care about this first class") + abstract class A + abstract class B : A() + """ val findings = subject.compileAndLintWithContext(env, code) assertFindingMessage(findings, message) }