KotlinElementActionsFactory.createAddAnnotationActions: adding @field annotation target for targetless annotations (KT-18459)
This commit is contained in:
+40
-10
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.text.StringUtilRt
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
||||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
|
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
|
||||||
|
import com.intellij.psi.util.PropertyUtil
|
||||||
import com.intellij.psi.util.PropertyUtilBase
|
import com.intellij.psi.util.PropertyUtilBase
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||||
@@ -36,14 +37,14 @@ import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
|||||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
import org.jetbrains.kotlin.idea.core.appendModifier
|
import org.jetbrains.kotlin.idea.core.appendModifier
|
||||||
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
||||||
@@ -52,6 +53,7 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
|||||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreateCallableFromUsageFix
|
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreateCallableFromUsageFix
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
|
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||||
@@ -70,7 +72,9 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
||||||
|
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||||
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -449,11 +453,21 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
|
|||||||
override fun createAddAnnotationActions(target: JvmModifiersOwner, request: AnnotationRequest): List<IntentionAction> {
|
override fun createAddAnnotationActions(target: JvmModifiersOwner, request: AnnotationRequest): List<IntentionAction> {
|
||||||
val declaration = (target as? KtLightElement<*, *>)?.kotlinOrigin as? KtModifierListOwner ?: return emptyList()
|
val declaration = (target as? KtLightElement<*, *>)?.kotlinOrigin as? KtModifierListOwner ?: return emptyList()
|
||||||
if (declaration.language != KotlinLanguage.INSTANCE) return emptyList()
|
if (declaration.language != KotlinLanguage.INSTANCE) return emptyList()
|
||||||
return listOf(CreateAnnotationAction(declaration, request))
|
val annotationUseSiteTarget = when (target) {
|
||||||
|
is JvmField -> AnnotationUseSiteTarget.FIELD
|
||||||
|
is JvmMethod -> when {
|
||||||
|
PropertyUtil.isSimplePropertySetter(target as? PsiMethod) -> AnnotationUseSiteTarget.PROPERTY_SETTER
|
||||||
|
PropertyUtil.isSimplePropertyGetter(target as? PsiMethod) -> AnnotationUseSiteTarget.PROPERTY_GETTER
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
return listOf(CreateAnnotationAction(declaration, annotationUseSiteTarget, request))
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CreateAnnotationAction(
|
private class CreateAnnotationAction(
|
||||||
target: KtModifierListOwner,
|
target: KtModifierListOwner,
|
||||||
|
val annotationTarget: AnnotationUseSiteTarget?,
|
||||||
val request: AnnotationRequest
|
val request: AnnotationRequest
|
||||||
) : IntentionAction {
|
) : IntentionAction {
|
||||||
|
|
||||||
@@ -471,14 +485,30 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
|
|||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
|
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
|
||||||
val target = pointer.element ?: return
|
val target = pointer.element ?: return
|
||||||
val kotlinAnnotation = JavaPsiFacade.getInstance(project).findClass(
|
val annotationClass = JavaPsiFacade.getInstance(project).findClass(request.qualifiedName, target.resolveScope)
|
||||||
request.qualifiedName,
|
|
||||||
target.resolveScope
|
val kotlinAnnotation = annotationClass?.language == KotlinLanguage.INSTANCE
|
||||||
)?.language == KotlinLanguage.INSTANCE
|
|
||||||
|
val annotationUseSiteTargetPrefix = run prefixEvaluation@{
|
||||||
|
if (annotationTarget == null) return@prefixEvaluation ""
|
||||||
|
|
||||||
|
val moduleDescriptor = (target as? KtDeclaration)?.resolveToDescriptorIfAny()?.module ?: return@prefixEvaluation ""
|
||||||
|
val annotationClassDescriptor = moduleDescriptor.resolveClassByFqName(
|
||||||
|
FqName(request.qualifiedName), NoLookupLocation.FROM_IDE
|
||||||
|
) ?: return@prefixEvaluation ""
|
||||||
|
|
||||||
|
val applicableTargetSet =
|
||||||
|
AnnotationChecker.applicableTargetSet(annotationClassDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
|
||||||
|
|
||||||
|
if (KotlinTarget.PROPERTY !in applicableTargetSet) return@prefixEvaluation ""
|
||||||
|
|
||||||
|
"${annotationTarget.renderName}:"
|
||||||
|
}
|
||||||
|
|
||||||
val entry = target.addAnnotationEntry(
|
val entry = target.addAnnotationEntry(
|
||||||
KtPsiFactory(target)
|
KtPsiFactory(target)
|
||||||
.createAnnotationEntry(
|
.createAnnotationEntry(
|
||||||
"@${request.qualifiedName}${
|
"@$annotationUseSiteTargetPrefix${request.qualifiedName}${
|
||||||
request.attributes.mapIndexed { i, p ->
|
request.attributes.mapIndexed { i, p ->
|
||||||
if (!kotlinAnnotation && i == 0 && p.name == "value")
|
if (!kotlinAnnotation && i == 0 && p.name == "value")
|
||||||
renderAttributeValue(p.value).toString()
|
renderAttributeValue(p.value).toString()
|
||||||
|
|||||||
+40
-14
@@ -20,10 +20,7 @@ import com.intellij.codeInsight.daemon.QuickFixBundle
|
|||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import com.intellij.codeInsight.intention.QuickFixFactory
|
import com.intellij.codeInsight.intention.QuickFixFactory
|
||||||
import com.intellij.lang.java.beans.PropertyKind
|
import com.intellij.lang.java.beans.PropertyKind
|
||||||
import com.intellij.lang.jvm.JvmClass
|
import com.intellij.lang.jvm.*
|
||||||
import com.intellij.lang.jvm.JvmElement
|
|
||||||
import com.intellij.lang.jvm.JvmModifier
|
|
||||||
import com.intellij.lang.jvm.JvmModifiersOwner
|
|
||||||
import com.intellij.lang.jvm.actions.*
|
import com.intellij.lang.jvm.actions.*
|
||||||
import com.intellij.lang.jvm.types.JvmType
|
import com.intellij.lang.jvm.types.JvmType
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
@@ -32,6 +29,7 @@ import com.intellij.openapi.util.text.StringUtilRt
|
|||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
||||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
|
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
|
||||||
|
import com.intellij.psi.util.PropertyUtil
|
||||||
import com.intellij.psi.util.PropertyUtilBase
|
import com.intellij.psi.util.PropertyUtilBase
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
|
||||||
@@ -39,14 +37,14 @@ import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
|||||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
import org.jetbrains.kotlin.idea.core.appendModifier
|
import org.jetbrains.kotlin.idea.core.appendModifier
|
||||||
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
import org.jetbrains.kotlin.idea.quickfix.AddModifierFix
|
||||||
@@ -55,6 +53,7 @@ import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.*
|
|||||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreateCallableFromUsageFix
|
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreateCallableFromUsageFix
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
|
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||||
@@ -73,7 +72,9 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
||||||
|
import org.jetbrains.kotlin.resolve.AnnotationChecker
|
||||||
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -452,11 +453,21 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
|
|||||||
override fun createAddAnnotationActions(target: JvmModifiersOwner, request: AnnotationRequest): List<IntentionAction> {
|
override fun createAddAnnotationActions(target: JvmModifiersOwner, request: AnnotationRequest): List<IntentionAction> {
|
||||||
val declaration = (target as? KtLightElement<*, *>)?.kotlinOrigin as? KtModifierListOwner ?: return emptyList()
|
val declaration = (target as? KtLightElement<*, *>)?.kotlinOrigin as? KtModifierListOwner ?: return emptyList()
|
||||||
if (declaration.language != KotlinLanguage.INSTANCE) return emptyList()
|
if (declaration.language != KotlinLanguage.INSTANCE) return emptyList()
|
||||||
return listOf(CreateAnnotationAction(declaration, request))
|
val annotationUseSiteTarget = when (target) {
|
||||||
|
is JvmField -> AnnotationUseSiteTarget.FIELD
|
||||||
|
is JvmMethod -> when {
|
||||||
|
PropertyUtil.isSimplePropertySetter(target as? PsiMethod) -> AnnotationUseSiteTarget.PROPERTY_SETTER
|
||||||
|
PropertyUtil.isSimplePropertyGetter(target as? PsiMethod) -> AnnotationUseSiteTarget.PROPERTY_GETTER
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
return listOf(CreateAnnotationAction(declaration, annotationUseSiteTarget, request))
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CreateAnnotationAction(
|
private class CreateAnnotationAction(
|
||||||
target: KtModifierListOwner,
|
target: KtModifierListOwner,
|
||||||
|
val annotationTarget: AnnotationUseSiteTarget?,
|
||||||
val request: AnnotationRequest
|
val request: AnnotationRequest
|
||||||
) : IntentionAction {
|
) : IntentionAction {
|
||||||
|
|
||||||
@@ -474,14 +485,29 @@ class KotlinElementActionsFactory : JvmElementActionsFactory() {
|
|||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
|
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
|
||||||
val target = pointer.element ?: return
|
val target = pointer.element ?: return
|
||||||
val kotlinAnnotation = JavaPsiFacade.getInstance(project).findClass(
|
val annotationClass = JavaPsiFacade.getInstance(project).findClass(request.qualifiedName, target.resolveScope)
|
||||||
request.qualifiedName,
|
|
||||||
target.resolveScope
|
val kotlinAnnotation = annotationClass?.language == KotlinLanguage.INSTANCE
|
||||||
)?.language == KotlinLanguage.INSTANCE
|
|
||||||
|
val annotationUseSiteTargetPrefix = run prefixEvaluation@{
|
||||||
|
if (annotationTarget == null) return@prefixEvaluation ""
|
||||||
|
|
||||||
|
val moduleDescriptor = (target as? KtDeclaration)?.resolveToDescriptorIfAny()?.module ?: return@prefixEvaluation ""
|
||||||
|
val annotationClassDescriptor = moduleDescriptor.resolveClassByFqName(
|
||||||
|
FqName(request.qualifiedName), NoLookupLocation.FROM_IDE
|
||||||
|
) ?: return@prefixEvaluation ""
|
||||||
|
|
||||||
|
val applicableTargetSet = AnnotationChecker.applicableTargetSet(annotationClassDescriptor) ?: KotlinTarget.DEFAULT_TARGET_SET
|
||||||
|
|
||||||
|
if (KotlinTarget.PROPERTY !in applicableTargetSet) return@prefixEvaluation ""
|
||||||
|
|
||||||
|
"${annotationTarget.renderName}:"
|
||||||
|
}
|
||||||
|
|
||||||
val entry = target.addAnnotationEntry(
|
val entry = target.addAnnotationEntry(
|
||||||
KtPsiFactory(target)
|
KtPsiFactory(target)
|
||||||
.createAnnotationEntry(
|
.createAnnotationEntry(
|
||||||
"@${request.qualifiedName}${
|
"@$annotationUseSiteTargetPrefix${request.qualifiedName}${
|
||||||
request.attributes.mapIndexed { i, p ->
|
request.attributes.mapIndexed { i, p ->
|
||||||
if (!kotlinAnnotation && i == 0 && p.name == "value")
|
if (!kotlinAnnotation && i == 0 && p.name == "value")
|
||||||
renderAttributeValue(p.value).toString()
|
renderAttributeValue(p.value).toString()
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.idea.quickfix
|
|||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import com.intellij.lang.jvm.JvmClass
|
import com.intellij.lang.jvm.JvmClass
|
||||||
import com.intellij.lang.jvm.JvmElement
|
import com.intellij.lang.jvm.JvmElement
|
||||||
import com.intellij.lang.jvm.JvmMethod
|
|
||||||
import com.intellij.lang.jvm.JvmModifier
|
import com.intellij.lang.jvm.JvmModifier
|
||||||
import com.intellij.lang.jvm.actions.*
|
import com.intellij.lang.jvm.actions.*
|
||||||
import com.intellij.lang.jvm.types.JvmSubstitutor
|
import com.intellij.lang.jvm.types.JvmSubstitutor
|
||||||
@@ -19,6 +18,7 @@ import com.intellij.psi.*
|
|||||||
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
||||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
|
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
|
||||||
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.asJava.toLightElements
|
import org.jetbrains.kotlin.asJava.toLightElements
|
||||||
import org.jetbrains.kotlin.idea.search.allScope
|
import org.jetbrains.kotlin.idea.search.allScope
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
@@ -240,6 +240,113 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testAddJavaAnnotationOnFieldWithoutTarget() {
|
||||||
|
|
||||||
|
myFixture.addFileToProject(
|
||||||
|
"pkg/myannotation/JavaAnnotation.java", """
|
||||||
|
package pkg.myannotation
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
//no @Target
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JavaAnnotation {
|
||||||
|
String value();
|
||||||
|
int param() default 0;
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"foo.kt", """class Foo {
|
||||||
|
| val bar: String = null
|
||||||
|
|}""".trim().trimMargin()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.launchAction(
|
||||||
|
createAddAnnotationActions(
|
||||||
|
myFixture.findElementByText("bar", KtModifierListOwner::class.java).toLightElements().single { it is PsiField } as PsiField,
|
||||||
|
annotationRequest("pkg.myannotation.JavaAnnotation")
|
||||||
|
).single()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.checkResult(
|
||||||
|
"""
|
||||||
|
import pkg.myannotation.JavaAnnotation
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
@field:JavaAnnotation()
|
||||||
|
val bar: String = null
|
||||||
|
}
|
||||||
|
""".trimIndent(), true
|
||||||
|
)
|
||||||
|
|
||||||
|
TestCase.assertEquals(
|
||||||
|
"KtLightMethodImpl -> org.jetbrains.annotations.NotNull," +
|
||||||
|
" KtLightFieldForDeclaration -> pkg.myannotation.JavaAnnotation, org.jetbrains.annotations.NotNull",
|
||||||
|
annotationsString(myFixture.findElementByText("bar", KtModifierListOwner::class.java))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testAddJavaAnnotationOnField() {
|
||||||
|
|
||||||
|
myFixture.addFileToProject(
|
||||||
|
"pkg/myannotation/JavaAnnotation.java", """
|
||||||
|
package pkg.myannotation
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JavaAnnotation {
|
||||||
|
String value();
|
||||||
|
int param() default 0;
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"foo.kt", """class Foo {
|
||||||
|
| val bar: String = null
|
||||||
|
|}""".trim().trimMargin()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.launchAction(
|
||||||
|
createAddAnnotationActions(
|
||||||
|
myFixture.findElementByText("bar", KtModifierListOwner::class.java).toLightElements().single { it is PsiField } as PsiField,
|
||||||
|
annotationRequest("pkg.myannotation.JavaAnnotation")
|
||||||
|
).single()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.checkResult(
|
||||||
|
"""
|
||||||
|
import pkg.myannotation.JavaAnnotation
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
@JavaAnnotation()
|
||||||
|
val bar: String = null
|
||||||
|
}
|
||||||
|
""".trimIndent(), true
|
||||||
|
)
|
||||||
|
|
||||||
|
TestCase.assertEquals(
|
||||||
|
"KtLightMethodImpl -> org.jetbrains.annotations.NotNull," +
|
||||||
|
" KtLightFieldForDeclaration -> pkg.myannotation.JavaAnnotation, org.jetbrains.annotations.NotNull",
|
||||||
|
annotationsString(myFixture.findElementByText("bar", KtModifierListOwner::class.java))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun annotationsString(findElementByText: KtModifierListOwner) = findElementByText.toLightElements()
|
||||||
|
.joinToString { elem -> "${elem.javaClass.simpleName} -> ${(elem as PsiModifierListOwner).annotations.joinToString { it.qualifiedName!! }}" }
|
||||||
|
|
||||||
fun testDontMakePublicPublic() {
|
fun testDontMakePublicPublic() {
|
||||||
myFixture.configureByText(
|
myFixture.configureByText(
|
||||||
"foo.kt", """class Foo {
|
"foo.kt", """class Foo {
|
||||||
|
|||||||
@@ -13,13 +13,11 @@ import com.intellij.lang.jvm.actions.*
|
|||||||
import com.intellij.lang.jvm.types.JvmSubstitutor
|
import com.intellij.lang.jvm.types.JvmSubstitutor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.Pair.pair
|
import com.intellij.openapi.util.Pair.pair
|
||||||
import com.intellij.psi.PsiJvmSubstitutor
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.PsiMethod
|
|
||||||
import com.intellij.psi.PsiSubstitutor
|
|
||||||
import com.intellij.psi.PsiType
|
|
||||||
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
import com.intellij.psi.codeStyle.SuggestedNameInfo
|
||||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
|
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase
|
||||||
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.asJava.toLightElements
|
import org.jetbrains.kotlin.asJava.toLightElements
|
||||||
import org.jetbrains.kotlin.idea.search.allScope
|
import org.jetbrains.kotlin.idea.search.allScope
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
@@ -238,6 +236,113 @@ class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testAddJavaAnnotationOnFieldWithoutTarget() {
|
||||||
|
|
||||||
|
myFixture.addFileToProject(
|
||||||
|
"pkg/myannotation/JavaAnnotation.java", """
|
||||||
|
package pkg.myannotation
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
//no @Target
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JavaAnnotation {
|
||||||
|
String value();
|
||||||
|
int param() default 0;
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"foo.kt", """class Foo {
|
||||||
|
| val bar: String = null
|
||||||
|
|}""".trim().trimMargin()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.launchAction(
|
||||||
|
createAddAnnotationActions(
|
||||||
|
myFixture.findElementByText("bar", KtModifierListOwner::class.java).toLightElements().single { it is PsiField } as PsiField,
|
||||||
|
annotationRequest("pkg.myannotation.JavaAnnotation")
|
||||||
|
).single()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.checkResult(
|
||||||
|
"""
|
||||||
|
import pkg.myannotation.JavaAnnotation
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
@field:JavaAnnotation()
|
||||||
|
val bar: String = null
|
||||||
|
}
|
||||||
|
""".trimIndent(), true
|
||||||
|
)
|
||||||
|
|
||||||
|
TestCase.assertEquals(
|
||||||
|
"KtLightMethodImpl -> org.jetbrains.annotations.NotNull," +
|
||||||
|
" KtLightFieldForDeclaration -> pkg.myannotation.JavaAnnotation, org.jetbrains.annotations.NotNull",
|
||||||
|
annotationsString(myFixture.findElementByText("bar", KtModifierListOwner::class.java))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testAddJavaAnnotationOnField() {
|
||||||
|
|
||||||
|
myFixture.addFileToProject(
|
||||||
|
"pkg/myannotation/JavaAnnotation.java", """
|
||||||
|
package pkg.myannotation
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface JavaAnnotation {
|
||||||
|
String value();
|
||||||
|
int param() default 0;
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.configureByText(
|
||||||
|
"foo.kt", """class Foo {
|
||||||
|
| val bar: String = null
|
||||||
|
|}""".trim().trimMargin()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.launchAction(
|
||||||
|
createAddAnnotationActions(
|
||||||
|
myFixture.findElementByText("bar", KtModifierListOwner::class.java).toLightElements().single { it is PsiField } as PsiField,
|
||||||
|
annotationRequest("pkg.myannotation.JavaAnnotation")
|
||||||
|
).single()
|
||||||
|
)
|
||||||
|
|
||||||
|
myFixture.checkResult(
|
||||||
|
"""
|
||||||
|
import pkg.myannotation.JavaAnnotation
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
@JavaAnnotation()
|
||||||
|
val bar: String = null
|
||||||
|
}
|
||||||
|
""".trimIndent(), true
|
||||||
|
)
|
||||||
|
|
||||||
|
TestCase.assertEquals(
|
||||||
|
"KtLightMethodImpl -> org.jetbrains.annotations.NotNull," +
|
||||||
|
" KtLightFieldForDeclaration -> pkg.myannotation.JavaAnnotation, org.jetbrains.annotations.NotNull",
|
||||||
|
annotationsString(myFixture.findElementByText("bar", KtModifierListOwner::class.java))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun annotationsString(findElementByText: KtModifierListOwner) = findElementByText.toLightElements()
|
||||||
|
.joinToString { elem -> "${elem.javaClass.simpleName} -> ${(elem as PsiModifierListOwner).annotations.joinToString { it.qualifiedName!! }}" }
|
||||||
|
|
||||||
fun testDontMakePublicPublic() {
|
fun testDontMakePublicPublic() {
|
||||||
myFixture.configureByText(
|
myFixture.configureByText(
|
||||||
"foo.kt", """class Foo {
|
"foo.kt", """class Foo {
|
||||||
|
|||||||
Reference in New Issue
Block a user