"Code Cleanup": don't remove deprecated imports when file has @file:Suppress("DEPRECATION") annotation

#KT-33594 Fixed
This commit is contained in:
Toshiaki Kameyama
2019-09-25 10:23:48 +09:00
committed by Yan Zhulanow
parent 4a328981c6
commit cf5a6274e2
10 changed files with 58 additions and 8 deletions
@@ -49,7 +49,7 @@ class KotlinCleanupInspection : LocalInspectionTool(), CleanupLocalInspectionToo
val problemDescriptors = arrayListOf<ProblemDescriptor>()
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)
@@ -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<KtImportDirective> {
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()
@@ -0,0 +1,6 @@
package bar
interface I
@Deprecated("", ReplaceWith("I"))
interface Bar : I
@@ -0,0 +1,7 @@
@file:Suppress("DEPRECATION")
package foo
import bar.Bar
fun foo(x: Bar) {}
@@ -0,0 +1,7 @@
@file:Suppress("DEPRECATION")
package foo
import bar.Bar
fun foo(x: Bar) {}
@@ -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"
)
}
}