Fix RemoveExpressionTargetFix and don't remove the whole annotation (KT-25574)

This commit is contained in:
Nikolay Krasko
2019-04-08 13:07:58 +03:00
parent ecda8cd889
commit a9beb04cb7
6 changed files with 59 additions and 5 deletions
@@ -9,9 +9,11 @@ import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
@@ -28,9 +30,10 @@ object RestrictedRetentionForExpressionAnnotationFactory : KotlinIntentionAction
val containingClass = annotationEntry.containingClass() ?: return emptyList()
val retentionAnnotation = containingClass.annotation(KotlinBuiltIns.FQ_NAMES.retention)
val targetAnnotation = containingClass.annotation(KotlinBuiltIns.FQ_NAMES.target)
val expressionTargetArgument = if (targetAnnotation != null) findExpressionTargetArgument(targetAnnotation) else null
return listOfNotNull(
if (targetAnnotation != null) RemoveExpressionTargetFix(targetAnnotation) else null,
if (expressionTargetArgument != null) RemoveExpressionTargetFix(expressionTargetArgument) else null,
if (retentionAnnotation == null) AddSourceRetentionFix(containingClass) else ChangeRetentionToSourceFix(retentionAnnotation)
)
}
@@ -42,6 +45,20 @@ object RestrictedRetentionForExpressionAnnotationFactory : KotlinIntentionAction
}
}
private fun findExpressionTargetArgument(targetAnnotation: KtAnnotationEntry): KtValueArgument? {
val valueArgumentList = targetAnnotation.valueArgumentList ?: return null
if (targetAnnotation.lambdaArguments.isNotEmpty()) return null
for (valueArgument in valueArgumentList.arguments) {
val argumentExpression = valueArgument.getArgumentExpression() ?: continue
if (argumentExpression.text.contains(KotlinTarget.EXPRESSION.toString())) {
return valueArgument
}
}
return null
}
private class AddSourceRetentionFix(element: KtClass) : KotlinQuickFixAction<KtClass>(element) {
override fun getText() = "Add SOURCE retention"
@@ -78,16 +95,23 @@ object RestrictedRetentionForExpressionAnnotationFactory : KotlinIntentionAction
}
}
private class RemoveExpressionTargetFix(targetAnnotation: KtAnnotationEntry) :
KotlinQuickFixAction<KtAnnotationEntry>(targetAnnotation) {
private class RemoveExpressionTargetFix(expressionTargetArgument: KtValueArgument) :
KotlinQuickFixAction<KtValueArgument>(expressionTargetArgument) {
override fun getText() = "Remove EXPRESSION target"
override fun getFamilyName() = text
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val targetAnnotation = element ?: return
targetAnnotation.delete()
val expressionTargetArgument = element ?: return
val argumentList = expressionTargetArgument.parent as? KtValueArgumentList ?: return
if (argumentList.arguments.size == 1) {
val annotation = argumentList.parent as? KtAnnotationEntry ?: return
annotation.delete()
} else {
argumentList.removeArgument(expressionTargetArgument)
}
}
}
}
@@ -0,0 +1,6 @@
// "Remove EXPRESSION target" "true"
import kotlin.annotation.AnnotationTarget.*
<caret>@Retention
@Target(FIELD, EXPRESSION, PROPERTY)
annotation class Ann
@@ -0,0 +1,6 @@
// "Remove EXPRESSION target" "true"
import kotlin.annotation.AnnotationTarget.*
<caret>@Retention
@Target(FIELD, PROPERTY)
annotation class Ann
@@ -0,0 +1,4 @@
// "Remove EXPRESSION target" "true"
<caret>@Retention
@Target(AnnotationTarget.FIELD, AnnotationTarget.EXPRESSION, AnnotationTarget.PROPERTY)
annotation class Ann
@@ -0,0 +1,4 @@
// "Remove EXPRESSION target" "true"
<caret>@Retention
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class Ann
@@ -10970,6 +10970,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/restrictedRetentionForExpressionAnnotation/removeExpressionTarget/emptyRetention2.kt");
}
@TestMetadata("multipleTargets.kt")
public void testMultipleTargets() throws Exception {
runTest("idea/testData/quickfix/restrictedRetentionForExpressionAnnotation/removeExpressionTarget/multipleTargets.kt");
}
@TestMetadata("multipleTargetsImported.kt")
public void testMultipleTargetsImported() throws Exception {
runTest("idea/testData/quickfix/restrictedRetentionForExpressionAnnotation/removeExpressionTarget/multipleTargetsImported.kt");
}
@TestMetadata("noRetention.kt")
public void testNoRetention() throws Exception {
runTest("idea/testData/quickfix/restrictedRetentionForExpressionAnnotation/removeExpressionTarget/noRetention.kt");