Move remove redundant imports to bg thread
#KT-24122 Fixed
This commit is contained in:
+44
-64
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.codeInsight
|
package org.jetbrains.kotlin.idea.codeInsight
|
||||||
|
|
||||||
|
import com.intellij.openapi.application.invokeLater
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
|
import com.intellij.openapi.progress.Task
|
||||||
import com.intellij.openapi.project.DumbService
|
import com.intellij.openapi.project.DumbService
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
@@ -26,81 +29,66 @@ import com.intellij.psi.codeStyle.CodeStyleManager
|
|||||||
import com.intellij.refactoring.RefactoringHelper
|
import com.intellij.refactoring.RefactoringHelper
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
import com.intellij.util.IncorrectOperationException
|
import com.intellij.util.IncorrectOperationException
|
||||||
import com.intellij.util.SequentialModalProgressTask
|
|
||||||
import com.intellij.util.SequentialTask
|
|
||||||
import org.jetbrains.kotlin.idea.inspections.KotlinUnusedImportInspection
|
import org.jetbrains.kotlin.idea.inspections.KotlinUnusedImportInspection
|
||||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
|
||||||
|
|
||||||
// Based on com.intellij.refactoring.OptimizeImportsRefactoringHelper
|
// Based on com.intellij.refactoring.OptimizeImportsRefactoringHelper
|
||||||
class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper<Set<KtFile>> {
|
class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper<Set<KtFile>> {
|
||||||
internal class CollectUnusedImportsTask(
|
internal open class CollectUnusedImportsTask(
|
||||||
private val task: SequentialModalProgressTask,
|
project: Project,
|
||||||
private val dumbService: DumbService,
|
private val dumbService: DumbService,
|
||||||
private val unusedImports: MutableSet<SmartPsiElementPointer<KtImportDirective>>,
|
private val unusedImports: MutableSet<SmartPsiElementPointer<KtImportDirective>>,
|
||||||
operationData: Set<KtFile>
|
private val operationData: Set<KtFile>
|
||||||
) : SequentialTask {
|
) : Task.Backgroundable(project, COLLECT_UNUSED_IMPORTS_TITLE, false) {
|
||||||
private val myTotalCount = operationData.size
|
|
||||||
private val operationIterator = operationData.withIndex().iterator()
|
|
||||||
|
|
||||||
override fun prepare() {}
|
override fun run(indicator: ProgressIndicator) {
|
||||||
|
val myTotalCount = operationData.size
|
||||||
|
for ((counter, file) in operationData.withIndex()) {
|
||||||
|
if (!file.isValid) return
|
||||||
|
val virtualFile = file.virtualFile ?: return
|
||||||
|
|
||||||
override fun stop() {}
|
with(indicator) {
|
||||||
|
text2 = virtualFile.presentableUrl
|
||||||
|
fraction = counter.toDouble() / myTotalCount
|
||||||
|
}
|
||||||
|
|
||||||
override fun isDone(): Boolean = !operationIterator.hasNext()
|
dumbService.runReadActionInSmartMode {
|
||||||
|
KotlinUnusedImportInspection.analyzeImports(file)?.unusedImports?.mapTo(unusedImports) { it.createSmartPointer() }
|
||||||
override fun iteration(): Boolean {
|
}
|
||||||
val (counter, file) = operationIterator.next()
|
|
||||||
if (!file.isValid) return isDone
|
|
||||||
val virtualFile = file.virtualFile ?: return isDone
|
|
||||||
|
|
||||||
with(task.indicator) {
|
|
||||||
text2 = virtualFile.presentableUrl
|
|
||||||
fraction = counter.toDouble() / myTotalCount
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dumbService.runReadActionInSmartMode {
|
|
||||||
KotlinUnusedImportInspection.analyzeImports(file)?.unusedImports?.mapTo(unusedImports) { it.createSmartPointer() }
|
|
||||||
}
|
|
||||||
return isDone
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class OptimizeImportsTask(
|
internal class OptimizeImportsTask(
|
||||||
private val task: SequentialModalProgressTask,
|
project: Project,
|
||||||
pointers: Set<SmartPsiElementPointer<KtImportDirective>>
|
private val pointers: Set<SmartPsiElementPointer<KtImportDirective>>
|
||||||
) : SequentialTask {
|
) : Task.Modal(project, REMOVING_REDUNDANT_IMPORTS_TITLE, false) {
|
||||||
private val pointerIterator = pointers.withIndex().iterator()
|
|
||||||
private val myTotal: Int = pointers.size
|
|
||||||
|
|
||||||
override fun prepare() {}
|
override fun run(indicator: ProgressIndicator) {
|
||||||
|
val myTotal: Int = pointers.size
|
||||||
|
for ((counter, pointer) in pointers.withIndex()) {
|
||||||
|
indicator.fraction = counter.toDouble() / myTotal
|
||||||
|
|
||||||
override fun isDone() = !pointerIterator.hasNext()
|
val directive = pointer.element
|
||||||
|
if (directive?.isValid == true) {
|
||||||
override fun iteration(): Boolean {
|
val presentableUrl = directive.containingFile.virtualFile.presentableUrl
|
||||||
val (counter, pointer) = pointerIterator.next()
|
indicator.text2 = presentableUrl
|
||||||
|
invokeLater {
|
||||||
task.indicator?.fraction = counter.toDouble() / myTotal
|
project.executeWriteCommand("delete $presentableUrl") {
|
||||||
|
try {
|
||||||
val directive = pointer.element
|
directive.delete()
|
||||||
if (directive?.isValid == true) {
|
} catch (e: IncorrectOperationException) {
|
||||||
task.indicator?.text2 = directive.containingFile.virtualFile.presentableUrl
|
LOG.error(e)
|
||||||
runWriteAction {
|
}
|
||||||
try {
|
}
|
||||||
directive.delete()
|
|
||||||
} catch (e: IncorrectOperationException) {
|
|
||||||
LOG.error(e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return isDone
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop() {}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val LOG = Logger.getInstance("#" + OptimizeImportsTask::class.java.name)
|
private val LOG = Logger.getInstance("#" + OptimizeImportsTask::class.java.name)
|
||||||
}
|
}
|
||||||
@@ -112,38 +100,30 @@ class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper<Set<KtFile>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareOperation(usages: Array<UsageInfo>): Set<KtFile> {
|
override fun prepareOperation(usages: Array<UsageInfo>): Set<KtFile> {
|
||||||
return usages.mapNotNullTo(LinkedHashSet<KtFile>()) {
|
return usages.mapNotNullTo(LinkedHashSet()) {
|
||||||
if (!it.isNonCodeUsage) it.file as? KtFile else null
|
if (!it.isNonCodeUsage) it.file as? KtFile else null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun performOperation(project: Project, operationData: Set<KtFile>) {
|
override fun performOperation(project: Project, operationData: Set<KtFile>) {
|
||||||
|
if (operationData.isEmpty()) return
|
||||||
|
|
||||||
CodeStyleManager.getInstance(project).performActionWithFormatterDisabled {
|
CodeStyleManager.getInstance(project).performActionWithFormatterDisabled {
|
||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operationData.isEmpty()) return
|
|
||||||
|
|
||||||
val unusedImports = mutableSetOf<SmartPsiElementPointer<KtImportDirective>>()
|
val unusedImports = mutableSetOf<SmartPsiElementPointer<KtImportDirective>>()
|
||||||
|
|
||||||
val progressManager = ProgressManager.getInstance()
|
val progressManager = ProgressManager.getInstance()
|
||||||
|
|
||||||
val dumbService = DumbService.getInstance(project)
|
val dumbService = DumbService.getInstance(project)
|
||||||
|
|
||||||
val collectTask = object : SequentialModalProgressTask(project, COLLECT_UNUSED_IMPORTS_TITLE, false) {
|
val collectTask = object : CollectUnusedImportsTask(project, dumbService, unusedImports, operationData) {
|
||||||
override fun onSuccess() {
|
override fun onSuccess() {
|
||||||
val progressTask = SequentialModalProgressTask(project, REMOVING_REDUNDANT_IMPORTS_TITLE, false)
|
val progressTask = OptimizeImportsTask(project, unusedImports)
|
||||||
with(progressTask) {
|
|
||||||
setMinIterationTime(200)
|
|
||||||
setTask(OptimizeImportsTask(this, unusedImports))
|
|
||||||
}
|
|
||||||
progressManager.run(progressTask)
|
progressManager.run(progressTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
with(collectTask) {
|
|
||||||
setMinIterationTime(200)
|
|
||||||
setTask(CollectUnusedImportsTask(this, dumbService, unusedImports, operationData))
|
|
||||||
}
|
|
||||||
progressManager.run(collectTask)
|
progressManager.run(collectTask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user