Repository: cqfn/diKTat
Pull request #1036 (2021-08-24 08:10:10)

Incorrect fix in COMPACT_OBJECT_INITIALIZATION rule
### What's done:
* Fix bug and process case, when receiver name is also used in right part of expression
* Add tests

codecov[bot]: # [Codecov](https://codecov.io/gh/cqfn/diKTat/pull/1036?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn) Report
> Merging [#1036](https://codecov.io/gh/cqfn/diKTat/pull/1036?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn) (6c99e35) into [master](https://codecov.io/gh/cqfn/diKTat/commit/9fb026fc58fb651b0fd7733ee7f09a08904b82b4?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn) (9fb026f) will **increase** coverage by `0.01%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/cqfn/diKTat/pull/1036/graphs/tree.svg?width=650&height=150&src=pr&token=P2quRDffpt&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn)](https://codecov.io/gh/cqfn/diKTat/pull/1036?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn)

```diff
@@             Coverage Diff              @@
##             master    #1036      +/-   ##
============================================
+ Coverage     83.74%   83.75%   +0.01%     
- Complexity     2433     2435       +2     
============================================
  Files           102      102              
  Lines          6126     6131       +5     
  Branches       1820     1821       +1     
============================================
+ Hits           5130     5135       +5     
  Misses          273      273              
  Partials        723      723              
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `83.75% <100.00%> (+0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/cqfn/diKTat/pull/1036?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn) | Coverage Δ | |
|---|---|---|
| [...et/rules/chapter6/classes/CompactInitialization.kt](https://codecov.io/gh/cqfn/diKTat/pull/1036/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn#diff-ZGlrdGF0LXJ1bGVzL3NyYy9tYWluL2tvdGxpbi9vcmcvY3Fmbi9kaWt0YXQvcnVsZXNldC9ydWxlcy9jaGFwdGVyNi9jbGFzc2VzL0NvbXBhY3RJbml0aWFsaXphdGlvbi5rdA==) | `87.95% <100.00%> (+0.77%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/cqfn/diKTat/pull/1036?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/cqfn/diKTat/pull/1036?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn). Last update [9fb026f...6c99e35](https://codecov.io/gh/cqfn/diKTat/pull/1036?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cqfn).


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 b0ca67db..4a9d29aa 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 6314741b..cbf2c873 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 00000000..60938671
--- /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 00000000..ab4295b7
--- /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!!
+}