Repository: analysis-dev/diktat (kotlin)

Issue:
Error in LOCAL_VARIABLE_EARLY_DECLARATION rule
```
java.lang.ClassCastException: class org.jetbrains.kotlin.psi.KtCallExpression cannot be cast to class org.jetbrains.kotlin.psi.KtNameReferenceExpression (org.jetbrains.kotlin.psi.KtCallExpression and org.jetbrains.kotlin.psi.KtNameReferenceExpression are in unnamed module of loader 'app')
        at org.cqfn.diktat.ruleset.rules.chapter3.identifiers.LocalVariablesRule.isWhitelistedMethod(LocalVariablesRule.kt:199)
        at org.cqfn.diktat.ruleset.rules.chapter3.identifiers.LocalVariablesRule.access$isWhitelistedMethod(LocalVariablesRule.kt:40)
        at org.cqfn.diktat.ruleset.rules.chapter3.identifiers.LocalVariablesRule$collectLocalPropertiesWithUsages$1.invoke(LocalVariablesRule.kt:68)
        at org.cqfn.diktat.ruleset.rules.chapter3.identifiers.LocalVariablesRule$collectLocalPropertiesWithUsages$1.invoke(LocalVariablesRule.kt:64)
        at org.cqfn.diktat.ruleset.utils.search.VariablesSearch.collectVariables(VariablesSearch.kt:126)
```

```
/*
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.samples.apps.iosched.shared.domain.users

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.google.samples.apps.iosched.model.SessionId
import com.google.samples.apps.iosched.shared.data.feedback.FeedbackEndpoint
import com.google.samples.apps.iosched.shared.data.session.DefaultSessionRepository
import com.google.samples.apps.iosched.shared.data.userevent.DefaultSessionAndUserEventRepository
import com.google.samples.apps.iosched.shared.domain.repository.TestUserEventDataSource
import com.google.samples.apps.iosched.shared.model.TestDataRepository
import com.google.samples.apps.iosched.shared.result.Result
import com.google.samples.apps.iosched.test.data.MainCoroutineRule
import com.google.samples.apps.iosched.test.data.TestData
import com.google.samples.apps.iosched.test.data.runBlockingTest
import junit.framework.Assert.assertEquals
import org.junit.Rule
import org.junit.Test

/**
 * Unit tests for [FeedbackUseCase]
 */
class FeedbackUseCaseTest {

    // Executes tasks in the Architecture Components in the same thread
    @get:Rule
    var instantTaskExecutorRule = InstantTaskExecutorRule()

    // Overrides Dispatchers.Main used in Coroutines
    @get:Rule
    var coroutineRule = MainCoroutineRule()

    @Test
    fun submit() = coroutineRule.runBlockingTest {
        val testFeedbackEndpoint = object : FeedbackEndpoint {
            override suspend fun sendFeedback(
                sessionId: SessionId,
                responses: Map<String, Int>
            ): Result<Unit> {
                return Result.Success(Unit)
            }
        }
        val testUserEventRepository = DefaultSessionAndUserEventRepository(
            TestUserEventDataSource(), DefaultSessionRepository(TestDataRepository)
        )

        val result = FeedbackUseCase(
            testFeedbackEndpoint,
            testUserEventRepository,
            coroutineRule.testDispatcher
        )(
            FeedbackParameter(
                "userIdTest",
                TestData.userEvents[0],
                TestData.userEvents[0].id,
                mapOf("q1" to 1)
            )
        )

        assertEquals(Result.Success(Unit), result)
    }
}

```

Pull request:
### What's done:
* Changed logic
* Added test

## Which rule and warnings did you add?

This pull request closes #925

Patch:
diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt
index 8170e552c3..74d6bb99b0 100644
--- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt
+++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/identifiers/LocalVariablesRule.kt
@@ -196,7 +196,9 @@ class LocalVariablesRule(configRules: List<RulesConfig>) : DiktatRule(
 
     private fun KtCallExpression?.isWhitelistedMethod() =
             this?.run {
-                (referenceExpression() as KtNameReferenceExpression).getReferencedName() in functionInitializers &&
+                // `referenceExpression()` can return something different than just a name, e.g. when function returns a function:
+                // `foo()()` `referenceExpression()` will be a `KtCallExpression` as well
+                (referenceExpression() as? KtNameReferenceExpression)?.getReferencedName() in functionInitializers &&
                         valueArguments.isEmpty()
             } ?: false
 


Test patch:
diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/LocalVariablesWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/LocalVariablesWarnTest.kt
index deab1036ef..391e6f8122 100644
--- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/LocalVariablesWarnTest.kt
+++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/LocalVariablesWarnTest.kt
@@ -673,4 +673,17 @@ class LocalVariablesWarnTest : LintTestBase(::LocalVariablesRule) {
                 """.trimMargin()
         )
     }
+
+    @Test
+    @Tag(LOCAL_VARIABLE_EARLY_DECLARATION)
+    fun `shouldn't fail on double invocations`() {
+        lintMethod(
+            """
+                |fun bar() {
+                |    val x = foo()()
+                |    val x = foo()()()
+                |}
+            """.trimMargin()
+        )
+    }
 }