summaryrefslogtreecommitdiff
path: root/platform/lang-impl/src/com/intellij/ide/util
diff options
context:
space:
mode:
Diffstat (limited to 'platform/lang-impl/src/com/intellij/ide/util')
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java25
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java144
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java1
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java7
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java27
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;