diff --git a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt index 98d0a78a0d5..de46fafdec6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt +++ b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt @@ -20,6 +20,8 @@ import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange import com.intellij.psi.* +import com.intellij.psi.search.LocalSearchScope +import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.util.PsiTreeUtil import org.intellij.plugins.intelliLang.Configuration import org.intellij.plugins.intelliLang.inject.InjectorUtils @@ -37,16 +39,19 @@ class KotlinLanguageInjector : LanguageInjector { if (!host.isValidHost) return val ktHost: KtElement = host as? KtElement ?: return - val injectionInfo = - injectWithExplicitCodeInstruction(ktHost) - ?: injectWithCall(ktHost) - ?: injectWithReceiver(ktHost) - ?: return + val injectionInfo = findInjectionInfo(host) ?: return val language = InjectorUtils.getLanguageByString(injectionInfo.languageId) ?: return injectionPlacesRegistrar.addPlace(language, TextRange.from(0, ktHost.textLength), injectionInfo.prefix, injectionInfo.suffix) } + private fun findInjectionInfo(place: KtElement): InjectionInfo? { + return injectWithExplicitCodeInstruction(place) + ?: injectWithCall(place) + ?: injectWithReceiver(place) + ?: injectWithVariableUsage(place) + } + private fun injectWithExplicitCodeInstruction(host: KtElement): InjectionInfo? { val support = kotlinSupport ?: return null val languageId = support.findAnnotationInjectionLanguageId(host) ?: return null @@ -77,6 +82,20 @@ class KotlinLanguageInjector : LanguageInjector { return null } + private fun injectWithVariableUsage(host: KtElement): InjectionInfo? { + val ktHost: KtElement = host + val ktProperty = host.parent as? KtProperty?: return null + if (ktProperty.initializer != host) return null + + if (isAnalyzeOff(ktHost.project)) return null + + 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) + }.firstOrNull() + } + private fun injectWithCall(host: KtElement): InjectionInfo? { val ktHost: KtElement = host val argument = ktHost.parent as? KtValueArgument ?: return null diff --git a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt index 8f4f9c009b9..9bc56d4a3b7 100644 --- a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt @@ -82,6 +82,20 @@ class KotlinInjectionTest : AbstractInjectionTest() { |val test = "simple" """) + fun testInjectionWithUsageOnReceiverWithRuntime() = testInjectionPresent( + """ + |val test = "some" + |fun foo() = test.toRegex() + """, + languageId = RegExpLanguage.INSTANCE.id, unInjectShouldBePresent = false) + + fun testInjectionWithUsageInParameterWithRuntime() = testInjectionPresent( + """ + |val test = "some" + |fun foo() = Regex(test) + """, + languageId = RegExpLanguage.INSTANCE.id, unInjectShouldBePresent = false) + fun testInjectionWithMultipleCommentsOnFun() = testInjectionPresent( """ |// Some comment