UX-931 intentions preview: create editor on EDT

GitOrigin-RevId: fec0eadeb7b558e427b920710e4bcac71d9a7399
This commit is contained in:
Dmitry.Krasilschikov
2019-12-03 16:04:11 +00:00
committed by intellij-monorepo-bot
parent 8e7f3ef597
commit 96350cb568
2 changed files with 50 additions and 21 deletions
@@ -12,10 +12,8 @@ import com.intellij.diff.fragments.LineFragment
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.progress.DumbProgressIndicator
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager
@@ -26,26 +24,17 @@ import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileFactory
class IntentionPreviewComputable(private val originalFile: PsiFile,
private val project: Project,
class IntentionPreviewComputable(private val project: Project,
private val action: IntentionAction,
private val originalFile: PsiFile,
private val originalEditor: Editor,
private val action: IntentionAction) : Computable<Pair<PsiFile?, List<LineFragment>>?> {
private val LOG = Logger.getInstance(IntentionPreviewComputable::class.java)
private val psiFileCopy: PsiFile,
private val editorCopy: Editor
) : Computable<Pair<PsiFile?, List<LineFragment>>?> {
override fun compute(): Pair<PsiFile?, List<LineFragment>>? {
ProgressManager.checkCanceled()
val psiFileCopy = ApplicationManager.getApplication().runReadAction(Computable<PsiFile> { nonPhysicalPsiCopy(originalFile, project) })
ProgressManager.checkCanceled()
val documentCopy = ApplicationManager.getApplication().runReadAction(
Computable<Document> { FileDocumentManager.getInstance().getDocument(psiFileCopy.viewProvider.virtualFile) })
if (documentCopy == null) return null
CommandProcessor.getInstance().runUndoTransparentAction(Runnable {
try {
ApplicationManager.getApplication().runReadAction(ThrowableComputable<Unit, RuntimeException> {
val editorCopy = EditorFactory.getInstance().createEditor(documentCopy, project)
.also { it.caretModel.moveToOffset(originalEditor.caretModel.offset) }
ApplicationManager.getApplication().runReadAction(ThrowableComputable<Unit, Exception> {
val actionWithTextCachingCopy = intentionActionWithTextCaching(editorCopy, psiFileCopy)
if (actionWithTextCachingCopy == null) return@ThrowableComputable
@@ -65,7 +54,7 @@ class IntentionPreviewComputable(private val originalFile: PsiFile,
}
catch (e: Exception) {
LOG.warn("There are exceptions on invocation the intention: '${action.text}' on a copy of the file.", e)
throw ProcessCanceledException()
throw ProcessCanceledException(e)
}
})
@@ -98,4 +87,8 @@ class IntentionPreviewComputable(private val originalFile: PsiFile,
.plus(cachedIntentions.intentions)
.plus(cachedIntentions.inspectionFixes)
.plus(cachedIntentions.errorFixes)
companion object {
private val LOG = Logger.getInstance(IntentionPreviewComputable::class.java)
}
}
@@ -3,14 +3,18 @@ package com.intellij.codeInsight.intention.impl.preview
import com.intellij.codeInsight.CodeInsightBundle
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.impl.CachedIntentions
import com.intellij.codeInsight.intention.impl.IntentionActionWithTextCaching
import com.intellij.codeInsight.intention.impl.IntentionHintComponent
import com.intellij.codeInsight.intention.impl.preview.IntentionPreviewComponent.Companion.LOADING_PREVIEW
import com.intellij.codeInsight.intention.impl.preview.IntentionPreviewComponent.Companion.NO_PREVIEW
import com.intellij.diff.fragments.LineFragment
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressIndicator
@@ -18,7 +22,9 @@ import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.Computable
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileFactory
import com.intellij.ui.popup.PopupPositionManager
import com.intellij.ui.popup.PopupUpdateProcessor
import com.intellij.util.Alarm
@@ -98,11 +104,26 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
fun start() {
component.startLoading()
ProgressManager.checkCanceled()
val psiFileCopy = ApplicationManager.getApplication().runReadAction(Computable<PsiFile> { nonPhysicalPsiCopy(originalFile, project) })
ProgressManager.checkCanceled()
val documentCopy = ApplicationManager.getApplication().runReadAction(
Computable<Document> { FileDocumentManager.getInstance().getDocument(psiFileCopy.viewProvider.virtualFile) })
if (documentCopy == null) {
select(NO_PREVIEW)
return
}
val editorCopy = EditorFactory.getInstance().createEditor(documentCopy, project)
.also { it.caretModel.moveToOffset(originalEditor.caretModel.offset) }
computation = ApplicationManager.getApplication().executeOnPooledThread(
Callable {
try {
ProgressManager.getInstance().runProcess(IntentionPreviewComputable(originalFile, project, originalEditor, action),
progressIndicator)
ProgressManager.getInstance().runProcess(
IntentionPreviewComputable(project, action, originalFile, originalEditor, psiFileCopy, editorCopy), progressIndicator)
}
catch (e: ProcessCanceledException) {
Pair<PsiFile?, List<LineFragment>>(null, emptyList())
@@ -134,6 +155,21 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
}
}
private fun nonPhysicalPsiCopy(psiFile: PsiFile, project: Project): PsiFile {
ProgressManager.checkCanceled()
return PsiFileFactory.getInstance(project).createFileFromText(psiFile.name,
psiFile.language,
psiFile.text, false, true, false,
psiFile.virtualFile)
}
fun getFixes(cachedIntentions: CachedIntentions): Sequence<IntentionActionWithTextCaching> =
sequenceOf<IntentionActionWithTextCaching>()
.plus(cachedIntentions.intentions)
.plus(cachedIntentions.inspectionFixes)
.plus(cachedIntentions.errorFixes)
fun toggleShow() {
show = !show
}