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 840b5fa0708..f9eda106719 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 @@ -35,6 +35,7 @@ import org.intellij.plugins.intelliLang.inject.TemporaryPlacesRegistry import org.intellij.plugins.intelliLang.inject.config.BaseInjection import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport import org.intellij.plugins.intelliLang.util.AnnotationUtilEx +import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.references.KtReference @@ -44,7 +45,9 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.annotations.argumentValue +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.resolve.source.getPsi import java.util.* import kotlin.collections.ArrayList @@ -153,6 +156,7 @@ class KotlinLanguageInjector( private fun findInjectionInfo(place: KtElement, originalHost: Boolean = true): InjectionInfo? { return injectWithExplicitCodeInstruction(place) ?: injectWithCall(place) + ?: injectInAnnotationCall(place) ?: injectWithReceiver(place) ?: injectWithVariableUsage(place, originalHost) ?: injectWithAnnotationEntry(place) @@ -262,6 +266,16 @@ class KotlinLanguageInjector( return null } + private fun injectInAnnotationCall(host: KtElement): InjectionInfo? { + val argument = host.parent as? KtValueArgument ?: return null + val annotationEntry = argument.parent.parent as? KtAnnotationEntry ?: return null + val callDescriptor = annotationEntry.getResolvedCall(annotationEntry.analyze())?.candidateDescriptor + val psiClass = (callDescriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() as? PsiClass ?: return null + val argumentName = argument.getArgumentName()?.asName?.identifier ?: "value" + val method = psiClass.findMethodsByName(argumentName, false).singleOrNull() ?: return null + return findInjection(method, Configuration.getInstance().getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)) + } + private fun injectionForJavaMethod(argument: KtValueArgument, javaMethod: PsiMethod): InjectionInfo? { val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument) val psiParameter = javaMethod.parameterList.parameters.getOrNull(argumentIndex) ?: return null diff --git a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt index bd96563bf60..3185c74f07b 100644 --- a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt @@ -488,4 +488,65 @@ class KotlinInjectionTest : AbstractInjectionTest() { Configuration.getInstance().replaceInjections(listOf(), listOf(customInjection), true) } } + + fun testInjectionInJavaAnnotation() { + val customInjection = BaseInjection("java") + customInjection.injectedLanguageId = HTMLLanguage.INSTANCE.id + val elementPattern = customInjection.compiler.createElementPattern( + """psiMethod().withName("value").withParameters().definedInClass("InHtml")""", + "SuppressWarnings temp rule") + customInjection.setInjectionPlaces(InjectionPlace(elementPattern, true)) + + try { + Configuration.getInstance().replaceInjections(listOf(customInjection), listOf(), true) + + doInjectionPresentTest( + """ + @InHtml("l>") + fun foo() { + } + """, """ + @interface InHtml { + String value(); + } + """.trimIndent(), + HTMLLanguage.INSTANCE.id, + unInjectShouldBePresent = false + ) + } + finally { + Configuration.getInstance().replaceInjections(listOf(), listOf(customInjection), true) + } + } + + fun testInjectionInJavaAnnotationWithNamedParam() { + val customInjection = BaseInjection("java") + customInjection.injectedLanguageId = HTMLLanguage.INSTANCE.id + val elementPattern = customInjection.compiler.createElementPattern( + """psiMethod().withName("html").withParameters().definedInClass("InHtml")""", + "SuppressWarnings temp rule") + customInjection.setInjectionPlaces(InjectionPlace(elementPattern, true)) + + try { + Configuration.getInstance().replaceInjections(listOf(customInjection), listOf(), true) + + doInjectionPresentTest( + """ + @InHtml(html = "l>") + fun foo() { + } + """, """ + @interface InHtml { + String html(); + } + """.trimIndent(), + HTMLLanguage.INSTANCE.id, + unInjectShouldBePresent = false + ) + } + finally { + Configuration.getInstance().replaceInjections(listOf(), listOf(customInjection), true) + } + } + }