diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspection.kt index 60cb787374c..39c00c8767f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspection.kt @@ -49,7 +49,7 @@ class KotlinCleanupInspection : LocalInspectionTool(), CleanupLocalInspectionToo val problemDescriptors = arrayListOf() - val importsToRemove = file.importDirectives.filter { DeprecatedSymbolUsageFix.isImportToBeRemoved(it) } + val importsToRemove = DeprecatedSymbolUsageFix.importDirectivesToBeRemoved(file) for (import in importsToRemove) { val removeImportFix = RemoveImportFix(import) val problemDescriptor = createProblemDescriptor(import, removeImportFix.text, listOf(removeImportFix), file, manager) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/DeprecatedSymbolUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/DeprecatedSymbolUsageFix.kt index be910e77c62..2c9eb967ff2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/DeprecatedSymbolUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/DeprecatedSymbolUsageFix.kt @@ -20,16 +20,21 @@ import com.intellij.codeInsight.intention.HighPriorityAction 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.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.idea.codeInliner.UsageReplacementStrategy import org.jetbrains.kotlin.idea.core.moveCaret import org.jetbrains.kotlin.idea.core.targetDescriptors import org.jetbrains.kotlin.idea.quickfix.CleanupFix import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtImportDirective import org.jetbrains.kotlin.psi.KtReferenceExpression +import org.jetbrains.kotlin.psi.KtStringTemplateExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe class DeprecatedSymbolUsageFix( element: KtReferenceExpression, @@ -55,7 +60,23 @@ class DeprecatedSymbolUsageFix( return DeprecatedSymbolUsageFix(referenceExpression, replacement) } - fun isImportToBeRemoved(import: KtImportDirective): Boolean { + fun importDirectivesToBeRemoved(file: KtFile): List { + if (file.hasAnnotationToSuppressDeprecation()) return emptyList() + return file.importDirectives.filter { isImportToBeRemoved(it) } + } + + private fun KtFile.hasAnnotationToSuppressDeprecation(): Boolean { + val suppressAnnotationEntry = annotationEntries.firstOrNull { + it.shortName?.asString() == "Suppress" + && it.resolveToCall()?.resultingDescriptor?.containingDeclaration?.fqNameSafe == KotlinBuiltIns.FQ_NAMES.suppress + } ?: return false + return suppressAnnotationEntry.valueArguments.any { + val text = (it.getArgumentExpression() as? KtStringTemplateExpression)?.entries?.singleOrNull()?.text ?: return@any false + text.equals("DEPRECATION", ignoreCase = true) + } + } + + private fun isImportToBeRemoved(import: KtImportDirective): Boolean { if (import.isAllUnder) return false val targetDescriptors = import.targetDescriptors() diff --git a/idea/testData/inspections/cleanup/JavaAnn.java b/idea/testData/inspections/cleanup/basic/JavaAnn.java similarity index 100% rename from idea/testData/inspections/cleanup/JavaAnn.java rename to idea/testData/inspections/cleanup/basic/JavaAnn.java diff --git a/idea/testData/inspections/cleanup/cleanup.kt b/idea/testData/inspections/cleanup/basic/basic.kt similarity index 100% rename from idea/testData/inspections/cleanup/cleanup.kt rename to idea/testData/inspections/cleanup/basic/basic.kt diff --git a/idea/testData/inspections/cleanup/cleanup.kt.after b/idea/testData/inspections/cleanup/basic/basic.kt.after similarity index 100% rename from idea/testData/inspections/cleanup/cleanup.kt.after rename to idea/testData/inspections/cleanup/basic/basic.kt.after diff --git a/idea/testData/inspections/cleanup/deprecatedSymbols.kt b/idea/testData/inspections/cleanup/basic/deprecatedSymbols.kt similarity index 100% rename from idea/testData/inspections/cleanup/deprecatedSymbols.kt rename to idea/testData/inspections/cleanup/basic/deprecatedSymbols.kt diff --git a/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/deprecatedSymbols.kt b/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/deprecatedSymbols.kt new file mode 100644 index 00000000000..94c87a70573 --- /dev/null +++ b/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/deprecatedSymbols.kt @@ -0,0 +1,6 @@ +package bar + +interface I + +@Deprecated("", ReplaceWith("I")) +interface Bar : I \ No newline at end of file diff --git a/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/fileWithAnnotationToSuppressDeprecation.kt b/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/fileWithAnnotationToSuppressDeprecation.kt new file mode 100644 index 00000000000..1420d8425c2 --- /dev/null +++ b/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/fileWithAnnotationToSuppressDeprecation.kt @@ -0,0 +1,7 @@ +@file:Suppress("DEPRECATION") + +package foo + +import bar.Bar + +fun foo(x: Bar) {} \ No newline at end of file diff --git a/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/fileWithAnnotationToSuppressDeprecation.kt.after b/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/fileWithAnnotationToSuppressDeprecation.kt.after new file mode 100644 index 00000000000..1420d8425c2 --- /dev/null +++ b/idea/testData/inspections/cleanup/fileWithAnnotationToSuppressDeprecation/fileWithAnnotationToSuppressDeprecation.kt.after @@ -0,0 +1,7 @@ +@file:Suppress("DEPRECATION") + +package foo + +import bar.Bar + +fun foo(x: Bar) {} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspectionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspectionTest.kt index 6b7031ec74d..52060f9ce2b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/KotlinCleanupInspectionTest.kt @@ -17,16 +17,16 @@ import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner import org.junit.runner.RunWith @RunWith(JUnit3WithIdeaConfigurationRunner::class) -class KotlinCleanupInspectionTest() : KotlinLightCodeInsightFixtureTestCase() { +class KotlinCleanupInspectionTest : KotlinLightCodeInsightFixtureTestCase() { override fun getTestDataPath(): String = PluginTestCaseBase.getTestDataPathBase() + "/inspections/cleanup" override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - private fun doTest(result: String, vararg files: String) { + private fun doTest(dir: String, result: String, vararg files: String) { myFixture.enableInspections(KotlinCleanupInspection::class.java) myFixture.enableInspections(SortModifiersInspection::class.java) myFixture.enableInspections(RedundantModalityModifierInspection::class.java) - myFixture.configureByFiles(*files) + myFixture.configureByFiles(*files.map { "$dir/$it" }.toTypedArray()) val project = myFixture.project val managerEx = InspectionManager.getInstance(project) @@ -35,10 +35,19 @@ class KotlinCleanupInspectionTest() : KotlinLightCodeInsightFixtureTestCase() { val profile = InspectionProjectProfileManager.getInstance(project).currentProfile globalContext.codeCleanup(analysisScope, profile, "Cleanup", null, true) - myFixture.checkResultByFile(result) + myFixture.checkResultByFile("$dir/$result") } - fun testCleanup() { - doTest("cleanup.kt.after", "cleanup.kt", "JavaAnn.java", "deprecatedSymbols.kt") + fun testBasic() { + doTest("basic", "basic.kt.after", "basic.kt", "JavaAnn.java", "deprecatedSymbols.kt") + } + + fun testFileWithAnnotationToSuppressDeprecation() { + doTest( + "fileWithAnnotationToSuppressDeprecation", + "fileWithAnnotationToSuppressDeprecation.kt.after", + "fileWithAnnotationToSuppressDeprecation.kt", + "deprecatedSymbols.kt" + ) } }