@theia/debug 1.67.0-next.86 → 1.68.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/lib/browser/breakpoint/breakpoint-manager.js +1 -1
  2. package/lib/browser/breakpoint/breakpoint-manager.js.map +1 -1
  3. package/lib/browser/debug-commands.d.ts +153 -0
  4. package/lib/browser/debug-commands.d.ts.map +1 -0
  5. package/lib/browser/debug-commands.js +399 -0
  6. package/lib/browser/debug-commands.js.map +1 -0
  7. package/lib/browser/debug-frontend-application-contribution.d.ts +1 -150
  8. package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
  9. package/lib/browser/debug-frontend-application-contribution.js +155 -532
  10. package/lib/browser/debug-frontend-application-contribution.js.map +1 -1
  11. package/lib/browser/debug-prefix-configuration.js +3 -3
  12. package/lib/browser/debug-prefix-configuration.js.map +1 -1
  13. package/lib/browser/debug-session-contribution.d.ts +2 -1
  14. package/lib/browser/debug-session-contribution.d.ts.map +1 -1
  15. package/lib/browser/debug-session-contribution.js +5 -1
  16. package/lib/browser/debug-session-contribution.js.map +1 -1
  17. package/lib/browser/debug-session-manager.d.ts +4 -3
  18. package/lib/browser/debug-session-manager.d.ts.map +1 -1
  19. package/lib/browser/debug-session-manager.js +46 -8
  20. package/lib/browser/debug-session-manager.js.map +1 -1
  21. package/lib/browser/debug-session.d.ts +3 -2
  22. package/lib/browser/debug-session.d.ts.map +1 -1
  23. package/lib/browser/debug-session.js +4 -3
  24. package/lib/browser/debug-session.js.map +1 -1
  25. package/lib/browser/model/debug-breakpoint.d.ts +4 -2
  26. package/lib/browser/model/debug-breakpoint.d.ts.map +1 -1
  27. package/lib/browser/model/debug-breakpoint.js +10 -2
  28. package/lib/browser/model/debug-breakpoint.js.map +1 -1
  29. package/lib/browser/model/debug-data-breakpoint.d.ts +2 -0
  30. package/lib/browser/model/debug-data-breakpoint.d.ts.map +1 -1
  31. package/lib/browser/model/debug-data-breakpoint.js +16 -5
  32. package/lib/browser/model/debug-data-breakpoint.js.map +1 -1
  33. package/lib/browser/model/debug-function-breakpoint.d.ts +3 -0
  34. package/lib/browser/model/debug-function-breakpoint.d.ts.map +1 -1
  35. package/lib/browser/model/debug-function-breakpoint.js +17 -1
  36. package/lib/browser/model/debug-function-breakpoint.js.map +1 -1
  37. package/lib/browser/model/debug-instruction-breakpoint.d.ts +2 -0
  38. package/lib/browser/model/debug-instruction-breakpoint.d.ts.map +1 -1
  39. package/lib/browser/model/debug-instruction-breakpoint.js +13 -1
  40. package/lib/browser/model/debug-instruction-breakpoint.js.map +1 -1
  41. package/lib/browser/model/debug-source-breakpoint.d.ts +6 -1
  42. package/lib/browser/model/debug-source-breakpoint.d.ts.map +1 -1
  43. package/lib/browser/model/debug-source-breakpoint.js +17 -1
  44. package/lib/browser/model/debug-source-breakpoint.js.map +1 -1
  45. package/lib/browser/view/debug-action.d.ts +1 -0
  46. package/lib/browser/view/debug-action.d.ts.map +1 -1
  47. package/lib/browser/view/debug-action.js +2 -2
  48. package/lib/browser/view/debug-action.js.map +1 -1
  49. package/lib/browser/view/debug-breakpoints-source.d.ts +2 -0
  50. package/lib/browser/view/debug-breakpoints-source.d.ts.map +1 -1
  51. package/lib/browser/view/debug-breakpoints-source.js +6 -1
  52. package/lib/browser/view/debug-breakpoints-source.js.map +1 -1
  53. package/lib/browser/view/debug-configuration-widget.js +2 -2
  54. package/lib/browser/view/debug-configuration-widget.js.map +1 -1
  55. package/lib/browser/view/debug-exception-breakpoint.d.ts +9 -2
  56. package/lib/browser/view/debug-exception-breakpoint.d.ts.map +1 -1
  57. package/lib/browser/view/debug-exception-breakpoint.js +26 -5
  58. package/lib/browser/view/debug-exception-breakpoint.js.map +1 -1
  59. package/lib/browser/view/debug-session-widget.d.ts +0 -1
  60. package/lib/browser/view/debug-session-widget.d.ts.map +1 -1
  61. package/lib/browser/view/debug-session-widget.js +0 -4
  62. package/lib/browser/view/debug-session-widget.js.map +1 -1
  63. package/lib/browser/view/debug-threads-widget.d.ts +6 -1
  64. package/lib/browser/view/debug-threads-widget.d.ts.map +1 -1
  65. package/lib/browser/view/debug-threads-widget.js +69 -5
  66. package/lib/browser/view/debug-threads-widget.js.map +1 -1
  67. package/lib/browser/view/debug-toolbar-widget.d.ts +5 -18
  68. package/lib/browser/view/debug-toolbar-widget.d.ts.map +1 -1
  69. package/lib/browser/view/debug-toolbar-widget.js +14 -58
  70. package/lib/browser/view/debug-toolbar-widget.js.map +1 -1
  71. package/lib/browser/view/debug-view-model.d.ts.map +1 -1
  72. package/lib/browser/view/debug-view-model.js +8 -9
  73. package/lib/browser/view/debug-view-model.js.map +1 -1
  74. package/package.json +16 -16
  75. package/src/browser/breakpoint/breakpoint-manager.ts +1 -1
  76. package/src/browser/debug-commands.ts +402 -0
  77. package/src/browser/debug-frontend-application-contribution.ts +35 -410
  78. package/src/browser/debug-prefix-configuration.ts +1 -1
  79. package/src/browser/debug-session-contribution.ts +5 -2
  80. package/src/browser/debug-session-manager.ts +52 -9
  81. package/src/browser/debug-session.tsx +4 -3
  82. package/src/browser/model/debug-breakpoint.tsx +12 -3
  83. package/src/browser/model/debug-data-breakpoint.tsx +21 -6
  84. package/src/browser/model/debug-function-breakpoint.tsx +22 -1
  85. package/src/browser/model/debug-instruction-breakpoint.tsx +16 -1
  86. package/src/browser/model/debug-source-breakpoint.tsx +24 -3
  87. package/src/browser/style/index.css +13 -5
  88. package/src/browser/view/debug-action.tsx +3 -2
  89. package/src/browser/view/debug-breakpoints-source.tsx +5 -1
  90. package/src/browser/view/debug-configuration-widget.tsx +1 -1
  91. package/src/browser/view/debug-exception-breakpoint.tsx +30 -5
  92. package/src/browser/view/debug-session-widget.ts +0 -5
  93. package/src/browser/view/debug-threads-widget.ts +84 -6
  94. package/src/browser/view/debug-toolbar-widget.tsx +13 -60
  95. package/src/browser/view/debug-view-model.ts +8 -9
