show a modal dialog when intention availability check on Alt+Enter is too slow (IDEA-227453, EA-218533)

GitOrigin-RevId: 8bc8000e228b0726acc900f8f08d8df309a707b4
This commit is contained in:
Peter Gromov
2019-11-25 12:09:00 +00:00
committed by intellij-monorepo-bot
parent b8c624cdf2
commit 899483290c
3 changed files with 36 additions and 20 deletions
@@ -9,19 +9,13 @@ import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.List;
class EditorNotificationActions implements IntentionMenuContributor {
@Override
public void collectActions(@NotNull Editor hostEditor,
@NotNull PsiFile hostFile,
@NotNull ShowIntentionsPass.IntentionsInfo intentions,
int passIdToShowIntentionsFor,
int offset) {
class EditorNotificationActions {
static void collectActions(@NotNull Editor hostEditor, @NotNull ShowIntentionsPass.IntentionsInfo intentions) {
Project project = hostEditor.getProject();
if (project == null) return;
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -31,6 +32,7 @@ import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.CommonProcessors;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -117,6 +119,7 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
boolean fixRangeIsNotEmpty = !info.getFixTextRange().isEmpty();
Editor injectedEditor = null;
PsiFile injectedFile = null;
ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
for (Pair<HighlightInfo.IntentionActionDescriptor, RangeMarker> pair : info.quickFixActionMarkers) {
HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first;
RangeMarker range = pair.second;
@@ -146,6 +149,9 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
editorToUse = editor;
fileToUse = file;
}
if (indicator != null) {
indicator.setText(actionInGroup.getDisplayName());
}
if (actionInGroup.getAction().isAvailable(project, editorToUse, fileToUse)) {
outList.add(actionInGroup);
}
@@ -231,7 +237,7 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
TemplateState state = TemplateManagerImpl.getTemplateState(myEditor);
if ((state == null || state.isFinished()) && cachedIntentions != null) {
IntentionsInfo syncInfo = new IntentionsInfo();
getActionsToShowSync(myEditor, myFile, syncInfo, myPassIdToShowIntentionsFor);
getActionsToShowSync(myEditor, myFile, syncInfo);
actionsChanged |= cachedIntentions.addActions(syncInfo);
IntentionsUI.getInstance(myProject).update(cachedIntentions, actionsChanged);
@@ -249,7 +255,7 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
IntentionsInfo result = new IntentionsInfo();
getActionsToShow(hostEditor, hostFile, result, -1);
if (includeSyncActions) {
getActionsToShowSync(hostEditor, hostFile, result, -1);
getActionsToShowSync(hostEditor, hostFile, result);
}
return result;
}
@@ -257,13 +263,12 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
/**
* Collects intention actions from providers intended to be invoked in EDT.
*/
private static void getActionsToShowSync(@NotNull final Editor hostEditor,
@NotNull final PsiFile hostFile,
@NotNull final IntentionsInfo intentions,
int passIdToShowIntentionsFor) {
@ApiStatus.Internal
public static void getActionsToShowSync(@NotNull Editor hostEditor,
@NotNull PsiFile hostFile,
@NotNull IntentionsInfo intentions) {
ApplicationManager.getApplication().assertIsDispatchThread();
new EditorNotificationActions().collectActions(hostEditor, hostFile, intentions, passIdToShowIntentionsFor,
hostEditor.getCaretModel().getOffset());
EditorNotificationActions.collectActions(hostEditor, intentions);
intentions.filterActions(hostFile);
}
@@ -299,9 +304,14 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
fillIntentionsInfoForHighlightInfo(infoAtCursor, intentions, fixes);
}
ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
if (queryIntentionActions) {
PsiFile injectedFile = InjectedLanguageUtil.findInjectedPsiNoCommit(hostFile, offset);
for (final IntentionAction action : IntentionManager.getInstance().getAvailableIntentionActions()) {
if (indicator != null) {
indicator.setText(action.getFamilyName());
}
Pair<PsiFile, Editor> place =
ShowIntentionActionsHandler.chooseBetweenHostAndInjected(hostFile, hostEditor, injectedFile,
(psiFile, editor) -> ShowIntentionActionsHandler.availableFor(psiFile, editor, action));
@@ -318,6 +328,9 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass {
}
}
if (indicator != null) {
indicator.setText("Searching for additional intention actions & quick fixes");
}
for (IntentionMenuContributor extension : IntentionMenuContributor.EP_NAME.getExtensionList()) {
extension.collectActions(hostEditor, hostFile, intentions, passIdToShowIntentionsFor, offset);
}
@@ -23,6 +23,7 @@ import com.intellij.featureStatistics.FeatureUsageTrackerImpl;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.internal.statistic.collectors.fus.actions.persistence.IntentionsCollector;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
@@ -69,7 +70,6 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler {
final DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
letAutoImportComplete(editor, file, codeAnalyzer);
ShowIntentionsPass.IntentionsInfo intentions = ShowIntentionsPass.getActionsToShow(editor, file, true);
IntentionsUI.getInstance(project).hide();
if (HintManagerImpl.getInstanceImpl().performCurrentQuestionAction()) return;
@@ -82,9 +82,7 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler {
}
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
Editor finalEditor = editor;
PsiFile finalFile = file;
showIntentionHint(project, finalEditor, finalFile, intentions, showFeedbackOnEmptyMenu);
showIntentionHint(project, editor, file, calcIntentions(project, editor, file), showFeedbackOnEmptyMenu);
}
protected void showIntentionHint(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file, @NotNull ShowIntentionsPass.IntentionsInfo intentions, boolean showFeedbackOnEmptyMenu) {
@@ -99,6 +97,17 @@ public class ShowIntentionActionsHandler implements CodeInsightActionHandler {
}
}
@NotNull
private static ShowIntentionsPass.IntentionsInfo calcIntentions(@NotNull Project project,
@NotNull Editor editor,
@NotNull PsiFile file) {
ShowIntentionsPass.IntentionsInfo intentions = ActionUtil.underModalProgress(project, "Finding Context Actions", () ->
ShowIntentionsPass.getActionsToShow(editor, file, false));
ShowIntentionsPass.getActionsToShowSync(editor, file, intentions);
return intentions;
}
private static void letAutoImportComplete(@NotNull Editor editor, @NotNull PsiFile file, DaemonCodeAnalyzerImpl codeAnalyzer) {
CommandProcessor.getInstance().runUndoTransparentAction(() -> codeAnalyzer.autoImportReferenceAtCursor(editor, file));
}