Make parameter injection work for Java methods
This commit is contained in:
+1
-1
@@ -19,7 +19,7 @@ New features:
|
|||||||
- [KT-2428](https://youtrack.jetbrains.com/issue/KT-11574) Support basic use-cases of language injection for expressions marked with @Language annotation
|
- [KT-2428](https://youtrack.jetbrains.com/issue/KT-11574) Support basic use-cases of language injection for expressions marked with @Language annotation
|
||||||
- [KT-11472](https://youtrack.jetbrains.com/issue/KT-11472) 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
|
- Apply injection for the literals in property initializer through property usages
|
||||||
- Enable injection in Kotlin by annotation function or method parameter with @Language annotation
|
- Enable injection from Java or Kotlin function declaration by annotating parameter with @Language annotation
|
||||||
- [KT-11807](https://youtrack.jetbrains.com/issue/KT-11807) Use function body template when generating overriding functions with default body
|
- [KT-11807](https://youtrack.jetbrains.com/issue/KT-11807) Use function body template when generating overriding functions with default body
|
||||||
|
|
||||||
Issues fixed:
|
Issues fixed:
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.intellij.plugins.intelliLang.Configuration
|
|||||||
import org.intellij.plugins.intelliLang.inject.InjectorUtils
|
import org.intellij.plugins.intelliLang.inject.InjectorUtils
|
||||||
import org.intellij.plugins.intelliLang.inject.config.BaseInjection
|
import org.intellij.plugins.intelliLang.inject.config.BaseInjection
|
||||||
import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport
|
import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport
|
||||||
|
import org.intellij.plugins.intelliLang.util.AnnotationUtilEx
|
||||||
import org.jetbrains.kotlin.idea.util.findAnnotation
|
import org.jetbrains.kotlin.idea.util.findAnnotation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -136,7 +137,21 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
|
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
|
||||||
val psiParameter = javaMethod.parameterList.parameters.getOrNull(argumentIndex) ?: return null
|
val psiParameter = javaMethod.parameterList.parameters.getOrNull(argumentIndex) ?: return null
|
||||||
|
|
||||||
return findInjection(psiParameter, Configuration.getInstance().getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID))
|
val injectionInfo = findInjection(psiParameter, Configuration.getInstance().getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID))
|
||||||
|
if (injectionInfo != null) {
|
||||||
|
return injectionInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
val annotations = AnnotationUtilEx.getAnnotationFrom(
|
||||||
|
psiParameter,
|
||||||
|
Configuration.getProjectInstance(psiParameter.project).advancedConfiguration.languageAnnotationPair,
|
||||||
|
true)
|
||||||
|
|
||||||
|
if (annotations.size > 0) {
|
||||||
|
return processAnnotationInjectionInner(annotations)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun injectionForKotlinCall(argument: KtValueArgument, ktFunction: KtFunction): InjectionInfo? {
|
private fun injectionForKotlinCall(argument: KtValueArgument, ktFunction: KtFunction): InjectionInfo? {
|
||||||
@@ -168,4 +183,12 @@ class KotlinLanguageInjector : LanguageInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class InjectionInfo(val languageId: String?, val prefix: String?, val suffix: String?)
|
private class InjectionInfo(val languageId: String?, val prefix: String?, val suffix: String?)
|
||||||
|
|
||||||
|
private fun processAnnotationInjectionInner(annotations: Array<PsiAnnotation>): InjectionInfo? {
|
||||||
|
val id = AnnotationUtilEx.calcAnnotationValue(annotations, "value")
|
||||||
|
val prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix")
|
||||||
|
val suffix = AnnotationUtilEx.calcAnnotationValue(annotations, "suffix")
|
||||||
|
|
||||||
|
return InjectionInfo(id, prefix, suffix)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
import org.intellij.lang.annotations.Language;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public Test(@Language("HTML") String str) {
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fun bar() {
|
||||||
|
Test("<caret>some")
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import org.intellij.lang.annotations.Language;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public static void foo(@Language("HTML") String str) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import some.Test
|
||||||
|
|
||||||
|
fun bar() { Test.foo("<caret>some") }
|
||||||
@@ -39,15 +39,19 @@ abstract class AbstractInjectionTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun assertInjectionPresent(text: String, languageId: String? = null, unInjectShouldBePresent: Boolean = true) {
|
protected fun doInjectionPresentTest(text: String, languageId: String? = null, unInjectShouldBePresent: Boolean = true) {
|
||||||
myFixture.configureByText("${getTestName(true)}.kt", text.trimIndent())
|
myFixture.configureByText("${getTestName(true)}.kt", text.trimIndent())
|
||||||
|
assertInjectionPresent(languageId, unInjectShouldBePresent)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected fun assertInjectionPresent(languageId: String?, unInjectShouldBePresent: Boolean) {
|
||||||
TestCase.assertFalse("Injection action is available. There's probably no injection at caret place",
|
TestCase.assertFalse("Injection action is available. There's probably no injection at caret place",
|
||||||
InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file))
|
InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file))
|
||||||
|
|
||||||
if (languageId != null) {
|
if (languageId != null) {
|
||||||
val injectedFile = (editor as? EditorWindow)?.injectedFile
|
val injectedFile = (editor as? EditorWindow)?.injectedFile
|
||||||
KotlinLightCodeInsightFixtureTestCaseBase.assertEquals("Wrong injection language", languageId, injectedFile?.language?.id)
|
assertEquals("Wrong injection language", languageId, injectedFile?.language?.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unInjectShouldBePresent) {
|
if (unInjectShouldBePresent) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
TestCase.assertNull(myFixture.getReferenceAtCaretPosition())
|
TestCase.assertNull(myFixture.getReferenceAtCaretPosition())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testInjectionOnJavaPredefinedMethodWithAnnotation() = assertInjectionPresent(
|
fun testInjectionOnJavaPredefinedMethodWithAnnotation() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
val test1 = java.util.regex.Pattern.compile("<caret>pattern")
|
val test1 = java.util.regex.Pattern.compile("<caret>pattern")
|
||||||
""",
|
""",
|
||||||
@@ -63,7 +63,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
try {
|
try {
|
||||||
Configuration.getInstance().replaceInjections(listOf(customInjection), listOf(), true)
|
Configuration.getInstance().replaceInjections(listOf(customInjection), listOf(), true)
|
||||||
|
|
||||||
assertInjectionPresent(
|
doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
val stringBuilder = StringBuilder().replace(0, 0, "<caret><html></html>")
|
val stringBuilder = StringBuilder().replace(0, 0, "<caret><html></html>")
|
||||||
""",
|
""",
|
||||||
@@ -76,20 +76,20 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testInjectionWithCommentOnProperty() = assertInjectionPresent(
|
fun testInjectionWithCommentOnProperty() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
//language=file-reference
|
//language=file-reference
|
||||||
val test = "<caret>simple"
|
val test = "<caret>simple"
|
||||||
""")
|
""")
|
||||||
|
|
||||||
fun testInjectionWithUsageOnReceiverWithRuntime() = assertInjectionPresent(
|
fun testInjectionWithUsageOnReceiverWithRuntime() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
val test = "<caret>some"
|
val test = "<caret>some"
|
||||||
fun foo() = test.toRegex()
|
fun foo() = test.toRegex()
|
||||||
""",
|
""",
|
||||||
languageId = RegExpLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
languageId = RegExpLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||||
|
|
||||||
fun testInjectionWithUsageInParameterWithRuntime() = assertInjectionPresent(
|
fun testInjectionWithUsageInParameterWithRuntime() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
val test = "<caret>some"
|
val test = "<caret>some"
|
||||||
fun foo() = Regex(test)
|
fun foo() = Regex(test)
|
||||||
@@ -103,7 +103,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
fun foo() = Regex(test)
|
fun foo() = Regex(test)
|
||||||
""")
|
""")
|
||||||
|
|
||||||
fun testInjectionWithMultipleCommentsOnFun() = assertInjectionPresent(
|
fun testInjectionWithMultipleCommentsOnFun() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
// Some comment
|
// Some comment
|
||||||
// Other comment
|
// Other comment
|
||||||
@@ -111,7 +111,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
fun test() = "<caret>simple"
|
fun test() = "<caret>simple"
|
||||||
""")
|
""")
|
||||||
|
|
||||||
fun testInjectionWithAnnotationOnPropertyWithAnnotation() = assertInjectionPresent(
|
fun testInjectionWithAnnotationOnPropertyWithAnnotation() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
@org.intellij.lang.annotations.Language("file-reference")
|
@org.intellij.lang.annotations.Language("file-reference")
|
||||||
val test = "<caret>simple"
|
val test = "<caret>simple"
|
||||||
@@ -300,7 +300,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
fun testInjectionWithUsageInFunctionWithMarkedParameterWithAnnotation() = assertInjectionPresent(
|
fun testInjectionWithUsageInFunctionWithMarkedParameterWithAnnotation() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
""",
|
""",
|
||||||
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||||
|
|
||||||
fun testInjectionOfCustomParameterWithAnnotation() = assertInjectionPresent(
|
fun testInjectionOfCustomParameterWithAnnotation() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
""",
|
""",
|
||||||
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||||
|
|
||||||
fun testInjectionOfCustomParameterInConstructorWithAnnotation() = assertInjectionPresent(
|
fun testInjectionOfCustomParameterInConstructorWithAnnotation() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
""",
|
""",
|
||||||
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||||
|
|
||||||
fun testInjectionOfCustomParameterDefaultCallWithAnnotation() = assertInjectionPresent(
|
fun testInjectionOfCustomParameterDefaultCallWithAnnotation() = doInjectionPresentTest(
|
||||||
"""
|
"""
|
||||||
import org.intellij.lang.annotations.Language
|
import org.intellij.lang.annotations.Language
|
||||||
|
|
||||||
@@ -341,4 +341,42 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
|||||||
fun other() { foo(s = "<caret>some") }
|
fun other() { foo(s = "<caret>some") }
|
||||||
""",
|
""",
|
||||||
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||||
|
|
||||||
|
// fun testInjectionOfCustomParameterJavaWithAnnotation() = dotInjectionPresentTest(
|
||||||
|
// """
|
||||||
|
// import some.Test
|
||||||
|
//
|
||||||
|
// fun bar() { Test.foo("<caret>some") }
|
||||||
|
// """,
|
||||||
|
// javaCode =
|
||||||
|
// """
|
||||||
|
// package some;
|
||||||
|
//
|
||||||
|
// import org.intellij.lang.annotations.Language;
|
||||||
|
//
|
||||||
|
// public class Test {
|
||||||
|
// public static void foo(@Language("HTML") String str) {}
|
||||||
|
// }
|
||||||
|
// """,
|
||||||
|
// languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// fun testInjectionOfCustomParameterInJavaConstructorWithAnnotation() = dotInjectionPresentTest(
|
||||||
|
// """
|
||||||
|
// import some.Test
|
||||||
|
//
|
||||||
|
// fun bar() { Test("<caret>some") }
|
||||||
|
// """,
|
||||||
|
// javaCode =
|
||||||
|
// """
|
||||||
|
// package some;
|
||||||
|
//
|
||||||
|
// import org.intellij.lang.annotations.Language;
|
||||||
|
//
|
||||||
|
// public class Test {
|
||||||
|
// public Test(@Language("HTML") String str) {}
|
||||||
|
// }
|
||||||
|
// """,
|
||||||
|
// languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false
|
||||||
|
// )
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
|
import com.intellij.lang.html.HTMLLanguage
|
||||||
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||||
|
|
||||||
|
class KotlinMultiFileInjectionTest : AbstractInjectionTest() {
|
||||||
|
public override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
myFixture.testDataPath = PluginTestCaseBase.getTestDataPathBase() + "/injection"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testInjectionOfCustomParameterInJavaConstructorWithAnnotation() = doMultiFileInjectionPresentTest(HTMLLanguage.INSTANCE.id, false)
|
||||||
|
|
||||||
|
fun testInjectionOfCustomParameterJavaWithAnnotation() = doMultiFileInjectionPresentTest(HTMLLanguage.INSTANCE.id, false)
|
||||||
|
|
||||||
|
override fun getTestDataPath(): String? {
|
||||||
|
return "idea/testData/injection/"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doMultiFileInjectionPresentTest(languageId: String? = null, unInjectShouldBePresent: Boolean = true) {
|
||||||
|
val testName = getTestName(false)
|
||||||
|
|
||||||
|
myFixture.configureByFile("$testName.java")
|
||||||
|
myFixture.configureByFile("$testName.kt")
|
||||||
|
|
||||||
|
assertInjectionPresent(languageId, unInjectShouldBePresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class KotlinStdlibInjectionTest : AbstractInjectionTest() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private fun assertInjectionPresent(text: String, languageId: String) {
|
private fun assertInjectionPresent(text: String, languageId: String) {
|
||||||
assertInjectionPresent(text, languageId, false)
|
doInjectionPresentTest(text, languageId = languageId, unInjectShouldBePresent = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||||
|
|||||||
Reference in New Issue
Block a user