xdebugger: asynchronously compute list of local processes to which debuggers can attach; allow to compute some data for all debuggable processes at once and reuse it to present these processes (RIDER-IC-CR-2)

This commit is contained in:
Artem Bukhonov
2016-07-22 20:27:28 +03:00
committed by nik
parent 317c49e66c
commit 2ae9e7ee36
10 changed files with 145 additions and 103 deletions
@@ -59,7 +59,7 @@ public class JavaAttachDebuggerProvider implements XLocalAttachDebuggerProvider
}
@Override
public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException {
public void attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException {
Pair<String, Integer> address = getAttachAddress(processInfo);
assert address != null;
@@ -87,10 +87,10 @@ public class JavaAttachDebuggerProvider implements XLocalAttachDebuggerProvider
DebugEnvironment environment = new DefaultDebugEnvironment(env, new RemoteStateState(project, remoteConnection), remoteConnection, 0);
final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(env.getProject()).attachVirtualMachine(environment);
if (debuggerSession == null) {
return null;
return;
}
return XDebuggerManager.getInstance(project).startSessionAndShowTab(name, null, new XDebugProcessStarter() {
XDebuggerManager.getInstance(project).startSessionAndShowTab(name, null, new XDebugProcessStarter() {
@Override
@NotNull
public XDebugProcess start(@NotNull XDebugSession session) {
@@ -118,7 +118,7 @@ public class JavaAttachDebuggerProvider implements XLocalAttachDebuggerProvider
@NotNull
@Override
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) {
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder) {
Pair<String, Integer> address = getAttachAddress(info);
assert address != null;
return StringUtil.notNullize(ArrayUtil.getLastElement(info.getCommandLine().split(" "))) + " (" + getAttachString(address) + ')';
@@ -16,6 +16,7 @@ xdebugger.attach.toLocal.popup.selectDebugger.title=Debugger
xdebugger.attach.toLocal.popup.recent=Recent
xdebugger.attach.toLocal.action=Attach to Local Process...
xdebugger.attach.toLocal.action.description=Attach to a locally running process with an available debugger
xdebugger.attach.toLocal.action.collectingProcesses=Collecting Processes...
xdebugger.remove.line.breakpoint.action.text=Remove breakpoint
xdebugger.disable.breakpoint.action.text=Disable breakpoint
@@ -18,6 +18,7 @@ package com.intellij.xdebugger.attach;
import com.intellij.execution.process.ProcessInfo;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolder;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -36,18 +37,18 @@ public class XDefaultLocalAttachGroup implements XLocalAttachGroup {
@NotNull
@Override
public Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info) {
public Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder) {
return AllIcons.RunConfigurations.Application;
}
@NotNull
@Override
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) {
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder) {
return info.getExecutableDisplayName();
}
@Override
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) {
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b, @NotNull UserDataHolder dataHolder) {
return a.getPid() - b.getPid();
}
}
@@ -18,13 +18,11 @@ package com.intellij.xdebugger.attach;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.ProcessInfo;
import com.intellij.openapi.project.Project;
import com.intellij.xdebugger.XDebugSession;
import org.jetbrains.annotations.NotNull;
public interface XLocalAttachDebugger {
@NotNull
String getDebuggerDisplayName();
@NotNull
XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException;
void attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException;
}
@@ -29,7 +29,7 @@ public interface XLocalAttachDebuggerProvider {
/**
* @return a group in which the supported processes should be visually organized.
* Return XLocalAttachGroup.DEFAULT for a common group.
*
*
*/
@NotNull
default XLocalAttachGroup getAttachGroup() {
@@ -39,14 +39,14 @@ public interface XLocalAttachDebuggerProvider {
/**
* Attach to Local Process action invokes {@link #getAvailableDebuggers} method for every running process.
* {@link XLocalAttachDebuggerProvider} should return a list of the debuggers that can attach and debug a given process.
*
* If there are several debuggers that can attach to a process, the user will have a choice between them.
*
* @param contextHolder use this data holder if you need to store temporary data during debuggers collection.
* Lifetime of the data is restricted by a single Attach to Local Process action invocation.
*
* If there are several debuggers that can attach to a process, the user will have a choice between them.
*
* @param contextHolder use this data holder if you need to store temporary data during debuggers collection.
* Lifetime of the data is restricted by a single Attach to Local Process action invocation.
*/
@NotNull
List<XLocalAttachDebugger> getAvailableDebuggers(@NotNull Project project,
@NotNull ProcessInfo processInfo,
List<XLocalAttachDebugger> getAvailableDebuggers(@NotNull Project project,
@NotNull ProcessInfo processInfo,
@NotNull UserDataHolder contextHolder);
}
@@ -17,6 +17,7 @@ package com.intellij.xdebugger.attach;
import com.intellij.execution.process.ProcessInfo;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolder;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -27,13 +28,28 @@ public interface XLocalAttachGroup {
@NotNull
String getGroupName();
/**
* @param dataHolder you may put your specific data into the holder at previous step in method @{@link XLocalAttachDebuggerProvider#getAvailableDebuggers(Project, ProcessInfo, UserDataHolder)}
* and use it for presentation
* @return an icon to be shown in popup menu for your debugger item
*/
@NotNull
Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info);
Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder);
/**
* @param dataHolder you may put your specific data into the holder at previous step in method @{@link XLocalAttachDebuggerProvider#getAvailableDebuggers(Project, ProcessInfo, UserDataHolder)}
* and use it for presentation
* @return a text to be shown on your debugger item
*/
@NotNull
String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info);
String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder);
int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b);
/**
* Specifies process order in your group
* @param dataHolder you may put your specific data into the holder at previous step in method @{@link XLocalAttachDebuggerProvider#getAvailableDebuggers(Project, ProcessInfo, UserDataHolder)}
* and use it for comparison
*/
int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b, @NotNull UserDataHolder dataHolder);
XLocalAttachGroup DEFAULT = new XDefaultLocalAttachGroup();
}
@@ -23,12 +23,17 @@ import com.intellij.internal.statistic.UsageTrigger;
import com.intellij.internal.statistic.beans.ConvertUsagesUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowId;
@@ -56,7 +61,7 @@ import java.util.List;
public class AttachToLocalProcessAction extends AnAction {
private static final Key<LinkedHashMap<String, HistoryItem>> HISTORY_KEY = Key.create("AttachToLocalProcessAction.HISTORY_KEY");
public AttachToLocalProcessAction() {
super(XDebuggerBundle.message("xdebugger.attach.toLocal.action"),
XDebuggerBundle.message("xdebugger.attach.toLocal.action.description"), null);
@@ -76,49 +81,62 @@ public class AttachToLocalProcessAction extends AnAction {
final Project project = getEventProject(e);
if (project == null) return;
ProcessInfo[] processList = OSProcessUtil.getProcessList();
XLocalAttachDebuggerProvider[] providers = Extensions.getExtensions(XLocalAttachDebuggerProvider.EP);
ProcessListStep step = new ProcessListStep(collectAttachItems(project, processList, providers), project);
new Task.Backgroundable(project, XDebuggerBundle.message("xdebugger.attach.toLocal.action.collectingProcesses"), true, PerformInBackgroundOption.DEAF) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
ProcessInfo[] processList = OSProcessUtil.getProcessList();
List<AttachItem> items = collectAttachItems(project, processList, indicator, providers);
ApplicationManager.getApplication().invokeLater(() -> {
if (project.isDisposed()) {
return;
}
ProcessListStep step = new ProcessListStep(items, project);
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(step);
final JList mainList = ((ListPopupImpl)popup).getList();
final ListPopup popup = JBPopupFactory.getInstance().createListPopup(step);
final JList mainList = ((ListPopupImpl) popup).getList();
ListSelectionListener listener = event -> {
if (event.getValueIsAdjusting()) return;
ListSelectionListener listener = event -> {
if (event.getValueIsAdjusting()) return;
Object item = ((JList)event.getSource()).getSelectedValue();
Object item = ((JList) event.getSource()).getSelectedValue();
// if a sub-list is closed, fallback to the selected value from the main list
if (item == null) {
item = mainList.getSelectedValue();
// if a sub-list is closed, fallback to the selected value from the main list
if (item == null) {
item = mainList.getSelectedValue();
}
if (item instanceof AttachItem) {
String debuggerName = ((AttachItem)item).getSelectedDebugger().getDebuggerDisplayName();
debuggerName = StringUtil.shortenTextWithEllipsis(debuggerName, 50, 0);
((ListPopupImpl)popup).setCaption(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title", debuggerName));
}
};
popup.addListSelectionListener(listener);
// force first valueChanged event
listener.valueChanged(new ListSelectionEvent(mainList, mainList.getMinSelectionIndex(), mainList.getMaxSelectionIndex(), false));
popup.showCenteredInCurrentWindow(project);
});
}
if (item instanceof AttachItem) {
String debuggerName = ((AttachItem)item).getSelectedDebugger().getDebuggerDisplayName();
debuggerName = StringUtil.shortenTextWithEllipsis(debuggerName, 50, 0);
((ListPopupImpl)popup).setCaption(XDebuggerBundle.message("xdebugger.attach.toLocal.popup.title", debuggerName));
}
};
popup.addListSelectionListener(listener);
// force first valueChanged event
listener.valueChanged(new ListSelectionEvent(mainList, mainList.getMinSelectionIndex(), mainList.getMaxSelectionIndex(), false));
popup.showCenteredInCurrentWindow(project);
}.queue();
}
@NotNull
public static List<AttachItem> collectAttachItems(@NotNull final Project project,
public static List<AttachItem> collectAttachItems(@NotNull final Project project,
@NotNull ProcessInfo[] processList,
@NotNull ProgressIndicator indicator,
@NotNull XLocalAttachDebuggerProvider... providers) {
MultiMap<XLocalAttachGroup, Pair<ProcessInfo, ArrayList<XLocalAttachDebugger>>> groupWithItems = new MultiMap<>();
UserDataHolderBase dataHolder = new UserDataHolderBase();
for (ProcessInfo eachInfo : processList) {
MultiMap<XLocalAttachGroup, XLocalAttachDebugger> groupsWithDebuggers = new MultiMap<>();
for (XLocalAttachDebuggerProvider eachProvider : providers) {
indicator.checkCanceled();
groupsWithDebuggers.putValues(eachProvider.getAttachGroup(), eachProvider.getAvailableDebuggers(project, eachInfo, dataHolder));
}
@@ -136,12 +154,12 @@ public class AttachToLocalProcessAction extends AnAction {
List<AttachItem> currentItems = new ArrayList<>();
for (final XLocalAttachGroup eachGroup : sortedGroups) {
List<Pair<ProcessInfo, ArrayList<XLocalAttachDebugger>>> sortedItems
= new ArrayList<>(groupWithItems.get(eachGroup));
Collections.sort(sortedItems, (a, b) -> eachGroup.compare(project, a.first, b.first));
= new ArrayList<>(groupWithItems.get(eachGroup));
Collections.sort(sortedItems, (a, b) -> eachGroup.compare(project, a.first, b.first, dataHolder));
boolean first = true;
for (Pair<ProcessInfo, ArrayList<XLocalAttachDebugger>> eachItem : sortedItems) {
currentItems.add(new AttachItem(eachGroup, first, eachItem.first, eachItem.second));
currentItems.add(new AttachItem(eachGroup, first, eachItem.first, eachItem.second, dataHolder));
first = false;
}
}
@@ -152,9 +170,9 @@ public class AttachToLocalProcessAction extends AnAction {
HistoryItem eachHistoryItem = history.get(i);
for (AttachItem eachCurrentItem : currentItems) {
boolean isSuitableItem = eachHistoryItem.getGroup().equals(eachCurrentItem.getGroup()) &&
eachHistoryItem.getProcessInfo().getCommandLine().equals(eachCurrentItem.getProcessInfo().getCommandLine());
eachHistoryItem.getProcessInfo().getCommandLine().equals(eachCurrentItem.getProcessInfo().getCommandLine());
if (!isSuitableItem) continue;
List<XLocalAttachDebugger> debuggers = eachCurrentItem.getDebuggers();
int selectedDebugger = -1;
for (int j = 0; j < debuggers.size(); j++) {
@@ -167,11 +185,12 @@ public class AttachToLocalProcessAction extends AnAction {
if (selectedDebugger == -1) continue;
currentHistoryItems.add(new AttachItem(eachCurrentItem.getGroup(),
currentHistoryItems.isEmpty(),
XDebuggerBundle.message("xdebugger.attach.toLocal.popup.recent"),
eachCurrentItem.getProcessInfo(),
debuggers,
selectedDebugger));
currentHistoryItems.isEmpty(),
XDebuggerBundle.message("xdebugger.attach.toLocal.popup.recent"),
eachCurrentItem.getProcessInfo(),
debuggers,
selectedDebugger,
dataHolder));
}
}
@@ -186,7 +205,7 @@ public class AttachToLocalProcessAction extends AnAction {
}
ProcessInfo processInfo = item.getProcessInfo();
history.remove(processInfo.getCommandLine());
history.put(processInfo.getCommandLine(), new HistoryItem(processInfo, item.getGroup(),
history.put(processInfo.getCommandLine(), new HistoryItem(processInfo, item.getGroup(),
item.getSelectedDebugger().getDebuggerDisplayName()));
while (history.size() > 4) {
history.remove(history.keySet().iterator().next());
@@ -255,6 +274,7 @@ public class AttachToLocalProcessAction extends AnAction {
@NotNull private final XLocalAttachGroup myGroup;
private final boolean myIsFirstInGroup;
@NotNull private final String myGroupName;
@NotNull private UserDataHolder myDataHolder;
@NotNull private final ProcessInfo myProcessInfo;
@NotNull private final List<XLocalAttachDebugger> myDebuggers;
private final int mySelectedDebugger;
@@ -263,8 +283,9 @@ public class AttachToLocalProcessAction extends AnAction {
public AttachItem(@NotNull XLocalAttachGroup group,
boolean isFirstInGroup,
@NotNull ProcessInfo info,
@NotNull List<XLocalAttachDebugger> debuggers) {
this(group, isFirstInGroup, group.getGroupName(), info, debuggers, 0);
@NotNull List<XLocalAttachDebugger> debuggers,
@NotNull UserDataHolder dataHolder) {
this(group, isFirstInGroup, group.getGroupName(), info, debuggers, 0, dataHolder);
}
public AttachItem(@NotNull XLocalAttachGroup group,
@@ -272,8 +293,10 @@ public class AttachToLocalProcessAction extends AnAction {
@NotNull String groupName,
@NotNull ProcessInfo info,
@NotNull List<XLocalAttachDebugger> debuggers,
int selectedDebugger) {
int selectedDebugger,
@NotNull UserDataHolder dataHolder) {
myGroupName = groupName;
myDataHolder = dataHolder;
assert !debuggers.isEmpty() : "debugger list should not be empty";
assert selectedDebugger >= 0 && selectedDebugger < debuggers.size() : "wrong selected debugger index";
@@ -284,7 +307,7 @@ public class AttachToLocalProcessAction extends AnAction {
mySelectedDebugger = selectedDebugger;
if (debuggers.size() > 1) {
mySubItems = ContainerUtil.map(debuggers, debugger -> new AttachItem(myGroup, false, myProcessInfo, Collections.singletonList(debugger)));
mySubItems = ContainerUtil.map(debuggers, debugger -> new AttachItem(myGroup, false, myProcessInfo, Collections.singletonList(debugger), dataHolder));
}
else {
mySubItems = Collections.emptyList();
@@ -308,12 +331,12 @@ public class AttachToLocalProcessAction extends AnAction {
@Nullable
public Icon getIcon(@NotNull Project project) {
return myGroup.getProcessIcon(project, myProcessInfo);
return myGroup.getProcessIcon(project, myProcessInfo, myDataHolder);
}
@NotNull
public String getText(@NotNull Project project) {
String shortenedText = StringUtil.shortenTextWithEllipsis(myGroup.getProcessDisplayText(project, myProcessInfo), 80, 0);
String shortenedText = StringUtil.shortenTextWithEllipsis(myGroup.getProcessDisplayText(project, myProcessInfo, myDataHolder), 200, 0);
return myProcessInfo.getPid() + " " + shortenedText;
}
@@ -336,7 +359,7 @@ public class AttachToLocalProcessAction extends AnAction {
XLocalAttachDebugger debugger = getSelectedDebugger();
UsageTrigger.trigger(ConvertUsagesUtil.ensureProperKey("debugger.attach.local"));
UsageTrigger.trigger(ConvertUsagesUtil.ensureProperKey("debugger.attach.local." + debugger.getDebuggerDisplayName()));
try {
debugger.attachDebugSession(project, myProcessInfo);
}
@@ -405,7 +428,7 @@ public class AttachToLocalProcessAction extends AnAction {
@Nullable
@Override
public String getTooltipTextFor(AttachItem value) {
return null;
return value.getText(myProject);
}
@Override
@@ -17,11 +17,12 @@ package com.intellij.xdebugger.impl.actions;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.ProcessInfo;
import com.intellij.openapi.progress.DumbProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.attach.XDefaultLocalAttachGroup;
import com.intellij.xdebugger.attach.XLocalAttachDebugger;
import com.intellij.xdebugger.attach.XLocalAttachDebuggerProvider;
@@ -134,7 +135,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
" dbg2\n",
new TestDebuggerProvider(group, "dbg1"),
new TestDebuggerProvider(group, "dbg2"));
assertItems("--------\n" +
"1 exec1: dbg1\n" +
" dbg1\n" +
@@ -220,7 +221,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
"2 exec2: dbg1\n",
new TestDebuggerProvider(new TestAttachGroup("group", 0) {
@Override
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) {
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b, @NotNull UserDataHolder dataHolder) {
return a.getPid() - b.getPid();
}
}, "dbg1"));
@@ -229,12 +230,12 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
"1 exec1: dbg1\n",
new TestDebuggerProvider(new TestAttachGroup("group", 0) {
@Override
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) {
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b, @NotNull UserDataHolder dataHolder) {
return b.getPid() - a.getPid();
}
}, "dbg1"));
}
public void testCollectingAttachItems_Groups_CustomItemTitles() throws Exception {
assertItems("----group----\n" +
"1 custom: dbg1\n" +
@@ -242,7 +243,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
new TestDebuggerProvider(new TestAttachGroup("group", 0) {
@NotNull
@Override
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) {
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder) {
return "custom";
}
}, "dbg1"));
@@ -256,18 +257,19 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
ProcessInfo info5 = new ProcessInfo(1, "command line 5", "exec1", "args1");
List<XLocalAttachDebugger> debuggers = createDebuggers("gdb");
AttachItem item1 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info1, debuggers);
AttachItem item2 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info2, debuggers);
AttachItem item3 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info3, debuggers);
AttachItem item4 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info4, debuggers);
AttachItem item5 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info5, debuggers);
UserDataHolderBase dataHolder = new UserDataHolderBase();
AttachItem item1 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info1, debuggers, dataHolder);
AttachItem item2 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info2, debuggers, dataHolder);
AttachItem item3 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info3, debuggers, dataHolder);
AttachItem item4 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info4, debuggers, dataHolder);
AttachItem item5 = new AttachItem(XLocalAttachGroup.DEFAULT, true, info5, debuggers, dataHolder);
HistoryItem historyItem1 = new HistoryItem(info1, XLocalAttachGroup.DEFAULT, "gdb");
HistoryItem historyItem2 = new HistoryItem(info2, XLocalAttachGroup.DEFAULT, "gdb");
HistoryItem historyItem3 = new HistoryItem(info3, XLocalAttachGroup.DEFAULT, "gdb");
HistoryItem historyItem4 = new HistoryItem(info4, XLocalAttachGroup.DEFAULT, "gdb");
HistoryItem historyItem5 = new HistoryItem(info5, XLocalAttachGroup.DEFAULT, "gdb");
// empty
assertEmpty(getHistory(getProject()));
@@ -285,22 +287,23 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
// limiting size to 4 items
addToHistory(getProject(), item5);
assertOrderedEquals(getHistory(getProject()), historyItem2, historyItem3, historyItem4, historyItem5);
// popping up recent items
addToHistory(getProject(), item3);
addToHistory(getProject(), item2);
assertOrderedEquals(getHistory(getProject()), historyItem4, historyItem5, historyItem3, historyItem2);
}
public void testHistory_UpdatingPreviousItems() throws Exception {
TestAttachGroup group1 = new TestAttachGroup("group1", 1);
TestAttachGroup group2 = new TestAttachGroup("group2", 2);
ProcessInfo info1 = new ProcessInfo(1, "same command line", "exec1", "args1");
ProcessInfo info2 = new ProcessInfo(2, "same command line", "exec2", "args2");
AttachItem item1 = new AttachItem(group1, true, info1, createDebuggers("gdb1"));
AttachItem item2 = new AttachItem(group2, true, info2, createDebuggers("gdb2"));
UserDataHolderBase dataHolder = new UserDataHolderBase();
AttachItem item1 = new AttachItem(group1, true, info1, createDebuggers("gdb1"), dataHolder);
AttachItem item2 = new AttachItem(group2, true, info2, createDebuggers("gdb2"), dataHolder);
HistoryItem historyItem1 = new HistoryItem(info1, group1, "gdb1");
HistoryItem historyItem2 = new HistoryItem(info2, group2, "gdb2");
@@ -321,9 +324,10 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
new ProcessInfo[]{
new ProcessInfo(1, "command line 1", "exec1", "args1"),
new ProcessInfo(2, "command line 2", "exec2", "args2")},
DumbProgressIndicator.INSTANCE,
new TestDebuggerProvider(1, group1, debuggers1),
new TestDebuggerProvider(2, group2, debuggers2));
// one item in history
addToHistory(getProject(), originalItems.get(0));
assertItems("----Recent----\n" +
@@ -368,7 +372,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
},
new TestDebuggerProvider(10, group1, debuggers1),
new TestDebuggerProvider(20, group2, debuggers2));
// put most recent item on top
addToHistory(getProject(), originalItems.get(0));
assertItems("----Recent----\n" +
@@ -392,7 +396,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
},
new TestDebuggerProvider(10, group1, debuggers1),
new TestDebuggerProvider(20, group2, debuggers2));
// put debugger used in history item on top
addToHistory(getProject(), originalItems.get(0).getSubItems().get(1));
addToHistory(getProject(), originalItems.get(1).getSubItems().get(1));
@@ -473,7 +477,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
},
new TestDebuggerProvider(10, group1, debuggers1),
new TestDebuggerProvider(20, group2, debuggers2));
// filter items from history by suitable group
assertItems("----Recent----\n" +
"10 exec10: lldb1\n" +
@@ -509,7 +513,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
},
new TestDebuggerProvider(10, group2, debuggers1),
new TestDebuggerProvider(20, group2, debuggers2));
// filter by group equality, not by name
// filter by group equality, not by name
assertItems("----group1----\n" +
"10 exec10: gdb1\n" +
" gdb1\n" +
@@ -544,8 +548,8 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
},
new TestDebuggerProvider(10, group1, debuggers1),
new TestDebuggerProvider(20, group2, debuggers1));
// filter debuggers by name, not by equality
// filter debuggers by name, not by equality
assertItems("----Recent----\n" +
"20 exec20: lldb2\n" +
" gdb2\n" +
@@ -578,7 +582,7 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
}
private void assertItems(String expected, ProcessInfo[] infos, @NotNull XLocalAttachDebuggerProvider... providers) {
assertEquals(expected, printItems(collectAttachItems(getProject(), infos, providers)));
assertEquals(expected, printItems(collectAttachItems(getProject(), infos, DumbProgressIndicator.INSTANCE, providers)));
}
private void assertItems(String expected, List<AttachItem> items) {
@@ -609,10 +613,8 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
return s;
}
@NotNull
@Override
public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException {
return null;
public void attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException {
}
});
}
@@ -678,4 +680,4 @@ public class AttachToLocalProcessActionTest extends PlatformTestCase {
return myDebuggers;
}
}
}
}
@@ -93,11 +93,10 @@ public class PyLocalAttachDebuggerProvider implements XLocalAttachDebuggerProvid
return myName;
}
@NotNull
@Override
public XDebugSession attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException {
public void attachDebugSession(@NotNull Project project, @NotNull ProcessInfo processInfo) throws ExecutionException {
PyAttachToProcessDebugRunner runner = new PyAttachToProcessDebugRunner(project, processInfo.getPid(), mySdkHome);
return runner.launch();
runner.launch();
}
}
}
@@ -17,7 +17,9 @@ package com.jetbrains.python.debugger.attach;
import com.intellij.execution.process.ProcessInfo;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.xdebugger.attach.XLocalAttachGroup;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -41,18 +43,18 @@ class PyLocalAttachGroup implements XLocalAttachGroup {
@NotNull
@Override
public Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info) {
return icons.PythonIcons.Python.Python;
public Icon getProcessIcon(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder) {
return PythonIcons.Python.Python;
}
@NotNull
@Override
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info) {
public String getProcessDisplayText(@NotNull Project project, @NotNull ProcessInfo info, @NotNull UserDataHolder dataHolder) {
return info.getArgs();
}
@Override
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b) {
return XLocalAttachGroup.DEFAULT.compare(project, a, b);
public int compare(@NotNull Project project, @NotNull ProcessInfo a, @NotNull ProcessInfo b, @NotNull UserDataHolder dataHolder) {
return XLocalAttachGroup.DEFAULT.compare(project, a, b, dataHolder);
}
}