[extract method] avoid use of EDT when introducing a result object

GitOrigin-RevId: 7156ba6737e17861155f68b847a5408f1303645a
This commit is contained in:
Alexandr Suhinin
2024-07-31 14:26:46 +00:00
committed by intellij-monorepo-bot
parent f6db6a0ef8
commit b2a8bd3b6d
2 changed files with 24 additions and 18 deletions
@@ -82,9 +82,7 @@ class MethodExtractor {
val outputVariables = readAction { analyzer.findOutputVariables().sortedBy { variable -> variable.textRange.startOffset } }
if (outputVariables.size > 1) {
withContext(Dispatchers.EDT) {
ResultObjectExtractor.run(editor, outputVariables, elements)
}
ResultObjectExtractor.run(editor, outputVariables, elements)
return
}
@@ -4,10 +4,12 @@ package com.intellij.refactoring.extractMethod.newImpl.parameterObject
import com.intellij.codeInsight.hint.EditorCodePreview
import com.intellij.codeInsight.hint.HintManager
import com.intellij.java.refactoring.JavaRefactoringBundle
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.invokeLater
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.application.readAction
import com.intellij.openapi.command.impl.FinishMarkAction
import com.intellij.openapi.command.impl.StartMarkAction
import com.intellij.openapi.command.writeCommandAction
import com.intellij.openapi.diff.DiffColors
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.Disposer
@@ -23,6 +25,8 @@ import com.intellij.refactoring.extractMethod.newImpl.inplace.ExtractMethodTempl
import com.intellij.refactoring.extractMethod.newImpl.inplace.InplaceExtractUtils
import com.intellij.refactoring.extractMethod.newImpl.inplace.InplaceExtractUtils.createGreedyRangeMarker
import com.intellij.refactoring.extractMethod.newImpl.inplace.TemplateField
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
private data class IntroduceObjectResult(
val introducedClass: PsiClass,
@@ -32,33 +36,37 @@ private data class IntroduceObjectResult(
/**
* Creates a class or record to wrap multiple variables inside a single instance.
* Used as a first step before extracting method from code fragment with multiple results.
* Used as a first step before extracting a method from a code fragment with multiple results.
*/
object ResultObjectExtractor {
fun run(editor: Editor, variables: List<PsiVariable>, scope: List<PsiElement>){
internal object ResultObjectExtractor {
suspend fun run(editor: Editor, variables: List<PsiVariable>, scope: List<PsiElement>){
require(variables.isNotEmpty())
require(scope.isNotEmpty())
val affectedReferences = ParameterObjectUtils.findAffectedReferences(variables, scope)
val affectedReferences = readAction { ParameterObjectUtils.findAffectedReferences(variables, scope) }
if (affectedReferences == null) {
InplaceExtractUtils.showExtractErrorHint(editor, ExtractException(JavaRefactoringBundle.message("extract.method.error.many.outputs"), variables))
withContext(Dispatchers.EDT) {
InplaceExtractUtils.showExtractErrorHint(editor, ExtractException(JavaRefactoringBundle.message("extract.method.error.many.outputs"), variables))
}
return
}
val shouldInsertRecord = PsiUtil.isAvailable(JavaFeature.RECORDS, variables.first())
val shouldInsertRecord = readAction { PsiUtil.isAvailable(JavaFeature.RECORDS, variables.first()) }
val objectBuilder = if (shouldInsertRecord) {
RecordResultObjectBuilder.create(variables)
readAction { RecordResultObjectBuilder.create(variables) }
} else {
ClassResultObjectBuilder.create(variables)
readAction { ClassResultObjectBuilder.create(variables) }
}
val file = scope.first().containingFile
val file = readAction { scope.first().containingFile }
val project = file.project
val extractRange = createGreedyRangeMarker(file.viewProvider.document, scope.first().textRange.union(scope.last().textRange))
val editorState = EditorState(project, editor)
val extractRange = readAction {
createGreedyRangeMarker (file.viewProvider.document, scope.first().textRange.union(scope.last().textRange))
}
val editorState = readAction { EditorState(project, editor) }
val disposable = Disposer.newDisposable()
WriteCommandAction.writeCommandAction(project).run<Throwable> {
writeCommandAction(project, ExtractMethodHandler.getRefactoringName()) {
val startMarkAction = StartMarkAction.start(editor, project, ExtractMethodHandler.getRefactoringName())
Disposer.register(disposable) { FinishMarkAction.finish(project, editor, startMarkAction) }
try {
val startMarkAction = StartMarkAction.start(editor, project, ExtractMethodHandler.getRefactoringName())
Disposer.register(disposable) { FinishMarkAction.finish(project, editor, startMarkAction) }
val (introducedClass, declaration, replacements) = introduceObjectForVariables(objectBuilder, variables, affectedReferences, scope.last())
val introducedVariableReferences = replacements.map { replacement ->
objectBuilder.findVariableReferenceInReplacement(replacement) ?: throw IllegalStateException()