Repository: analysis-dev/diktat (kotlin)

Issue:
`CLASS_SHOULD_NOT_BE_ABSTRACT` breaks code when abstract class implements an interface
## Describe the bug
```kotlin
interface I {
    fun foo()
}

abstract class A : I  // diktat raises CLASS_SHOULD_NOT_BE_ABSTRACT, changes `abstract` to `open` and breaks compilation

class B : A() {
    override fun foo() {}
}
```

## Observed behavior
Diktat raises CLASS_SHOULD_NOT_BE_ABSTRACT, changes `abstract` to `open` and breaks compilation

## Environment information
* diktat version: 1.0.1

Pull request:
### What's done:
* Class can have `abstract` modifier if it implements interface, don't trigger on such cases

Patch:
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt
index d95aa0dbf3..feb43a14d1 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/AbstractClassesRule.kt
@@ -16,6 +16,7 @@ import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST
 import com.pinterest.ktlint.core.ast.ElementType.OPEN_KEYWORD
 import com.pinterest.ktlint.core.ast.ElementType.PROPERTY
 import com.pinterest.ktlint.core.ast.ElementType.SUPER_TYPE_CALL_ENTRY
+import com.pinterest.ktlint.core.ast.ElementType.SUPER_TYPE_ENTRY
 import com.pinterest.ktlint.core.ast.ElementType.SUPER_TYPE_LIST
 import org.jetbrains.kotlin.com.intellij.lang.ASTNode
 import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
@@ -35,6 +36,7 @@ class AbstractClassesRule(configRules: List<RulesConfig>) : DiktatRule(
 
             // If an abstract class extends another class, than that base class can be abstract too.
             // Then this class must have `abstract` modifier even if it doesn't have any abstract members.
+            // Class also can have `abstract` modifier if it implements interface
             if (node.hasAbstractModifier() && node.isNotSubclass()) {
                 handleAbstractClass(classBody, node)
             }
@@ -45,7 +47,7 @@ class AbstractClassesRule(configRules: List<RulesConfig>) : DiktatRule(
             getFirstChildWithType(MODIFIER_LIST)?.hasChildOfType(ABSTRACT_KEYWORD) ?: false
 
     private fun ASTNode.isNotSubclass(): Boolean = findChildByType(SUPER_TYPE_LIST)?.children()?.filter {
-        it.elementType == SUPER_TYPE_CALL_ENTRY
+        it.elementType == SUPER_TYPE_CALL_ENTRY || it.elementType == SUPER_TYPE_ENTRY
     }?.none() ?: true
 
     @Suppress("UnsafeCallOnNullableType")


Test patch:
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesWarnTest.kt
index d6e51203a6..56ba487987 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesWarnTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesWarnTest.kt
@@ -116,14 +116,13 @@ class AbstractClassesWarnTest : LintTestBase(::AbstractClassesRule) {
 
     @Test
     @Tag(CLASS_SHOULD_NOT_BE_ABSTRACT)
-    fun `should trigger on classes that implement interfaces`() {
+    fun `should not trigger on classes that implement interfaces`() {
         lintMethod(
             """
                 |abstract class Example: Base {
                 |    fun foo() {}
                 |}
             """.trimMargin(),
-            LintError(1, 30, ruleId, "[CLASS_SHOULD_NOT_BE_ABSTRACT] class should not be abstract, because it has no abstract functions: Example", true)
         )
     }
 }