Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBaha El Kassaby2018-05-02 19:52:39 +0000
committerJonah Graham2019-11-25 17:01:21 +0000
commit949efc65727a2db644b0436f4df3a203a904fceb (patch)
tree4ab0c044275a35dd19c59c3c1767f385e9c5afaf
parent7e267a47915bb79d384528be5be713e6fd3c10fd (diff)
downloadorg.eclipse.cdt-949efc65727a2db644b0436f4df3a203a904fceb.tar.gz
org.eclipse.cdt-949efc65727a2db644b0436f4df3a203a904fceb.tar.xz
org.eclipse.cdt-949efc65727a2db644b0436f4df3a203a904fceb.zip
Bug 530443: Add support for "info sources" MI equivalent
*Implementation of -file-list-exec-source-files MI command. *Add new Debug Sources view with tree-like structure Change-Id: I6e734799712c059c8e53aa882777dfebd85aa0d5 Also-by: Jonah Graham <jonah@kichwacoders.com> Signed-off-by: Baha El Kassaby <baha.elkassaby@gmail.com>
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF2
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout.pngbin0 -> 131 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout@2x.pngbin0 -> 180 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout.pngbin0 -> 154 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout@2x.pngbin0 -> 207 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/collapse_all.gifbin0 -> 161 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/existingFiles.gifbin0 -> 354 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/expand_all.gifbin0 -> 167 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout.pngbin0 -> 123 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout@2x.pngbin0 -> 199 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout.pngbin0 -> 148 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout@2x.pngbin0 -> 230 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/debugsources_view.gifbin0 -> 353 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/refresh.gifbin0 -> 385 bytes
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties2
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml41
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesLabelProvider.java119
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.java52
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.properties35
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeContentProvider.java105
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeElement.java220
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesView.java736
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesViewComparator.java85
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/IDebugSourcesImagesConst.java30
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesCollapseAction.java52
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesExpandAction.java51
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesFlattendedTree.java64
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesNormalTree.java64
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesShowExistingFilesOnly.java66
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesViewRefresh.java93
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF2
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBSourceLookup.java157
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IDebugSourceFiles.java67
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java7
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIFileListExecSourceFiles.java39
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MiSourceFilesInfo.java164
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java25
-rw-r--r--dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java58
38 files changed, 2313 insertions, 23 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
index d8a7d4c4ef6..b41fa97f10c 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
@@ -37,6 +37,8 @@ Export-Package: org.eclipse.cdt.dsf.gdb.internal.ui;x-friends:="org.eclipse.cdt.
org.eclipse.cdt.dsf.gdb.internal.ui.commands;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.console;x-friends:="org.eclipse.cdt.examples.dsf.gdb",
org.eclipse.cdt.dsf.gdb.internal.ui.console.actions;x-internal:=true,
+ org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;x-internal:=true,
+ org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.disassembly;x-internal:=true,
org.eclipse.cdt.dsf.gdb.internal.ui.launching;x-friends:="org.eclipse.cdt.debug.gdbjtag.ui,org.eclipse.cdt.examples.dsf.gdb,org.eclipse.cdt.docker.launcher",
org.eclipse.cdt.dsf.gdb.internal.ui.memory;x-internal:=true,
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout.png
new file mode 100644
index 00000000000..061b593caa2
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout@2x.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout@2x.png
new file mode 100644
index 00000000000..23540f72b63
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/flatLayout@2x.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout.png
new file mode 100644
index 00000000000..64822eaa0d8
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout@2x.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout@2x.png
new file mode 100644
index 00000000000..b84fb01bf15
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/dlcl16/hierarchicalLayout@2x.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/collapse_all.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/collapse_all.gif
new file mode 100644
index 00000000000..b004e7c3374
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/collapse_all.gif
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/existingFiles.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/existingFiles.gif
new file mode 100644
index 00000000000..b226e41c527
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/existingFiles.gif
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/expand_all.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/expand_all.gif
new file mode 100644
index 00000000000..d66de6d100e
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/expand_all.gif
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout.png
new file mode 100644
index 00000000000..13f83a23741
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout@2x.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout@2x.png
new file mode 100644
index 00000000000..280561aeb4c
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/flatLayout@2x.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout.png
new file mode 100644
index 00000000000..665aa5cee3a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout@2x.png b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout@2x.png
new file mode 100644
index 00000000000..84039be3a93
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/elcl16/hierarchicalLayout@2x.png
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/debugsources_view.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/debugsources_view.gif
new file mode 100644
index 00000000000..37b47054630
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/debugsources_view.gif
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/refresh.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/refresh.gif
new file mode 100644
index 00000000000..b6b8dc6836d
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/refresh.gif
Binary files differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
index 14cee021f4b..bb0e517600e 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
@@ -36,6 +36,7 @@ tracepoints.action.page.label=Actions
tracepointActionsPrefPage.name=Tracepoint Actions\u0020
dynamicPrintf.property.common=Common
action.addDynamicPrintf.label=Add Dynamic-Printf...
+debugSourcesRefresh.name=Refresh
# Tracepoints
view.traceControl.name=Trace Control
@@ -59,6 +60,7 @@ action.fetchMoreChildren.label=Fetch More Children
# OS view
view.osresources.name=OS Resources
+view.debugsources.name=Debug Sources
command.connect.description = Connect to selected processes
command.connect.name = Connect
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
index 75ae7454c99..bc74c689b2f 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
@@ -296,6 +296,14 @@
name="%view.osresources.name"
icon="icons/full/view16/osresources_view.gif">
</view>
+ <view
+ category="org.eclipse.debug.ui"
+ class="org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesView"
+ icon="icons/full/view16/debugsources_view.gif"
+ id="org.eclipse.cdt.dsf.gdb.ui.debugsources.view"
+ name="%view.debugsources.name"
+ restorable="true">
+ </view>
</extension>
<extension
point="org.eclipse.ui.perspectiveExtensions">
@@ -327,6 +335,18 @@
id="org.eclipse.cdt.debug.ui.debuggerConsoleView">
</viewShortcut>
</perspectiveExtension>
+ <perspectiveExtension
+ targetID="org.eclipse.debug.ui.DebugPerspective">
+ <view
+ relative="org.eclipse.ui.console.ConsoleView"
+ visible="false"
+ relationship="stack"
+ id="org.eclipse.cdt.dsf.gdb.ui.debugsources.view">
+ </view>
+ <viewShortcut
+ id="org.eclipse.cdt.dsf.gdb.ui.debugsources.view">
+ </viewShortcut>
+ </perspectiveExtension>
</extension>
<extension
point="org.eclipse.ui.commands">
@@ -630,4 +650,25 @@
name="GDB Remote Serial">
</wizard2>
</extension>
+ <extension
+ point="org.eclipse.debug.ui.contextViewBindings">
+ <contextViewBinding
+ autoOpen="false"
+ contextId="org.eclipse.cdt.debug.ui.debugging"
+ viewId="org.eclipse.cdt.dsf.gdb.ui.debugsources.view">
+ </contextViewBinding>
+ </extension>
+ <extension point="org.eclipse.ui.viewActions">
+ <viewContribution
+ id="org.eclipse.cdt.dsf.gdb.ui.debugsources.view.refresh"
+ targetID="org.eclipse.cdt.dsf.gdb.ui.debugsources.view">
+ <action
+ class="org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions.DebugSourcesViewRefresh"
+ icon="icons/refresh.gif"
+ id="org.eclipse.cdt.dsf.gdb.ui.debugsources.view.refresh"
+ label="%debugSourcesRefresh.name"
+ toolbarPath="additions">
+ </action>
+ </viewContribution>
+ </extension>
</plugin>
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesLabelProvider.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesLabelProvider.java
new file mode 100644
index 00000000000..87ce3a47094
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesLabelProvider.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;
+
+import java.io.File;
+import java.util.Set;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesTreeElement.FileExist;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Display;
+
+public class DebugSourcesLabelProvider extends ColumnLabelProvider {
+ private int index;
+ private boolean flattenFoldersWithNoFiles = true;
+ private boolean showExistingFilesOnly = true;
+
+ /**
+ *
+ * @param index
+ * of column
+ */
+ public DebugSourcesLabelProvider(int index) {
+ this.index = index;
+ }
+
+ public void setFlattenFoldersWithNoFiles(boolean flattenFoldersWithNoFiles) {
+ this.flattenFoldersWithNoFiles = flattenFoldersWithNoFiles;
+ }
+
+ public boolean isFlattenFoldersWithNoFiles() {
+ return flattenFoldersWithNoFiles;
+ }
+
+ public void setShowExistingFilesOnly(boolean showExistingFilesOnly) {
+ this.showExistingFilesOnly = showExistingFilesOnly;
+ }
+
+ public boolean isShowExistingFilesOnly() {
+ return showExistingFilesOnly;
+ }
+
+ @Override
+ public String getText(Object element) {
+ return getLabel(element, index);
+ }
+
+ private String getLabel(Object element, int columnIdx) {
+ String emptyString = ""; //$NON-NLS-1$
+ if (element instanceof DebugSourcesTreeElement) {
+ DebugSourcesTreeElement node = (DebugSourcesTreeElement) element;
+ if (columnIdx == 0) {
+ Set<DebugSourcesTreeElement> children;
+ StringBuilder sb = new StringBuilder();
+ sb.append(node.getName());
+ if (flattenFoldersWithNoFiles) {
+ while (true) {
+ if (node.getFullPath() != null) {
+ break;
+ }
+ children = node.getChildren(showExistingFilesOnly);
+
+ if (children.size() != 1) {
+ break;
+ }
+ DebugSourcesTreeElement child = children.iterator().next();
+ if (child.getFullPath() != null) {
+ break;
+ }
+
+ node = child;
+ if (sb.length() > 0 && sb.charAt(sb.length() - 1) != File.separatorChar) {
+ sb.append(File.separatorChar);
+ }
+ sb.append(node.getName());
+ }
+ }
+ return sb.toString();
+ }
+ if (columnIdx == 1) {
+ return node.hasChildren() ? emptyString : (String) node.getFullPath();
+ }
+ }
+ return emptyString;
+ }
+
+ @Override
+ public Color getForeground(Object element) {
+ if (index == 1) {
+ if (element instanceof DebugSourcesTreeElement) {
+ DebugSourcesTreeElement node = (DebugSourcesTreeElement) element;
+ if (node.getExists() == FileExist.NO) {
+ return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
+ }
+ }
+ }
+
+ return super.getForeground(element);
+ }
+
+ @Override
+ public Font getFont(Object element) {
+ // TODO Auto-generated method stub
+ return super.getFont(element);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.java
new file mode 100644
index 00000000000..d1502b7967f
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ *
+ */
+public class DebugSourcesMessages extends NLS {
+
+ public static String DebugSourcesMessages_name_column;
+ public static String DebugSourcesMessages_path_column;
+ public static String DebugSourcesMessages_unknown;
+
+ public static String DebugSourcesMessages_filter_search_tooltip;
+ public static String DebugSourcesMessages_sort_name_column_tooltip;
+ public static String DebugSourcesMessages_sort_path_column_tooltip;
+
+ public static String DebugSourcesExpandAction_name;
+ public static String DebugSourcesExpandAction_description;
+ public static String DebugSourcesCollapseAction_name;
+ public static String DebugSourcesCollapseAction_description;
+ public static String DebugSourcesFlattendedTree_name;
+ public static String DebugSourcesFlattendedTree_description;
+ public static String DebugSourcesNormalTree_description;
+ public static String DebugSourcesNormalTree_name;
+ public static String DebugSourcesShowExistingFilesOnly_description;
+ public static String DebugSourcesShowExistingFilesOnly_name;
+ public static String DebugSourcesView_unrooted;
+
+ public static String GdbDebugSourcesPreferences_name;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(DebugSourcesMessages.class.getName(), DebugSourcesMessages.class);
+ }
+
+ private DebugSourcesMessages() {
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.properties
new file mode 100644
index 00000000000..f90c7c064ce
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesMessages.properties
@@ -0,0 +1,35 @@
+##########################################################################
+# Copyright (c) 2018, 2019 Kichwa Coders and others.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Contributors:
+# Baha El-Kassaby - Initial API and implementation
+##########################################################################
+
+DebugSourcesMessages_name_column=Name
+DebugSourcesMessages_path_column=Path
+DebugSourcesMessages_unknown=Unknown
+
+DebugSourcesMessages_filter_search_tooltip=Search on debug sources file names
+DebugSourcesMessages_sort_name_column_tooltip=Left-click on the \"Name\" column to sort by name
+DebugSourcesMessages_sort_path_column_tooltip=Left-click on the \"Path\" column to sort by path
+
+DebugSourcesExpandAction_name=Expand
+DebugSourcesExpandAction_description=Expand the tree structure
+DebugSourcesCollapseAction_name=Collapse
+DebugSourcesCollapseAction_description=Collapse the tree structure
+DebugSourcesFlattendedTree_name=Flat View
+DebugSourcesFlattendedTree_description=Display tree by flattening folders with no files.
+DebugSourcesNormalTree_description=Normal tree view
+DebugSourcesNormalTree_name=Normal View
+DebugSourcesShowExistingFilesOnly_description=Show only files that are found on disk.
+DebugSourcesShowExistingFilesOnly_name=Show
+DebugSourcesView_unrooted=<unrooted>
+
+GdbDebugSourcesPreferences_name=Preferences...
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeContentProvider.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeContentProvider.java
new file mode 100644
index 00000000000..f11a37ed80b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeContentProvider.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;
+
+import java.util.Set;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+
+public class DebugSourcesTreeContentProvider implements ITreeContentProvider {
+ private boolean flattenFoldersWithNoFiles = true;
+ private boolean showExistingFilesOnly = true;
+
+ public DebugSourcesTreeContentProvider() {
+ }
+
+ public void setFlattenFoldersWithNoFiles(boolean flattenFoldersWithNoFiles) {
+ this.flattenFoldersWithNoFiles = flattenFoldersWithNoFiles;
+ }
+
+ public boolean isFlattenFoldersWithNoFiles() {
+ return flattenFoldersWithNoFiles;
+ }
+
+ public void setShowExistingFilesOnly(boolean showExistingFilesOnly) {
+ this.showExistingFilesOnly = showExistingFilesOnly;
+ }
+
+ public boolean isShowExistingFilesOnly() {
+ return showExistingFilesOnly;
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof DebugSourcesTreeElement) {
+ DebugSourcesTreeElement tree = (DebugSourcesTreeElement) inputElement;
+ Set<DebugSourcesTreeElement> children = tree.getChildren(showExistingFilesOnly);
+ return children.toArray();
+ }
+ return null;
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ if (parentElement instanceof DebugSourcesTreeElement) {
+ DebugSourcesTreeElement tree = (DebugSourcesTreeElement) parentElement;
+ Set<DebugSourcesTreeElement> children = tree.getChildren(showExistingFilesOnly);
+
+ if (flattenFoldersWithNoFiles) {
+ if (children.size() == 1) {
+ DebugSourcesTreeElement child = children.iterator().next();
+ if (child.getFullPath() == null) {
+ return getChildren(child);
+ }
+ }
+ }
+ return children.toArray();
+ }
+ return null;
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ if (element == null)
+ return null;
+ if (element instanceof DebugSourcesTreeElement) {
+ DebugSourcesTreeElement node = (DebugSourcesTreeElement) element;
+ DebugSourcesTreeElement parent = node.getParent();
+ if (parent == null) {
+ return null;
+ }
+ if (flattenFoldersWithNoFiles) {
+ DebugSourcesTreeElement grandParent = parent.getParent();
+ if (grandParent != null) {
+ Set<DebugSourcesTreeElement> children = grandParent.getChildren(showExistingFilesOnly);
+ if (children.size() == 1) {
+ return getParent(parent);
+ }
+ }
+ }
+ return parent;
+ }
+ return null;
+
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ if (element instanceof DebugSourcesTreeElement) {
+ return getChildren(element).length > 0;
+ }
+ return false;
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeElement.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeElement.java
new file mode 100644
index 00000000000..a5ccee1ed61
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesTreeElement.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;
+
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * A basic tree used to display source files in the debug view
+ */
+public class DebugSourcesTreeElement {
+
+ public enum FileExist {
+ YES, NO, UNKNOWN;
+ }
+
+ // preserve insertion order with LinkedHashSet
+ private final Set<DebugSourcesTreeElement> children = new LinkedHashSet<>();
+ private final String name;
+ private final String fullPath;
+ private DebugSourcesTreeElement parent;
+ private FileExist exists;
+
+ /**
+ *
+ * @param name part of the path
+ * @param exists
+ */
+ public DebugSourcesTreeElement(String name, FileExist exists) {
+ this.name = name;
+ this.fullPath = null;
+ this.exists = exists;
+ }
+
+ /**
+ * If node is a leaf, add the fullPath as well
+ *
+ * @param name part of the path
+ * @param leafData full path of the file
+ */
+ private DebugSourcesTreeElement(String name, String fullPath, FileExist exist) {
+ this.name = name;
+ this.fullPath = fullPath;
+ this.exists = exist;
+ }
+
+ /**
+ *
+ * @param name part of the path
+ * @param exists
+ * @return a new node if not already existing, existing node otherwise
+ */
+ public DebugSourcesTreeElement addNode(String name, FileExist exists) {
+ for (DebugSourcesTreeElement child : children) {
+ if (child.name.equals(name)) {
+ if (exists == FileExist.YES) {
+ child.exists = FileExist.YES;
+ }
+ return child;
+ }
+ }
+ return addChild(new DebugSourcesTreeElement(name, exists));
+ }
+
+ /**
+ *
+ * @param name part of the path
+ * @param fullPath of leaf
+ * @return a new leaf if not already existing, existing leaf otherwise
+ */
+ public DebugSourcesTreeElement addLeaf(String name, String fullPath, FileExist exists) {
+ for (DebugSourcesTreeElement child : children) {
+ if (child.name.equals(name)) {
+ return child;
+ }
+ }
+ return addChild(new DebugSourcesTreeElement(name, fullPath, exists));
+ }
+
+ private DebugSourcesTreeElement addChild(DebugSourcesTreeElement child) {
+ children.add(child);
+ return child;
+ }
+
+ /**
+ *
+ * @return list of children of the node
+ */
+ public Set<DebugSourcesTreeElement> getChildren() {
+ return children;
+ }
+
+ /**
+ *
+ * @param filesThatMayExistOnly only include files that may exist
+ * @return list of children of the node
+ */
+ public Set<DebugSourcesTreeElement> getChildren(boolean filesThatMayExistOnly) {
+ if (filesThatMayExistOnly) {
+ return children.stream().filter(c -> c.getExists() != FileExist.NO).collect(Collectors.toSet());
+ } else {
+ return children;
+ }
+ }
+
+ /**
+ *
+ * @return true if node has children, false otherwise
+ */
+ public boolean hasChildren() {
+ if (children != null && children.size() > 0)
+ return true;
+ return false;
+ }
+
+ /**
+ *
+ * @return name of the file or folder segment
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ *
+ * @return full path to file (or null if not a file)
+ */
+ public String getFullPath() {
+ return fullPath;
+ }
+
+ /**
+ * Return true for leaf data that really exists on disk.
+ *
+ * This can be used to display differently.
+ */
+ public FileExist getExists() {
+ return exists;
+ }
+
+ /**
+ *
+ * @return node parent
+ */
+ public DebugSourcesTreeElement getParent() {
+ return parent;
+ }
+
+ /**
+ * Set parent of node
+ *
+ * @param parent
+ */
+ public void setParent(DebugSourcesTreeElement parent) {
+ this.parent = parent;
+ }
+
+ public void setExist(FileExist exists) {
+ this.exists = exists;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toString(getName());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((exists == null) ? 0 : exists.hashCode());
+ result = prime * result + ((fullPath == null) ? 0 : fullPath.hashCode());
+ result = prime * result + ((parent == null) ? 0 : parent.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DebugSourcesTreeElement other = (DebugSourcesTreeElement) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (exists != other.exists)
+ return false;
+ if (fullPath == null) {
+ if (other.fullPath != null)
+ return false;
+ } else if (!fullPath.equals(other.fullPath))
+ return false;
+ if (parent == null) {
+ if (other.parent != null)
+ return false;
+ } else if (!parent.equals(other.parent))
+ return false;
+ return true;
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesView.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesView.java
new file mode 100644
index 00000000000..4a76461cb9a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesView.java
@@ -0,0 +1,736 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Tracy Miranda / Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;
+
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceNotFoundElement;
+import org.eclipse.cdt.debug.internal.core.sourcelookup.ICSourceNotFoundDescription;
+import org.eclipse.cdt.debug.internal.ui.sourcelookup.CSourceNotFoundEditorInput;
+import org.eclipse.cdt.debug.ui.ICDebugUIConstants;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesTreeElement.FileExist;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions.DebugSourcesCollapseAction;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions.DebugSourcesExpandAction;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions.DebugSourcesFlattendedTree;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions.DebugSourcesNormalTree;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions.DebugSourcesShowExistingFilesOnly;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFilesChangedEvent;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobManager;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.contexts.DebugContextEvent;
+import org.eclipse.debug.ui.contexts.IDebugContextListener;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+import org.eclipse.ui.ide.FileStoreEditorInput;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.ViewPart;
+
+@SuppressWarnings("restriction")
+public class DebugSourcesView extends ViewPart implements IDebugContextListener {
+
+ public static final String ID = "org.eclipse.cdt.dsf.gdb.ui.debugsources.view"; //$NON-NLS-1$
+ private static final String KEY_FLATTEN_FOLDERS_WITH_NO_FILES = "KEY_FLATTEN_FOLDERS_WITH_NO_FILES"; //$NON-NLS-1$
+ private static final String KEY_SHOW_EXISTING_FILES_ONLY = "KEY_SHOW_EXISTING_FILES_ONLY"; //$NON-NLS-1$
+
+ private DsfSession fSession;
+ private TreeViewer viewer;
+ private DebugSourcesViewComparator<DebugSourcesTreeElement> comparator;
+ private IContainerDMContext dmcontext;
+ private DebugSourcesTreeElement debugTree;
+ private IMemento fMemento;
+
+ public DebugSourcesView() {
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ composite.setLayout(new GridLayout(1, false));
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ final DebugPatternFilter filter = new DebugPatternFilter();
+
+ int treeStyle = SWT.MULTI | SWT.FULL_SELECTION | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
+ FilteredTree tree = new FilteredTree(composite, treeStyle, filter, true, true);
+ tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ tree.getFilterControl().setToolTipText(DebugSourcesMessages.DebugSourcesMessages_filter_search_tooltip);
+ viewer = tree.getViewer();
+ viewer.getTree().setLinesVisible(true);
+ viewer.getTree().setHeaderVisible(true);
+ viewer.setContentProvider(new DebugSourcesTreeContentProvider());
+ viewer.setUseHashlookup(true);
+
+ comparator = new DebugSourcesViewComparator<>();
+
+ createColumns(viewer);
+
+ loadState();
+
+ viewer.setComparator(comparator);
+ viewer.addDoubleClickListener(new IDoubleClickListener() {
+ @Override
+ public void doubleClick(DoubleClickEvent event) {
+ IStructuredSelection thisSelection = (IStructuredSelection) event.getSelection();
+ Object selectedNode = thisSelection.getFirstElement();
+ if (selectedNode instanceof DebugSourcesTreeElement) {
+ DebugSourcesTreeElement node = (DebugSourcesTreeElement) selectedNode;
+ // only leafs can be opened!
+ if (!node.hasChildren()) {
+ openSourceFile(node.getFullPath());
+ }
+ }
+ }
+ });
+
+ createActions(viewer);
+
+ registerForEvents();
+ DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow())
+ .addDebugContextListener(this);
+
+ }
+
+ @Override
+ public void init(IViewSite site, IMemento memento) throws PartInitException {
+ fMemento = memento;
+ super.init(site, memento);
+ }
+
+ public void loadState() {
+ boolean flattenFoldersWithNoFiles = true;
+ boolean showExistingFilesOnly = true;
+
+ if (fMemento != null) {
+ Boolean b = fMemento.getBoolean(KEY_FLATTEN_FOLDERS_WITH_NO_FILES);
+ if (b != null) {
+ flattenFoldersWithNoFiles = b;
+ }
+ b = fMemento.getBoolean(KEY_SHOW_EXISTING_FILES_ONLY);
+ if (b != null) {
+ showExistingFilesOnly = b;
+ }
+ }
+
+ if (viewer != null) {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer
+ .getContentProvider();
+
+ contentProvider.setFlattenFoldersWithNoFiles(flattenFoldersWithNoFiles);
+ contentProvider.setShowExistingFilesOnly(showExistingFilesOnly);
+ for (int i = 0; i < viewer.getTree().getColumnCount(); i++) {
+ DebugSourcesLabelProvider labelProvider = (DebugSourcesLabelProvider) viewer.getLabelProvider(i);
+ labelProvider.setFlattenFoldersWithNoFiles(flattenFoldersWithNoFiles);
+ labelProvider.setShowExistingFilesOnly(showExistingFilesOnly);
+ }
+
+ }
+ }
+
+ @Override
+ public void saveState(IMemento memento) {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer.getContentProvider();
+ memento.putBoolean(KEY_FLATTEN_FOLDERS_WITH_NO_FILES, contentProvider.isFlattenFoldersWithNoFiles());
+ memento.putBoolean(KEY_SHOW_EXISTING_FILES_ONLY, contentProvider.isShowExistingFilesOnly());
+ super.saveState(memento);
+ }
+
+ private void createColumns(TreeViewer viewer) {
+ String[] titles = { DebugSourcesMessages.DebugSourcesMessages_name_column,
+ DebugSourcesMessages.DebugSourcesMessages_path_column };
+ String[] tooltips = { DebugSourcesMessages.DebugSourcesMessages_sort_name_column_tooltip,
+ DebugSourcesMessages.DebugSourcesMessages_sort_path_column_tooltip };
+ int[] bounds = { 300, 800 };
+ ColumnViewerToolTipSupport.enableFor(viewer);
+
+ for (int i = 0; i < titles.length; i++) {
+ TreeViewerColumn tc = createTreeViewerColumn(viewer, titles[i], bounds[i], i);
+ tc.getColumn().setToolTipText(tooltips[i]);
+ tc.setLabelProvider(new DebugSourcesLabelProvider(i));
+ }
+ }
+
+ private TreeViewerColumn createTreeViewerColumn(TreeViewer viewer, String title, int bound, final int colNumber) {
+ final TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.NONE);
+ final TreeColumn column = viewerColumn.getColumn();
+ column.setText(title);
+ column.setWidth(bound);
+ column.setResizable(true);
+ column.setMoveable(true);
+ if (colNumber == 0)
+ comparator.setColumn(e -> e.getName(), colNumber);
+ if (colNumber == 1)
+ comparator.setColumn(e -> e.getFullPath() != null ? e.getFullPath() : e.getName(), colNumber);
+
+ column.addSelectionListener(getSelectionAdapter(column, colNumber));
+ return viewerColumn;
+ }
+
+ private SelectionAdapter getSelectionAdapter(final TreeColumn column, final int index) {
+ SelectionAdapter selectionAdapter = new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (index == 0)
+ comparator.setColumn(e1 -> e1.getName(), index);
+ if (index == 1)
+ comparator.setColumn(e1 -> e1.getFullPath() != null ? e1.getFullPath() : e1.getName(), index);
+ int dir = comparator.getDirection();
+ viewer.getTree().setSortDirection(dir);
+ viewer.getTree().setSortColumn(column);
+ viewer.refresh();
+ // This is due to the tree collapsing to level 2 at every comparison
+ viewer.expandAll();
+ }
+ };
+ return selectionAdapter;
+ }
+
+ private void createActions(TreeViewer viewer) {
+ IActionBars actionBars = getViewSite().getActionBars();
+ IToolBarManager toolBar = actionBars.getToolBarManager();
+ toolBar.add(new DebugSourcesExpandAction(viewer));
+ toolBar.add(new DebugSourcesCollapseAction(viewer));
+ toolBar.add(new DebugSourcesFlattendedTree(viewer));
+ toolBar.add(new DebugSourcesNormalTree(viewer));
+ toolBar.add(new DebugSourcesShowExistingFilesOnly(viewer));
+ }
+
+ private DsfSession getSession() {
+ if (viewer == null || viewer.getControl().isDisposed()) {
+ return null;
+ }
+
+ // Get the debug selection to know what the user is looking at in the Debug view
+ IAdaptable context = DebugUITools.getDebugContext();
+ if (context == null) {
+ return null;
+ }
+
+ // Extract the data model context to use with the DSF services
+ IDMContext dmcontext = context.getAdapter(IDMContext.class);
+ if (dmcontext == null) {
+ // Not dealing with a DSF session
+ return null;
+ }
+
+ // Extract DSF session id from the DM context
+ String sessionId = dmcontext.getSessionId();
+ // Get the full DSF session to have access to the DSF executor
+ DsfSession session = DsfSession.getSession(sessionId);
+ if (session == null) {
+ // It could be that this session is no longer active
+ return null;
+ }
+
+ if (!session.isActive() || session.getExecutor().isShutdown()) {
+ return null;
+ }
+
+ return session;
+ }
+
+ private void asyncExecRegisterForEvents() {
+ if (getSite() == null || getSite().getShell() == null || getSite().getShell().getDisplay() == null
+ || getSite().getShell().getDisplay().isDisposed()) {
+ return;
+ }
+ getSite().getShell().getDisplay().asyncExec(this::registerForEvents);
+ }
+
+ private void registerForEvents() {
+ DsfSession session = getSession();
+ if (session == null) {
+ return;
+ }
+
+ // Get the debug selection to know what the user is looking at in the Debug view
+ IAdaptable context = DebugUITools.getDebugContext();
+ if (context == null) {
+ return;
+ }
+
+ // Extract the data model context to use with the DSF services
+ IDMContext dmcontext = context.getAdapter(IDMContext.class);
+ if (dmcontext == null) {
+ // Not dealing with a DSF session
+ return;
+ }
+
+ registerForEvents(session);
+
+ // Show the current frame if there is one
+ displaySourceFiles(session, dmcontext);
+ }
+
+ @Override
+ public void setFocus() {
+ viewer.getControl().setFocus();
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ viewer.getControl().dispose();
+ DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow())
+ .removeDebugContextListener(this);
+ if (fSession != null) {
+ DsfSession lastSession = fSession;
+ if (!lastSession.getExecutor().isShutdown()) {
+ lastSession.getExecutor().submit(new DsfRunnable() {
+ @Override
+ public void run() {
+ lastSession.removeServiceEventListener(DebugSourcesView.this);
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * This method registers with the specified session to receive DSF events.
+ *
+ * @param session
+ * The session for which we want to receive events
+ */
+ private void registerForEvents(DsfSession session) {
+ if (session != null) {
+ if (fSession != session) {
+ if (fSession != null) {
+ DsfSession lastSession = fSession;
+ if (!lastSession.getExecutor().isShutdown()) {
+ lastSession.getExecutor().submit(new DsfRunnable() {
+ @Override
+ public void run() {
+ lastSession.removeServiceEventListener(DebugSourcesView.this);
+ }
+ });
+ }
+ }
+ fSession = session;
+ fSession.getExecutor().submit(new DsfRunnable() {
+
+ @Override
+ public void run() {
+ fSession.addServiceEventListener(DebugSourcesView.this, null);
+ }
+
+ });
+ }
+ }
+ }
+
+ private void displaySourceFiles(DsfSession session, IDMContext dmcontext) {
+ if (session.getExecutor().isShutdown()) {
+ // can't do anything
+ return;
+ }
+
+ IContainerDMContext containerDMContext = DMContexts.getAncestorOfType(dmcontext, IContainerDMContext.class);
+ if (containerDMContext == null || Objects.equals(containerDMContext, this.dmcontext)) {
+ return;
+ }
+ this.dmcontext = containerDMContext;
+ session.getExecutor().submit(new DsfRunnable() {
+ @Override
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
+ IDebugSourceFiles srcService = tracker.getService(IDebugSourceFiles.class);
+ // Don't forgot to dispose of a tracker before it goes out of scope
+ tracker.dispose();
+
+ if (srcService == null) {
+ // service not available. The debug session
+ // is probably terminating.
+ return;
+ }
+
+ // Get the full DSF session to have access to the DSF executor
+ srcService.getSources(containerDMContext,
+ new DataRequestMonitor<IDebugSourceFileInfo[]>(session.getExecutor(), null) {
+ @Override
+ protected void handleSuccess() {
+ // The service called 'handleSuccess()' so we know there is no error.
+ IDebugSourceFileInfo[] srcFileInfo = getData();
+ // We have a frame context. It is just a 'pointer' though.
+ // We need to get the data associated with it.
+ // Populate the tree synchronously
+ PopulateTreeJob populateTreeJob = new PopulateTreeJob(srcFileInfo);
+ CheckFileExistenceJob checkFileExistenceJob = new CheckFileExistenceJob();
+
+ populateTreeJob.addJobChangeListener(new JobChangeAdapter() {
+ @Override
+ public void done(IJobChangeEvent event) {
+ debugTree = populateTreeJob.getTree();
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!viewer.getControl().isDisposed()) {
+ viewer.setInput(debugTree);
+ }
+ }
+ });
+ if (checkFileExistenceJob.getState() == Job.RUNNING)
+ checkFileExistenceJob.cancel();
+ checkFileExistenceJob.schedule();
+ }
+ });
+ checkFileExistenceJob.addJobChangeListener(new JobChangeAdapter() {
+ @Override
+ public void done(IJobChangeEvent event) {
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (!viewer.getControl().isDisposed()) {
+ viewer.refresh();
+ }
+ }
+ });
+ }
+ });
+ // return all populate and file check jobs already running and cancel them.
+ IJobManager jobMan = Job.getJobManager();
+ Job[] populateJobS = jobMan.find(POPULATE_FAMILY);
+ for (Job job : populateJobS) {
+ job.cancel();
+ }
+ Job[] fileCheckJobS = jobMan.find(FILECHECK_FAMILY);
+ for (Job job : fileCheckJobS) {
+ job.cancel();
+ }
+ populateTreeJob.schedule();
+ }
+
+ @Override
+ protected void handleError() {
+ // Ignore errors when we select elements
+ // that don't contain frames
+ }
+ });
+ }
+ });
+ }
+
+ // This method must be public for the DSF callback to be found
+ @DsfServiceEventHandler
+ public void eventReceived(ISuspendedDMEvent event) {
+ asyncExecRegisterForEvents();
+ }
+
+ // This method must be public for the DSF callback to be found
+ @DsfServiceEventHandler
+ public void eventReceived(IDebugSourceFilesChangedEvent event) {
+ asyncExecRegisterForEvents();
+ }
+
+ public boolean canRefresh() {
+ return getSession() != null;
+ }
+
+ public void refresh() {
+ this.dmcontext = null; // force the refresh
+ DsfSession session = getSession();
+ if (session == null) {
+ return;
+ }
+ session.getExecutor().submit(new DsfRunnable() {
+
+ @Override
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
+ IDebugSourceFiles srcService = tracker.getService(IDebugSourceFiles.class);
+ // Don't forgot to dispose of a tracker before it goes out of scope
+ tracker.dispose();
+
+ if (srcService instanceof ICachingService) {
+ ICachingService cache = (ICachingService) srcService;
+ cache.flushCache(dmcontext);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void debugContextChanged(DebugContextEvent event) {
+ if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) {
+ registerForEvents();
+ }
+ }
+
+ private void openSourceFile(String fullPath) {
+ if (fullPath == null) {
+ return;
+ }
+ Path path = Paths.get(fullPath);
+ boolean exists = Files.exists(path);
+ IEditorInput editorInput = null;
+ String editorId = null;
+ if (exists) {
+ try {
+ URI uriLocation = path.toUri();
+ IFileStore fileStore = EFS.getStore(uriLocation);
+ editorInput = new FileStoreEditorInput(fileStore);
+ editorId = IDE.getEditorDescriptorForFileStore(fileStore, false).getId();
+ } catch (CoreException e1) {
+ CSourceNotFoundElement element = new CSourceNotFoundElement(new TempElement(), null, fullPath);
+ editorInput = new CSourceNotFoundEditorInput(element);
+ editorId = ICDebugUIConstants.CSOURCENOTFOUND_EDITOR_ID;
+ }
+ } else {
+ CSourceNotFoundElement element = new CSourceNotFoundElement(new TempElement(), null, fullPath);
+ editorInput = new CSourceNotFoundEditorInput(element);
+ editorId = ICDebugUIConstants.CSOURCENOTFOUND_EDITOR_ID;
+ }
+ IWorkbenchPage page = CUIPlugin.getActivePage();
+ try {
+ page.openEditor(editorInput, editorId);
+ } catch (PartInitException e) {
+ GdbUIPlugin.log(e);
+ }
+ }
+
+ private class TempElement implements IAdaptable, ICSourceNotFoundDescription {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getAdapter(Class<T> adapter) {
+ if (adapter == ICSourceNotFoundDescription.class)
+ return (T) this;
+ return null;
+ }
+
+ @Override
+ public String getDescription() {
+ return DebugSourcesMessages.DebugSourcesMessages_unknown;
+ }
+
+ @Override
+ public boolean isAddressOnly() {
+ return false;
+ }
+ }
+
+ class DebugPatternFilter extends PatternFilter {
+
+ @Override
+ protected boolean isLeafMatch(Viewer viewer, Object element) {
+ String name = ((DebugSourcesTreeElement) element).getName();
+ String path = ((DebugSourcesTreeElement) element).getFullPath();
+ return wordMatches(path) || wordMatches(name);
+ }
+ }
+
+ private static final String POPULATE_FAMILY = "populateJobFamily"; //$NON-NLS-1$
+ private static final String FILECHECK_FAMILY = "fileCheckJobFamily"; //$NON-NLS-1$
+
+ /**
+ * Job used to populate the tree
+ *
+ */
+ class PopulateTreeJob extends Job {
+
+ private IDebugSourceFileInfo[] srcFileInfo;
+ private DebugSourcesTreeElement populateTree;
+
+ public PopulateTreeJob(IDebugSourceFileInfo[] srcFileInfo) {
+ super("Populate Tree Job"); //$NON-NLS-1$
+ this.srcFileInfo = srcFileInfo;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ if (srcFileInfo == null)
+ return Status.CANCEL_STATUS;
+ populateTree = populateTree(srcFileInfo, monitor);
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ public boolean belongsTo(Object family) {
+ return POPULATE_FAMILY.equals(family);
+ }
+
+ public DebugSourcesTreeElement getTree() {
+ return populateTree;
+ }
+
+ private DebugSourcesTreeElement populateTree(IDebugSourceFileInfo[] srcFileInfo, IProgressMonitor monitor) {
+ DebugSourcesTreeElement debugTree = new DebugSourcesTreeElement("", FileExist.UNKNOWN); //$NON-NLS-1$
+ DebugSourcesTreeElement current = debugTree;
+ for (int i = 0; i < srcFileInfo.length; i++) {
+ DebugSourcesTreeElement root = current;
+ DebugSourcesTreeElement parent = root;
+ String path = srcFileInfo[i].getPath();
+ if (path == null) {
+ continue;
+ }
+ // Use Path API to clean the path
+ try {
+ Path p = Paths.get(path);
+ Path filename = p.getFileName();
+ // add root
+ Path pRoot = p.getRoot();
+ if (pRoot == null || !p.isAbsolute()) {
+ current = current.addLeaf(DebugSourcesMessages.DebugSourcesView_unrooted, p.toString(),
+ FileExist.UNKNOWN);
+ } else if (pRoot.equals(filename)) {
+ current = current.addLeaf(srcFileInfo[i].getName(), p.toString(), FileExist.UNKNOWN);
+ } else {
+ current = current.addNode(pRoot.toString(), FileExist.UNKNOWN);
+ }
+ parent = current;
+ // Add each sub-path
+ Path normalizedPath = p.normalize();
+ for (Path subpath : normalizedPath) {
+ if (subpath.equals(filename)) { // this is a leaf
+ current = current.addLeaf(srcFileInfo[i].getName(), p.toString(), FileExist.UNKNOWN);
+ } else {
+ current = current.addNode(subpath.toString(), FileExist.UNKNOWN);
+ }
+ current.setParent(parent);
+ parent = current;
+ }
+ current = root;
+ parent = root;
+ } catch (InvalidPathException e) {
+ GdbUIPlugin.log(e);
+ }
+ if (monitor != null && monitor.isCanceled()) {
+ return current;
+ }
+ }
+ return current;
+ }
+ }
+
+ /**
+ * Job used to check the existence of a file, updates the tree accordingly
+ *
+ */
+ class CheckFileExistenceJob extends Job {
+
+ public CheckFileExistenceJob() {
+ super("Checking file existence"); //$NON-NLS-1$
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ DebugSourcesTreeElement tmpTree = debugTree;
+ traverseDebugTree(tmpTree, monitor);
+ debugTree = tmpTree;
+ if (monitor != null && monitor.isCanceled())
+ return Status.CANCEL_STATUS;
+ } catch (Exception e) {
+ GdbUIPlugin.log(e);
+ }
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ public boolean belongsTo(Object family) {
+ return FILECHECK_FAMILY.equals(family);
+ }
+
+ /**
+ * Sets the file exist field of a leaf node
+ *
+ * @param child
+ * @param monitor
+ */
+ private void traverseDebugTree(DebugSourcesTreeElement child, IProgressMonitor monitor) {
+ Set<DebugSourcesTreeElement> children = child.getChildren();
+ for (DebugSourcesTreeElement each : children) {
+ String path = each.getFullPath();
+ if (path != null) {
+ Path p = Paths.get(path);
+ boolean exists = Files.exists(p);
+ each.setExist(exists ? FileExist.YES : FileExist.NO);
+ // if leaf, and it exists, we need to make the parent nodes exist too
+ if (!each.hasChildren() && exists) {
+ traverseParent(each);
+ }
+ }
+ if (monitor != null && monitor.isCanceled())
+ return;
+
+ traverseDebugTree(each, monitor);
+ }
+ if (child.getExists() == FileExist.UNKNOWN) {
+ child.setExist(FileExist.NO);
+ }
+ }
+
+ private void traverseParent(DebugSourcesTreeElement node) {
+ DebugSourcesTreeElement parent = node.getParent();
+ if (parent.getExists() != FileExist.YES) {
+ parent.setExist(FileExist.YES);
+ if (parent.getParent() != null) {
+ traverseParent(parent);
+ }
+ }
+ }
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesViewComparator.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesViewComparator.java
new file mode 100644
index 00000000000..b15e836b71b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/DebugSourcesViewComparator.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;
+
+import java.util.function.Function;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.swt.SWT;
+
+/**
+ * Comparator used for the Debug Sources Table viewer
+ *
+ */
+public class DebugSourcesViewComparator<T> extends ViewerComparator {
+
+ private Function<T, Comparable<?>> func;
+
+ private int propertyIndex;
+
+ private enum Direction {
+ ASCENDING, DESCENDING;
+
+ /**
+ *
+ * @param direction the previous direction
+ * @return the new direction
+ */
+ public static Direction toggle(Direction direction) {
+ return direction == ASCENDING ? DESCENDING : ASCENDING;
+ }
+ }
+
+ private Direction direction = Direction.DESCENDING;
+
+ public DebugSourcesViewComparator(Function<T, Comparable<?>> func) {
+ this.func = func;
+ }
+
+ public DebugSourcesViewComparator() {
+ this.propertyIndex = 0;
+ direction = Direction.DESCENDING;
+ }
+
+ public int getDirection() {
+ return direction == Direction.DESCENDING ? SWT.DOWN : SWT.UP;
+ }
+
+ public void setColumn(Function<T, Comparable<?>> column, int idx) {
+ this.func = column;
+ if (idx == this.propertyIndex) {
+ // Same column as last sort; toggle the direction
+ direction = Direction.toggle(direction);
+ } else {
+ // New column
+ this.propertyIndex = idx;
+ direction = Direction.DESCENDING;
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ Comparable s1 = func.apply((T) e1);
+ Comparable s2 = func.apply((T) e2);
+ int rc = s1.compareTo(s2);
+ // If descending order, flip the direction
+ if (direction.equals(Direction.DESCENDING)) {
+ rc = -rc;
+ }
+ return rc;
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/IDebugSourcesImagesConst.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/IDebugSourcesImagesConst.java
new file mode 100644
index 00000000000..bcd29f864e1
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/IDebugSourcesImagesConst.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2919 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources;
+
+/**
+ *
+ */
+public interface IDebugSourcesImagesConst {
+
+ public static final String IMG_COLLAPSE_DEBUG_SOURCES = "icons/full/elcl16/collapse_all.gif"; //$NON-NLS-1$
+
+ public static final String IMG_EXPAND_DEBUG_SOURCES = "icons/full/elcl16/expand_all.gif"; //$NON-NLS-1$
+
+ public static final String IMG_FLAT_LAYOUT = "icons/full/elcl16/flatLayout.png"; //$NON-NLS-1$
+
+ public static final String IMG_NORMAL_LAYOUT = "icons/full/elcl16/hierarchicalLayout.png"; //$NON-NLS-1$
+
+ public static final String IMG_SHOW_EXISTING_FILES_ONLY = "icons/full/elcl16/existingFiles.gif"; //$NON-NLS-1$
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesCollapseAction.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesCollapseAction.java
new file mode 100644
index 00000000000..77a0c16617d
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesCollapseAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions;
+
+import java.util.Optional;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesMessages;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.IDebugSourcesImagesConst;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ResourceLocator;
+import org.eclipse.jface.viewers.TreeViewer;
+
+/**
+ * Action to collapse of the nodes of the Debug Sources tree
+ */
+public class DebugSourcesCollapseAction extends Action {
+
+ private final TreeViewer viewer;
+
+ public DebugSourcesCollapseAction(TreeViewer viewer) {
+ super();
+ this.viewer = viewer;
+ if (viewer == null || viewer.getControl().isDisposed()) {
+ setEnabled(false);
+ }
+ setText(DebugSourcesMessages.DebugSourcesCollapseAction_name);
+ setToolTipText(DebugSourcesMessages.DebugSourcesCollapseAction_description);
+ Optional<ImageDescriptor> descriptor = ResourceLocator.imageDescriptorFromBundle(GdbUIPlugin.PLUGIN_ID,
+ IDebugSourcesImagesConst.IMG_COLLAPSE_DEBUG_SOURCES);
+ descriptor.ifPresent(this::setImageDescriptor);
+ }
+
+ @Override
+ public void run() {
+ if (viewer != null) {
+ viewer.collapseAll();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesExpandAction.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesExpandAction.java
new file mode 100644
index 00000000000..d02a1f95905
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesExpandAction.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Baha El-Kassaby - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions;
+
+import java.util.Optional;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesMessages;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.IDebugSourcesImagesConst;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ResourceLocator;
+import org.eclipse.jface.viewers.TreeViewer;
+
+/**
+ * Action to Expand all the nodes of the Debug Sources tree
+ */
+public class DebugSourcesExpandAction extends Action {
+
+ private final TreeViewer viewer;
+
+ public DebugSourcesExpandAction(TreeViewer viewer) {
+ this.viewer = viewer;
+ if (viewer == null || viewer.getControl().isDisposed()) {
+ setEnabled(false);
+ }
+ setText(DebugSourcesMessages.DebugSourcesExpandAction_name);
+ setToolTipText(DebugSourcesMessages.DebugSourcesExpandAction_description);
+ Optional<ImageDescriptor> descriptor = ResourceLocator.imageDescriptorFromBundle(GdbUIPlugin.PLUGIN_ID,
+ IDebugSourcesImagesConst.IMG_EXPAND_DEBUG_SOURCES);
+ descriptor.ifPresent(this::setImageDescriptor);
+ }
+
+ @Override
+ public void run() {
+ if (viewer != null) {
+ viewer.expandAll();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesFlattendedTree.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesFlattendedTree.java
new file mode 100644
index 00000000000..efced7519f9
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesFlattendedTree.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham- Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions;
+
+import java.util.Optional;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesLabelProvider;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesMessages;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesTreeContentProvider;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.IDebugSourcesImagesConst;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ResourceLocator;
+import org.eclipse.jface.viewers.TreeViewer;
+
+public class DebugSourcesFlattendedTree extends Action {
+ private final TreeViewer viewer;
+
+ public DebugSourcesFlattendedTree(TreeViewer viewer) {
+ super(null, IAction.AS_RADIO_BUTTON);
+ this.viewer = viewer;
+ if (viewer == null || viewer.getControl().isDisposed()) {
+ setEnabled(false);
+ }
+ setText(DebugSourcesMessages.DebugSourcesFlattendedTree_name);
+ setToolTipText(DebugSourcesMessages.DebugSourcesFlattendedTree_description);
+ Optional<ImageDescriptor> descriptor = ResourceLocator.imageDescriptorFromBundle(GdbUIPlugin.PLUGIN_ID,
+ IDebugSourcesImagesConst.IMG_FLAT_LAYOUT);
+ descriptor.ifPresent(this::setImageDescriptor);
+ if (viewer != null) {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer
+ .getContentProvider();
+ setChecked(contentProvider.isFlattenFoldersWithNoFiles());
+ }
+ }
+
+ @Override
+ public void run() {
+ if (isChecked()) {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer
+ .getContentProvider();
+ contentProvider.setFlattenFoldersWithNoFiles(true);
+ for (int i = 0; i < viewer.getTree().getColumnCount(); i++) {
+ DebugSourcesLabelProvider labelProvider = (DebugSourcesLabelProvider) viewer.getLabelProvider(i);
+ labelProvider.setFlattenFoldersWithNoFiles(true);
+ }
+ viewer.refresh(true);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesNormalTree.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesNormalTree.java
new file mode 100644
index 00000000000..3ec7609394c
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesNormalTree.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham- Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions;
+
+import java.util.Optional;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesLabelProvider;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesMessages;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesTreeContentProvider;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.IDebugSourcesImagesConst;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ResourceLocator;
+import org.eclipse.jface.viewers.TreeViewer;
+
+public class DebugSourcesNormalTree extends Action {
+ private final TreeViewer viewer;
+
+ public DebugSourcesNormalTree(TreeViewer viewer) {
+ super(null, IAction.AS_RADIO_BUTTON);
+ this.viewer = viewer;
+ if (viewer == null || viewer.getControl().isDisposed()) {
+ setEnabled(false);
+ }
+ setText(DebugSourcesMessages.DebugSourcesNormalTree_name);
+ setToolTipText(DebugSourcesMessages.DebugSourcesNormalTree_description);
+ Optional<ImageDescriptor> descriptor = ResourceLocator.imageDescriptorFromBundle(GdbUIPlugin.PLUGIN_ID,
+ IDebugSourcesImagesConst.IMG_NORMAL_LAYOUT);
+ descriptor.ifPresent(this::setImageDescriptor);
+ if (viewer != null) {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer
+ .getContentProvider();
+ setChecked(!contentProvider.isFlattenFoldersWithNoFiles());
+ }
+ }
+
+ @Override
+ public void run() {
+ if (isChecked()) {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer
+ .getContentProvider();
+ contentProvider.setFlattenFoldersWithNoFiles(false);
+ for (int i = 0; i < viewer.getTree().getColumnCount(); i++) {
+ DebugSourcesLabelProvider labelProvider = (DebugSourcesLabelProvider) viewer.getLabelProvider(i);
+ labelProvider.setFlattenFoldersWithNoFiles(false);
+ }
+ viewer.refresh(true);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesShowExistingFilesOnly.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesShowExistingFilesOnly.java
new file mode 100644
index 00000000000..5501325cc33
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesShowExistingFilesOnly.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham- Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions;
+
+import java.util.Optional;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesLabelProvider;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesMessages;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesTreeContentProvider;
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.IDebugSourcesImagesConst;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ResourceLocator;
+import org.eclipse.jface.viewers.TreeViewer;
+
+public class DebugSourcesShowExistingFilesOnly extends Action {
+ private final TreeViewer viewer;
+
+ public DebugSourcesShowExistingFilesOnly(TreeViewer viewer) {
+ super(null, IAction.AS_CHECK_BOX);
+ this.viewer = viewer;
+ if (viewer == null || viewer.getControl().isDisposed()) {
+ setEnabled(false);
+ }
+ setText(DebugSourcesMessages.DebugSourcesShowExistingFilesOnly_name);
+ setToolTipText(DebugSourcesMessages.DebugSourcesShowExistingFilesOnly_description);
+ Optional<ImageDescriptor> descriptor = ResourceLocator.imageDescriptorFromBundle(GdbUIPlugin.PLUGIN_ID,
+ IDebugSourcesImagesConst.IMG_SHOW_EXISTING_FILES_ONLY);
+ descriptor.ifPresent(this::setImageDescriptor);
+ if (viewer != null) {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer
+ .getContentProvider();
+ setChecked(contentProvider.isShowExistingFilesOnly());
+ }
+ }
+
+ @Override
+ public void run() {
+ DebugSourcesTreeContentProvider contentProvider = (DebugSourcesTreeContentProvider) viewer.getContentProvider();
+ boolean showExistingFilesOnly = contentProvider.isShowExistingFilesOnly();
+ showExistingFilesOnly = !showExistingFilesOnly;
+ contentProvider.setShowExistingFilesOnly(showExistingFilesOnly);
+
+ for (int i = 0; i < viewer.getTree().getColumnCount(); i++) {
+ DebugSourcesLabelProvider labelProvider = (DebugSourcesLabelProvider) viewer.getLabelProvider(i);
+ labelProvider.setShowExistingFilesOnly(showExistingFilesOnly);
+ }
+
+ setChecked(showExistingFilesOnly);
+ viewer.refresh(true);
+ }
+
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesViewRefresh.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesViewRefresh.java
new file mode 100644
index 00000000000..4fe13968771
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/debugsources/actions/DebugSourcesViewRefresh.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2018, 2019 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham- Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.actions;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.debugsources.DebugSourcesView;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.contexts.DebugContextEvent;
+import org.eclipse.debug.ui.contexts.IDebugContextListener;
+import org.eclipse.debug.ui.contexts.IDebugContextService;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.IActionDelegate2;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+
+public class DebugSourcesViewRefresh implements IViewActionDelegate, IDebugContextListener, IActionDelegate2 {
+
+ private IViewPart view;
+ private IAction action;
+
+ @Override
+ public void selectionChanged(IAction action, ISelection selection) {
+ this.action = action;
+ updateEnablement();
+ }
+
+ @Override
+ public void init(IViewPart view) {
+ this.view = view;
+ if (view != null) {
+ IDebugContextService debugContextService = DebugUITools.getDebugContextManager()
+ .getContextService(view.getSite().getWorkbenchWindow());
+ debugContextService.addPostDebugContextListener(this);
+ }
+ updateEnablement();
+ }
+
+ private void updateEnablement() {
+ if (view instanceof DebugSourcesView) {
+ DebugSourcesView debugSourcesView = (DebugSourcesView) view;
+ action.setEnabled(debugSourcesView.canRefresh());
+ } else {
+ action.setEnabled(false);
+ }
+ }
+
+ @Override
+ public void init(IAction action) {
+ this.action = action;
+ updateEnablement();
+ }
+
+ @Override
+ public void dispose() {
+ if (view != null) {
+ DebugUITools.getDebugContextManager().getContextService(view.getSite().getWorkbenchWindow())
+ .removePostDebugContextListener(this);
+ view = null;
+ }
+ updateEnablement();
+ }
+
+ @Override
+ public void debugContextChanged(DebugContextEvent event) {
+ updateEnablement();
+ }
+
+ @Override
+ public void run(IAction action) {
+ throw new UnsupportedOperationException("call runWithEvent instead"); //$NON-NLS-1$
+ }
+
+ @Override
+ public void runWithEvent(IAction action, Event event) {
+ if (view instanceof DebugSourcesView) {
+ DebugSourcesView debugSourcesView = (DebugSourcesView) view;
+ debugSourcesView.refresh();
+ }
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF
index f040489bedb..9d97873b2bc 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb;singleton:=true
-Bundle-Version: 5.7.300.qualifier
+Bundle-Version: 5.8.0.qualifier
Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.GdbPlugin
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime,
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBSourceLookup.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBSourceLookup.java
index 3a292ea7953..739f4e9f1e5 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBSourceLookup.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBSourceLookup.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2016 Kichwa Coders and others.
+ * Copyright (c) 2015, 2018 Kichwa Coders and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -13,6 +13,10 @@
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
@@ -24,13 +28,19 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
-import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
+import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.launching.GdbSourceLookupDirector;
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.MiSourceFilesInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.MiSourceFilesInfo.SourceFileInfo;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -40,9 +50,16 @@ import org.eclipse.core.runtime.Status;
*
* @since 5.0
*/
-public class GDBSourceLookup extends CSourceLookup implements IGDBSourceLookup {
+public class GDBSourceLookup extends CSourceLookup implements IGDBSourceLookup, IDebugSourceFiles, ICachingService {
- private ICommandControl fCommand;
+ private static class DebugSourceFilesChangedEvent extends AbstractDMEvent<IDMContext>
+ implements IDebugSourceFilesChangedEvent {
+ public DebugSourceFilesChangedEvent(IDMContext context) {
+ super(context);
+ }
+ }
+
+ private ICommandControlService fCommand;
private CommandFactory fCommandFactory;
private Map<ISourceLookupDMContext, CSourceLookupDirector> fDirectors = new HashMap<>();
/**
@@ -50,6 +67,8 @@ public class GDBSourceLookup extends CSourceLookup implements IGDBSourceLookup {
*/
private Map<String, String> fCachedEntries = Collections.emptyMap();
+ private CommandCache fDebugSourceFilesCache;
+
public GDBSourceLookup(DsfSession session) {
super(session);
}
@@ -65,12 +84,14 @@ public class GDBSourceLookup extends CSourceLookup implements IGDBSourceLookup {
}
private void doInitialize(RequestMonitor rm) {
- fCommand = getServicesTracker().getService(ICommandControl.class);
+ fCommand = getServicesTracker().getService(ICommandControlService.class);
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
- register(new String[] { IGDBSourceLookup.class.getName(), GDBSourceLookup.class.getName() },
- new Hashtable<String, String>());
+ fDebugSourceFilesCache = new CommandCache(getSession(), fCommand);
+ fDebugSourceFilesCache.setContextAvailable(fCommand.getContext(), true);
+ register(new String[] { IGDBSourceLookup.class.getName(), GDBSourceLookup.class.getName(),
+ IDebugSourceFiles.class.getName() }, new Hashtable<String, String>());
rm.done();
}
@@ -120,10 +141,9 @@ public class GDBSourceLookup extends CSourceLookup implements IGDBSourceLookup {
rm.done(false);
} else {
/*
- * Issue the clear and set commands back to back so that the
- * executor thread atomically changes the source lookup settings.
- * Any commands to GDB issued after this call will get the new
- * source substitute settings.
+ * Issue the clear and set commands back to back so that the executor thread
+ * atomically changes the source lookup settings. Any commands to GDB issued
+ * after this call will get the new source substitute settings.
*/
CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
@Override
@@ -143,14 +163,19 @@ public class GDBSourceLookup extends CSourceLookup implements IGDBSourceLookup {
fCachedEntries = entries;
CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
@Override
- protected void handleFailure() {
- /*
- * We failed to apply the changes. Clear the cache as it does
- * not represent the state of the backend. However we don't have
- * a good recovery here, so on future sourceContainersChanged()
- * calls we will simply reissue the substitutions.
- */
- fCachedEntries = null;
+ protected void handleCompleted() {
+ // Reset the list of source files when source path substitutions change
+ fDebugSourceFilesCache.reset();
+ getSession().dispatchEvent(new DebugSourceFilesChangedEvent(sourceLookupCtx), getProperties());
+ if (!isSuccess()) {
+ /*
+ * We failed to apply the changes. Clear the cache as it does not represent the
+ * state of the backend. However we don't have a good recovery here, so on
+ * future sourceContainersChanged() calls we will simply reissue the
+ * substitutions.
+ */
+ fCachedEntries = null;
+ }
rm.done();
}
};
@@ -160,6 +185,100 @@ public class GDBSourceLookup extends CSourceLookup implements IGDBSourceLookup {
fCommandFactory.createMISetSubstitutePath(sourceLookupCtx, entry.getKey(), entry.getValue()),
new DataRequestMonitor<MIInfo>(getExecutor(), countingRm));
}
+
+ }
+
+ private static final class DebugSourceFileInfo implements IDebugSourceFileInfo {
+ private final SourceFileInfo miInfo;
+
+ private DebugSourceFileInfo(SourceFileInfo miInfo) {
+ if (miInfo == null)
+ throw new IllegalArgumentException("The SourceFileInfo provided is null"); //$NON-NLS-1$
+ this.miInfo = miInfo;
+ }
+
+ @Override
+ public String getName() {
+ // we get the file name without the path
+ String name = miInfo != null ? miInfo.getFile() : null;
+ if (name == null)
+ return name;
+ try {
+ Path p = Paths.get(name);
+ name = p.getFileName() != null ? p.getFileName().toString() : ""; //$NON-NLS-1$
+ } catch (InvalidPathException e) {
+ // do nothing
+ }
+ return name;
+ }
+
+ @Override
+ public String getPath() {
+ // we get the file name without the path
+ String path = miInfo != null ? miInfo.getFullName() : null;
+ if (path == null)
+ return path;
+ try {
+ Path p = Paths.get(path);
+ path = p.toString();
+ } catch (InvalidPathException e) {
+ // do nothing
+ }
+ return path;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((miInfo == null) ? 0 : miInfo.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DebugSourceFileInfo other = (DebugSourceFileInfo) obj;
+ if (miInfo == null) {
+ if (other.miInfo != null)
+ return false;
+ } else if (!miInfo.equals(other.miInfo))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "DebugSourceFileInfo [miInfo=" + miInfo + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
}
+ @Override
+ public void getSources(final IDMContext dmc, final DataRequestMonitor<IDebugSourceFileInfo[]> rm) {
+ fDebugSourceFilesCache.execute(fCommandFactory.createMiFileListExecSourceFiles(dmc),
+ new DataRequestMonitor<MiSourceFilesInfo>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ IDebugSourceFileInfo[] result = null;
+ MiSourceFilesInfo sourceFiles = getData();
+ SourceFileInfo[] info = sourceFiles.getSourceFiles();
+ result = Arrays.asList(info).stream().map(DebugSourceFileInfo::new)
+ .toArray(IDebugSourceFileInfo[]::new);
+ rm.setData(result);
+ rm.done();
+ }
+ });
+ }
+
+ @Override
+ public void flushCache(IDMContext context) {
+ fDebugSourceFilesCache.reset();
+ getSession().dispatchEvent(new DebugSourceFilesChangedEvent(fCommand.getContext()), getProperties());
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IDebugSourceFiles.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IDebugSourceFiles.java
new file mode 100644
index 00000000000..0bd066cc433
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IDebugSourceFiles.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2018 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham (Kichwa Coders) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.datamodel.IDMEvent;
+import org.eclipse.cdt.dsf.service.IDsfService;
+
+/**
+ * Provides the ability to obtain the list of source files for the given debug
+ * context. For GDB this is using the -file-list-exec-source-files command
+ *
+ * @since 5.8
+ */
+public interface IDebugSourceFiles extends IDsfService {
+
+ /**
+ * Data type for what is returned by
+ * {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)}
+ */
+ public interface IDebugSourceFileInfo {
+
+ /**
+ * The name of the source file as it appears in the debug information. This may
+ * be relative, just the name, or absolute. Use {@link #getPath()} for the
+ * absolute path to the file name.
+ *
+ * @return name of the file
+ */
+ public String getName();
+
+ /**
+ * The absolute path of the the file.
+ *
+ * @return path to the file
+ */
+ public String getPath();
+ }
+
+ /**
+ * Event indicating that the list of the files may have changed for the given context.
+ */
+ public interface IDebugSourceFilesChangedEvent extends IDMEvent<IDMContext> {
+ }
+
+ /**
+ * Retrieves the list of sources data/files for the given context.
+ *
+ * @param context
+ * execution context
+ * @param rm
+ * Request completion monitor.
+ */
+ void getSources(IDMContext context, DataRequestMonitor<IDebugSourceFileInfo[]> rm);
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
index a1aef544584..7e1287d02db 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java
@@ -120,6 +120,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUncall;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUntil;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIFileExecAndSymbols;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIFileExecFile;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIFileListExecSourceFiles;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIFileSymbolFile;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBExit;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSet;
@@ -254,6 +255,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIVarSetFormatInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarShowAttributesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarShowFormatInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarUpdateInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.MiSourceFilesInfo;
/**
* Factory to create MI/CLI commands.
@@ -739,6 +741,11 @@ public class CommandFactory {
return new MIFileExecFile(dmc);
}
+ /** @since 5.8*/
+ public ICommand<MiSourceFilesInfo> createMiFileListExecSourceFiles(IDMContext ctx) {
+ return new MIFileListExecSourceFiles(ctx);
+ }
+
public ICommand<MIInfo> createMIFileSymbolFile(ICommandControlDMContext dmc, String file) {
return new MIFileSymbolFile(dmc, file);
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIFileListExecSourceFiles.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIFileListExecSourceFiles.java
new file mode 100644
index 00000000000..c58b4e41e6a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIFileListExecSourceFiles.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2018 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham (Kichwa Coders) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.mi.service.command.commands;
+
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
+import org.eclipse.cdt.dsf.mi.service.command.output.MiSourceFilesInfo;
+
+/**
+ *
+ * -file-list-exec-source-files
+ *
+ * Returns the list of source files for the current execution context. It
+ * outputs both filename and full (absolute path) file name of a source file.
+ *
+ * @since 5.8
+ */
+public class MIFileListExecSourceFiles extends MICommand<MiSourceFilesInfo> {
+
+ public MIFileListExecSourceFiles(IDMContext ctx) {
+ super(ctx, "-file-list-exec-source-files"); //$NON-NLS-1$
+ }
+
+ @Override
+ public MiSourceFilesInfo getResult(MIOutput out) {
+ return new MiSourceFilesInfo(out);
+ }
+} \ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MiSourceFilesInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MiSourceFilesInfo.java
new file mode 100644
index 00000000000..f1441cfde0a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MiSourceFilesInfo.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2018 Kichwa Coders and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Jonah Graham (Kichwa Coders) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.mi.service.command.output;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Example output is:
+ *
+ * <pre>
+ * (gdb) -file-list-exec-source-files
+ * ^done,files=[{file=foo.c,fullname=/home/foo.c},
+ * {file=/home/bar.c,fullname=/home/bar.c},
+ * {file=gdb_could_not_find_fullpath.c}]
+ * </pre>
+ *
+ * @since 5.8
+ */
+public class MiSourceFilesInfo extends MIInfo {
+
+ private SourceFileInfo[] sourceFileInfos;
+
+ public MiSourceFilesInfo(MIOutput record) {
+ super(record);
+ parse();
+ if (sourceFileInfos == null) {
+ sourceFileInfos = new SourceFileInfo[0];
+ }
+ }
+
+ /**
+ * Returns array of source files infos
+ *
+ * @return
+ */
+ public SourceFileInfo[] getSourceFiles() {
+ return sourceFileInfos;
+ }
+
+ private void parse() {
+ if (isDone()) {
+ MIOutput out = getMIOutput();
+ MIResultRecord rr = out.getMIResultRecord();
+ if (rr != null) {
+ MIResult[] results = rr.getMIResults();
+ for (int i = 0; i < results.length; i++) {
+ String var = results[i].getVariable();
+ if (var.equals("files")) { //$NON-NLS-1$
+ MIValue value = results[i].getMIValue();
+ if (value instanceof MIList) {
+ parseResults((MIList) value);
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ private void parseResults(MIList list) {
+ MIValue[] miValues = list.getMIValues();
+ List<SourceFileInfo> infos = new LinkedList<>();
+ if (miValues != null) {
+ for (MIValue miValue : miValues) {
+ if (miValue instanceof MITuple) {
+ MITuple miTuple = (MITuple) miValue;
+ SourceFileInfo info = new SourceFileInfo();
+ info.parse(miTuple.getMIResults());
+ infos.add(info);
+ }
+ }
+ }
+ sourceFileInfos = infos.toArray(new SourceFileInfo[infos.size()]);
+ }
+
+ public static class SourceFileInfo {
+ private String file;
+ private String fullname;
+
+ public void setFile(String file) {
+ this.file = file;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public void setFullName(String fullname) {
+ this.fullname = fullname;
+ }
+
+ public String getFullName() {
+ return fullname;
+ }
+
+ private void parse(MIResult[] results) {
+ for (MIResult result : results) {
+ String variable = result.getVariable();
+ MIValue miVal = result.getMIValue();
+ if (!(miVal instanceof MIConst)) {
+ continue;
+ }
+ String value = ((MIConst) miVal).getCString();
+ switch (variable) {
+ case "file": //$NON-NLS-1$
+ file = value;
+ break;
+ case "fullname": //$NON-NLS-1$
+ fullname = value;
+ break;
+ }
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((file == null) ? 0 : file.hashCode());
+ result = prime * result + ((fullname == null) ? 0 : fullname.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SourceFileInfo other = (SourceFileInfo) obj;
+ if (file == null) {
+ if (other.file != null)
+ return false;
+ } else if (!file.equals(other.file))
+ return false;
+ if (fullname == null) {
+ if (other.fullname != null)
+ return false;
+ } else if (!fullname.equals(other.fullname))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "SourceFileInfo [file=" + file + ", fullname=" + fullname + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java
index 0a97f39caf7..43af9dbbc2f 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/framework/SyncUtil.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2016 Ericsson and others.
+ * Copyright (c) 2007, 2018 Ericsson and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -67,6 +67,8 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo;
import org.eclipse.cdt.dsf.gdb.service.IGDBMemory2;
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
@@ -107,6 +109,8 @@ public class SyncUtil {
private static ISourceLookup fSourceLookup;
+ private static IDebugSourceFiles fDebugSourceFiles;
+
// Static list of register names as obtained directly from GDB.
// We make it static, key'ed on each version of gdb, so it does not
// get re-set for every test.
@@ -128,7 +132,7 @@ public class SyncUtil {
fMemory = tracker.getService(IMemory.class);
fCommandFactory = fGdbControl.getCommandFactory();
fSourceLookup = tracker.getService(ISourceLookup.class);
-
+ fDebugSourceFiles = tracker.getService(IDebugSourceFiles.class);
tracker.dispose();
};
fSession.getExecutor().submit(runnable).get();
@@ -979,4 +983,21 @@ public class SyncUtil {
return query.get();
}
+
+ /**
+ * Get the sources from the debugger.
+ *
+ * Wrapper around
+ * {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)}
+ */
+ public static IDebugSourceFileInfo[] getSources(IDMContext ctx) throws Exception {
+ Query<IDebugSourceFileInfo[]> query = new Query<IDebugSourceFileInfo[]>() {
+ @Override
+ protected void execute(DataRequestMonitor<IDebugSourceFileInfo[]> rm) {
+ fDebugSourceFiles.getSources(ctx, rm);
+ }
+ };
+ fDebugSourceFiles.getExecutor().execute(query);
+ return query.get();
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java
index c4bb8c8d648..94c20e34cbc 100644
--- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java
+++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/SourceLookupTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2016 Kichwa Coders and others.
+ * Copyright (c) 2015, 2018 Kichwa Coders and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -54,6 +54,8 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
import org.eclipse.cdt.dsf.debug.sourcelookup.DsfSourceLookupDirector;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles;
+import org.eclipse.cdt.dsf.gdb.service.IDebugSourceFiles.IDebugSourceFileInfo;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
@@ -1157,4 +1159,58 @@ public class SourceLookupTest extends BaseParametrizedTestCase {
*/
waitUntil("Timeout waiting for launches to terminate", () -> launch1.isTerminated() && launch2.isTerminated());
}
+
+ /**
+ * Helper method that actually performs the test/assertions for
+ * {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)} tests.
+ */
+ private void testGetSourcesListInner(String path) throws Throwable {
+ IDebugSourceFileInfo[] sources = SyncUtil.getSources(SyncUtil.getContainerContext());
+ String expectedPath = Paths.get(path, SOURCE_NAME).toString();
+ boolean anyMatch = Arrays.asList(sources).stream().anyMatch(source -> {
+ return source.getPath().equals(expectedPath);
+ });
+ assertTrue(anyMatch);
+ }
+
+ /**
+ * Test for {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)}
+ * with source path substitution on. Therefore make sure there is an entry
+ * for the resolved source path of {@value #SOURCE_NAME}
+ */
+ private void testGetSourcesList(String execName) throws Throwable {
+ doMappingAndLaunch(execName, true);
+ testGetSourcesListInner(SOURCE_ABSPATH);
+ }
+
+ /**
+ * Test for {@link IDebugSourceFiles#getSources(IDMContext, DataRequestMonitor)}
+ * with no source path substitution on. Therefore make sure there is an entry
+ * for the build path of {@value #SOURCE_NAME}
+ */
+ @Test
+ public void testGetSourcesListNoSourceLookup() throws Throwable {
+ doLaunch(EXEC_PATH + EXEC_AC_NAME);
+ testGetSourcesListInner(BUILD_ABSPATH);
+ }
+
+ @Test
+ public void testGetSourcesListAC() throws Throwable {
+ testGetSourcesList(EXEC_AC_NAME);
+ }
+
+ @Test
+ public void testGetSourcesListAN() throws Throwable {
+ testGetSourcesList(EXEC_AN_NAME);
+ }
+
+ @Test
+ public void testGetSourcesListRC() throws Throwable {
+ testGetSourcesList(EXEC_RC_NAME);
+ }
+
+ @Test
+ public void testGetSourcesListRN() throws Throwable {
+ testGetSourcesList(EXEC_RN_NAME);
+ }
}

Back to the top