Repository: analysis-dev/diktat (kotlin)

Issue:
Incorrect fix lambda
## Describe the bug
Incorrect fix lambda in this case
```kotlin
@Suppress("UnsafeCallOnNullableType")
    private fun saveExecution(project: Project, type: ExecutionType, sdk: Sdk): Long {
        val execution = Execution(project, LocalDateTime.now(), null, ExecutionStatus.PENDING, null,
            null, 0, null, type, null, 0, 0, 0, sdk.toString())
        execution.id = executionService.saveExecution(execution)
        log.info("Creating a new execution id=${execution.id} for project id=${project.id}")
        return execution.id!!
    }
```

## Expected behavior

```kotlin
@Suppress("UnsafeCallOnNullableType")
    private fun saveExecution(project: Project, type: ExecutionType, sdk: Sdk): Long {
        val execution = Execution(project, LocalDateTime.now(), null, ExecutionStatus.PENDING, null,
            null, 0, null, type, null, 0, 0, 0, sdk.toString()).apply {
            id = executionService.saveExecution(this)
        }
        log.info("Creating a new execution id=${execution.id} for project id=${project.id}")
        return execution.id!!
    }
```

## Actual behavior

```kotlin
@Suppress("UnsafeCallOnNullableType")
    private fun saveExecution(project: Project, type: ExecutionType, sdk: Sdk): Long {
        val execution = Execution(project, LocalDateTime.now(), null, ExecutionStatus.PENDING, null,
            null, 0, null, type, null, 0, 0, 0, sdk.toString()).apply {
            id = executionService.saveExecution(execution)
        }
        log.info("Creating a new execution id=${execution.id} for project id=${project.id}")
        return execution.id!!
    }
```

## Environment information
* diktat version: 1.0.0-rc.2

Pull request description:
### What's done:
* Fix bug and process case, when receiver name is also used in right part of expression
* Add tests

Patch:
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt
index b0ca67dbfe..4a9d29aa91 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter6/classes/CompactInitialization.kt
@@ -4,13 +4,16 @@ import org.cqfn.diktat.common.config.rules.RulesConfig
 import org.cqfn.diktat.ruleset.constants.Warnings.COMPACT_OBJECT_INITIALIZATION
 import org.cqfn.diktat.ruleset.rules.DiktatRule
 import org.cqfn.diktat.ruleset.utils.KotlinParser
+import org.cqfn.diktat.ruleset.utils.findAllDescendantsWithSpecificType
 import org.cqfn.diktat.ruleset.utils.findLeafWithSpecificType
 import org.cqfn.diktat.ruleset.utils.getFunctionName
 
 import com.pinterest.ktlint.core.ast.ElementType.BLOCK_COMMENT
+import com.pinterest.ktlint.core.ast.ElementType.CALL_EXPRESSION
 import com.pinterest.ktlint.core.ast.ElementType.EOL_COMMENT
 import com.pinterest.ktlint.core.ast.ElementType.KDOC
 import com.pinterest.ktlint.core.ast.ElementType.LBRACE
+import com.pinterest.ktlint.core.ast.ElementType.REFERENCE_EXPRESSION
 import com.pinterest.ktlint.core.ast.ElementType.THIS_KEYWORD
 import com.pinterest.ktlint.core.ast.ElementType.WHITE_SPACE
 import com.pinterest.ktlint.core.ast.isPartOfComment
@@ -82,7 +85,10 @@ class CompactInitialization(configRules: List<RulesConfig>) : DiktatRule(
             }
     }
 
-    @Suppress("UnsafeCallOnNullableType", "NestedBlockDepth")
+    @Suppress(
+        "UnsafeCallOnNullableType",
+        "NestedBlockDepth",
+        "TOO_LONG_FUNCTION")
     private fun moveAssignmentIntoApply(property: KtProperty, assignment: KtBinaryExpression) {
         // get apply expression or create empty; convert `apply(::foo)` to `apply { foo(this) }` if necessary
         getOrCreateApplyBlock(property).let(::convertValueParametersToLambdaArgument)
@@ -114,6 +120,14 @@ class CompactInitialization(configRules: List<RulesConfig>) : DiktatRule(
                             }
                             it.treeParent.removeChild(it)
                         }
+                    val receiverName = (assignment.left as KtDotQualifiedExpression).receiverExpression
+                    // looking for usages of receiver in right part
+                    val identifiers = assignment.right!!.node.findAllDescendantsWithSpecificType(REFERENCE_EXPRESSION)
+                    identifiers.forEach {
+                        if (it.text == receiverName.text && it.treeParent.elementType != CALL_EXPRESSION) {
+                            it.treeParent.replaceChild(it, kotlinParser.createNode("this"))
+                        }
+                    }
                     // strip receiver name and move assignment itself into `apply`
                     bodyExpression.addChild(kotlinParser.createNode(assignment.text.substringAfter('.')), null)
                     assignment.node.run { treeParent.removeChild(this) }


Test patch:
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/CompactInitializationFixTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/CompactInitializationFixTest.kt
index 6314741b7b..cbf2c873cd 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/CompactInitializationFixTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter6/CompactInitializationFixTest.kt
@@ -31,4 +31,10 @@ class CompactInitializationFixTest : FixTestBase("test/chapter6/compact_initiali
     fun `should not move statements with this keyword into apply block`() {
         fixAndCompare("ApplyOnStatementsWithThisKeywordExpected.kt", "ApplyOnStatementsWithThisKeywordTest.kt")
     }
+
+    @Test
+    @Tag(WarningNames.COMPACT_OBJECT_INITIALIZATION)
+    fun `should rename field in apply block to this keyword`() {
+        fixAndCompare("StatementUseFieldMultipleTimesExpected.kt", "StatementUseFieldMultipleTimesTest.kt")
+    }
 }
diff --git a/diktat-rules/src/test/resources/test/chapter6/compact_initialization/StatementUseFieldMultipleTimesExpected.kt b/diktat-rules/src/test/resources/test/chapter6/compact_initialization/StatementUseFieldMultipleTimesExpected.kt
new file mode 100644
index 0000000000..60938671ab
--- /dev/null
+++ b/diktat-rules/src/test/resources/test/chapter6/compact_initialization/StatementUseFieldMultipleTimesExpected.kt
@@ -0,0 +1,14 @@
+fun foo() {
+    val execution = Execution().apply {
+    id = executionService.saveExecution(this)}
+    return execution.id!!
+}
+
+fun foo() {
+    val execution = Execution().apply {
+    id = executionService.saveExecution(this)
+    sdk = this.defaultSdk(this)
+    id2 = this.id + shift
+    name = this.execution(this)}
+    return execution.id!!
+}
diff --git a/diktat-rules/src/test/resources/test/chapter6/compact_initialization/StatementUseFieldMultipleTimesTest.kt b/diktat-rules/src/test/resources/test/chapter6/compact_initialization/StatementUseFieldMultipleTimesTest.kt
new file mode 100644
index 0000000000..ab4295b7e3
--- /dev/null
+++ b/diktat-rules/src/test/resources/test/chapter6/compact_initialization/StatementUseFieldMultipleTimesTest.kt
@@ -0,0 +1,14 @@
+fun foo() {
+    val execution = Execution()
+    execution.id = executionService.saveExecution(execution)
+    return execution.id!!
+}
+
+fun foo() {
+    val execution = Execution()
+    execution.id = executionService.saveExecution(execution)
+    execution.sdk = execution.defaultSdk(execution)
+    execution.id2 = execution.id + shift
+    execution.name = execution.execution(execution)
+    return execution.id!!
+}