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 5d4e526a549..02ddc043757 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,9 @@ 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 ba65e69f96c..9710ae617e1 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,8 +86,7 @@ class UnnecessaryAbstractClassSpec(val env: KotlinCoreEnvironment) { } abstract class B : A() """ - val findings = subject.compileAndLintWithContext(env, code) - assertFindingMessage(findings, message) + assertThat(subject.compileAndLintWithContext(env, code)).isEmpty() } }