From b0433b2904605d0922f23ce86305ba99a35fbaae Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Wed, 20 Apr 2016 19:10:46 +0300 Subject: [PATCH] Prevent stepping through indirect assignments in injection search --- .../kotlin/idea/injection/KotlinLanguageInjector.kt | 11 +++++++---- .../org/jetbrains/kotlin/psi/AbstractInjectionTest.kt | 7 +++++++ .../org/jetbrains/kotlin/psi/KotlinInjectionTest.kt | 7 +++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt index de46fafdec6..efb8468f12c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt +++ b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt @@ -45,11 +45,11 @@ class KotlinLanguageInjector : LanguageInjector { injectionPlacesRegistrar.addPlace(language, TextRange.from(0, ktHost.textLength), injectionInfo.prefix, injectionInfo.suffix) } - private fun findInjectionInfo(place: KtElement): InjectionInfo? { + private fun findInjectionInfo(place: KtElement, originalHost: Boolean = true): InjectionInfo? { return injectWithExplicitCodeInstruction(place) ?: injectWithCall(place) ?: injectWithReceiver(place) - ?: injectWithVariableUsage(place) + ?: injectWithVariableUsage(place, originalHost) } private fun injectWithExplicitCodeInstruction(host: KtElement): InjectionInfo? { @@ -82,7 +82,10 @@ class KotlinLanguageInjector : LanguageInjector { return null } - private fun injectWithVariableUsage(host: KtElement): InjectionInfo? { + private fun injectWithVariableUsage(host: KtElement, originalHost: Boolean): InjectionInfo? { + // Given place is not original host of the injection so we stop to prevent stepping through indirect references + if (!originalHost) return null + val ktHost: KtElement = host val ktProperty = host.parent as? KtProperty?: return null if (ktProperty.initializer != host) return null @@ -92,7 +95,7 @@ class KotlinLanguageInjector : LanguageInjector { val searchScope = LocalSearchScope(arrayOf(ktProperty.containingFile), "", true) return ReferencesSearch.search(ktProperty, searchScope).asSequence().mapNotNull { psiReference -> val element = psiReference.element as? KtElement ?: return@mapNotNull null - findInjectionInfo(element) + findInjectionInfo(element, false) }.firstOrNull() } diff --git a/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt b/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt index edff0d3db0f..469ee08d7c7 100644 --- a/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt @@ -56,6 +56,13 @@ abstract class AbstractInjectionTest : KotlinLightCodeInsightFixtureTestCase() { } } + protected fun testNoInjection(text: String) { + myFixture.configureByText("${getTestName(true)}.kt", text.trimMargin()) + + TestCase.assertTrue("Injection action is not available. There's probably some injection but nothing was expected.", + InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) + } + protected fun doRemoveInjectionTest(before: String, after: String) { myFixture.setCaresAboutInjection(false) diff --git a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt index 9bc56d4a3b7..ab739dcfc17 100644 --- a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt @@ -96,6 +96,13 @@ class KotlinInjectionTest : AbstractInjectionTest() { """, languageId = RegExpLanguage.INSTANCE.id, unInjectShouldBePresent = false) + fun testNoInjectionThoughSeveralAssignmentsWithRuntime() = testNoInjection( + """ + |val first = "some" + |val test = first + |fun foo() = Regex(test) + """) + fun testInjectionWithMultipleCommentsOnFun() = testInjectionPresent( """ |// Some comment