From 777b16e0a30b08c499d263db1c1242f9234f8ce0 Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Wed, 19 Aug 2020 19:03:59 -0700 Subject: [PATCH] Fix @Language injection when using named parameters Start using names of arguments if they are available when fetching the @Language injection information. Fixes KT-35859 --- .../idea/injection/KotlinLanguageInjector.kt | 15 ++++++++++--- .../kotlin/psi/KotlinInjectionTest.kt | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt index 37ff5c7ae59..f8a6558554a 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt @@ -347,9 +347,14 @@ class KotlinLanguageInjector( } private fun injectionForKotlinCall(argument: KtValueArgument, ktFunction: KtFunction, reference: PsiReference): InjectionInfo? { + val argumentName = argument.getArgumentName()?.asName val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument) - val ktParameter = ktFunction.valueParameters.getOrNull(argumentIndex) ?: return null - + // Prefer using argument name if present + val ktParameter = if (argumentName != null) { + ktFunction.valueParameters.firstOrNull { it.nameAsName == argumentName } + } else { + ktFunction.valueParameters.getOrNull(argumentIndex) + } ?: return null val patternInjection = findInjection(ktParameter, configuration.getInjections(KOTLIN_SUPPORT_ID)) if (patternInjection != null) { return patternInjection @@ -363,7 +368,11 @@ class KotlinLanguageInjector( ktReference.resolveToDescriptors(bindingContext).singleOrNull() as? FunctionDescriptor } ?: return null - val parameterDescriptor = functionDescriptor.valueParameters.getOrNull(argumentIndex) ?: return null + val parameterDescriptor = if (argumentName != null) { + functionDescriptor.valueParameters.firstOrNull { it.name == argumentName } + } else { + functionDescriptor.valueParameters.getOrNull(argumentIndex) + } ?: return null return injectionInfoByAnnotation(parameterDescriptor) } diff --git a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt index 95c5dbf64b2..7355a180be5 100644 --- a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.psi import com.intellij.codeInsight.completion.CompletionType import com.intellij.lang.html.HTMLLanguage +import com.intellij.lang.xml.XMLLanguage import com.intellij.openapi.fileTypes.PlainTextLanguage import org.intellij.lang.annotations.Language import org.intellij.lang.regexp.RegExpLanguage @@ -780,5 +781,26 @@ class KotlinInjectionTest : AbstractInjectionTest() { languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false ) + fun testInjectionWithUsageInFunctionWithMarkedSecondNamedParameterWithAnnotation() = doInjectionPresentTest( + """ + import org.intellij.lang.annotations.Language + + fun foo(@Language("XML") a: String = "", @Language("HTML") b: String = "") {} + + fun other() { foo(b = "some") } + """, + languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false + ) + + fun testInjectionWithUsageInFunctionWithMarkedFirstNamedParameterWithAnnotation() = doInjectionPresentTest( + """ + import org.intellij.lang.annotations.Language + + fun foo(@Language("XML") a: String = "", @Language("HTML") b: String = "") {} + + fun other() { foo(a = "some") } + """, + languageId = XMLLanguage.INSTANCE.id, unInjectShouldBePresent = false + ) }