Repository: analysis-dev/diktat (kotlin)

Issue:
KotlinParseException on string concatenation
Diktate falls in fix plugin on string concatenation: `"data:image/png;base64, " + state.image?.base64"`

```
[ERROR] 2022-01-21 17:53:17 Internal error has occurred in rule [string-concatenation]. Please make an issue on this bug at https://github.com/cqfn/diKTat/. 
                       As a workaround you can disable these inspections in yml config: <[STRING_CONCATENATION]>.
                       Root cause of the problem is in [C:\Users\vwx1020336\IdeaProjects\save-cloud-frontend\save-frontend\src\main\kotlin\org\cqfn\save\frontend\components\views\OwnerView.kt] file.
org.cqfn.diktat.ruleset.utils.KotlinParseException: Text is not valid: [""data:image/png;base64, " + state.image?.base64"]
	at org.cqfn.diktat.ruleset.utils.KotlinParser.createNode(KotlinParser.kt:75) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.utils.KotlinParser.createNode$default(KotlinParser.kt:75) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.rules.chapter3.StringConcatenationRule.fixBinaryExpressionWithConcatenation(StringConcatenationRule.kt:115) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.rules.chapter3.StringConcatenationRule.access$fixBinaryExpressionWithConcatenation(StringConcatenationRule.kt:31) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.rules.chapter3.StringConcatenationRule$detectStringConcatenation$1.invoke(StringConcatenationRule.kt:65) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.rules.chapter3.StringConcatenationRule$detectStringConcatenation$1.invoke(StringConcatenationRule.kt:61) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.constants.Warnings.warnAndFix(Warnings.kt:261) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.constants.Warnings.warnAndFix$default(Warnings.kt:203) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.rules.chapter3.StringConcatenationRule.detectStringConcatenation(StringConcatenationRule.kt:61) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.rules.chapter3.StringConcatenationRule.logic(StringConcatenationRule.kt:44) ~[diktat-rules-1.0.1.jar:?]
	at org.cqfn.diktat.ruleset.rules.DiktatRule.visit(DiktatRule.kt:50) ~[diktat-rules-1.0.1.jar:?]
```

Pull request description:
### What's done:
* fixed null-safety in rule
This pull request closes #1181

Patch:
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt
index 7bd89a5081..4cfb720d9e 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/StringConcatenationRule.kt
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
 import org.jetbrains.kotlin.psi.KtOperationExpression
 import org.jetbrains.kotlin.psi.KtParenthesizedExpression
 import org.jetbrains.kotlin.psi.KtReferenceExpression
+import org.jetbrains.kotlin.psi.KtSafeQualifiedExpression
 import org.jetbrains.kotlin.psi.KtStringTemplateExpression
 
 /**
@@ -153,7 +154,8 @@ class StringConcatenationRule(configRules: List<RulesConfig>) : DiktatRule(
             // =========== "a " + "b" -> "a b"
             val rvalueTextNew = rvalueText?.trim('"')
             return "$lvalueText$rvalueTextNew"
-        } else if (binaryExpressionPsi.isRvalueCallExpression() || binaryExpressionPsi.isRvalueDotQualifiedExpression() || binaryExpressionPsi.isRvalueOperation()) {
+        } else if (binaryExpressionPsi.isRvalueCallExpression() || binaryExpressionPsi.isRvalueDotQualifiedExpression() ||
+                binaryExpressionPsi.isRvalueOperation() || binaryExpressionPsi.isRvalueSafeQualifiedExpression()) {
             // ===========  "a " + foo() -> "a ${foo()}}"
             return "$lvalueText\${$rvalueText}"
         } else if (binaryExpressionPsi.isRvalueReferenceExpression()) {
@@ -216,4 +218,7 @@ class StringConcatenationRule(configRules: List<RulesConfig>) : DiktatRule(
 
     private fun KtBinaryExpression.isLvalueConstantExpression() =
             this.left is KtConstantExpression
+
+    private fun KtBinaryExpression.isRvalueSafeQualifiedExpression() =
+            this.right is KtSafeQualifiedExpression
 }


Test patch:
diff --git a/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt b/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt
index 87fc861338..80d319ae76 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationExpected.kt
@@ -31,4 +31,5 @@ val myTest20 = "${x}string"
 val myTest21 = "${x} string"
 val myTest22 = "string${foo()}"
 val myTest23 = x.toString() + foo()
-val myTest24 = foo() + "string"
\ No newline at end of file
+val myTest24 = foo() + "string"
+val myTest25 = "String ${valueStr?.value}"
\ No newline at end of file
diff --git a/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationTest.kt b/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationTest.kt
index b14425bfa1..8c49d00fdb 100644
--- a/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationTest.kt
+++ b/diktat-rules/src/test/resources/test/paragraph3/string_concatenation/StringConcatenationTest.kt
@@ -32,3 +32,4 @@ val myTest21 = x.toString() + " string"
 val myTest22 = "string" + foo()
 val myTest23 = x.toString() + foo()
 val myTest24 = foo() + "string"
+val myTest25 = "String " + valueStr?.value