diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt index 8f9179558f..935e7805f7 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/SortRule.kt @@ -5,23 +5,28 @@ import org.cqfn.diktat.common.config.rules.RulesConfig import org.cqfn.diktat.common.config.rules.getRuleConfig import org.cqfn.diktat.ruleset.constants.Warnings.WRONG_DECLARATIONS_ORDER import org.cqfn.diktat.ruleset.rules.DiktatRule +import org.cqfn.diktat.ruleset.utils.findAllNodesWithSpecificType import org.cqfn.diktat.ruleset.utils.hasChildOfType import org.cqfn.diktat.ruleset.utils.isClassEnum -import com.pinterest.ktlint.core.ast.ElementType import com.pinterest.ktlint.core.ast.ElementType.CLASS_BODY import com.pinterest.ktlint.core.ast.ElementType.COMMA import com.pinterest.ktlint.core.ast.ElementType.CONST_KEYWORD +import com.pinterest.ktlint.core.ast.ElementType.ENUM_ENTRY +import com.pinterest.ktlint.core.ast.ElementType.EOL_COMMENT import com.pinterest.ktlint.core.ast.ElementType.IDENTIFIER import com.pinterest.ktlint.core.ast.ElementType.MODIFIER_LIST import com.pinterest.ktlint.core.ast.ElementType.PROPERTY import com.pinterest.ktlint.core.ast.ElementType.SEMICOLON +import com.pinterest.ktlint.core.ast.isPartOfComment +import com.pinterest.ktlint.core.ast.isWhiteSpace import com.pinterest.ktlint.core.ast.isWhiteSpaceWithNewline import com.pinterest.ktlint.core.ast.nextSibling import org.jetbrains.kotlin.com.intellij.lang.ASTNode import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl import org.jetbrains.kotlin.psi.KtObjectDeclaration +import org.jetbrains.kotlin.psi.psiUtil.siblings /** * Rule that sorts class properties and enum members alphabetically @@ -67,17 +72,41 @@ class SortRule(configRules: List) : DiktatRule("sort-rule", configR } } + @OptIn(ExperimentalStdlibApi::class) private fun swapSortNodes( sortList: List, nonSortList: List, node: ASTNode) { - val nodeBefore: ASTNode? = nonSortList.last().treeNext + val isEnum = nonSortList.first().elementType == ENUM_ENTRY + val spaceBefore = if (node.findAllNodesWithSpecificType(EOL_COMMENT).isNotEmpty() && isEnum) { + nonSortList.last().run { + if (this.hasChildOfType(EOL_COMMENT) && !this.hasChildOfType(COMMA)) { + this.addChild(LeafPsiElement(COMMA, ","), this.findChildByType(EOL_COMMENT)) + } + } + buildList(nonSortList.size) { + add(null) + repeat(nonSortList.size - 1) { + add(listOf(PsiWhiteSpaceImpl("\n"))) + } + } + } else { + nonSortList.map { astNode -> + astNode + .siblings(false) + .toList() + .takeWhile { it.isWhiteSpace() || it.isPartOfComment() } + .ifEmpty { null } + } + } + val nodeInsertBefore: ASTNode? = nonSortList.last().treeNext node.removeRange(nonSortList.first(), nonSortList.last().treeNext) - sortList.forEachIndexed { nodeIndex, astNode -> - if (nodeIndex != 0) { - node.addChild(PsiWhiteSpaceImpl("\n"), nodeBefore) + sortList.mapIndexed { index, astNode -> + spaceBefore[index]?.let { prevList -> prevList.map { node.addChild(it, nodeInsertBefore) } } + if (!astNode.hasChildOfType(COMMA) && isEnum) { + astNode.addChild(LeafPsiElement(COMMA, ","), null) } - node.addChild(astNode, nodeBefore) + node.addChild(astNode, nodeInsertBefore) } } @@ -99,7 +128,7 @@ class SortRule(configRules: List) : DiktatRule("sort-rule", configR @Suppress("UnsafeCallOnNullableType") private fun sortEnum(node: ASTNode) { - val enumEntryList = node.getChildren(null).filter { it.elementType == ElementType.ENUM_ENTRY } + val enumEntryList = node.getChildren(null).filter { it.elementType == ENUM_ENTRY } if (enumEntryList.size <= 1) { return } @@ -110,8 +139,8 @@ class SortRule(configRules: List) : DiktatRule("sort-rule", configR val hasTrailingComma = (sortList.last() != enumEntryList.last() && enumEntryList.last().hasChildOfType(COMMA)) swapSortNodes(sortList, enumEntryList, node) if (!hasTrailingComma) { - enumEntryList.last().addChild(LeafPsiElement(COMMA, ","), null) - sortList.last().removeChild(sortList.last().findChildByType(COMMA)!!) + val lastEntry = node.findAllNodesWithSpecificType(ENUM_ENTRY).last() + lastEntry.removeChild(lastEntry.findChildByType(COMMA)!!) } if (isEndSpace) { sortList.last().addChild(PsiWhiteSpaceImpl("\n"), null) diff --git a/diktat-rules/src/test/resources/test/paragraph3/sort_error/ConstantsExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/sort_error/ConstantsExpected.kt index ba8d1eedb5..c10d078c44 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/sort_error/ConstantsExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/sort_error/ConstantsExpected.kt @@ -3,8 +3,8 @@ package test.paragraph3.sort_error class Test { companion object { private const val B = 4 -private const val C = 4 -private const val D = 4 + private const val C = 4 + private const val D = 4 private val SIMPLE_VALUE = listOf(IDENTIFIER, WHITE_SPACE, COMMA, SEMICOLON) } } @@ -28,7 +28,7 @@ class Test2 { private const val D = 4 private val SIMPLE_VALUE = listOf(IDENTIFIER, WHITE_SPACE, COMMA, SEMICOLON) private const val Ba = 4 -private const val Baa = 4 -private const val Bb = 4 + private const val Baa = 4 + private const val Bb = 4 } } diff --git a/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortExpected.kt index 348610a1a6..e48588d699 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortExpected.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortExpected.kt @@ -2,8 +2,8 @@ package test.paragraph3.sort_error enum class Alp { BLUE(0x0000FF), -GREEN(0x00FF00), -RED(0xFF0000), + GREEN(0x00FF00), + RED(0xFF0000), ; } @@ -11,7 +11,7 @@ enum class Warnings { TALKING { override fun signal() = TALKING }, -WAITING { + WAITING { override fun signal() = TALKING }, ; @@ -23,7 +23,7 @@ enum class Warnings { TALKING { override fun signal() = TALKING }, -WAITING { + WAITING { override fun signal() = TALKING }; @@ -32,13 +32,33 @@ WAITING { enum class Alp { BLUE(0x0000FF), -GREEN(0x00FF00), -RED(0xFF0000), + GREEN(0x00FF00), + RED(0xFF0000), } enum class Alp { BLUE(0x0000FF), -GREEN(0x00FF00), -RED(0xFF0000) + GREEN(0x00FF00), + RED(0xFF0000) ; } + +enum class IssueType { + PROJECT_STRUCTURE, TESTS, VCS +} + +enum class IssueType { + PROJECT_STRUCTURE,TESTS,VCS +} + +enum class IssueType { + PROJECT_STRUCTURE, // comment +TESTS, +VCS +} + +enum class IssueType { + PROJECT_STRUCTURE ,// comment +TESTS, +VCS +} diff --git a/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortTest.kt b/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortTest.kt index e663ba99f7..1c87f8c520 100644 --- a/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortTest.kt +++ b/diktat-rules/src/test/resources/test/paragraph3/sort_error/EnumSortTest.kt @@ -40,5 +40,22 @@ enum class Alp { RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF) - ; +; +} + +enum class IssueType { + VCS, PROJECT_STRUCTURE, TESTS +} + +enum class IssueType { + VCS,PROJECT_STRUCTURE,TESTS +} + +enum class IssueType { + VCS,PROJECT_STRUCTURE, // comment + TESTS +} + +enum class IssueType { + VCS, TESTS, PROJECT_STRUCTURE // comment } diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt b/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt index 943de52b8a..92c20ffb49 100644 --- a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt +++ b/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Expected.kt @@ -35,6 +35,10 @@ class Example { } } +enum class IssueType { + PROJECT_STRUCTURE, TESTS, VCS +} + class Foo { /** * @implNote lorem ipsum diff --git a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt b/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt index ddd801edf8..ee6d20b539 100644 --- a/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt +++ b/diktat-rules/src/test/resources/test/smoke/src/main/kotlin/Example3Test.kt @@ -41,6 +41,9 @@ class Example { } } +enum class IssueType { + VCS, PROJECT_STRUCTURE, TESTS +} class Foo { /**