diff --git a/ChangeLog.md b/ChangeLog.md index 0661b640fea..55eedd95785 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,8 +17,9 @@ New features: - [KT-11692](https://youtrack.jetbrains.com/issue/KT-11692) Support Spring model diagrams for Kotlin classes - [KT-11574](https://youtrack.jetbrains.com/issue/KT-11574) Support predefined Java positions for language injection - [KT-2428](https://youtrack.jetbrains.com/issue/KT-11574) Support basic use-cases of language injection for expressions marked with @Language annotation -- Add comment or @Language annotation after "Inject language or reference" intention automatically +- [KT-11472](https://youtrack.jetbrains.com/issue/KT-11472) Add comment or @Language annotation after "Inject language or reference" intention automatically - Apply injection for the literals in property initializer through property usages +- Enable injection in Kotlin by annotation function or method parameter with @Language annotation - [KT-11807](https://youtrack.jetbrains.com/issue/KT-11807) Use function body template when generating overriding functions with default body Issues fixed: diff --git a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjectionSupport.kt b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjectionSupport.kt index 3342a72cf3d..1cc721a66b7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjectionSupport.kt +++ b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjectionSupport.kt @@ -103,11 +103,13 @@ class KotlinLanguageInjectionSupport : AbstractLanguageInjectionSupport() { } } - fun findAnnotationInjectionLanguageId(host: KtElement): String? = doFindAnnotationInjectionLanguageId(host) + fun findAnnotationInjectionLanguageId(host: KtElement): String? { + val annotationEntry = findAnnotationInjection(host) ?: return null + return extractLanguageFromInjectAnnotation(annotationEntry) + } } -private fun doFindAnnotationInjectionLanguageId(host: KtElement): String? { - val annotationEntry = findAnnotationInjection(host) ?: return null +fun extractLanguageFromInjectAnnotation(annotationEntry: KtAnnotationEntry): String? { val firstArgument: ValueArgument = annotationEntry.valueArguments.firstOrNull() ?: return null val firstStringArgument = firstArgument.getArgumentExpression() as? KtStringTemplateExpression ?: return null diff --git a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt index efb8468f12c..57918c30339 100644 --- a/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt +++ b/idea/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.injection +import com.intellij.codeInsight.AnnotationUtil import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange @@ -27,6 +28,8 @@ import org.intellij.plugins.intelliLang.Configuration import org.intellij.plugins.intelliLang.inject.InjectorUtils import org.intellij.plugins.intelliLang.inject.config.BaseInjection import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport +import org.jetbrains.kotlin.idea.util.findAnnotation +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import java.util.* @@ -140,7 +143,14 @@ class KotlinLanguageInjector : LanguageInjector { val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument) val ktParameter = ktFunction.valueParameters.getOrNull(argumentIndex) ?: return null - return findInjection(ktParameter, Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID)) + val patternInjection = findInjection(ktParameter, Configuration.getInstance().getInjections(KOTLIN_SUPPORT_ID)) + if (patternInjection != null) { + return patternInjection + } + + val injectAnnotation = ktParameter.findAnnotation(FqName(AnnotationUtil.LANGUAGE)) ?: return null + val languageId = extractLanguageFromInjectAnnotation(injectAnnotation) ?: return null + return InjectionInfo(languageId, null, null) } private fun findInjection(element: PsiElement?, injections: List): InjectionInfo? { diff --git a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt index 1a962e6b434..000b8af438c 100644 --- a/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/psi/KotlinInjectionTest.kt @@ -299,4 +299,46 @@ class KotlinInjectionTest : AbstractInjectionTest() { } """ ) + + fun testInjectionWithUsageInFunctionWithMarkedParameterWithAnnotation() = assertInjectionPresent( + """ + import org.intellij.lang.annotations.Language + + val v = "some" + + fun foo(@Language("HTML") s: String) {} + + fun other() { foo(v) } + """, + languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false) + + fun testInjectionOfCustomParameterWithAnnotation() = assertInjectionPresent( + """ + import org.intellij.lang.annotations.Language + + fun foo(@Language("HTML") s: String) {} + + fun other() { foo("some") } + """, + languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false) + + fun testInjectionOfCustomParameterInConstructorWithAnnotation() = assertInjectionPresent( + """ + import org.intellij.lang.annotations.Language + + class Test(@Language("HTML") val s: String) + + fun other() { Test("some") } + """, + languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false) + + fun testInjectionOfCustomParameterDefaultCallWithAnnotation() = assertInjectionPresent( + """ + import org.intellij.lang.annotations.Language + + fun foo(@Language("HTML") s: String) {} + + fun other() { foo(s = "some") } + """, + languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false) } \ No newline at end of file