Code cleanup to remove deprecated symbol imports that have ReplaceWith
This commit is contained in:
@@ -19,11 +19,15 @@ package org.jetbrains.kotlin.idea.core
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getFileTopLevelScope
|
import org.jetbrains.kotlin.idea.caches.resolve.getFileTopLevelScope
|
||||||
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstanceToExpression
|
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstanceToExpression
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
@@ -102,3 +106,8 @@ public fun PsiElement.getResolutionScope(bindingContext: BindingContext, resolut
|
|||||||
}
|
}
|
||||||
error("Not in JetFile")
|
error("Not in JetFile")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun JetImportDirective.targetDescriptors(): Collection<DeclarationDescriptor> {
|
||||||
|
val nameExpression = importedReference?.getQualifiedElementSelector() as? JetSimpleNameExpression ?: return emptyList()
|
||||||
|
return nameExpression.mainReference.resolveToDescriptors(nameExpression.analyze())
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,16 +29,17 @@ import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||||
import org.jetbrains.kotlin.idea.highlighter.JetPsiChecker
|
import org.jetbrains.kotlin.idea.highlighter.JetPsiChecker
|
||||||
import org.jetbrains.kotlin.idea.quickfix.CleanupFix
|
import org.jetbrains.kotlin.idea.quickfix.CleanupFix
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.DeprecatedSymbolUsageFix
|
||||||
|
import org.jetbrains.kotlin.idea.quickfix.JetIntentionAction
|
||||||
import org.jetbrains.kotlin.idea.quickfix.ReplaceObsoleteLabelSyntaxFix
|
import org.jetbrains.kotlin.idea.quickfix.ReplaceObsoleteLabelSyntaxFix
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
import org.jetbrains.kotlin.psi.JetAnnotationEntry
|
import org.jetbrains.kotlin.psi.JetAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
import org.jetbrains.kotlin.psi.JetImportDirective
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||||
import kotlin.properties.Delegates
|
|
||||||
|
|
||||||
public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspectionTool {
|
public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspectionTool {
|
||||||
// required to simplify the inspection registration in tests
|
// required to simplify the inspection registration in tests
|
||||||
@@ -61,6 +62,14 @@ public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspe
|
|||||||
}
|
}
|
||||||
|
|
||||||
val problems = arrayListOf<ProblemData>()
|
val problems = arrayListOf<ProblemData>()
|
||||||
|
|
||||||
|
val importsToRemove = file.importDirectives.filter { DeprecatedSymbolUsageFix.isImportToBeRemoved(it) }
|
||||||
|
for (import in importsToRemove) {
|
||||||
|
val removeImportFix = RemoveImportFix(import)
|
||||||
|
val problemDescriptor = createProblemDescriptor(import, removeImportFix.text, listOf(removeImportFix), file, manager)
|
||||||
|
problems.add(ProblemData(problemDescriptor, import))
|
||||||
|
}
|
||||||
|
|
||||||
file.forEachDescendantOfType<PsiElement> { element ->
|
file.forEachDescendantOfType<PsiElement> { element ->
|
||||||
for (diagnostic in diagnostics.forElement(element)) {
|
for (diagnostic in diagnostics.forElement(element)) {
|
||||||
if (diagnostic.isCleanup()) {
|
if (diagnostic.isCleanup()) {
|
||||||
@@ -111,10 +120,23 @@ public class KotlinCleanupInspection(): LocalInspectionTool(), CleanupLocalInspe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Diagnostic.toProblemDescriptor(fixes: Collection<CleanupFix>, file: JetFile, manager: InspectionManager): ProblemDescriptor {
|
private fun Diagnostic.toProblemDescriptor(fixes: Collection<CleanupFix>, file: JetFile, manager: InspectionManager): ProblemDescriptor {
|
||||||
return manager.createProblemDescriptor(getPsiElement(),
|
return createProblemDescriptor(psiElement, DefaultErrorMessages.render(this), fixes, file, manager)
|
||||||
DefaultErrorMessages.render(this),
|
}
|
||||||
false,
|
|
||||||
fixes.map { Wrapper(it, file) }.toTypedArray(),
|
private fun createProblemDescriptor(element: PsiElement, message: String, fixes: Collection<CleanupFix>, file: JetFile, manager: InspectionManager): ProblemDescriptor {
|
||||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING)
|
return manager.createProblemDescriptor(element,
|
||||||
|
message,
|
||||||
|
false,
|
||||||
|
fixes.map { Wrapper(it, file) }.toTypedArray(),
|
||||||
|
ProblemHighlightType.GENERIC_ERROR_OR_WARNING)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RemoveImportFix(import: JetImportDirective) : JetIntentionAction<JetImportDirective>(import), CleanupFix {
|
||||||
|
override fun getFamilyName() = "Remove deprecated symbol import"
|
||||||
|
override fun getText() = familyName
|
||||||
|
|
||||||
|
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||||
|
element.delete()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,15 +41,12 @@ import com.intellij.psi.PsiFile
|
|||||||
import com.intellij.util.DocumentUtil
|
import com.intellij.util.DocumentUtil
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||||
import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
|
import org.jetbrains.kotlin.idea.imports.KotlinImportOptimizer
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.JetFile
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
|
|
||||||
import org.jetbrains.kotlin.resolve.ImportPath
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class UnusedImportInspection : AbstractKotlinInspection() {
|
class UnusedImportInspection : AbstractKotlinInspection() {
|
||||||
@@ -104,8 +101,7 @@ class UnusedImportInspection : AbstractKotlinInspection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isUsed) {
|
if (!isUsed) {
|
||||||
val nameExpression = directive.importedReference?.getQualifiedElementSelector() as? JetSimpleNameExpression
|
if (directive.targetDescriptors().isEmpty()) continue // do not highlight unresolved imports as unused
|
||||||
if (nameExpression == null || nameExpression.getReferenceTargets(nameExpression.analyze()).isEmpty()) continue // do not highlight unresolved imports as unused
|
|
||||||
|
|
||||||
val fixes = arrayListOf<LocalQuickFix>()
|
val fixes = arrayListOf<LocalQuickFix>()
|
||||||
fixes.add(OptimizeImportsQuickFix(file))
|
fixes.add(OptimizeImportsQuickFix(file))
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||||
@@ -72,5 +73,9 @@ public class DeprecatedSymbolUsageFix(
|
|||||||
return DeprecatedSymbolUsageFix(nameExpression, replacement)
|
return DeprecatedSymbolUsageFix(nameExpression, replacement)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun isImportToBeRemoved(import: JetImportDirective): Boolean {
|
||||||
|
return !import.isAllUnder
|
||||||
|
&& import.targetDescriptors().all { DeprecatedSymbolUsageFixBase.replaceWithPattern(it, import.project) != null }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-22
@@ -17,31 +17,16 @@
|
|||||||
package org.jetbrains.kotlin.idea.refactoring.safeDelete
|
package org.jetbrains.kotlin.idea.refactoring.safeDelete
|
||||||
|
|
||||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo
|
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.psi.JetDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.JetImportDirective
|
||||||
|
|
||||||
public class SafeDeleteImportDirectiveUsageInfo(
|
public class SafeDeleteImportDirectiveUsageInfo(
|
||||||
importDirective: JetImportDirective, declaration: JetDeclaration
|
importDirective: JetImportDirective, declaration: JetDeclaration
|
||||||
) : SafeDeleteReferenceSimpleDeleteUsageInfo(importDirective, declaration, importDirective.isSafeToDelete(declaration))
|
) : SafeDeleteReferenceSimpleDeleteUsageInfo(importDirective, declaration, importDirective.isSafeToDelete(declaration))
|
||||||
|
|
||||||
fun JetImportDirective.isSafeToDelete(declaration: JetDeclaration): Boolean {
|
private fun JetImportDirective.isSafeToDelete(declaration: JetDeclaration): Boolean {
|
||||||
val importExpr = getImportedReference()
|
val referencedDescriptor = targetDescriptors().singleOrNull() ?: return false
|
||||||
val importReference: JetReferenceExpression? = when (importExpr) {
|
return referencedDescriptor == declaration.resolveToDescriptor()
|
||||||
is JetSimpleNameExpression ->
|
|
||||||
importExpr
|
|
||||||
is JetDotQualifiedExpression ->
|
|
||||||
importExpr.getSelectorExpression()?.let { selector ->
|
|
||||||
if (selector is JetSimpleNameExpression) selector else null
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (importReference != null) {
|
|
||||||
val bindingContext = importReference.analyze()
|
|
||||||
val referenceDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, importReference)
|
|
||||||
val declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
|
|
||||||
return referenceDescriptor == declarationDescriptor
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.getFileTopLevelScope
|
import org.jetbrains.kotlin.idea.caches.resolve.getFileTopLevelScope
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
|
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
|
||||||
|
import org.jetbrains.kotlin.idea.core.targetDescriptors
|
||||||
import org.jetbrains.kotlin.idea.imports.getImportableTargets
|
import org.jetbrains.kotlin.idea.imports.getImportableTargets
|
||||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||||
@@ -299,9 +300,8 @@ public class ImportInsertHelperImpl(private val project: Project) : ImportInsert
|
|||||||
|
|
||||||
val importsToCheck = ArrayList<FqName>()
|
val importsToCheck = ArrayList<FqName>()
|
||||||
for (import in dropCandidates) {
|
for (import in dropCandidates) {
|
||||||
val importedReference = import.getImportedReference() ?: continue
|
if (import.importedReference == null) continue
|
||||||
val refExpr = (importedReference as JetDotQualifiedExpression).getSelectorExpression() as JetSimpleNameExpression
|
val targets = import.targetDescriptors()
|
||||||
val targets = refExpr.resolveTargets()
|
|
||||||
if (targets.any { it is PackageViewDescriptor }) continue // do not drop import of package
|
if (targets.any { it is PackageViewDescriptor }) continue // do not drop import of package
|
||||||
val classDescriptor = targets.filterIsInstance<ClassDescriptor>().firstOrNull()
|
val classDescriptor = targets.filterIsInstance<ClassDescriptor>().firstOrNull()
|
||||||
importsToCheck.addIfNotNull(classDescriptor?.importableFqName)
|
importsToCheck.addIfNotNull(classDescriptor?.importableFqName)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import pack.oldFun1
|
||||||
|
import pack.oldFun2 // should not be removed for non-deprecated overload used
|
||||||
|
import pack.oldFun3
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,6 +20,8 @@ fun foo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldFun1(oldFun2(10))
|
oldFun1(oldFun2(10))
|
||||||
|
|
||||||
|
oldFun2()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unnecessarySafeCall(x: String) {
|
fun unnecessarySafeCall(x: String) {
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import pack.bar
|
||||||
|
import pack.oldFun2 // should not be removed for non-deprecated overload used
|
||||||
|
|
||||||
interface Foo {
|
interface Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,6 +19,8 @@ fun foo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bar(bar(10 + 2) + 1)
|
bar(bar(10 + 2) + 1)
|
||||||
|
|
||||||
|
oldFun2()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun unnecessarySafeCall(x: String) {
|
fun unnecessarySafeCall(x: String) {
|
||||||
|
|||||||
@@ -1,7 +1,17 @@
|
|||||||
|
package pack
|
||||||
|
|
||||||
@deprecated("", ReplaceWith("bar(p + 1)"))
|
@deprecated("", ReplaceWith("bar(p + 1)"))
|
||||||
public fun oldFun1(p: Int): Int = 0
|
public fun oldFun1(p: Int): Int = 0
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("bar(-1)"))
|
||||||
|
public fun oldFun1(): Int = 0
|
||||||
|
|
||||||
@deprecated("", ReplaceWith("bar(p + 2)"))
|
@deprecated("", ReplaceWith("bar(p + 2)"))
|
||||||
public fun oldFun2(p: Int): Int = 0
|
public fun oldFun2(p: Int): Int = 0
|
||||||
|
|
||||||
|
public fun oldFun2(): Int = 0
|
||||||
|
|
||||||
|
@deprecated("", ReplaceWith("bar(p)"))
|
||||||
|
public fun oldFun3(p: Int): Int = 0
|
||||||
|
|
||||||
public fun bar(p: Int): Int = p
|
public fun bar(p: Int): Int = p
|
||||||
Reference in New Issue
Block a user