diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinOptimizeImportsRefactoringHelper.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinOptimizeImportsRefactoringHelper.kt index f0b19376ca9..373ab69f193 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinOptimizeImportsRefactoringHelper.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/KotlinOptimizeImportsRefactoringHelper.kt @@ -16,8 +16,11 @@ package org.jetbrains.kotlin.idea.codeInsight +import com.intellij.openapi.application.invokeLater import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.progress.Task import com.intellij.openapi.project.DumbService import com.intellij.openapi.project.Project import com.intellij.psi.PsiDocumentManager @@ -26,81 +29,66 @@ import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.refactoring.RefactoringHelper import com.intellij.usageView.UsageInfo 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.util.application.runWriteAction +import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtImportDirective import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer // Based on com.intellij.refactoring.OptimizeImportsRefactoringHelper class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper> { - internal class CollectUnusedImportsTask( - private val task: SequentialModalProgressTask, + internal open class CollectUnusedImportsTask( + project: Project, private val dumbService: DumbService, private val unusedImports: MutableSet>, - operationData: Set - ) : SequentialTask { - private val myTotalCount = operationData.size - private val operationIterator = operationData.withIndex().iterator() + private val operationData: Set + ) : Task.Backgroundable(project, COLLECT_UNUSED_IMPORTS_TITLE, false) { - 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() - - 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() } + } } - - dumbService.runReadActionInSmartMode { - KotlinUnusedImportInspection.analyzeImports(file)?.unusedImports?.mapTo(unusedImports) { it.createSmartPointer() } - } - return isDone } } internal class OptimizeImportsTask( - private val task: SequentialModalProgressTask, - pointers: Set> - ) : SequentialTask { - private val pointerIterator = pointers.withIndex().iterator() - private val myTotal: Int = pointers.size + project: Project, + private val pointers: Set> + ) : Task.Modal(project, REMOVING_REDUNDANT_IMPORTS_TITLE, false) { - 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() - - override fun iteration(): Boolean { - val (counter, pointer) = pointerIterator.next() - - task.indicator?.fraction = counter.toDouble() / myTotal - - val directive = pointer.element - if (directive?.isValid == true) { - task.indicator?.text2 = directive.containingFile.virtualFile.presentableUrl - runWriteAction { - try { - directive.delete() - } catch (e: IncorrectOperationException) { - LOG.error(e) + val directive = pointer.element + if (directive?.isValid == true) { + val presentableUrl = directive.containingFile.virtualFile.presentableUrl + indicator.text2 = presentableUrl + invokeLater { + project.executeWriteCommand("delete $presentableUrl") { + try { + directive.delete() + } catch (e: IncorrectOperationException) { + LOG.error(e) + } + } } } } - - return isDone } - override fun stop() {} - companion object { private val LOG = Logger.getInstance("#" + OptimizeImportsTask::class.java.name) } @@ -112,38 +100,30 @@ class KotlinOptimizeImportsRefactoringHelper : RefactoringHelper> { } override fun prepareOperation(usages: Array): Set { - return usages.mapNotNullTo(LinkedHashSet()) { + return usages.mapNotNullTo(LinkedHashSet()) { if (!it.isNonCodeUsage) it.file as? KtFile else null } } override fun performOperation(project: Project, operationData: Set) { + if (operationData.isEmpty()) return + CodeStyleManager.getInstance(project).performActionWithFormatterDisabled { PsiDocumentManager.getInstance(project).commitAllDocuments() } - if (operationData.isEmpty()) return - val unusedImports = mutableSetOf>() val progressManager = ProgressManager.getInstance() 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() { - val progressTask = SequentialModalProgressTask(project, REMOVING_REDUNDANT_IMPORTS_TITLE, false) - with(progressTask) { - setMinIterationTime(200) - setTask(OptimizeImportsTask(this, unusedImports)) - } + val progressTask = OptimizeImportsTask(project, unusedImports) progressManager.run(progressTask) } } - with(collectTask) { - setMinIterationTime(200) - setTask(CollectUnusedImportsTask(this, dumbService, unusedImports, operationData)) - } progressManager.run(collectTask) } }