KotlinLanguageInjector: support for nested annotations (#KT-21753)

This commit is contained in:
Nicolay Mitropolsky
2018-02-27 15:11:38 +03:00
parent 5c04264218
commit fd4f4ef853
2 changed files with 47 additions and 4 deletions
@@ -276,9 +276,14 @@ class KotlinLanguageInjector(
private fun injectInAnnotationCall(host: KtElement): InjectionInfo? {
if (!annotationInjectionsEnabled) return null
val argument = host.parent as? KtValueArgument ?: return null
val annotationEntry = argument.parent.parent as? KtAnnotationEntry ?: return null
val annotationEntry = argument.parent.parent as? KtCallElement ?: return null
if (!fastCheckInjectionsExists(annotationEntry)) return null
val calleeReference = annotationEntry.calleeExpression?.constructorReferenceExpression?.mainReference
val calleeExpression = annotationEntry.calleeExpression ?: return null
val calleeReference = when (calleeExpression) {
is KtConstructorCalleeExpression -> calleeExpression.constructorReferenceExpression?.mainReference // for top annotations
is KtNameReferenceExpression -> calleeExpression.mainReference // for nested annotations
else -> return null
}
val callee = calleeReference?.resolve()
when (callee) {
is KtFunction -> return injectionForKotlinCall(argument, callee, calleeReference)
@@ -378,8 +383,13 @@ class KotlinLanguageInjector(
}, configuration)
}, false)
private fun fastCheckInjectionsExists(annotationEntry: KtAnnotationEntry): Boolean {
val referencedName = (annotationEntry.typeReference?.typeElement as? KtUserType)?.referencedName ?: return false
private fun fastCheckInjectionsExists(annotationEntry: KtCallElement): Boolean {
val referencedName = when (annotationEntry) {
is KtAnnotationEntry -> // for top annotations
(annotationEntry.typeReference?.typeElement as? KtUserType)?.referencedName ?: return false
else -> // for nested annotations
(annotationEntry.calleeExpression as? KtNameReferenceExpression)?.getReferencedName() ?: return false
}
val annotationShortName = annotationEntry.containingKtFile.aliasImportMap()[referencedName].singleOrNull() ?: referencedName
return annotationShortName in injectableTargetClassShortNames.value
}
@@ -519,6 +519,39 @@ class KotlinInjectionTest : AbstractInjectionTest() {
""")
}
fun testInjectionInJavaNestedAnnotation() {
myFixture.addClass(
"""
package myinjection;
public @interface InHtml {
String html();
}
"""
)
myFixture.addClass(
"""
package myinjection;
public @interface InHtmls {
InHtml[] htmls();
}
"""
)
doAnnotationInjectionTest(
injectedLanguage = HTMLLanguage.INSTANCE.id,
pattern = """psiMethod().withName("html").withParameters().definedInClass("myinjection.InHtml")""",
kotlinCode = """
import myinjection.InHtml
import myinjection.InHtmls
@InHtmls(htmls = [InHtml(html = "<htm<caret>l></html>")])
fun foo() {
}
"""
)
}
fun testInjectionInAliasedJavaAnnotation() {
myFixture.addClass("""
@interface InHtml {