diff options
Diffstat (limited to 'platform/lang-impl/src/com/intellij/ide/util')
6 files changed, 90 insertions, 116 deletions
diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index f260c732adf5..35f7f658edfd 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -65,6 +65,7 @@ import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder; import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; +import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.HashSet; @@ -83,7 +84,6 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.*; -import java.lang.reflect.Field; import java.util.*; import java.util.List; @@ -1018,22 +1018,13 @@ public class FileStructurePopup implements Disposable { public FileStructureTree(Object rootElement, boolean fastExpand) { super(new DefaultMutableTreeNode(rootElement)); if (fastExpand) { - boolean newValueIsSet; - try { - final Field field = JTree.class.getDeclaredField("expandedState"); - field.setAccessible(true); - field.set(this, new Hashtable() { - @Override - public synchronized Object get(Object key) { - return Boolean.TRUE; - } - }); - newValueIsSet = true; - } - catch (Exception e) { - newValueIsSet = false; - } - fast = newValueIsSet; + Hashtable hashtable = new Hashtable() { + @Override + public synchronized Object get(Object key) { + return Boolean.TRUE; + } + }; + fast = ReflectionUtil.setField(JTree.class, this, Hashtable.class, "expandedState", hashtable); } else { fast = false; diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index dcc1429c8bbd..3e90f2310884 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -35,6 +35,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationAdapter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.fileTypes.UnknownFileType; @@ -102,6 +103,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; public abstract class ChooseByNameBase { + private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.ChooseByNameBase"); protected final Project myProject; protected final ChooseByNameModel myModel; protected ChooseByNameItemProvider myProvider; @@ -133,7 +135,6 @@ public abstract class ChooseByNameBase { private final ListUpdater myListUpdater = new ListUpdater(); - private volatile boolean myListIsUpToDate = false; private boolean myDisposedFlag = false; private ActionCallback myPostponedOkAction; @@ -278,7 +279,7 @@ public abstract class ChooseByNameBase { if (PlatformDataKeys.HELP_ID.is(dataId)) { return myModel.getHelpId(); } - if (!myListIsUpToDate) { + if (myCalcElementsThread != null) { return null; } if (CommonDataKeys.PSI_ELEMENT.is(dataId)) { @@ -499,7 +500,7 @@ public abstract class ChooseByNameBase { myTextField.addFocusListener(new FocusAdapter() { @Override public void focusLost(@NotNull final FocusEvent e) { - cancelCalcElementsThread(); // cancel thread as early as possible + cancelListUpdater(); // cancel thread as early as possible myHideAlarm.addRequest(new Runnable() { @Override public void run() { @@ -531,7 +532,7 @@ public abstract class ChooseByNameBase { if (queue instanceof IdeEventQueue) { if (!((IdeEventQueue)queue).wasRootRecentlyClicked(oppositeComponent)) { Component root = SwingUtilities.getRoot(myTextField); - if (root != null) { + if (root != null && root.isShowing()) { root.requestFocus(); myTextField.requestFocus(); return; @@ -759,24 +760,29 @@ public abstract class ChooseByNameBase { } protected void doClose(final boolean ok) { - try { - if (checkDisposed()) return; + if (checkDisposed()) return; - if (postponeCloseWhenListReady(ok)) return; + if (postponeCloseWhenListReady(ok)) return; - cancelListUpdater(); - close(ok); + cancelListUpdater(); + close(ok); - clearPostponedOkAction(ok); - } - finally { - myListModel.clear(); - cancelCalcElementsThread(); - } + clearPostponedOkAction(ok); + myListModel.clear(); } protected void cancelListUpdater() { - cancelCalcElementsThread(); + final CalcElementsThread calcElementsThread = myCalcElementsThread; + if (calcElementsThread != null && calcElementsThread.cancel()) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + if (!checkDisposed() && calcElementsThread == myCalcElementsThread) { + backgroundCalculationFinished(Collections.emptyList(), 0); + } + } + }); + } myListUpdater.cancelAll(); } @@ -784,7 +790,7 @@ public abstract class ChooseByNameBase { if (!isToFixLostTyping()) return false; final String text = myTextField.getText(); - if (ok && !myListIsUpToDate && text != null && !text.trim().isEmpty()) { + if (ok && myCalcElementsThread != null && text != null && !text.trim().isEmpty()) { myPostponedOkAction = new ActionCallback(); IdeFocusManager.getInstance(myProject).typeAheadUntil(myPostponedOkAction); return true; @@ -885,7 +891,7 @@ public abstract class ChooseByNameBase { Disposer.register(myTextPopup, new Disposable() { @Override public void dispose() { - cancelCalcElementsThread(); + cancelListUpdater(); } }); myTextPopup.show(layeredPane); @@ -917,8 +923,6 @@ public abstract class ChooseByNameBase { return layeredPane; } - private final Object myRebuildMutex = new Object(); - protected void rebuildList(final int pos, final int delay, @NotNull final ModalityState modalityState, @@ -928,11 +932,13 @@ public abstract class ChooseByNameBase { return; } - myListIsUpToDate = false; myAlarm.cancelAllRequests(); myListUpdater.cancelAll(); - cancelCalcElementsThread(); + final CalcElementsThread calcElementsThread = myCalcElementsThread; + if (calcElementsThread != null) { + calcElementsThread.cancel(); + } final String text = myTextField.getText(); if (!canShowListForEmptyPattern() && @@ -960,24 +966,14 @@ public abstract class ChooseByNameBase { scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer<Set<?>>() { @Override public void consume(Set<?> elements) { - synchronized (myRebuildMutex) { - ApplicationManager.getApplication().assertIsDispatchThread(); - if (checkDisposed()) { - return; - } - - myListIsUpToDate = true; - setElementsToList(pos, elements); - myList.repaint(); - chosenElementMightChange(); - - if (elements.isEmpty()) { - myTextFieldPanel.hideHint(); - } + ApplicationManager.getApplication().assertIsDispatchThread(); + if (checkDisposed()) { + return; + } + backgroundCalculationFinished(elements, pos); - if (postRunnable != null) { - postRunnable.run(); - } + if (postRunnable != null) { + postRunnable.run(); } } }); @@ -992,6 +988,17 @@ public abstract class ChooseByNameBase { } } + private void backgroundCalculationFinished(Collection<?> result, int toSelect) { + myCalcElementsThread = null; + setElementsToList(toSelect, result); + myList.repaint(); + chosenElementMightChange(); + + if (result.isEmpty()) { + myTextFieldPanel.hideHint(); + } + } + public void scheduleCalcElements(String text, boolean checkboxState, ModalityState modalityState, @@ -1008,16 +1015,7 @@ public abstract class ChooseByNameBase { return myShowListAfterCompletionKeyStroke; } - private CalcElementsThread cancelCalcElementsThread() { - CalcElementsThread calcElementsThread = myCalcElementsThread; - if (calcElementsThread != null) { - calcElementsThread.cancel(); - myCalcElementsThread = null; - } - return calcElementsThread; - } - - private void setElementsToList(int pos, @NotNull Set<?> elements) { + private void setElementsToList(int pos, @NotNull Collection<?> elements) { myListUpdater.cancelAll(); if (checkDisposed()) return; if (elements.isEmpty()) { @@ -1202,33 +1200,12 @@ public abstract class ChooseByNameBase { } protected List<Object> getChosenElements() { - - List<Object> values = new ArrayList<Object>(Arrays.asList(myList.getSelectedValues())); - values.remove(EXTRA_ELEM); - values.remove(NON_PREFIX_SEPARATOR); - - if (myListIsUpToDate || !values.isEmpty()) { - return values; - } - - final String text = myTextField.getText(); - if (text.length() == 0) return Collections.emptyList(); - final boolean checkBoxState = myCheckBox.isSelected(); - final String[] names = ourLoadNamesEachTime ? ensureNamesLoaded(checkBoxState) : getNamesSync(checkBoxState); - if (names == null) return Collections.emptyList(); - - Object uniqueElement = null; - - for (final String name : names) { - if (text.equalsIgnoreCase(name)) { - final Object[] elements = myModel.getElementsByName(name, checkBoxState, text); - if (elements.length > 1) return Collections.emptyList(); - if (elements.length == 0) continue; - if (uniqueElement != null) return Collections.emptyList(); - uniqueElement = elements[0]; + return ContainerUtil.filter(myList.getSelectedValues(), new Condition<Object>() { + @Override + public boolean value(Object o) { + return o != EXTRA_ELEM && o != NON_PREFIX_SEPARATOR; } - } - return uniqueElement == null ? Collections.emptyList() : Collections.singletonList(uniqueElement); + }); } protected void chosenElementMightChange() { @@ -1565,6 +1542,7 @@ public abstract class ChooseByNameBase { @Override public void run() { if (!myCancelled.isCanceled()) { + LOG.assertTrue(myCalcElementsThread == CalcElementsThread.this); myCallback.consume(edt ? filter(elements) : filtered); } } @@ -1622,8 +1600,12 @@ public abstract class ChooseByNameBase { return elementsArray.size() >= myMaximumListSizeLimit; } - private void cancel() { + private boolean cancel() { + if (myCancelled.isCanceled()) { + return false; + } myCancelled.cancel(); + return true; } } @@ -1705,7 +1687,7 @@ public abstract class ChooseByNameBase { final LinkedHashSet<Object> nonPrefixMatchElementsArray = new LinkedHashSet<Object>(); hideHint(); ProgressManager.getInstance().run(new Task.Modal(myProject, prefixPattern, true) { - private ChooseByNameBase.CalcElementsThread myCalcElementsThread; + private ChooseByNameBase.CalcElementsThread myCalcUsagesThread; @Override public void run(@NotNull final ProgressIndicator indicator) { @@ -1716,7 +1698,7 @@ public abstract class ChooseByNameBase { @Override public void run() { final boolean[] overFlow = {false}; - myCalcElementsThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) { + myCalcUsagesThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) { private final AtomicBoolean userAskedToAbort = new AtomicBoolean(); @Override protected boolean isOverflow(@NotNull Set<Object> elementsArray) { @@ -1734,11 +1716,11 @@ public abstract class ChooseByNameBase { boolean anyPlace = isSearchInAnyPlace(); setSearchInAnyPlace(false); - myCalcElementsThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere); + myCalcUsagesThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere); setSearchInAnyPlace(anyPlace); if (anyPlace && !overFlow[0]) { - myCalcElementsThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere); + myCalcUsagesThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere); nonPrefixMatchElementsArray.removeAll(prefixMatchElementsArray); } @@ -1756,7 +1738,7 @@ public abstract class ChooseByNameBase { @Override public void onCancel() { - cancelCalcElementsThread(); + myCalcUsagesThread.cancel(); } }); } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java index cb03b68bfadb..86d9c1782b2a 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java @@ -339,7 +339,7 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP } private static final Pattern patternToDetectLinesAndColumns = Pattern.compile("([^:]+)(?::|@|,|)\\[?(\\d+)?(?:(?:\\D)(\\d+)?)?\\]?"); - private static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)"); + public static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)"); private static final Pattern patternToDetectMembers = Pattern.compile("(.+)(#)(.*)"); @Override diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java index aa6a360c84e5..cc5915c26bb6 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java @@ -189,6 +189,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider @NotNull private static String getQualifierPattern(@NotNull ChooseByNameBase base, @NotNull String pattern) { + pattern = base.transformPattern(pattern); final String[] separators = base.getModel().getSeparators(); int lastSeparatorOccurrence = 0; for (String separator : separators) { diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java index a6e6c8fdf658..99d3c9b338ae 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java @@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.util.Function; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; @@ -128,17 +129,19 @@ public class GotoActionItemProvider implements ChooseByNameItemProvider { List<AnAction> actions = ContainerUtil.newArrayList(); if (everywhere) { for (String id : ((ActionManagerImpl)myActionManager).getActionIds()) { + ProgressManager.checkCanceled(); ContainerUtil.addIfNotNull(actions, myActionManager.getAction(id)); } } else { - actions.addAll(myModel.myActionsMap.keySet()); + actions.addAll(myModel.myActionGroups.keySet()); } List<ActionWrapper> actionWrappers = ContainerUtil.newArrayList(); for (AnAction action : actions) { + ProgressManager.checkCanceled(); MatchMode mode = myModel.actionMatches(pattern, action); if (mode != MatchMode.NONE) { - actionWrappers.add(new ActionWrapper(action, myModel.myActionsMap.get(action), mode, dataContext)); + actionWrappers.add(new ActionWrapper(action, myModel.myActionGroups.get(action), mode, dataContext)); } } return processItems(pattern, actionWrappers, consumer); diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 91f0d3368521..348283dc3885 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -66,16 +66,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C private Pattern myCompiledPattern; protected final SearchableOptionsRegistrar myIndex; - protected final Map<AnAction, String> myActionsMap = new TreeMap<AnAction, String>(new Comparator<AnAction>() { - @Override - public int compare(@NotNull AnAction o1, @NotNull AnAction o2) { - int compare = Comparing.compare(o1.getTemplatePresentation().getText(), o2.getTemplatePresentation().getText()); - if (compare == 0 && !o1.equals(o2)) { - return o1.hashCode() - o2.hashCode(); - } - return compare; - } - }); + protected final Map<AnAction, String> myActionGroups = ContainerUtil.newHashMap(); protected final Map<String, ApplyIntentionAction> myIntentions = new TreeMap<String, ApplyIntentionAction>(); private final Map<String, String> myConfigurablesNames = ContainerUtil.newTroveMap(); @@ -88,7 +79,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C myProject = project; myContextComponent = component; final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU); - collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText()); + collectActions(myActionGroups, mainMenu, mainMenu.getTemplatePresentation().getText()); if (project != null && editor != null && file != null) { final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file); if (children != null) { @@ -98,6 +89,9 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C } } myIndex = SearchableOptionsRegistrar.getInstance(); + if (!EventQueue.isDispatchThread()) { + return; + } fillConfigurablesNames(ShowSettingsUtilImpl.getConfigurables(project, true)); } @@ -457,11 +451,14 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C else if (description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) { return MatchMode.DESCRIPTION; } - final String groupName = myActionsMap.get(anAction); + if (text == null) { + return MatchMode.NONE; + } + final String groupName = myActionGroups.get(anAction); if (groupName == null) { - return text != null && matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE; + return matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE; } - return text != null && matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE; + return matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE; } @Nullable @@ -611,7 +608,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C PatternMatcher getMatcher() { return myMatcher.get(); } - + public static class ActionWrapper implements Comparable<ActionWrapper>{ private final AnAction myAction; private final MatchMode myMode; |