mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-06 06:21:16 +07:00
propagate available intentions to find action/search everywhere (IDEA-117167)
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ApplyIntentionAction extends AnAction {
|
||||
|
||||
private final HighlightInfo.IntentionActionDescriptor myDescriptor;
|
||||
private final Editor myEditor;
|
||||
private final PsiFile myFile;
|
||||
|
||||
public ApplyIntentionAction(HighlightInfo.IntentionActionDescriptor descriptor, Editor editor, PsiFile file) {
|
||||
super(descriptor.getAction().getText());
|
||||
myDescriptor = descriptor;
|
||||
myEditor = editor;
|
||||
myFile = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final IntentionAction action = myDescriptor.getAction();
|
||||
ShowIntentionActionsHandler.chooseActionAndInvoke(myFile, myEditor, action, action.getText());
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myDescriptor.getAction().getText();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ApplyIntentionAction[] getAvailableIntentions(final Editor editor, final PsiFile file) {
|
||||
final ShowIntentionsPass.IntentionsInfo info = new ShowIntentionsPass.IntentionsInfo();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ShowIntentionsPass.getActionsToShow(editor, file, info, -1);
|
||||
}
|
||||
});
|
||||
if (info.isEmpty()) return null;
|
||||
|
||||
final List<HighlightInfo.IntentionActionDescriptor> actions = new ArrayList<HighlightInfo.IntentionActionDescriptor>();
|
||||
actions.addAll(info.errorFixesToShow);
|
||||
actions.addAll(info.inspectionFixesToShow);
|
||||
actions.addAll(info.intentionsToShow);
|
||||
|
||||
final ApplyIntentionAction[] result = new ApplyIntentionAction[actions.size()];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = new ApplyIntentionAction(actions.get(i), editor, file);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,12 @@ import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -54,9 +56,11 @@ public class GotoActionAction extends GotoActionBase implements DumbAware {
|
||||
public void gotoActionPerformed(final AnActionEvent e) {
|
||||
final Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
final Component component = e.getData(PlatformDataKeys.CONTEXT_COMPONENT);
|
||||
final Editor editor = e.getData(CommonDataKeys.EDITOR);
|
||||
final PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
|
||||
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.action");
|
||||
final GotoActionModel model = new GotoActionModel(project, component);
|
||||
final GotoActionModel model = new GotoActionModel(project, component, editor, file);
|
||||
final GotoActionCallback<Object> callback = new GotoActionCallback<Object>() {
|
||||
@Override
|
||||
public void elementChosen(ChooseByNamePopup popup, final Object element) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder;
|
||||
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
|
||||
import com.intellij.ide.ui.search.BooleanOptionDescription;
|
||||
import com.intellij.ide.ui.search.OptionDescription;
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
|
||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.ide.util.gotoByName.*;
|
||||
@@ -37,10 +36,10 @@ import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.AnActionListener;
|
||||
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.actions.TextComponentEditorAction;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
|
||||
@@ -256,6 +255,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
private Component myFocusOwner;
|
||||
private ChooseByNamePopup myFileChooseByName;
|
||||
|
||||
private Editor myEditor;
|
||||
private PsiFile myFile;
|
||||
|
||||
@Override
|
||||
public JComponent createCustomComponent(Presentation presentation) {
|
||||
JPanel panel = new JPanel(new BorderLayout()) {
|
||||
@@ -624,6 +626,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
rebuildList(myPopupField.getText());
|
||||
return;
|
||||
}
|
||||
if (e != null) {
|
||||
myEditor = e.getData(CommonDataKeys.EDITOR);
|
||||
myFile = e.getData(CommonDataKeys.PSI_FILE);
|
||||
}
|
||||
if (e == null && myFocusOwner != null) {
|
||||
e = new AnActionEvent(me, DataManager.getInstance().getDataContext(myFocusOwner), ActionPlaces.UNKNOWN, getTemplatePresentation(), ActionManager.getInstance(), 0);
|
||||
}
|
||||
@@ -1474,76 +1480,11 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
|
||||
private GotoActionModel createActionModel() {
|
||||
return new GotoActionModel(project, myFocusComponent) {
|
||||
return new GotoActionModel(project, myFocusComponent, myEditor, myFile) {
|
||||
@Override
|
||||
public boolean matches(@NotNull String name, @NotNull String pattern) {
|
||||
final AnAction anAction = ActionManager.getInstance().getAction(name);
|
||||
if (anAction == null) return true;
|
||||
return NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE).matches(
|
||||
anAction.getTemplatePresentation().getText());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getElementsByName(String id, boolean checkBoxState, String pattern) {
|
||||
final HashMap<AnAction, String> map = new HashMap<AnAction, String>();
|
||||
final AnAction act = myActionManager.getAction(id);
|
||||
if (act != null) {
|
||||
map.put(act, myActionsMap.get(act));
|
||||
if (checkBoxState) {
|
||||
final Set<String> ids = ((ActionManagerImpl)myActionManager).getActionIds();
|
||||
for (AnAction action : map.keySet()) { //do not add already included actions
|
||||
ids.remove(getActionId(action));
|
||||
}
|
||||
if (ids.contains(id)) {
|
||||
final AnAction anAction = myActionManager.getAction(id);
|
||||
map.put(anAction, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Object[] objects = map.entrySet().toArray(new Map.Entry[map.size()]);
|
||||
if (Comparing.strEqual(id, SETTINGS_KEY)) {
|
||||
final Set<String> words = myIndex.getProcessedWords(pattern);
|
||||
Set<OptionDescription> optionDescriptions = null;
|
||||
final String actionManagerName = myActionManager.getComponentName();
|
||||
for (String word : words) {
|
||||
final Set<OptionDescription> descriptions = ((SearchableOptionsRegistrarImpl)myIndex).getAcceptableDescriptions(word);
|
||||
if (descriptions != null) {
|
||||
for (Iterator<OptionDescription> iterator = descriptions.iterator(); iterator.hasNext(); ) {
|
||||
OptionDescription description = iterator.next();
|
||||
if (actionManagerName.equals(description.getPath())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (!descriptions.isEmpty()) {
|
||||
if (optionDescriptions == null) {
|
||||
optionDescriptions = descriptions;
|
||||
}
|
||||
else {
|
||||
optionDescriptions.retainAll(descriptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
optionDescriptions = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optionDescriptions != null && !optionDescriptions.isEmpty()) {
|
||||
Set<String> currentHits = new HashSet<String>();
|
||||
for (Iterator<OptionDescription> iterator = optionDescriptions.iterator(); iterator.hasNext(); ) {
|
||||
OptionDescription description = iterator.next();
|
||||
final String hit = description.getHit();
|
||||
if (hit == null || !currentHits.add(hit.trim())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
final Object[] descriptions = optionDescriptions.toArray();
|
||||
Arrays.sort(descriptions);
|
||||
objects = ArrayUtil.mergeArrays(objects, descriptions);
|
||||
}
|
||||
}
|
||||
return objects;
|
||||
protected boolean actionMatches(String pattern, @NotNull AnAction anAction) {
|
||||
return NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE)
|
||||
.matches(anAction.getTemplatePresentation().getText());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.ide.util.gotoByName;
|
||||
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.actions.ApplyIntentionAction;
|
||||
import com.intellij.ide.ui.search.OptionDescription;
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
|
||||
@@ -25,11 +26,13 @@ import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.LayeredIcon;
|
||||
import com.intellij.ui.LightColors;
|
||||
@@ -48,6 +51,7 @@ import java.util.*;
|
||||
|
||||
public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, Comparator<Object> {
|
||||
@NonNls public static final String SETTINGS_KEY = "$$$SETTINGS$$$";
|
||||
@NonNls public static final String INTENTIONS_KEY = "$$$INTENTIONS_KEY$$$";
|
||||
@Nullable private final Project myProject;
|
||||
private final Component myContextComponent;
|
||||
|
||||
@@ -69,11 +73,25 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
}
|
||||
});
|
||||
|
||||
protected final Map<String, ApplyIntentionAction> myIntentions = new TreeMap<String, ApplyIntentionAction>();
|
||||
|
||||
public GotoActionModel(@Nullable Project project, final Component component) {
|
||||
this(project, component, null, null);
|
||||
}
|
||||
|
||||
public GotoActionModel(@Nullable Project project, final Component component, @Nullable Editor editor, @Nullable PsiFile file) {
|
||||
myProject = project;
|
||||
myContextComponent = component;
|
||||
final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU);
|
||||
collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText());
|
||||
if (project != null && editor != null && file != null) {
|
||||
final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file);
|
||||
if (children != null) {
|
||||
for (ApplyIntentionAction action : children) {
|
||||
myIntentions.put(action.getName(), action);
|
||||
}
|
||||
}
|
||||
}
|
||||
myIndex = SearchableOptionsRegistrar.getInstance();
|
||||
}
|
||||
|
||||
@@ -266,6 +284,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
@NotNull
|
||||
public String[] getNames(boolean checkBoxState) {
|
||||
final ArrayList<String> result = new ArrayList<String>();
|
||||
result.add(INTENTIONS_KEY);
|
||||
for (AnAction action : myActionsMap.keySet()) {
|
||||
result.add(getActionId(action));
|
||||
}
|
||||
@@ -296,6 +315,13 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
map.put(anAction, null);
|
||||
}
|
||||
}
|
||||
} else if (Comparing.strEqual(id, INTENTIONS_KEY)) {
|
||||
for (String intentionText : myIntentions.keySet()) {
|
||||
final ApplyIntentionAction intentionAction = myIntentions.get(intentionText);
|
||||
if (actionMatches(pattern, intentionAction)) {
|
||||
map.put(intentionAction, intentionText);
|
||||
}
|
||||
}
|
||||
}
|
||||
Object[] objects = map.entrySet().toArray(new Map.Entry[map.size()]);
|
||||
if (Comparing.strEqual(id, SETTINGS_KEY)) {
|
||||
@@ -409,6 +435,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
|
||||
public boolean matches(@NotNull final String name, @NotNull final String pattern) {
|
||||
final AnAction anAction = myActionManager.getAction(name);
|
||||
if (anAction == null) return true;
|
||||
return actionMatches(pattern, anAction);
|
||||
}
|
||||
|
||||
protected boolean actionMatches(String pattern, @NotNull AnAction anAction) {
|
||||
final Pattern compiledPattern = getPattern(pattern);
|
||||
final Presentation presentation = anAction.getTemplatePresentation();
|
||||
final String text = presentation.getText();
|
||||
|
||||
Reference in New Issue
Block a user