From 9ad427fcbaea8ca0afa1c4bfb099239762faa20c Mon Sep 17 00:00:00 2001 From: soWhoAmI Date: Mon, 26 Oct 2020 13:57:35 +0300 Subject: [PATCH 1/6] feature/rule-6.1.6-abstract-classes(#442) ### What's done: * Rule logic made * Added fix and warn tests --- diktat-analysis.yml | 4 ++ .../src/main/kotlin/generated/WarningNames.kt | 2 + .../cqfn/diktat/ruleset/constants/Warnings.kt | 1 + .../ruleset/rules/DiktatRuleSetProvider.kt | 2 + .../rules/classes/AbstractClassesRule.kt | 57 +++++++++++++++++++ .../main/resources/diktat-analysis-huawei.yml | 4 ++ .../src/main/resources/diktat-analysis.yml | 4 ++ .../chapter6/AbstractClassesFixTest.kt | 16 ++++++ .../chapter6/AbstractClassesWarnTest.kt | 42 ++++++++++++++ .../ShouldRemoveAbstractKeywordExpected.kt | 13 +++++ .../ShouldRemoveAbstractKeywordTest.kt | 13 +++++ info/available-rules.md | 3 +- 12 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt create mode 100644 diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt create mode 100644 diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesWarnTest.kt create mode 100644 diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt create mode 100644 diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt diff --git a/diktat-analysis.yml b/diktat-analysis.yml index b6e7b717df..5bd9ce5ee7 100644 --- a/diktat-analysis.yml +++ b/diktat-analysis.yml @@ -331,5 +331,9 @@ configuration: {} # Checks that never use the name of a variable in the custom getter or setter - name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR + enabled: true + configuration: {} +# Checks that there are abstract functions in abstract class +- name: CLASS_SHOULD_NOT_BE_ABSTRACT enabled: true configuration: {} \ No newline at end of file diff --git a/diktat-rules/src/main/kotlin/generated/WarningNames.kt b/diktat-rules/src/main/kotlin/generated/WarningNames.kt index 1ca16e251a..7b8c4475b5 100644 --- a/diktat-rules/src/main/kotlin/generated/WarningNames.kt +++ b/diktat-rules/src/main/kotlin/generated/WarningNames.kt @@ -196,4 +196,6 @@ public object WarningNames { public const val WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR: String = "WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR" + + public const val CLASS_SHOULD_NOT_BE_ABSTRACT: String = "CLASS_SHOULD_NOT_BE_ABSTRACT" } diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt index 22ca2beaea..b6e73e9eb0 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt @@ -119,6 +119,7 @@ enum class Warnings(private val canBeAutoCorrected: Boolean, private val warn: S // ======== chapter 6 ======== USE_DATA_CLASS(false, "this class can be converted to a data class"), WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR(false, "Use `field` keyword instead of property name inside property accessors"), + CLASS_SHOULD_NOT_BE_ABSTRACT(true, "class should not be abstract"), ; /** diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt index 7aef04bfb9..25cc20cb2e 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/DiktatRuleSetProvider.kt @@ -7,6 +7,7 @@ import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.common.config.rules.RulesConfigReader import org.cqfn.diktat.ruleset.constants.Warnings import org.cqfn.diktat.ruleset.rules.calculations.AccurateCalculationsRule +import org.cqfn.diktat.ruleset.rules.classes.AbstractClassesRule import org.cqfn.diktat.ruleset.rules.classes.DataClassesRule import org.cqfn.diktat.ruleset.rules.comments.CommentsRule import org.cqfn.diktat.ruleset.rules.comments.HeaderCommentRule @@ -63,6 +64,7 @@ class DiktatRuleSetProvider(private val diktatConfigFile: String = "diktat-analy ::SmartCastRule, ::PropertyAccessorFields, ::EnumsSeparated, + ::AbstractClassesRule, ::VariableGenericTypeDeclarationRule, ::SingleLineStatementsRule, ::CommentsFormatting, diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt new file mode 100644 index 0000000000..16a12ccf23 --- /dev/null +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt @@ -0,0 +1,57 @@ +package org.cqfn.diktat.ruleset.rules.classes + +import com.pinterest.ktlint.core.Rule +import com.pinterest.ktlint.core.ast.ElementType.ABSTRACT_KEYWORD +import com.pinterest.ktlint.core.ast.ElementType.CLASS +import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY +import com.pinterest.ktlint.core.ast.ElementType.FUN +import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER +import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST +import com.pinterest.ktlint.core.ast.isWhiteSpace +import org.cqfn.diktat.common.config.rules.RulesConfig +import org.cqfn.diktat.ruleset.constants.Warnings.CLASS_SHOULD_NOT_BE_ABSTRACT +import org.cqfn.diktat.ruleset.utils.getAllChildrenWithType +import org.cqfn.diktat.ruleset.utils.getFirstChildWithType +import org.cqfn.diktat.ruleset.utils.hasChildOfType +import org.jetbrains.kotlin.com.intellij.lang.ASTNode + +/** + * Checks if abstract class has any abstract method. If not, warns that class should not be abstract + */ +class AbstractClassesRule(private val configRule: List) : Rule("abstract-classes") { + private lateinit var emitWarn: ((offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) + private var isFixMode: Boolean = false + + override fun visit(node: ASTNode, + autoCorrect: Boolean, + emit: (offset: Int, errorMessage: String, canBeAutoCorrected: Boolean) -> Unit) { + emitWarn = emit + isFixMode = autoCorrect + + if (node.elementType == CLASS) { + val classBody = node.getFirstChildWithType(CLASS_BODY) ?: return + + if (checkAbstractModifier(node)) { + handleAbstractClass(classBody, node) + } + } + } + + private fun checkAbstractModifier(node: ASTNode): Boolean = + node.getFirstChildWithType(MODIFIER_LIST)?.hasChildOfType(ABSTRACT_KEYWORD) ?: false + + private fun handleAbstractClass(node: ASTNode, classNode: ASTNode) { + val functions = node.getAllChildrenWithType(FUN) + + val identifier = classNode.getFirstChildWithType(IDENTIFIER)!!.text + + if (functions.isNotEmpty() && functions.none { checkAbstractModifier(it) }) { + CLASS_SHOULD_NOT_BE_ABSTRACT.warnAndFix(configRule, emitWarn, isFixMode, identifier, node.startOffset, node) { + classNode.removeChild(classNode.getFirstChildWithType(MODIFIER_LIST)!!) + if (classNode.firstChildNode.isWhiteSpace()) { + classNode.removeChild(classNode.firstChildNode) + } + } + } + } +} diff --git a/diktat-rules/src/main/resources/diktat-analysis-huawei.yml b/diktat-rules/src/main/resources/diktat-analysis-huawei.yml index 19a9c80ed5..de907e9834 100644 --- a/diktat-rules/src/main/resources/diktat-analysis-huawei.yml +++ b/diktat-rules/src/main/resources/diktat-analysis-huawei.yml @@ -330,5 +330,9 @@ configuration: {} # Checks that never use the name of a variable in the custom getter or setter - name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR + enabled: true + configuration: {} +# Checks that there are abstract functions in abstract class +- name: CLASS_SHOULD_NOT_BE_ABSTRACT enabled: true configuration: {} \ No newline at end of file diff --git a/diktat-rules/src/main/resources/diktat-analysis.yml b/diktat-rules/src/main/resources/diktat-analysis.yml index b314f395c2..639bcdd582 100644 --- a/diktat-rules/src/main/resources/diktat-analysis.yml +++ b/diktat-rules/src/main/resources/diktat-analysis.yml @@ -332,5 +332,9 @@ configuration: {} # Checks that never use the name of a variable in the custom getter or setter - name: WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR + enabled: true + configuration: {} +# Checks that there are abstract functions in abstract class +- name: CLASS_SHOULD_NOT_BE_ABSTRACT enabled: true configuration: {} \ No newline at end of file diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt new file mode 100644 index 0000000000..cec86a5504 --- /dev/null +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt @@ -0,0 +1,16 @@ +package org.cqfn.diktat.ruleset.chapter6 + +import generated.WarningNames +import generated.WarningNames.CLASS_SHOULD_NOT_BE_ABSTRACT +import org.cqfn.diktat.util.FixTestBase +import org.cqfn.diktat.ruleset.rules.classes.AbstractClassesRule +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.Test + +class AbstractClassesFixTest : FixTestBase("test/paragraph6/abstract_classes", ::AbstractClassesRule) { + @Test + @Tag(CLASS_SHOULD_NOT_BE_ABSTRACT) + fun `fix abstract class`() { + fixAndCompare("ShouldRemoveAbstractKeywordExpected.kt", "ShouldRemoveAbstractKeywordTest.kt") + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..80673d1437 --- /dev/null +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesWarnTest.kt @@ -0,0 +1,42 @@ +package org.cqfn.diktat.ruleset.chapter6 + +import com.pinterest.ktlint.core.LintError +import generated.WarningNames.CLASS_SHOULD_NOT_BE_ABSTRACT +import org.cqfn.diktat.ruleset.constants.Warnings +import org.cqfn.diktat.ruleset.rules.DIKTAT_RULE_SET_ID +import org.cqfn.diktat.ruleset.rules.classes.AbstractClassesRule +import org.cqfn.diktat.util.LintTestBase +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.Test + +class AbstractClassesWarnTest : LintTestBase(::AbstractClassesRule) { + private val ruleId = "$DIKTAT_RULE_SET_ID:abstract-classes" + + @Test + @Tag(CLASS_SHOULD_NOT_BE_ABSTRACT) + fun `should not remove abstract`() { + lintMethod( + """ + |abstract class Some(val a: Int = 5) { + | abstract fun func() {} + | + | fun another() {} + |} + """.trimMargin() + ) + } + + + @Test + @Tag(CLASS_SHOULD_NOT_BE_ABSTRACT) + fun `should remove abstract`() { + lintMethod( + """ + |abstract class Some(val a: Int = 5) { + | fun func() {} + |} + """.trimMargin(), + LintError(1, 37, ruleId, "${Warnings.CLASS_SHOULD_NOT_BE_ABSTRACT.warnText()} Some", true) + ) + } +} diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt new file mode 100644 index 0000000000..acda4406c6 --- /dev/null +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt @@ -0,0 +1,13 @@ +package test.paragraph6.abstract_classes + +class Some() { + fun some(){} + + fun another(){} +} + +abstract class Another { + abstract fun absFunc() + + fun someFunc(){} +} diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt new file mode 100644 index 0000000000..676c12b570 --- /dev/null +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt @@ -0,0 +1,13 @@ +package test.paragraph6.abstract_classes + +abstract class Some() { + fun some(){} + + fun another(){} +} + +abstract class Another { + abstract fun absFunc() + + fun someFunc(){} +} \ No newline at end of file diff --git a/info/available-rules.md b/info/available-rules.md index 0ce1e8cdcd..64d0f9a380 100644 --- a/info/available-rules.md +++ b/info/available-rules.md @@ -92,4 +92,5 @@ | 5 | 5.2.2 | TOO_MANY_PARAMETERS | Check: if function contains more parameters than allowed | no | maxParameterListSize | | 5 | 5.2.3 | WRONG_OVERLOADING_FUNCTION_ARGUMENTS | Check: function has overloading instead use default arguments | no | -| | 6 | 6.1.2 | USE_DATA_CLASS | Check: if class can be made as data class | no | - | yes | -| 6 | 6.1.9 | WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR | Check: used the name of a variable in the custom getter or setter | no | - | \ No newline at end of file +| 6 | 6.1.9 | WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR | Check: used the name of a variable in the custom getter or setter | no | - | +| 6 | 6.1.6 | CLASS_SHOULD_NOT_BE_ABSTRACT | Checks: if abstract class has any abstract method. If not, warns that class should not be abstract
Fix: deletes abstract modifier | yes | - | - | \ No newline at end of file From b58fa8e61779ebff3cb5361e3d55eb27121d4a91 Mon Sep 17 00:00:00 2001 From: soWhoAmI Date: Mon, 26 Oct 2020 14:05:15 +0300 Subject: [PATCH 2/6] feature/rule-6.1.6-abstract-classes(#442) ### What's done: * Fixed bugs --- .../cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt | 1 + .../org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt index 16a12ccf23..6969e7e2ff 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt @@ -40,6 +40,7 @@ class AbstractClassesRule(private val configRule: List) : Rule("abs private fun checkAbstractModifier(node: ASTNode): Boolean = node.getFirstChildWithType(MODIFIER_LIST)?.hasChildOfType(ABSTRACT_KEYWORD) ?: false + @Suppress("UnsafeCallOnNullableType") private fun handleAbstractClass(node: ASTNode, classNode: ASTNode) { val functions = node.getAllChildrenWithType(FUN) diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt index cec86a5504..9c0a40fa4d 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/AbstractClassesFixTest.kt @@ -13,4 +13,4 @@ class AbstractClassesFixTest : FixTestBase("test/paragraph6/abstract_classes", : fun `fix abstract class`() { fixAndCompare("ShouldRemoveAbstractKeywordExpected.kt", "ShouldRemoveAbstractKeywordTest.kt") } -} \ No newline at end of file +} From 61fae19e422a7413acd24b1f8d0266d2960572ef Mon Sep 17 00:00:00 2001 From: soWhoAmI Date: Mon, 26 Oct 2020 15:51:38 +0300 Subject: [PATCH 3/6] feature/rule-6.1.6-abstract-classes(#442) ### What's done: * Fixed bugs --- .../cqfn/diktat/ruleset/constants/Warnings.kt | 2 +- .../rules/classes/AbstractClassesRule.kt | 20 +++++++++++++------ .../chapter6/AbstractClassesWarnTest.kt | 17 ++++++++++++++++ .../ShouldRemoveAbstractKeywordExpected.kt | 4 ++++ .../ShouldRemoveAbstractKeywordTest.kt | 4 ++++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt index b6e73e9eb0..2fded88830 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/constants/Warnings.kt @@ -119,7 +119,7 @@ enum class Warnings(private val canBeAutoCorrected: Boolean, private val warn: S // ======== chapter 6 ======== USE_DATA_CLASS(false, "this class can be converted to a data class"), WRONG_NAME_OF_VARIABLE_INSIDE_ACCESSOR(false, "Use `field` keyword instead of property name inside property accessors"), - CLASS_SHOULD_NOT_BE_ABSTRACT(true, "class should not be abstract"), + CLASS_SHOULD_NOT_BE_ABSTRACT(true, "class should not be abstract, because it has no abstract functions"), ; /** diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt index 6969e7e2ff..b49403ea50 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt @@ -31,13 +31,13 @@ class AbstractClassesRule(private val configRule: List) : Rule("abs if (node.elementType == CLASS) { val classBody = node.getFirstChildWithType(CLASS_BODY) ?: return - if (checkAbstractModifier(node)) { + if (hasAbstractModifier(node)) { handleAbstractClass(classBody, node) } } } - private fun checkAbstractModifier(node: ASTNode): Boolean = + private fun hasAbstractModifier(node: ASTNode): Boolean = node.getFirstChildWithType(MODIFIER_LIST)?.hasChildOfType(ABSTRACT_KEYWORD) ?: false @Suppress("UnsafeCallOnNullableType") @@ -46,11 +46,19 @@ class AbstractClassesRule(private val configRule: List) : Rule("abs val identifier = classNode.getFirstChildWithType(IDENTIFIER)!!.text - if (functions.isNotEmpty() && functions.none { checkAbstractModifier(it) }) { + if (functions.isNotEmpty() && functions.none { hasAbstractModifier(it) }) { CLASS_SHOULD_NOT_BE_ABSTRACT.warnAndFix(configRule, emitWarn, isFixMode, identifier, node.startOffset, node) { - classNode.removeChild(classNode.getFirstChildWithType(MODIFIER_LIST)!!) - if (classNode.firstChildNode.isWhiteSpace()) { - classNode.removeChild(classNode.firstChildNode) + val modList = classNode.getFirstChildWithType(MODIFIER_LIST)!! + if (modList.getChildren(null).size > 1) { + modList.removeChild(modList.getFirstChildWithType(ABSTRACT_KEYWORD)!!) + if (modList.firstChildNode.isWhiteSpace()) { + modList.removeChild(modList.firstChildNode) + } + } else { + classNode.removeChild(modList) + if (classNode.firstChildNode.isWhiteSpace()) { + classNode.removeChild(classNode.firstChildNode) + } } } } 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 80673d1437..c66a636ce7 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 @@ -39,4 +39,21 @@ class AbstractClassesWarnTest : LintTestBase(::AbstractClassesRule) { LintError(1, 37, ruleId, "${Warnings.CLASS_SHOULD_NOT_BE_ABSTRACT.warnText()} Some", true) ) } + + @Test + @Tag(CLASS_SHOULD_NOT_BE_ABSTRACT) + fun `should remove abstract with inner`() { + lintMethod( + """ + |class Some(val a: Int = 5) { + | fun func() {} + | + | inner abstract class Inner { + | fun another() + | } + |} + """.trimMargin(), + LintError(4, 32, ruleId, "${Warnings.CLASS_SHOULD_NOT_BE_ABSTRACT.warnText()} Inner", true) + ) + } } diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt index acda4406c6..913a756740 100644 --- a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt @@ -4,6 +4,10 @@ class Some() { fun some(){} fun another(){} + + inner class Any { + fun func(){} + } } abstract class Another { diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt index 676c12b570..69a3cd4cb5 100644 --- a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt @@ -4,6 +4,10 @@ abstract class Some() { fun some(){} fun another(){} + + abstract inner class Any { + fun func(){} + } } abstract class Another { From 4c5ad8a3ce18c6d5384a99ab9c2c0f9979893001 Mon Sep 17 00:00:00 2001 From: soWhoAmI Date: Mon, 26 Oct 2020 16:31:05 +0300 Subject: [PATCH 4/6] feature/rule-6.1.6-abstract-classes(#442) ### What's done: * Fixed bugs --- .../diktat/ruleset/rules/classes/AbstractClassesRule.kt | 7 +++++-- .../ShouldRemoveAbstractKeywordExpected.kt | 4 ++++ .../abstract_classes/ShouldRemoveAbstractKeywordTest.kt | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt index b49403ea50..4fb70f6c6f 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt @@ -7,6 +7,7 @@ import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.FUN import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST +import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE import com.pinterest.ktlint.core.ast.isWhiteSpace import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.ruleset.constants.Warnings.CLASS_SHOULD_NOT_BE_ABSTRACT @@ -50,9 +51,11 @@ class AbstractClassesRule(private val configRule: List) : Rule("abs CLASS_SHOULD_NOT_BE_ABSTRACT.warnAndFix(configRule, emitWarn, isFixMode, identifier, node.startOffset, node) { val modList = classNode.getFirstChildWithType(MODIFIER_LIST)!! if (modList.getChildren(null).size > 1) { + // we are deleting one keyword, so we need to delete extra space + val spaceInModifiers = modList.getFirstChildWithType(WHITE_SPACE) modList.removeChild(modList.getFirstChildWithType(ABSTRACT_KEYWORD)!!) - if (modList.firstChildNode.isWhiteSpace()) { - modList.removeChild(modList.firstChildNode) + if (spaceInModifiers != null && spaceInModifiers.isWhiteSpace()) { + modList.removeChild(spaceInModifiers) } } else { classNode.removeChild(modList) diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt index 913a756740..9fcffd4a28 100644 --- a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt @@ -8,6 +8,10 @@ class Some() { inner class Any { fun func(){} } + + inner class Second { + fun someFunc(){} + } } abstract class Another { diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt index 69a3cd4cb5..889c835c5e 100644 --- a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt @@ -8,6 +8,10 @@ abstract class Some() { abstract inner class Any { fun func(){} } + + inner abstract class Second { + fun someFunc(){} + } } abstract class Another { From b50584de52739d8e871e7f63d7262b7e7d63771e Mon Sep 17 00:00:00 2001 From: soWhoAmI Date: Mon, 26 Oct 2020 17:20:46 +0300 Subject: [PATCH 5/6] feature/rule-6.1.6-abstract-classes(#442) ### What's done: * Fixed bugs --- .../diktat/ruleset/rules/classes/AbstractClassesRule.kt | 8 +++++++- .../ShouldRemoveAbstractKeywordExpected.kt | 2 +- .../abstract_classes/ShouldRemoveAbstractKeywordTest.kt | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt index 4fb70f6c6f..da075868f5 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt @@ -51,8 +51,14 @@ class AbstractClassesRule(private val configRule: List) : Rule("abs CLASS_SHOULD_NOT_BE_ABSTRACT.warnAndFix(configRule, emitWarn, isFixMode, identifier, node.startOffset, node) { val modList = classNode.getFirstChildWithType(MODIFIER_LIST)!! if (modList.getChildren(null).size > 1) { + val abstractKeyword = modList.getFirstChildWithType(ABSTRACT_KEYWORD)!! + // we are deleting one keyword, so we need to delete extra space - val spaceInModifiers = modList.getFirstChildWithType(WHITE_SPACE) + val spaceInModifiers = if (abstractKeyword == modList.lastChildNode) { + modList.treeNext + } else { + abstractKeyword.treeNext + } modList.removeChild(modList.getFirstChildWithType(ABSTRACT_KEYWORD)!!) if (spaceInModifiers != null && spaceInModifiers.isWhiteSpace()) { modList.removeChild(spaceInModifiers) diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt index 9fcffd4a28..e1b6d5167b 100644 --- a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordExpected.kt @@ -5,7 +5,7 @@ class Some() { fun another(){} - inner class Any { + @SomeAnnotation @Another inner class Any { fun func(){} } diff --git a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt index 889c835c5e..6784219efb 100644 --- a/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph6/abstract_classes/ShouldRemoveAbstractKeywordTest.kt @@ -5,7 +5,7 @@ abstract class Some() { fun another(){} - abstract inner class Any { + @SomeAnnotation @Another abstract inner class Any { fun func(){} } From 0b8caa2936f9cf254a739fe57b5a4084add97266 Mon Sep 17 00:00:00 2001 From: soWhoAmI Date: Mon, 26 Oct 2020 17:53:38 +0300 Subject: [PATCH 6/6] feature/rule-6.1.6-abstract-classes(#442) ### What's done: * Fixed bugs --- .../ruleset/rules/classes/AbstractClassesRule.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt index da075868f5..2f719ad9cd 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/classes/AbstractClassesRule.kt @@ -54,20 +54,20 @@ class AbstractClassesRule(private val configRule: List) : Rule("abs val abstractKeyword = modList.getFirstChildWithType(ABSTRACT_KEYWORD)!! // we are deleting one keyword, so we need to delete extra space - val spaceInModifiers = if (abstractKeyword == modList.lastChildNode) { - modList.treeNext - } else { + val spaceInModifiers = if (abstractKeyword == modList.firstChildNode) { abstractKeyword.treeNext + } else { + abstractKeyword.treePrev } - modList.removeChild(modList.getFirstChildWithType(ABSTRACT_KEYWORD)!!) + modList.removeChild(abstractKeyword) if (spaceInModifiers != null && spaceInModifiers.isWhiteSpace()) { modList.removeChild(spaceInModifiers) } } else { - classNode.removeChild(modList) - if (classNode.firstChildNode.isWhiteSpace()) { - classNode.removeChild(classNode.firstChildNode) + if (modList.treeNext.isWhiteSpace()) { + classNode.removeChild(modList.treeNext) } + classNode.removeChild(modList) } } }