@@ -16,8 +16,9 @@
16
16
 
17
17
  import { injectable, inject, postConstruct, interfaces, Container } from '@theia/core/shared/inversify';
18
18
  import { MenuPath } from '@theia/core';
19
- import { TreeNode, NodeProps, SelectableTreeNode } from '@theia/core/lib/browser';
19
+ import { TreeNode, NodeProps, SelectableTreeNode, CompositeTreeNode } from '@theia/core/lib/browser';
20
20
  import { SourceTreeWidget, TreeElementNode } from '@theia/core/lib/browser/source-tree';
21
+ import { ExpandableTreeNode } from '@theia/core/lib/browser/tree/tree-expansion';
21
22
  import { DebugThreadsSource } from './debug-threads-source';
22
23
  import { DebugSession } from '../debug-session';
23
24
  import { DebugThread } from '../model/debug-thread';
@@ -65,28 +66,105 @@ export class DebugThreadsWidget extends SourceTreeWidget {
65
66
  this.toDispose.push(this.threads);
66
67
  this.source = this.threads;
67
68
 
68
- this.toDispose.push(this.viewModel.onDidChange(() => this.updateWidgetSelection()));
69
+ this.toDispose.push(this.viewModel.onDidChange(() => {
70
+ this.updateWidgetSelection();
71
+ }));
69
72
  this.toDispose.push(this.model.onSelectionChanged(() => this.updateModelSelection()));
70
73
  }
