IDEA-CR-55846 UX-931 intentions preview: corrections by review

GitOrigin-RevId: b3d846559e37f2012906a7e2cfa91da1a5a0fd01
This commit is contained in:
Dmitry.Krasilschikov
2019-12-03 16:04:11 +00:00
committed by intellij-monorepo-bot
parent 968d8bbcba
commit 2396f2de00
11 changed files with 171 additions and 185 deletions
@@ -10,6 +10,7 @@ import com.intellij.codeInsight.intention.impl.CachedIntentions;
import com.intellij.codeInsight.intention.impl.EditIntentionSettingsAction;
import com.intellij.codeInsight.intention.impl.EnableDisableIntentionAction;
import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
import com.intellij.codeInsight.intention.impl.preview.IntentionPreviewUnsupportedOperationException;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.lang.annotation.HighlightSeverity;
@@ -335,7 +336,7 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
try {
extension.collectActions(hostEditor, hostFile, intentions, passIdToShowIntentionsFor, offset);
}
catch (UnsupportedOperationException e) {
catch (IntentionPreviewUnsupportedOperationException e) {
//can collect action on a mock memory editor and produce exceptions - ignore
}
}
@@ -80,8 +80,9 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint {
private static final Border INACTIVE_BORDER = BorderFactory.createEmptyBorder(NORMAL_BORDER_SIZE, NORMAL_BORDER_SIZE, NORMAL_BORDER_SIZE, NORMAL_BORDER_SIZE);
private static final Border INACTIVE_BORDER_SMALL = BorderFactory.createEmptyBorder(SMALL_BORDER_SIZE, SMALL_BORDER_SIZE, SMALL_BORDER_SIZE, SMALL_BORDER_SIZE);
public static final KeyboardShortcut ALT_SPACE_SHORTCUT = KeyboardShortcut.fromString(("alt SPACE"));
public static final String ALT_SPACE_SHORTCUT_TEXT = KeymapUtil.getShortcutText(ALT_SPACE_SHORTCUT);
private static final ShortcutSet INTENTION_PREVIEW_SHORTCUT_SET = KeymapUtil.getActiveKeymapShortcuts(IdeActions.ACTION_QUICK_IMPLEMENTATIONS);
public static final String INTENTION_PREVIEW_SHORTCUT_TEXT = KeymapUtil.getPreferredShortcutText(INTENTION_PREVIEW_SHORTCUT_SET.getShortcuts());
private final IntentionPreviewPopupUpdateProcessor myPreviewPopupUpdateProcessor;
@TestOnly
@@ -524,7 +525,7 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint {
}
private void registerShowPreviewAction() {
((WizardPopup)myPopup).registerAction("showIntentionPreview", ALT_SPACE_SHORTCUT.getFirstKeyStroke(), new AbstractAction() {
((WizardPopup)myPopup).registerAction("showIntentionPreview", KeymapUtil.getKeyStroke(INTENTION_PREVIEW_SHORTCUT_SET), new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
myPreviewPopupUpdateProcessor.toggleShow();
@@ -538,7 +539,7 @@ public class IntentionHintComponent implements Disposable, ScrollAwareHint {
}
}
});
myPopup.setAdText(CodeInsightBundle.message("intention.preview.adv.show.text", ALT_SPACE_SHORTCUT_TEXT), SwingConstants.LEFT);
myPopup.setAdText(CodeInsightBundle.message("intention.preview.adv.show.text", INTENTION_PREVIEW_SHORTCUT_TEXT), SwingConstants.LEFT);
}
void canceled(@NotNull ListPopupStep intentionListStep) {
@@ -13,6 +13,7 @@ import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionActionDelegate;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.codeInsight.intention.impl.preview.IntentionPreviewUnsupportedOperationException;
import com.intellij.codeInsight.lookup.LookupEx;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
@@ -41,6 +42,7 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.stubs.StubTextInconsistencyException;
import com.intellij.util.PairProcessor;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -150,7 +152,7 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler {
catch (IndexNotReadyException e) {
return false;
}
catch (Exception e) {
catch (IntentionPreviewUnsupportedOperationException e) {
//check action availability can be invoked on a mock editor and may produce exceptions
return false;
}
@@ -182,7 +184,7 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler {
if (editorToApply == null) return null;
return Pair.create(fileToApply, editorToApply);
}
catch (UnsupportedOperationException e) {
catch (IntentionPreviewUnsupportedOperationException e) {
return null;
}
}
@@ -225,6 +227,7 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler {
}
}
@ApiStatus.Internal
public static void invokeIntention(@NotNull IntentionAction action, @Nullable Editor editor, @NotNull PsiFile file) {
IntentionsCollector.getInstance().record(file.getProject(), action, file.getLanguage());
PsiElement elementToMakeWritable = action.getElementToMakeWritable(file);
@@ -14,8 +14,8 @@ import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JPanel
class IntentionPreviewComponent(project: Project) : JBLoadingPanel(BorderLayout(),
{ panel -> IntentionPreviewLoadingDecorator(panel, project) }) {
internal class IntentionPreviewComponent(project: Project) : JBLoadingPanel(BorderLayout(),
{ panel -> IntentionPreviewLoadingDecorator(panel, project) }) {
private var NO_PREVIEW_LABEL = JLabel(CodeInsightBundle.message("intention.preview.no.available.text") + " ").also { setupLabel(it) }
private var LOADING_LABEL = JLabel(CodeInsightBundle.message("intention.preview.loading.preview") + " ").also { setupLabel(it) }
@@ -9,73 +9,55 @@ import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler
import com.intellij.diff.comparison.ComparisonManager
import com.intellij.diff.comparison.ComparisonPolicy
import com.intellij.diff.fragments.LineFragment
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.progress.DumbProgressIndicator
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.ThrowableComputable
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileFactory
import java.util.concurrent.Callable
class IntentionPreviewComputable(private val project: Project,
private val action: IntentionAction,
private val originalFile: PsiFile,
private val originalEditor: Editor) : Computable<Pair<PsiFile?, List<LineFragment>>?> {
override fun compute(): Pair<PsiFile?, List<LineFragment>>? {
val psiFileCopy = runReadAction { nonPhysicalPsiCopy(originalFile, project) }
internal class IntentionPreviewComputable(private val project: Project,
private val action: IntentionAction,
private val originalFile: PsiFile,
private val originalEditor: Editor) : Callable<Pair<PsiFile?, List<LineFragment>>> {
override fun call(): Pair<PsiFile?, List<LineFragment>> {
val psiFileCopy = nonPhysicalPsiCopy(originalFile, project)
ProgressManager.checkCanceled()
val editorCopy = try {
IntentionPreviewEditor(psiFileCopy, runReadAction { originalEditor.caretModel.offset })
}
catch (e: IllegalStateException) {
LOG.warn(e)
throw ProcessCanceledException()
}
val editorCopy = IntentionPreviewEditor(psiFileCopy, originalEditor.caretModel.offset)
try {
ApplicationManager.getApplication().runReadAction(ThrowableComputable<Unit, Exception> {
val action = (intentionActionWithTextCaching(editorCopy, psiFileCopy) ?: return@ThrowableComputable).action
val fileEditorPair = ShowIntentionActionsHandler.chooseFileForAction(psiFileCopy, editorCopy, action)
?: return@ThrowableComputable
val action = findCopyIntention(project, editorCopy, psiFileCopy, action) ?: throw ProcessCanceledException()
val fileEditorPair = ShowIntentionActionsHandler.chooseFileForAction(psiFileCopy, editorCopy, action)
?: throw ProcessCanceledException()
try {
originalEditor.document.setReadOnly(true)
ProgressManager.checkCanceled()
action.invoke(project, fileEditorPair.second, fileEditorPair.first)
ProgressManager.checkCanceled()
}
finally {
originalEditor.document.setReadOnly(false)
}
})
val writable = originalEditor.document.isWritable
try {
originalEditor.document.setReadOnly(true)
ProgressManager.checkCanceled()
action.invoke(project, fileEditorPair.second, fileEditorPair.first)
ProgressManager.checkCanceled()
}
finally {
originalEditor.document.setReadOnly(!writable)
}
return Pair<PsiFile?, List<LineFragment>>(
psiFileCopy,
ComparisonManager.getInstance().compareLines(originalFile.text, editorCopy.document.text, ComparisonPolicy.TRIM_WHITESPACES,
DumbProgressIndicator.INSTANCE)
)
}
catch (e: UnsupportedOperationException) {
catch (e: IntentionPreviewUnsupportedOperationException) {
throw ProcessCanceledException()
}
catch (e: Exception) {
LOG.debug("There are exceptions on invocation the intention: '${action.text}' on a copy of the file.", e)
throw ProcessCanceledException()
throw ProcessCanceledException(e)
}
return Pair<PsiFile?, List<LineFragment>>(
psiFileCopy,
PsiDocumentManager.getInstance(project).commitAndRunReadAction(Computable {
ComparisonManager.getInstance().compareLines(originalFile.text, psiFileCopy.text, ComparisonPolicy.TRIM_WHITESPACES,
DumbProgressIndicator.INSTANCE)
}))
}
private fun intentionActionWithTextCaching(editorCopy: Editor, psiFileCopy: PsiFile): IntentionActionWithTextCaching? {
val actionsToShow = ShowIntentionsPass.getActionsToShow(editorCopy, psiFileCopy, false)
val cachedIntentions = CachedIntentions.createAndUpdateActions(project, psiFileCopy, editorCopy, actionsToShow)
return getFixes(cachedIntentions).find { it.text == action.text }
}
private fun nonPhysicalPsiCopy(psiFile: PsiFile, project: Project): PsiFile {
@@ -86,13 +68,23 @@ class IntentionPreviewComputable(private val project: Project,
psiFile.virtualFile)
}
fun getFixes(cachedIntentions: CachedIntentions): Sequence<IntentionActionWithTextCaching> =
sequenceOf<IntentionActionWithTextCaching>()
.plus(cachedIntentions.intentions)
.plus(cachedIntentions.inspectionFixes)
.plus(cachedIntentions.errorFixes)
companion object {
private val LOG = Logger.getInstance(IntentionPreviewComputable::class.java)
fun getFixes(cachedIntentions: CachedIntentions): Sequence<IntentionActionWithTextCaching> =
sequenceOf<IntentionActionWithTextCaching>()
.plus(cachedIntentions.intentions)
.plus(cachedIntentions.inspectionFixes)
.plus(cachedIntentions.errorFixes)
private fun findCopyIntention(project: Project,
editorCopy: Editor,
psiFileCopy: PsiFile,
originalAction: IntentionAction): IntentionAction? {
val actionsToShow = ShowIntentionsPass.getActionsToShow(editorCopy, psiFileCopy, false)
val cachedIntentions = CachedIntentions.createAndUpdateActions(project, psiFileCopy, editorCopy, actionsToShow)
return getFixes(cachedIntentions).find { it.text == originalAction.text }?.action
}
}
}
@@ -2,7 +2,6 @@
package com.intellij.codeInsight.intention.impl.preview
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.editor.*
import com.intellij.openapi.editor.colors.EditorColorsScheme
import com.intellij.openapi.editor.event.CaretListener
@@ -22,93 +21,92 @@ import java.awt.geom.Point2D
import javax.swing.JComponent
import javax.swing.border.Border
class IntentionPreviewEditor(private val psiFileCopy: PsiFile, private var caretOffset: Int) : UserDataHolderBase(), Editor {
private val document: Document = runReadAction { FileDocumentManager.getInstance().getDocument(psiFileCopy.viewProvider.virtualFile) }
internal class IntentionPreviewEditor(private val psiFileCopy: PsiFile, private var caretOffset: Int) : UserDataHolderBase(), Editor {
private val document: Document = FileDocumentManager.getInstance().getDocument(psiFileCopy.viewProvider.virtualFile)
?: throw IllegalStateException("Document should be not null.")
companion object {
const val UNSUPPORTED_MESSAGE: String = "It's unexpected to invoke this method on an intention preview calculating."
}
private val caretModel = IntentionPreviewCaretModel()
override fun getDocument(): Document = document
override fun getCaretModel() = caretModel
override fun isViewer(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getComponent(): JComponent = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getContentComponent(): JComponent = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun setBorder(border: Border?) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getInsets(): Insets = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getMarkupModel(): MarkupModel = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getScrollingModel(): ScrollingModel = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getSoftWrapModel(): SoftWrapModel = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getSettings(): EditorSettings = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getColorsScheme(): EditorColorsScheme = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getLineHeight(): Int = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun logicalPositionToXY(pos: LogicalPosition): Point = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun logicalPositionToOffset(pos: LogicalPosition): Int = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun logicalToVisualPosition(logicalPos: LogicalPosition): VisualPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun visualPositionToXY(visible: VisualPosition): Point = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun visualPositionToPoint2D(pos: VisualPosition): Point2D = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun visualToLogicalPosition(visiblePos: VisualPosition): LogicalPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun offsetToLogicalPosition(offset: Int): LogicalPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun offsetToVisualPosition(offset: Int): VisualPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun offsetToVisualPosition(offset: Int, leanForward: Boolean, beforeSoftWrap: Boolean): VisualPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getFoldingModel(): FoldingModel = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun xyToLogicalPosition(p: Point): LogicalPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun xyToVisualPosition(p: Point): VisualPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun xyToVisualPosition(p: Point2D): VisualPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun addEditorMouseListener(listener: EditorMouseListener) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun removeEditorMouseListener(listener: EditorMouseListener) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun addEditorMouseMotionListener(listener: EditorMouseMotionListener) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun removeEditorMouseMotionListener(listener: EditorMouseMotionListener) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun isDisposed(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getProject(): Project? = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun isInsertMode(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getSelectionModel(): SelectionModel = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun isColumnMode(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun isOneLineMode(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getGutter(): EditorGutter = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getMouseEventArea(e: MouseEvent): EditorMouseEventArea? = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun setHeaderComponent(header: JComponent?) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun hasHeaderComponent(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getHeaderComponent(): JComponent? = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getIndentsModel(): IndentsModel = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getInlayModel(): InlayModel = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getEditorKind(): EditorKind = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun isViewer(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun getComponent(): JComponent = throw IntentionPreviewUnsupportedOperationException()
override fun getContentComponent(): JComponent = throw IntentionPreviewUnsupportedOperationException()
override fun setBorder(border: Border?) = throw IntentionPreviewUnsupportedOperationException()
override fun getInsets(): Insets = throw IntentionPreviewUnsupportedOperationException()
override fun getMarkupModel(): MarkupModel = throw IntentionPreviewUnsupportedOperationException()
override fun getScrollingModel(): ScrollingModel = throw IntentionPreviewUnsupportedOperationException()
override fun getSoftWrapModel(): SoftWrapModel = throw IntentionPreviewUnsupportedOperationException()
override fun getSettings(): EditorSettings = throw IntentionPreviewUnsupportedOperationException()
override fun getColorsScheme(): EditorColorsScheme = throw IntentionPreviewUnsupportedOperationException()
override fun getLineHeight(): Int = throw IntentionPreviewUnsupportedOperationException()
override fun logicalPositionToXY(pos: LogicalPosition): Point = throw IntentionPreviewUnsupportedOperationException()
override fun logicalPositionToOffset(pos: LogicalPosition): Int = throw IntentionPreviewUnsupportedOperationException()
override fun logicalToVisualPosition(logicalPos: LogicalPosition): VisualPosition = throw IntentionPreviewUnsupportedOperationException()
override fun visualPositionToXY(visible: VisualPosition): Point = throw IntentionPreviewUnsupportedOperationException()
override fun visualPositionToPoint2D(pos: VisualPosition): Point2D = throw IntentionPreviewUnsupportedOperationException()
override fun visualToLogicalPosition(visiblePos: VisualPosition): LogicalPosition = throw IntentionPreviewUnsupportedOperationException()
override fun offsetToLogicalPosition(offset: Int): LogicalPosition = throw IntentionPreviewUnsupportedOperationException()
override fun offsetToVisualPosition(offset: Int): VisualPosition = throw IntentionPreviewUnsupportedOperationException()
override fun offsetToVisualPosition(offset: Int, leanForward: Boolean, beforeSoftWrap: Boolean): VisualPosition = throw IntentionPreviewUnsupportedOperationException()
override fun getFoldingModel(): FoldingModel = throw IntentionPreviewUnsupportedOperationException()
override fun xyToLogicalPosition(p: Point): LogicalPosition = throw IntentionPreviewUnsupportedOperationException()
override fun xyToVisualPosition(p: Point): VisualPosition = throw IntentionPreviewUnsupportedOperationException()
override fun xyToVisualPosition(p: Point2D): VisualPosition = throw IntentionPreviewUnsupportedOperationException()
override fun addEditorMouseListener(listener: EditorMouseListener) = throw IntentionPreviewUnsupportedOperationException()
override fun removeEditorMouseListener(listener: EditorMouseListener) = throw IntentionPreviewUnsupportedOperationException()
override fun addEditorMouseMotionListener(listener: EditorMouseMotionListener) = throw IntentionPreviewUnsupportedOperationException()
override fun removeEditorMouseMotionListener(listener: EditorMouseMotionListener) = throw IntentionPreviewUnsupportedOperationException()
override fun isDisposed(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun getProject(): Project? = throw IntentionPreviewUnsupportedOperationException()
override fun isInsertMode(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun getSelectionModel(): SelectionModel = throw IntentionPreviewUnsupportedOperationException()
override fun isColumnMode(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun isOneLineMode(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun getGutter(): EditorGutter = throw IntentionPreviewUnsupportedOperationException()
override fun getMouseEventArea(e: MouseEvent): EditorMouseEventArea? = throw IntentionPreviewUnsupportedOperationException()
override fun setHeaderComponent(header: JComponent?) = throw IntentionPreviewUnsupportedOperationException()
override fun hasHeaderComponent(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun getHeaderComponent(): JComponent? = throw IntentionPreviewUnsupportedOperationException()
override fun getIndentsModel(): IndentsModel = throw IntentionPreviewUnsupportedOperationException()
override fun getInlayModel(): InlayModel = throw IntentionPreviewUnsupportedOperationException()
override fun getEditorKind(): EditorKind = throw IntentionPreviewUnsupportedOperationException()
inner class IntentionPreviewCaretModel : CaretModel {
override fun moveToOffset(offset: Int) { caretOffset = offset }
override fun getOffset(): Int = caretOffset
override fun moveCaretRelatively(columnShift: Int, lineShift: Int, withSelection: Boolean, blockSelection: Boolean, scrollToCaret: Boolean) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun moveToLogicalPosition(pos: LogicalPosition) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun moveToVisualPosition(pos: VisualPosition) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun moveToOffset(offset: Int, locateBeforeSoftWrap: Boolean) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun isUpToDate(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getLogicalPosition(): LogicalPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getVisualPosition(): VisualPosition = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun addCaretListener(listener: CaretListener) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun removeCaretListener(listener: CaretListener) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getVisualLineStart(): Int = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getVisualLineEnd(): Int = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getTextAttributes(): TextAttributes = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun supportsMultipleCarets(): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getCurrentCaret(): Caret = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getPrimaryCaret(): Caret = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getCaretCount(): Int = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getAllCarets(): MutableList<Caret> = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getCaretAt(pos: VisualPosition): Caret? = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun addCaret(pos: VisualPosition): Caret? = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun addCaret(pos: VisualPosition, makePrimary: Boolean): Caret? = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun removeCaret(caret: Caret): Boolean = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun removeSecondaryCarets() = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun setCaretsAndSelections(caretStates: MutableList<out CaretState>) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun setCaretsAndSelections(caretStates: MutableList<out CaretState>, updateSystemSelection: Boolean) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun getCaretsAndSelections(): MutableList<CaretState> = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun runForEachCaret(action: CaretAction) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun runForEachCaret(action: CaretAction, reverseOrder: Boolean) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun addCaretActionListener(listener: CaretActionListener, disposable: Disposable) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun runBatchCaretOperation(runnable: Runnable) = throw UnsupportedOperationException(UNSUPPORTED_MESSAGE)
override fun moveCaretRelatively(columnShift: Int, lineShift: Int, withSelection: Boolean, blockSelection: Boolean, scrollToCaret: Boolean) = throw IntentionPreviewUnsupportedOperationException()
override fun moveToLogicalPosition(pos: LogicalPosition) = throw IntentionPreviewUnsupportedOperationException()
override fun moveToVisualPosition(pos: VisualPosition) = throw IntentionPreviewUnsupportedOperationException()
override fun moveToOffset(offset: Int, locateBeforeSoftWrap: Boolean) = throw IntentionPreviewUnsupportedOperationException()
override fun isUpToDate(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun getLogicalPosition(): LogicalPosition = throw IntentionPreviewUnsupportedOperationException()
override fun getVisualPosition(): VisualPosition = throw IntentionPreviewUnsupportedOperationException()
override fun addCaretListener(listener: CaretListener) = throw IntentionPreviewUnsupportedOperationException()
override fun removeCaretListener(listener: CaretListener) = throw IntentionPreviewUnsupportedOperationException()
override fun getVisualLineStart(): Int = throw IntentionPreviewUnsupportedOperationException()
override fun getVisualLineEnd(): Int = throw IntentionPreviewUnsupportedOperationException()
override fun getTextAttributes(): TextAttributes = throw IntentionPreviewUnsupportedOperationException()
override fun supportsMultipleCarets(): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun getCurrentCaret(): Caret = throw IntentionPreviewUnsupportedOperationException()
override fun getPrimaryCaret(): Caret = throw IntentionPreviewUnsupportedOperationException()
override fun getCaretCount(): Int = throw IntentionPreviewUnsupportedOperationException()
override fun getAllCarets(): MutableList<Caret> = throw IntentionPreviewUnsupportedOperationException()
override fun getCaretAt(pos: VisualPosition): Caret? = throw IntentionPreviewUnsupportedOperationException()
override fun addCaret(pos: VisualPosition): Caret? = throw IntentionPreviewUnsupportedOperationException()
override fun addCaret(pos: VisualPosition, makePrimary: Boolean): Caret? = throw IntentionPreviewUnsupportedOperationException()
override fun removeCaret(caret: Caret): Boolean = throw IntentionPreviewUnsupportedOperationException()
override fun removeSecondaryCarets() = throw IntentionPreviewUnsupportedOperationException()
override fun setCaretsAndSelections(caretStates: MutableList<out CaretState>) = throw IntentionPreviewUnsupportedOperationException()
override fun setCaretsAndSelections(caretStates: MutableList<out CaretState>, updateSystemSelection: Boolean) = throw IntentionPreviewUnsupportedOperationException()
override fun getCaretsAndSelections(): MutableList<CaretState> = throw IntentionPreviewUnsupportedOperationException()
override fun runForEachCaret(action: CaretAction) = throw IntentionPreviewUnsupportedOperationException()
override fun runForEachCaret(action: CaretAction, reverseOrder: Boolean) = throw IntentionPreviewUnsupportedOperationException()
override fun addCaretActionListener(listener: CaretActionListener, disposable: Disposable) = throw IntentionPreviewUnsupportedOperationException()
override fun runBatchCaretOperation(runnable: Runnable) = throw IntentionPreviewUnsupportedOperationException()
}
}
}
class IntentionPreviewUnsupportedOperationException
: UnsupportedOperationException("It's unexpected to invoke this method on an intention preview calculating.")
@@ -10,7 +10,7 @@ import com.intellij.ui.JBColor
import com.intellij.util.ui.JBUI
import javax.swing.JPanel
class IntentionPreviewEditorsPanel(val editors: List<EditorEx>) : JPanel(VerticalFlowLayout(0, 0)) {
internal class IntentionPreviewEditorsPanel(val editors: List<EditorEx>) : JPanel(VerticalFlowLayout(0, 0)) {
init {
editors.forEachIndexed { index, editor ->
add(editor.component)
@@ -13,7 +13,7 @@ import java.awt.FlowLayout
import javax.swing.JLabel
import javax.swing.JPanel
class IntentionPreviewLoadingDecorator(panel: JPanel, project: Project) :
internal class IntentionPreviewLoadingDecorator(panel: JPanel, project: Project) :
LoadingDecorator(panel, project, 500, false, AsyncProcessIcon("IntentionPreviewProcessLoading")) {
override fun customizeLoadingLayer(parent: JPanel, text: JLabel, icon: AsyncProcessIcon): NonOpaquePanel {
val iconNonOpaquePanel = OpaquePanel(FlowLayout(FlowLayout.RIGHT, 2, 2))
@@ -17,7 +17,7 @@ import com.intellij.psi.PsiFile
import com.intellij.psi.codeStyle.CodeStyleManager
import com.intellij.util.ui.JBUI
class IntentionPreviewModel {
internal class IntentionPreviewModel {
companion object {
fun reformatRange(project: Project, psiFileCopy: PsiFile, lineFragment: LineFragment) {
val start = lineFragment.startOffset2
@@ -66,16 +66,16 @@ class IntentionPreviewModel {
val editor = (editorFactory.createEditor(document, project, fileType, false) as EditorEx)
.also { it.setBorder(JBUI.Borders.empty(2, 0, 2, 0)) }
editor.settings.also {
it.isLineNumbersShown = true
it.isCaretRowShown = false
it.isLineMarkerAreaShown = false
it.isFoldingOutlineShown = false
it.additionalColumnsCount = 0
it.additionalLinesCount = 0
it.isRightMarginShown = false
it.isUseSoftWraps = false
it.isAdditionalPageAtBottom = false
editor.settings.apply {
isLineNumbersShown = true
isCaretRowShown = false
isLineMarkerAreaShown = false
isFoldingOutlineShown = false
additionalColumnsCount = 0
additionalLinesCount = 0
isRightMarginShown = false
isUseSoftWraps = false
isAdditionalPageAtBottom = false
}
editor.gutterComponentEx.also {
@@ -7,14 +7,12 @@ 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.actionSystem.CommonShortcuts.ESCAPE
import com.intellij.openapi.application.ReadAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.ex.EditorEx
import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.keymap.KeymapUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
@@ -22,17 +20,15 @@ import com.intellij.psi.PsiFile
import com.intellij.ui.popup.PopupPositionManager
import com.intellij.ui.popup.PopupUpdateProcessor
import com.intellij.util.Alarm
import java.util.concurrent.Callable
import java.util.concurrent.Future
import com.intellij.util.concurrency.AppExecutorUtil
import org.jetbrains.concurrency.CancellablePromise
import java.util.concurrent.TimeUnit
class IntentionPreviewPopupUpdateProcessor(private val project: Project,
private val originalFile: PsiFile,
private val originalEditor: Editor) : PopupUpdateProcessor(project) {
internal class IntentionPreviewPopupUpdateProcessor(private val project: Project,
private val originalFile: PsiFile,
private val originalEditor: Editor) : PopupUpdateProcessor(project) {
private var index: Int = LOADING_PREVIEW
private var show = false
private var progressIndicator: ProgressIndicator = EmptyProgressIndicator()
private val alarm = Alarm()
private lateinit var popup: JBPopup
@@ -41,12 +37,10 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
private var editorsToRelease = mutableListOf<EditorEx>()
override fun updatePopup(lookupItemObject: Any?) {
override fun updatePopup(intentionAction: Any?) {
if (!show) return
alarm.cancelAllRequests()
progressIndicator.cancel()
if (!::popup.isInitialized || popup.isDisposed) {
component = IntentionPreviewComponent(project)
component.multiPanel.select(LOADING_PREVIEW, true)
@@ -57,7 +51,7 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
PopupPositionManager.positionPopupInBestPosition(popup, originalEditor, null)
updateAdvText.invoke(CodeInsightBundle.message("intention.preview.adv.hide.text"))
updateAdvText.invoke(CodeInsightBundle.message("intention.preview.adv.hide.text", Companion.ESCAPE_SHORTCUT_TEXT))
}
val value = component.multiPanel.getValue(index, false)
@@ -66,7 +60,7 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
return
}
val action = lookupItemObject as IntentionAction
val action = intentionAction as IntentionAction
if (!action.startInWriteAction() || action.getElementToMakeWritable(originalFile) !== originalFile) {
select(NO_PREVIEW)
return
@@ -86,7 +80,8 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
component.removeAll()
alarm.cancelAllRequests()
show = false
updateAdvText.invoke(CodeInsightBundle.message("intention.preview.adv.show.text", IntentionHintComponent.ALT_SPACE_SHORTCUT_TEXT))
updateAdvText.invoke(
CodeInsightBundle.message("intention.preview.adv.show.text", IntentionHintComponent.INTENTION_PREVIEW_SHORTCUT_TEXT))
return true
}
@@ -94,21 +89,13 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
private val action: IntentionAction,
private val originalFile: PsiFile,
private val originalEditor: Editor) : Runnable {
lateinit var computation: Future<Pair<PsiFile?, List<LineFragment>>?>
lateinit var computation: CancellablePromise<Pair<PsiFile?, List<LineFragment>>?>
fun start() {
component.startLoading()
computation = ApplicationManager.getApplication().executeOnPooledThread(
Callable {
try {
ProgressManager.getInstance().runProcess(IntentionPreviewComputable(project, action, originalFile, originalEditor),
progressIndicator)
}
catch (e: ProcessCanceledException) {
Pair<PsiFile?, List<LineFragment>>(null, emptyList())
}
})
computation = ReadAction.nonBlocking<Pair<PsiFile?, List<LineFragment>>>(
IntentionPreviewComputable(project, action, originalFile, originalEditor)).submit(AppExecutorUtil.getAppExecutorService())
alarm.addRequest(this, 100)
}
@@ -146,4 +133,8 @@ class IntentionPreviewPopupUpdateProcessor(private val project: Project,
popup.pack(true, true)
}
companion object {
private val ESCAPE_SHORTCUT_TEXT = KeymapUtil.getPreferredShortcutText(ESCAPE.shortcuts)
}
}
@@ -269,7 +269,7 @@ intention.wrap.with.unmodifiable.set=Wrap with unmodifiable set
intention.wrap.with.unmodifiable.map=Wrap with unmodifiable map
intention.preview.adv.show.text=Press {0} to open preview
intention.preview.adv.hide.text=Press Escape to hide preview
intention.preview.adv.hide.text=Press {0} to hide preview
intention.preview.no.available.text=Preview isn't available
intention.preview.loading.preview=Loading...
intention.preview.initial.loading.preview=Intention Preview