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-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
|
||||
- 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
|
||||
|
||||
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.config.BaseInjection
|
||||
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.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -136,7 +137,21 @@ class KotlinLanguageInjector : LanguageInjector {
|
||||
val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument)
|
||||
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? {
|
||||
@@ -168,4 +183,12 @@ class KotlinLanguageInjector : LanguageInjector {
|
||||
}
|
||||
|
||||
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())
|
||||
assertInjectionPresent(languageId, unInjectShouldBePresent)
|
||||
}
|
||||
|
||||
|
||||
protected fun assertInjectionPresent(languageId: String?, unInjectShouldBePresent: Boolean) {
|
||||
TestCase.assertFalse("Injection action is available. There's probably no injection at caret place",
|
||||
InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file))
|
||||
|
||||
if (languageId != null) {
|
||||
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) {
|
||||
|
||||
@@ -44,7 +44,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
TestCase.assertNull(myFixture.getReferenceAtCaretPosition())
|
||||
}
|
||||
|
||||
fun testInjectionOnJavaPredefinedMethodWithAnnotation() = assertInjectionPresent(
|
||||
fun testInjectionOnJavaPredefinedMethodWithAnnotation() = doInjectionPresentTest(
|
||||
"""
|
||||
val test1 = java.util.regex.Pattern.compile("<caret>pattern")
|
||||
""",
|
||||
@@ -63,7 +63,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
try {
|
||||
Configuration.getInstance().replaceInjections(listOf(customInjection), listOf(), true)
|
||||
|
||||
assertInjectionPresent(
|
||||
doInjectionPresentTest(
|
||||
"""
|
||||
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
|
||||
val test = "<caret>simple"
|
||||
""")
|
||||
|
||||
fun testInjectionWithUsageOnReceiverWithRuntime() = assertInjectionPresent(
|
||||
fun testInjectionWithUsageOnReceiverWithRuntime() = doInjectionPresentTest(
|
||||
"""
|
||||
val test = "<caret>some"
|
||||
fun foo() = test.toRegex()
|
||||
""",
|
||||
languageId = RegExpLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||
|
||||
fun testInjectionWithUsageInParameterWithRuntime() = assertInjectionPresent(
|
||||
fun testInjectionWithUsageInParameterWithRuntime() = doInjectionPresentTest(
|
||||
"""
|
||||
val test = "<caret>some"
|
||||
fun foo() = Regex(test)
|
||||
@@ -103,7 +103,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
fun foo() = Regex(test)
|
||||
""")
|
||||
|
||||
fun testInjectionWithMultipleCommentsOnFun() = assertInjectionPresent(
|
||||
fun testInjectionWithMultipleCommentsOnFun() = doInjectionPresentTest(
|
||||
"""
|
||||
// Some comment
|
||||
// Other comment
|
||||
@@ -111,7 +111,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
fun test() = "<caret>simple"
|
||||
""")
|
||||
|
||||
fun testInjectionWithAnnotationOnPropertyWithAnnotation() = assertInjectionPresent(
|
||||
fun testInjectionWithAnnotationOnPropertyWithAnnotation() = doInjectionPresentTest(
|
||||
"""
|
||||
@org.intellij.lang.annotations.Language("file-reference")
|
||||
val test = "<caret>simple"
|
||||
@@ -300,7 +300,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
"""
|
||||
)
|
||||
|
||||
fun testInjectionWithUsageInFunctionWithMarkedParameterWithAnnotation() = assertInjectionPresent(
|
||||
fun testInjectionWithUsageInFunctionWithMarkedParameterWithAnnotation() = doInjectionPresentTest(
|
||||
"""
|
||||
import org.intellij.lang.annotations.Language
|
||||
|
||||
@@ -312,7 +312,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
""",
|
||||
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||
|
||||
fun testInjectionOfCustomParameterWithAnnotation() = assertInjectionPresent(
|
||||
fun testInjectionOfCustomParameterWithAnnotation() = doInjectionPresentTest(
|
||||
"""
|
||||
import org.intellij.lang.annotations.Language
|
||||
|
||||
@@ -322,7 +322,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
""",
|
||||
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||
|
||||
fun testInjectionOfCustomParameterInConstructorWithAnnotation() = assertInjectionPresent(
|
||||
fun testInjectionOfCustomParameterInConstructorWithAnnotation() = doInjectionPresentTest(
|
||||
"""
|
||||
import org.intellij.lang.annotations.Language
|
||||
|
||||
@@ -332,7 +332,7 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
""",
|
||||
languageId = HTMLLanguage.INSTANCE.id, unInjectShouldBePresent = false)
|
||||
|
||||
fun testInjectionOfCustomParameterDefaultCallWithAnnotation() = assertInjectionPresent(
|
||||
fun testInjectionOfCustomParameterDefaultCallWithAnnotation() = doInjectionPresentTest(
|
||||
"""
|
||||
import org.intellij.lang.annotations.Language
|
||||
|
||||
@@ -341,4 +341,42 @@ class KotlinInjectionTest : AbstractInjectionTest() {
|
||||
fun other() { foo(s = "<caret>some") }
|
||||
""",
|
||||
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) {
|
||||
assertInjectionPresent(text, languageId, false)
|
||||
doInjectionPresentTest(text, languageId = languageId, unInjectShouldBePresent = false)
|
||||
}
|
||||
|
||||
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||
|
||||
Reference in New Issue
Block a user