From eb4e6e6c1acfc0e4a69ae7e2267202cc7684d169 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 31 Mar 2017 18:41:46 +0300 Subject: [PATCH] Ad hoc solution to avoid resolution in language injection by receiver (KT-16995) #KT-16995 Fixed --- .../idea/injection/KotlinLanguageInjector.kt | 37 +++++++++++++++++-- 1 file changed, 33 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 e7834a1ecaf..f3184da3d13 100644 --- a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt +++ b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt @@ -38,8 +38,13 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import java.util.* +import kotlin.collections.ArrayList class KotlinLanguageInjector : LanguageInjector { + companion object { + private val STRING_LITERALS_REGEXP = "\"([^\"]*)\"".toRegex() + } + val kotlinSupport: KotlinLanguageInjectionSupport? by lazy { ArrayList(InjectorUtils.getActiveInjectionSupports()).filterIsInstance(KotlinLanguageInjectionSupport::class.java).firstOrNull() } @@ -58,9 +63,9 @@ class KotlinLanguageInjector : LanguageInjector { private fun findInjectionInfo(place: KtElement, originalHost: Boolean = true): InjectionInfo? { return injectWithExplicitCodeInstruction(place) - ?: injectWithCall(place) - ?: injectWithReceiver(place) - ?: injectWithVariableUsage(place, originalHost) + ?: injectWithCall(place) + ?: injectWithReceiver(place) + ?: injectWithVariableUsage(place, originalHost) } private fun injectWithExplicitCodeInstruction(host: KtElement): InjectionInfo? { @@ -78,12 +83,21 @@ class KotlinLanguageInjector : LanguageInjector { if (isAnalyzeOff(qualifiedExpression.project)) return null + val kotlinInjections = Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID) + + val calleeName = callee.text + val possibleNames = collectPossibleNames(kotlinInjections) + + if (calleeName !in possibleNames) { + return null + } + for (reference in callee.references) { ProgressManager.checkCanceled() val resolvedTo = reference.resolve() if (resolvedTo is KtFunction) { - val injectionInfo = findInjection(resolvedTo.receiverTypeReference, Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID)) + val injectionInfo = findInjection(resolvedTo.receiverTypeReference, kotlinInjections) if (injectionInfo != null) { return injectionInfo } @@ -93,6 +107,21 @@ class KotlinLanguageInjector : LanguageInjector { return null } + private fun collectPossibleNames(injections: List): Set { + val result = HashSet() + + for (injection in injections) { + val injectionPlaces = injection.injectionPlaces + for (place in injectionPlaces) { + val placeStr = place.toString() + val literals = STRING_LITERALS_REGEXP.findAll(placeStr).map { it.groupValues[1] } + result.addAll(literals) + } + } + + return result + } + 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