71
74
 
72
75
  protected updatingSelection = false;
73
- protected updateWidgetSelection(): void {
76
+ protected async updateWidgetSelection(): Promise<void> {
74
77
  if (this.updatingSelection) {
75
78
  return;
76
79
  }
77
80
  this.updatingSelection = true;
78
81
  try {
82
+ await this.model.refresh();
83
+
79
84
  const { currentThread } = this.viewModel;
80
- if (currentThread) {
81
- const node = this.model.getNode(currentThread.id);
82
- if (SelectableTreeNode.is(node)) {
85
+
86
+ // Check if current selection still exists in the tree
87
+ const selectedNode = this.model.selectedNodes[0];
88
+ const selectionStillValid = selectedNode && this.model.getNode(selectedNode.id);
89
+
90
+ // Only update selection if:
91
+ // 1. Current selection is invalid (node no longer in tree), OR
92
+ // 2. There's a stopped thread to show
93
+ if (selectionStillValid && (!currentThread || !currentThread.stopped)) {
94
+ return;
95
+ }
96
+
97
+ // Try to select the current stopped thread, or clear if none
98
+ if (currentThread && currentThread.stopped) {
99
+ const node = await this.waitForNode(currentThread);
100
+
101
+ // Re-check stopped state after async wait
102
+ if (!currentThread.stopped) {
103
+ return;
104
+ }
105
+
106
+ if (node && SelectableTreeNode.is(node)) {
83
107
  this.model.selectNode(node);
108
+
109
+ // Set context key
110
+ if (TreeElementNode.is(node)) {
111
+ if (node.element instanceof DebugThread) {
112
+ this.debugCallStackItemTypeKey.set('thread');
113
+ } else if (node.element instanceof DebugSession) {
114
+ this.debugCallStackItemTypeKey.set('session');
115
+ }
116
+ }
84
117
  }
118
+ } else if (!selectionStillValid) {
119
+ // Selection is stale and no stopped thread to select
120
+ this.model.clearSelection();
85
121
  }
86
122
  } finally {
87
123
  this.updatingSelection = false;
88
124
  }
89
125
  }
126
+
127
+ /**
128
+ * Wait for a node to appear in the tree, expanding root children to populate the tree
129
+ */
130
+ protected async waitForNode(thread: DebugThread): Promise<TreeNode | undefined> {
131
+ const maxAttempts = 10;
132
+ const delayMs = 50;
133
+ const threadId = thread.id;
134
+
135
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
136
+ // If thread continued during wait, abort
137
+ if (!thread.stopped) {
138
+ return undefined;
139
+ }
140
+
141
+ await this.model.refresh();
142
+
143
+ const root = this.model.root;
144
+
145
+ // Expand all root's direct children to populate the tree
146
+ if (root && CompositeTreeNode.is(root)) {
147
+ for (const child of root.children) {
148
+ if (ExpandableTreeNode.is(child) && !child.expanded) {
149
+ await this.model.expandNode(child);
150
+ }
151
+ }
152
+ }
153
+
154
+ // Now look directly for the thread node
155
+ const threadNode = this.model.getNode(threadId);
156
+ if (threadNode) {
157
+ return threadNode;
158
+ }
159
+
160
+ if (attempt < maxAttempts - 1) {
161
+ await new Promise(resolve => setTimeout(resolve, delayMs));
162
+ }
163
+ }
164
+
165
+ return undefined;
166
+ }
167
+
90
168
  protected updateModelSelection(): void {
91
169
  if (this.updatingSelection) {
92
170
  return;
@@ -16,69 +16,38 @@
16
16
 
17
17
  import * as React from '@theia/core/shared/react';
18
18
  import { inject, postConstruct, injectable } from '@theia/core/shared/inversify';
19
- import { CommandMenu, CommandRegistry, CompoundMenuNode, Disposable, DisposableCollection, MenuModelRegistry, MenuPath } from '@theia/core';
19
+ import { CommandMenu, CompoundMenuNode, MenuModelRegistry, MenuPath } from '@theia/core';
20
+ import { KeybindingRegistry } from '@theia/core/lib/browser';
20
21
  import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
21
22
  import { ReactWidget } from '@theia/core/lib/browser/widgets';
22
23
  import { DebugViewModel } from './debug-view-model';
23
- import { DebugState } from '../debug-session';
24
24
  import { DebugAction } from './debug-action';
25
- import { nls } from '@theia/core/lib/common/nls';
26
25
 
27
26
  @injectable()
28
27
  export class DebugToolBar extends ReactWidget {
29
28
 
30
29
  static readonly MENU: MenuPath = ['debug-toolbar-menu'];
30
+ static readonly CONTROLS: MenuPath = [...DebugToolBar.MENU, 'z_controls'];
31
31
 
32
- @inject(CommandRegistry) protected readonly commandRegistry: CommandRegistry;
33
32
  @inject(MenuModelRegistry) protected readonly menuModelRegistry: MenuModelRegistry;
33
+ @inject(KeybindingRegistry) protected readonly keybindingRegistry: KeybindingRegistry;
34
34
  @inject(ContextKeyService) protected readonly contextKeyService: ContextKeyService;
35
35
  @inject(DebugViewModel) protected readonly model: DebugViewModel;
36
36
 
37
- protected readonly onRender = new DisposableCollection();
38
-
39
37
  @postConstruct()
40
38
  protected init(): void {
41
39
  this.id = 'debug:toolbar:' + this.model.id;
42
40
  this.addClass('debug-toolbar');
43
41
  this.toDispose.push(this.model);
44
42
  this.toDispose.push(this.model.onDidChange(() => this.update()));
43
+ this.toDispose.push(this.keybindingRegistry.onKeybindingsChanged(() => this.update()));
45
44
  this.scrollOptions = undefined;
46
45
  this.update();
47
46
  }
48
47
 
49
- focus(): void {
50
- if (!this.doFocus()) {
51
- this.onRender.push(Disposable.create(() => this.doFocus()));
52
- this.update();
53
- }
54
- }
55
- protected doFocus(): boolean {
56
- if (!this.stepRef) {
57
- return false;
58
- }
59
- this.stepRef.focus();
60
- return true;
61
- }
62
- protected stepRef: DebugAction | undefined;
63
- protected setStepRef = (stepRef: DebugAction | null) => {
64
- this.stepRef = stepRef || undefined;
65
- this.onRender.dispose();
66
- };
67
-
68
48
  protected render(): React.ReactNode {
69
- const { state } = this.model;
70
49
  return <React.Fragment>
71
50
  {this.renderContributedCommands()}
72
- {this.renderContinue()}
73
- <DebugAction enabled={state === DebugState.Stopped} run={this.stepOver} label={nls.localizeByDefault('Step Over')}
74
- iconClass='debug-step-over' ref={this.setStepRef} />
75
- <DebugAction enabled={state === DebugState.Stopped} run={this.stepIn} label={nls.localizeByDefault('Step Into')}
76
- iconClass='debug-step-into' />
77
- <DebugAction enabled={state === DebugState.Stopped} run={this.stepOut} label={nls.localizeByDefault('Step Out')}
78
- iconClass='debug-step-out' />
79
- <DebugAction enabled={state !== DebugState.Inactive} run={this.restart} label={nls.localizeByDefault('Restart')}
80
- iconClass='debug-restart' />
81
- {this.renderStart()}
82
51
  </React.Fragment>;
83
52
  }
84
53
 
@@ -99,36 +68,20 @@ export class DebugToolBar extends ReactWidget {
99
68
  }
100
69
 
101
70
  protected debugAction(commandMenuNode: CommandMenu): React.ReactNode {
71
+ const accelerator = this.acceleratorFor(commandMenuNode.id);
72
+ const run = (effectiveMenuPath: MenuPath) => commandMenuNode.run(effectiveMenuPath).catch(e => console.error(e));
102
73
  return <DebugAction
103
74
  key={commandMenuNode.id}
104
- enabled={true}
75
+ enabled={commandMenuNode.isEnabled(DebugToolBar.MENU)}
105
76
  label={commandMenuNode.label}
77
+ tooltip={commandMenuNode.label + (accelerator ? ` (${accelerator})` : '')}
106
78
  iconClass={commandMenuNode.icon || ''}
107
- run={commandMenuNode.run} />;
79
+ run={run} />;
108
80
  }
109
81
 
110
- protected renderStart(): React.ReactNode {
111
- const { state } = this.model;
112
- if (state === DebugState.Inactive && this.model.sessionCount === 1) {
113
- return <DebugAction run={this.start} label={nls.localizeByDefault('Start')} iconClass='debug-start' />;
114
- }
115
- return <DebugAction enabled={state !== DebugState.Inactive} run={this.stop} label={nls.localizeByDefault('Stop')} iconClass='debug-stop' />;
116
- }
117
- protected renderContinue(): React.ReactNode {
118
- const { state } = this.model;
119
- if (state === DebugState.Stopped) {
120
- return <DebugAction run={this.continue} label={nls.localizeByDefault('Continue')} iconClass='debug-continue' />;
121
- }
122
- return <DebugAction enabled={state === DebugState.Running} run={this.pause} label={nls.localizeByDefault('Pause')} iconClass='debug-pause' />;
82
+ protected acceleratorFor(commandId: string): string | undefined {
83
+ const keybindings = this.keybindingRegistry.getKeybindingsForCommand(commandId);
84
+ return keybindings.length ? this.keybindingRegistry.acceleratorFor(keybindings[0], '+').join(' ') : undefined;
123
85
  }
124
86
 
125
- protected start = () => this.model.start({ startedByUser: true });
126
- protected restart = () => this.model.restart();
127
- protected stop = () => this.model.terminate();
128
- protected continue = () => this.model.currentThread && this.model.currentThread.continue();
129
- protected pause = () => this.model.currentThread && this.model.currentThread.pause();
130
- protected stepOver = () => this.model.currentThread && this.model.currentThread.stepOver();
131
- protected stepIn = () => this.model.currentThread && this.model.currentThread.stepIn();
132
- protected stepOut = () => this.model.currentThread && this.model.currentThread.stepOut();
133
-
134
87
  }
@@ -96,14 +96,13 @@ export class DebugViewModel implements Disposable {
96
96
  this.fireDidChange();
97
97
  }));
98
98
  this.toDispose.push(this.manager.onDidChange(current => {
99
- if (current === this.currentSession) {
100
- this.fireDidChange();
101
- }
99
+ // Always fire change to update views, even if session is not current
100
+ // This ensures threads view updates for all sessions
101
+ this.fireDidChange();
102
102
  }));
103
103
  this.toDispose.push(this.manager.onDidChangeBreakpoints(({ session, uri }) => {
104
- if (!session || session === this.currentSession) {
105
- this.fireDidChangeBreakpoints(uri);
106
- }
104
+ // Fire for all sessions since we now show breakpoints from all active sessions
105
+ this.fireDidChangeBreakpoints(uri);
107
106
  }));
108
107
  this.toDispose.push(this.manager.onDidResolveLazyVariable(({ session, variable }) => {
109
108
  if (session === this.currentSession) {
@@ -140,15 +139,15 @@ export class DebugViewModel implements Disposable {
140
139
  }
141
140
 
142
141
  get breakpoints(): DebugSourceBreakpoint[] {
143
- return this.manager.getBreakpoints(this.currentSession);
142
+ return this.manager.getBreakpoints();
144
143
  }
145
144
 
146
145
  get functionBreakpoints(): DebugFunctionBreakpoint[] {
147
- return this.manager.getFunctionBreakpoints(this.currentSession);
146
+ return this.manager.getFunctionBreakpoints();
148
147
  }
149
148
 
150
149
  get instructionBreakpoints(): DebugInstructionBreakpoint[] {
151
- return this.manager.getInstructionBreakpoints(this.currentSession);
150
+ return this.manager.getInstructionBreakpoints();
152
151
  }
153
152
 
154
153
  get dataBreakpoints(): DebugDataBreakpoint[] {