Repository: analysis-dev/diktat (kotlin)

Issue:
TRAILLING_COMMA: endless number of trailing commas added with -F (fix mode)
```
enum class ReflektEntity(
    val entityType: String, val smartClassName: String  // SmartReflekt nested class,
)
```

incorreclty adds commas if stupid comment is after the argument:
```
enum class ReflektEntity(
    val entityType: String, val smartClassName: String  // SmartReflekt nested class,,
)
```

Pull request:
### What's done:
* Bugfix in TRAILLING_COMMA: insert comma in a proper place when there are exists comments
* Expand tests

Patch:
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt
index 814f1121e9..94af992387 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/TrailingCommaRule.kt
@@ -7,11 +7,14 @@ import org.cqfn.diktat.common.config.rules.getRuleConfig
 import org.cqfn.diktat.ruleset.constants.Warnings.TRAILING_COMMA
 import org.cqfn.diktat.ruleset.rules.DiktatRule
 
+import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT
 import com.pinterest.ktlint.core.ast.ElementType.COLLECTION_LITERAL_EXPRESSION
 import com.pinterest.ktlint.core.ast.ElementType.COMMA
 import com.pinterest.ktlint.core.ast.ElementType.DESTRUCTURING_DECLARATION
 import com.pinterest.ktlint.core.ast.ElementType.DESTRUCTURING_DECLARATION_ENTRY
+import com.pinterest.ktlint.core.ast.ElementType.EOL_COMMENT
 import com.pinterest.ktlint.core.ast.ElementType.INDICES
+import com.pinterest.ktlint.core.ast.ElementType.KDOC
 import com.pinterest.ktlint.core.ast.ElementType.REFERENCE_EXPRESSION
 import com.pinterest.ktlint.core.ast.ElementType.STRING_TEMPLATE
 import com.pinterest.ktlint.core.ast.ElementType.TYPE_ARGUMENT_LIST
@@ -102,7 +105,17 @@ class TrailingCommaRule(configRules: List<RulesConfig>) : DiktatRule(
             // we should write type of node in warning, to make it easier for user to find the parameter
             TRAILING_COMMA.warnAndFix(configRules, emitWarn, isFixMode, "after ${this.elementType}: ${this.text}", this.startOffset, this) {
                 val parent = this.treeParent
-                parent.addChild(LeafPsiElement(COMMA, ","), this.treeNext)
+
+                // In case, when we got VALUE_PARAMETER, it may contain comments, which follows the actual parameter and all of them are actually in the same node
+                // Ex: `class A(val a: Int, val b: Int  // comment)`
+                // `val b: Int  // comment` --> the whole expression is VALUE_PARAMETER
+                // So, in this case we must insert comma before the comment, in other cases we will insert it after current node
+                val comments = listOf(EOL_COMMENT, BLOCK_COMMENT, KDOC)
+                val firstCommentNodeOrNull = if (this.elementType == VALUE_PARAMETER) this.children().firstOrNull { it.elementType in comments } else null
+                firstCommentNodeOrNull?.let {
+                    this.addChild(LeafPsiElement(COMMA, ","), firstCommentNodeOrNull)
+                }
+                    ?: parent.addChild(LeafPsiElement(COMMA, ","), this.treeNext)
             }
         }
     }


Test patch:
diff --git a/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaExpected.kt
index 82256db930..6b452b7dc6 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaExpected.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaExpected.kt
@@ -38,6 +38,15 @@ fun isReferenceApplicable(myReference: KClass<*>,
     else -> false
 }
 
+fun isReferenceApplicable(myReference: KClass<*> ,// comment
+) = when (myReference) {
+    Comparable::class,
+    Iterable::class,
+    String::class,
+    -> true
+    else -> false
+}
+
 @ApplicableFor([
     "serializer",
     "balancer",
@@ -70,4 +79,45 @@ fun printMeanValue() {
         meanValue += year
     }
     println(meanValue/cars.size)
+}
+
+enum class SomeEnum(
+    val a: Int, val b: Int  ,// comment
+)
+
+enum class SomeEnum(
+    val a: Int, val b: Int,// comment
+)
+
+enum class SomeEnum(
+    val a: Int, val b: Int  ,/* comment */
+)
+
+enum class SomeEnum(
+    val a: Int, val b: Int,  /**
+    some comment */
+)
+
+fun foo() {
+    val sum: (Int, Int, Int,) -> Int = fun(
+        x,
+        y,
+        z ,// trailing comma
+    ): Int {
+        return x + y + x
+    }
+    println(sum(8, 8, 8))
+}
+
+fun shift(x: Int, y: Int) {
+    shift(
+        25,
+        20, // trailing comma
+    )
+
+    val colors = listOf(
+        "red",
+        "green",
+        "blue", // trailing comma
+    )
 }
\ No newline at end of file
diff --git a/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaTest.kt b/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaTest.kt
index 2aa00d994b..f1aabc5aa6 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaTest.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/trailing_comma/TrailingCommaTest.kt
@@ -38,6 +38,15 @@ fun isReferenceApplicable(myReference: KClass<*>
     else -> false
 }
 
+fun isReferenceApplicable(myReference: KClass<*> // comment
+) = when (myReference) {
+    Comparable::class,
+    Iterable::class,
+    String::class
+    -> true
+    else -> false
+}
+
 @ApplicableFor([
     "serializer",
     "balancer",
@@ -70,4 +79,45 @@ fun printMeanValue() {
         meanValue += year
     }
     println(meanValue/cars.size)
+}
+
+enum class SomeEnum(
+    val a: Int, val b: Int  // comment
+)
+
+enum class SomeEnum(
+    val a: Int, val b: Int// comment
+)
+
+enum class SomeEnum(
+    val a: Int, val b: Int  /* comment */
+)
+
+enum class SomeEnum(
+    val a: Int, val b: Int  /**
+    some comment */
+)
+
+fun foo() {
+    val sum: (Int, Int, Int,) -> Int = fun(
+        x,
+        y,
+        z // trailing comma
+    ): Int {
+        return x + y + x
+    }
+    println(sum(8, 8, 8))
+}
+
+fun shift(x: Int, y: Int) {
+    shift(
+        25,
+        20 // trailing comma
+    )
+
+    val colors = listOf(
+        "red",
+        "green",
+        "blue" // trailing comma
+    )
 }
\ No newline at end of file