From 374eec04d404665e7bb617eff60a9f4c19291be3 Mon Sep 17 00:00:00 2001 From: Matthew Runo Date: Wed, 17 Oct 2018 15:06:56 -0700 Subject: [PATCH] KT-27445: Add QuickFix for DEPRECATED_JAVA_ANNOTATION compiler warning --- .../quickfix/DeprecatedJavaAnnotationFix.kt | 62 +++++++++++++++++++ .../kotlin/idea/quickfix/QuickFixRegistrar.kt | 1 + .../deprecatedJavaAnnotation/withArgument.kt | 8 +++ .../withArgument.kt.after | 8 +++ .../withoutArguments.kt | 6 ++ .../withoutArguments.kt.after | 6 ++ .../QuickFixMultiFileTestGenerated.java | 13 ++++ .../idea/quickfix/QuickFixTestGenerated.java | 23 +++++++ 8 files changed, 127 insertions(+) create mode 100644 idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedJavaAnnotationFix.kt create mode 100644 idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt create mode 100644 idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt.after create mode 100644 idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt create mode 100644 idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedJavaAnnotationFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedJavaAnnotationFix.kt new file mode 100644 index 00000000000..6e2ab11f77e --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/DeprecatedJavaAnnotationFix.kt @@ -0,0 +1,62 @@ +package org.jetbrains.kotlin.idea.quickfix + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.load.java.components.JavaAnnotationMapper +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.ImportPath +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm + +internal class DeprecatedJavaAnnotationFix(element: KtAnnotationEntry, + private val annotationFqName: FqName, + private val arguments: List) : KotlinQuickFixAction(element) { + override fun getFamilyName() = "Replace Annotation" + override fun getText(): String = "Replace annotation with ${annotationFqName.asString()}" + + override fun invoke(project: Project, editor: Editor?, file: KtFile) { + val element = element ?: return + + val psiFactory = KtPsiFactory(project) + + val argumentString = if(arguments.isEmpty()) { + "" + } else { + "("+ arguments.joinToString(",") { it.text } + ")" + } + + element.replace(psiFactory.createAnnotationEntry("@" + annotationFqName.shortName() + argumentString)) + + for ((java, kotlin) in JavaAnnotationMapper.javaToKotlinNameMap) { + if (kotlin == annotationFqName) { + val oldImport = file.importDirectives.find { it -> it.importedFqName == java } ?: return + oldImport.delete() + break + } + } + + file.importList?.add(psiFactory.createImportDirective(ImportPath(annotationFqName, false, null))) + } + + companion object Factory : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val castedDiagnostic = ErrorsJvm.DEPRECATED_JAVA_ANNOTATION.cast(diagnostic) + + val updatedAnnotation = castedDiagnostic.a as? FqName ?: return null + + val entry = diagnostic.psiElement as? KtAnnotationEntry ?: return null + + val arguments = mutableListOf() + entry.valueArguments.forEach { + (it as KtValueArgument).children.forEach { child -> + arguments.add(child.context as KtValueArgument) + } + } + + return DeprecatedJavaAnnotationFix(entry, updatedAnnotation, arguments) + } + + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 19c0e042243..5504afd44e4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -449,6 +449,7 @@ class QuickFixRegistrar : QuickFixContributor { UNDERSCORE_IS_RESERVED.registerFactory(RenameUnderscoreFix) DEPRECATED_TYPE_PARAMETER_SYNTAX.registerFactory(MigrateTypeParameterListFix) + ErrorsJvm.DEPRECATED_JAVA_ANNOTATION.registerFactory(DeprecatedJavaAnnotationFix) UNRESOLVED_REFERENCE.registerFactory(KotlinAddOrderEntryActionFactory) diff --git a/idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt b/idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt new file mode 100644 index 00000000000..e5160ea08f5 --- /dev/null +++ b/idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt @@ -0,0 +1,8 @@ +// "Replace annotation with kotlin.annotation.Retention" "true" +// ERROR: Type mismatch: inferred type is RetentionPolicy but AnnotationRetention was expected + +import java.lang.annotation.RetentionPolicy +import java.lang.annotation.Retention + +@Retention(RetentionPolicy.SOURCE) +annotation class Foo \ No newline at end of file diff --git a/idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt.after b/idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt.after new file mode 100644 index 00000000000..f65a21279d3 --- /dev/null +++ b/idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt.after @@ -0,0 +1,8 @@ +// "Replace annotation with kotlin.annotation.Retention" "true" +// ERROR: Type mismatch: inferred type is RetentionPolicy but AnnotationRetention was expected + +import java.lang.annotation.RetentionPolicy +import kotlin.annotation.Retention + +@Retention(RetentionPolicy.SOURCE) +annotation class Foo \ No newline at end of file diff --git a/idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt b/idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt new file mode 100644 index 00000000000..b24a3fba38a --- /dev/null +++ b/idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt @@ -0,0 +1,6 @@ +// "Replace annotation with kotlin.annotation.MustBeDocumented" "true" + +import java.lang.annotation.Documented + +@Documented +annotation class Foo \ No newline at end of file diff --git a/idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt.after b/idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt.after new file mode 100644 index 00000000000..2e10b63540a --- /dev/null +++ b/idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt.after @@ -0,0 +1,6 @@ +// "Replace annotation with kotlin.annotation.MustBeDocumented" "true" + +import kotlin.annotation.MustBeDocumented + +@MustBeDocumented +annotation class Foo \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index e7ce615fc68..c8570308457 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -2301,6 +2301,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes } } + @TestMetadata("idea/testData/quickfix/deprecatedJavaAnnotation") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DeprecatedJavaAnnotation extends AbstractQuickFixMultiFileTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestWithExtraFile, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInDeprecatedJavaAnnotation() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedJavaAnnotation"), Pattern.compile("^(\\w+)\\.((before\\.Main\\.\\w+)|(test))$"), TargetBackend.ANY, true); + } + } + @TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index ca07c38e46a..61438e080bc 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -5251,6 +5251,29 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/deprecatedJavaAnnotation") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DeprecatedJavaAnnotation extends AbstractQuickFixTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath); + } + + public void testAllFilesPresentInDeprecatedJavaAnnotation() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/deprecatedJavaAnnotation"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("withArgument.kt") + public void testWithArgument() throws Exception { + runTest("idea/testData/quickfix/deprecatedJavaAnnotation/withArgument.kt"); + } + + @TestMetadata("withoutArguments.kt") + public void testWithoutArguments() throws Exception { + runTest("idea/testData/quickfix/deprecatedJavaAnnotation/withoutArguments.kt"); + } + } + @TestMetadata("idea/testData/quickfix/deprecatedSymbolUsage") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)