Ad hoc solution to avoid resolution in language injection by receiver (KT-16995)
#KT-16995 Fixed
This commit is contained in:
@@ -38,8 +38,13 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class KotlinLanguageInjector : LanguageInjector {
|
class KotlinLanguageInjector : LanguageInjector {
|
||||||
|
companion object {
|
||||||
|
private val STRING_LITERALS_REGEXP = "\"([^\"]*)\"".toRegex()
|
||||||
|
}
|
||||||
|
|
||||||
val kotlinSupport: KotlinLanguageInjectionSupport? by lazy {
|
val kotlinSupport: KotlinLanguageInjectionSupport? by lazy {
|
||||||
ArrayList(InjectorUtils.getActiveInjectionSupports()).filterIsInstance(KotlinLanguageInjectionSupport::class.java).firstOrNull()
|
ArrayList(InjectorUtils.getActiveInjectionSupports()).filterIsInstance(KotlinLanguageInjectionSupport::class.java).firstOrNull()
|
||||||
}
|
}
|
||||||
@@ -58,9 +63,9 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
|
|
||||||
private fun findInjectionInfo(place: KtElement, originalHost: Boolean = true): InjectionInfo? {
|
private fun findInjectionInfo(place: KtElement, originalHost: Boolean = true): InjectionInfo? {
|
||||||
return injectWithExplicitCodeInstruction(place)
|
return injectWithExplicitCodeInstruction(place)
|
||||||
?: injectWithCall(place)
|
?: injectWithCall(place)
|
||||||
?: injectWithReceiver(place)
|
?: injectWithReceiver(place)
|
||||||
?: injectWithVariableUsage(place, originalHost)
|
?: injectWithVariableUsage(place, originalHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun injectWithExplicitCodeInstruction(host: KtElement): InjectionInfo? {
|
private fun injectWithExplicitCodeInstruction(host: KtElement): InjectionInfo? {
|
||||||
@@ -78,12 +83,21 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
|
|
||||||
if (isAnalyzeOff(qualifiedExpression.project)) return null
|
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) {
|
for (reference in callee.references) {
|
||||||
ProgressManager.checkCanceled()
|
ProgressManager.checkCanceled()
|
||||||
|
|
||||||
val resolvedTo = reference.resolve()
|
val resolvedTo = reference.resolve()
|
||||||
if (resolvedTo is KtFunction) {
|
if (resolvedTo is KtFunction) {
|
||||||
val injectionInfo = findInjection(resolvedTo.receiverTypeReference, Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID))
|
val injectionInfo = findInjection(resolvedTo.receiverTypeReference, kotlinInjections)
|
||||||
if (injectionInfo != null) {
|
if (injectionInfo != null) {
|
||||||
return injectionInfo
|
return injectionInfo
|
||||||
}
|
}
|
||||||
@@ -93,6 +107,21 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun collectPossibleNames(injections: List<BaseInjection>): Set<String> {
|
||||||
|
val result = HashSet<String>()
|
||||||
|
|
||||||
|
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? {
|
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
|
// Given place is not original host of the injection so we stop to prevent stepping through indirect references
|
||||||
if (!originalHost) return null
|
if (!originalHost) return null
|
||||||
|
|||||||
Reference in New Issue
Block a user