diff --git a/src/ddebug/common/debugger.d b/src/ddebug/common/debugger.d index d6f3192..0db24da 100644 --- a/src/ddebug/common/debugger.d +++ b/src/ddebug/common/debugger.d @@ -36,6 +36,24 @@ class LocationBase { LocationBase clone() { return new LocationBase(this); } } +class Breakpoint : LocationBase { + int id; + bool enabled = true; + string projectName; + this() { + id = _nextBreakpointId++; + } + this(Breakpoint v) { + super(v); + id = v.id; + enabled = v.enabled; + projectName = v.projectName; + } + override Breakpoint clone() { + return new Breakpoint(this); + } +} + class DebugFrame : LocationBase { ulong address; string func; @@ -65,24 +83,6 @@ class DebugFrame : LocationBase { } } -class Breakpoint : LocationBase { - int id; - bool enabled = true; - string projectName; - this() { - id = _nextBreakpointId++; - } - this(Breakpoint v) { - super(v); - id = v.id; - enabled = v.enabled; - projectName = v.projectName; - } - override Breakpoint clone() { - return new Breakpoint(this); - } -} - class DebugThread { ulong id; string name; @@ -103,8 +103,22 @@ class DebugThread { } DebugThread clone() { return new DebugThread(this); } - @property int length() { return stack ? stack.length : 0; } - DebugFrame opIndex(int index) { return stack ? stack[index] : null; } + @property int length() { + if (stack && stack.length > 0) + return stack.length; + if (frame) + return 1; + return 0; + } + DebugFrame opIndex(int index) { + if (index < 0 || index > length) + return null; + if (stack && stack.length > 0) + return stack[index]; + if (frame && index == 0) + return frame; + return null; + } } class DebugThreadList { diff --git a/src/ddebug/gdb/gdbmiparser.d b/src/ddebug/gdb/gdbmiparser.d index fa0a834..290be10 100644 --- a/src/ddebug/gdb/gdbmiparser.d +++ b/src/ddebug/gdb/gdbmiparser.d @@ -5,6 +5,7 @@ import std.utf; import std.conv : to; import std.array : empty; import std.algorithm : startsWith, equal; +import std.string : format; import ddebug.common.debugger; /// result class @@ -123,6 +124,8 @@ DebugThread parseThread(MIValue params) { DebugThread res = new DebugThread(); res.id = params.getUlong("id"); res.name = params.getString("target-id"); + if (res.name.empty) + res.name = "Thread%d".format(res.id); string stateName = params.getString("state"); if (stateName == "stopped") res.state = DebuggingState.paused; diff --git a/src/dlangide/ui/debuggerui.d b/src/dlangide/ui/debuggerui.d index 5d53b4b..2e5738f 100644 --- a/src/dlangide/ui/debuggerui.d +++ b/src/dlangide/ui/debuggerui.d @@ -14,10 +14,13 @@ import ddebug.common.execution; import ddebug.common.debugger; class DebuggerUIHandler : DebuggerCallback { - IDEFrame _ide; - Debugger _debugger; - DebuggingState _state = DebuggingState.loaded; - DebugFrame _location; + + private IDEFrame _ide; + private Debugger _debugger; + private DebuggingState _state = DebuggingState.loaded; + private DebugFrame _location; + private WatchPanel _watchPanel; + private StackPanel _stackPanel; this(IDEFrame ide, Debugger debugger) { _ide = ide; @@ -37,6 +40,8 @@ class DebuggerUIHandler : DebuggerCallback { /// send debug context (threads, stack frames, local vars...) void onDebugContextInfo(DebugThreadList info) { Log.d("Debugger context received"); + _stackPanel.updateDebugInfo(info, info.currentThreadId, 0); + _watchPanel.updateDebugInfo(info, info.currentThreadId, 0); } void onResponse(ResponseCode code, string msg) { @@ -172,8 +177,6 @@ class DebuggerUIHandler : DebuggerCallback { } - private WatchPanel _watchPanel; - private StackPanel _stackPanel; void switchToDebugPerspective() { _ide.dockHost.layoutPriority = [DockAlignment.Bottom, DockAlignment.Top, DockAlignment.Left, DockAlignment.Right]; diff --git a/src/dlangide/ui/stackpanel.d b/src/dlangide/ui/stackpanel.d index 9a97f86..7daef90 100644 --- a/src/dlangide/ui/stackpanel.d +++ b/src/dlangide/ui/stackpanel.d @@ -2,6 +2,9 @@ module dlangide.ui.stackpanel; import dlangui; +import std.string : format; +import ddebug.common.debugger; + class StackPanel : DockWindow { this(string id) { @@ -10,26 +13,75 @@ class StackPanel : DockWindow { } override protected Widget createBodyWidget() { + layoutWidth = FILL_PARENT; + layoutHeight = FILL_PARENT; VerticalLayout root = new VerticalLayout(); - root.layoutWeight = FILL_PARENT; + root.layoutWidth = FILL_PARENT; root.layoutHeight = FILL_PARENT; - ComboBox comboBox = new ComboBox("threadComboBox", ["Thread1"d]); - comboBox.layoutWidth = FILL_PARENT; - comboBox.selectedItemIndex = 0; - StringGridWidget grid = new StringGridWidget("stackGrid"); - grid.resize(2, 20); - grid.showColHeaders = true; - grid.showRowHeaders = false; - grid.layoutHeight = FILL_PARENT; - grid.layoutWidth = FILL_PARENT; - grid.setColTitle(0, "Function"d); - grid.setColTitle(1, "Address"d); - grid.setCellText(0, 0, "main()"d); - root.addChild(comboBox); - root.addChild(grid); + _comboBox = new ComboBox("threadComboBox", ["Thread1"d]); + _comboBox.layoutWidth = FILL_PARENT; + _comboBox.selectedItemIndex = 0; + _grid = new StringGridWidget("stackGrid"); + _grid.resize(2, 20); + _grid.showColHeaders = true; + _grid.showRowHeaders = false; + _grid.layoutHeight = FILL_PARENT; + _grid.layoutWidth = FILL_PARENT; + _grid.setColTitle(0, "Function"d); + _grid.setColTitle(1, "Address"d); + _grid.setCellText(0, 0, "main()"d); + _grid.layoutWidth = FILL_PARENT; + _grid.layoutHeight = FILL_PARENT; + root.addChild(_comboBox); + root.addChild(_grid); return root; } + StringGridWidget _grid; + ComboBox _comboBox; + DebugThreadList _debugInfo; + DebugThread _selectedThread; + ulong _currentThreadId; + int _currentThreadIndex; + int _currentFrame; + void updateDebugInfo(DebugThreadList data, ulong currentThreadId, int currentFrame) { + _debugInfo = data; + if (currentThreadId == 0) + currentThreadId = data.currentThreadId; + _currentThreadId = currentThreadId; + _currentThreadIndex = -1; + _currentFrame = 0; + _selectedThread = null; + if (_debugInfo) { + _comboBox.enabled = true; + dstring[] threadNames; + for (int i = 0; i < _debugInfo.length; i++) { + threadNames ~= _debugInfo[i].name.toUTF32; + if (_debugInfo[i].id == _currentThreadId) { + _currentThreadIndex = i; + _selectedThread = _debugInfo[i]; + if (currentFrame <= _selectedThread.length) + _currentFrame = currentFrame; + } + } + _comboBox.items = threadNames; + if (_currentThreadIndex >= 0 && _selectedThread.length > 0) { + _comboBox.selectedItemIndex = _currentThreadIndex; + _grid.resize(2, _selectedThread.length); + for (int i = 0; i < _selectedThread.length; i++) { + _grid.setCellText(0, i, _selectedThread[i].func.toUTF32); + _grid.setCellText(1, i, ""d); + } + } else { + _grid.resize(2, 1); + _grid.setCellText(0, 0, "No info"d); + _grid.setCellText(1, 0, ""d); + } + } else { + _comboBox.enabled = false; + } + } + protected void onPopupMenuItem(MenuItem item) { if (item.action) handleAction(item.action); diff --git a/src/dlangide/ui/watchpanel.d b/src/dlangide/ui/watchpanel.d index 56c6b6d..90a3969 100644 --- a/src/dlangide/ui/watchpanel.d +++ b/src/dlangide/ui/watchpanel.d @@ -2,6 +2,9 @@ module dlangide.ui.watchpanel; import dlangui; +import std.string : format; +import ddebug.common.debugger; + class VariablesWindow : StringGridWidget { this(string ID = null) { super(ID); @@ -67,5 +70,36 @@ class WatchPanel : DockWindow { override bool handleAction(const Action a) { return super.handleAction(a); } + + DebugThreadList _debugInfo; + DebugThread _selectedThread; + DebugFrame _frame; + ulong _currentThreadId; + int _currentThreadIndex; + int _currentFrame; + void updateDebugInfo(DebugThreadList data, ulong currentThreadId, int currentFrame) { + _debugInfo = data; + if (currentThreadId == 0) + currentThreadId = data.currentThreadId; + _currentThreadId = currentThreadId; + _currentThreadIndex = -1; + _currentFrame = 0; + _selectedThread = null; + _frame = null; + + if (_debugInfo) { + for (int i = 0; i < _debugInfo.length; i++) { + if (_debugInfo[i].id == _currentThreadId) { + _currentThreadIndex = i; + _selectedThread = _debugInfo[i]; + if (currentFrame <= _selectedThread.length) { + _currentFrame = currentFrame; + _frame = _selectedThread[_currentFrame]; + } + } + } + } else { + } + } }