@opensumi/ide-debug 2.21.6 → 2.21.7-rc-1669780664.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 (166) hide show
  1. package/lib/browser/index.d.ts.map +1 -1
  2. package/lib/browser/index.js +2 -9
  3. package/lib/browser/index.js.map +1 -1
  4. package/lib/browser/preferences/launch-folder-preference-provider.d.ts +2 -2
  5. package/lib/browser/preferences/launch-folder-preference-provider.d.ts.map +1 -1
  6. package/lib/browser/preferences/launch-folder-preference-provider.js +2 -2
  7. package/lib/browser/preferences/launch-folder-preference-provider.js.map +1 -1
  8. package/lib/browser/view/configuration/debug-configuration.module.less +5 -5
  9. package/lib/browser/view/configuration/debug-configuration.view.d.ts.map +1 -1
  10. package/lib/browser/view/configuration/debug-configuration.view.js +1 -1
  11. package/lib/browser/view/configuration/debug-configuration.view.js.map +1 -1
  12. package/lib/browser/view/configuration/debug-toolbar.view.js +2 -2
  13. package/lib/browser/view/configuration/debug-toolbar.view.js.map +1 -1
  14. package/lib/browser/view/console/debug-console.module.less +2 -1
  15. package/lib/browser/view/console/debug-console.view.js +2 -2
  16. package/lib/browser/view/console/debug-console.view.js.map +1 -1
  17. package/lib/browser/view/variables/debug-variables.module.less +2 -1
  18. package/lib/browser/view/variables/debug-variables.view.js +1 -1
  19. package/lib/browser/view/variables/debug-variables.view.js.map +1 -1
  20. package/lib/browser/view/watch/debug-watch.module.less +2 -1
  21. package/lib/browser/view/watch/debug-watch.view.js +1 -1
  22. package/lib/browser/view/watch/debug-watch.view.js.map +1 -1
  23. package/package.json +25 -24
  24. package/src/browser/assets/breakpoint-conditional-disabled.svg +4 -0
  25. package/src/browser/assets/breakpoint-conditional-unverified.svg +4 -0
  26. package/src/browser/assets/breakpoint-conditional.svg +4 -0
  27. package/src/browser/assets/breakpoint-disabled.svg +4 -0
  28. package/src/browser/assets/breakpoint-hint.svg +4 -0
  29. package/src/browser/assets/breakpoint-log-disabled.svg +4 -0
  30. package/src/browser/assets/breakpoint-log-unverified.svg +4 -0
  31. package/src/browser/assets/breakpoint-log.svg +4 -0
  32. package/src/browser/assets/breakpoint-unsupported.svg +4 -0
  33. package/src/browser/assets/breakpoint-unverified.svg +4 -0
  34. package/src/browser/assets/breakpoint.svg +4 -0
  35. package/src/browser/assets/breakpoints-activate-inverse.svg +4 -0
  36. package/src/browser/assets/breakpoints-activate.svg +4 -0
  37. package/src/browser/assets/configure-inverse.svg +4 -0
  38. package/src/browser/assets/configure.svg +4 -0
  39. package/src/browser/assets/continue-inverse.svg +4 -0
  40. package/src/browser/assets/current-and-breakpoint.svg +4 -0
  41. package/src/browser/assets/current-arrow.svg +4 -0
  42. package/src/browser/assets/remove-all-inverse.svg +4 -0
  43. package/src/browser/assets/remove-all.svg +4 -0
  44. package/src/browser/assets/repl-inverse.svg +4 -0
  45. package/src/browser/assets/repl.svg +4 -0
  46. package/src/browser/assets/restart-inverse.svg +4 -0
  47. package/src/browser/assets/stackframe-and-breakpoint.svg +4 -0
  48. package/src/browser/assets/stackframe-arrow.svg +4 -0
  49. package/src/browser/assets/start-inverse.svg +4 -0
  50. package/src/browser/breakpoint/breakpoint-decoration.ts +57 -0
  51. package/src/browser/breakpoint/breakpoint-manager.ts +348 -0
  52. package/src/browser/breakpoint/breakpoint-marker.ts +70 -0
  53. package/src/browser/breakpoint/index.ts +3 -0
  54. package/src/browser/components/debug-action/index.module.less +73 -0
  55. package/src/browser/components/debug-action/index.tsx +40 -0
  56. package/src/browser/components/debug-exception-widget.less +42 -0
  57. package/src/browser/components/floating-click-widget/index.module.less +5 -0
  58. package/src/browser/components/floating-click-widget/index.tsx +21 -0
  59. package/src/browser/components/index.ts +1 -0
  60. package/src/browser/contextkeys/debug-call-stack-item-type-key.ts +4 -0
  61. package/src/browser/contextkeys/debug-contextkey.service.ts +54 -0
  62. package/src/browser/contextkeys/index.ts +1 -0
  63. package/src/browser/debug-ansi-handle.ts +521 -0
  64. package/src/browser/debug-configuration-manager.ts +513 -0
  65. package/src/browser/debug-configuration-model.ts +66 -0
  66. package/src/browser/debug-contribution.ts +904 -0
  67. package/src/browser/debug-exception-widget.tsx +89 -0
  68. package/src/browser/debug-link-detector.ts +234 -0
  69. package/src/browser/debug-memory.ts +220 -0
  70. package/src/browser/debug-preferences.ts +70 -0
  71. package/src/browser/debug-progress.service.ts +122 -0
  72. package/src/browser/debug-schema-updater.ts +67 -0
  73. package/src/browser/debug-service.ts +42 -0
  74. package/src/browser/debug-session-connection.ts +333 -0
  75. package/src/browser/debug-session-contribution.ts +57 -0
  76. package/src/browser/debug-session-manager.ts +622 -0
  77. package/src/browser/debug-session.ts +1179 -0
  78. package/src/browser/debug-style.less +128 -0
  79. package/src/browser/debugUtils.ts +110 -0
  80. package/src/browser/editor/debug-breakpoint-widget.ts +99 -0
  81. package/src/browser/editor/debug-breakpoint-zone-widget.tsx +262 -0
  82. package/src/browser/editor/debug-breakpoint.module.less +31 -0
  83. package/src/browser/editor/debug-editor-contribution.ts +590 -0
  84. package/src/browser/editor/debug-expression-provider.ts +101 -0
  85. package/src/browser/editor/debug-hover-model.ts +38 -0
  86. package/src/browser/editor/debug-hover-source.ts +107 -0
  87. package/src/browser/editor/debug-hover-tree.model.service.ts +332 -0
  88. package/src/browser/editor/debug-hover-widget.tsx +200 -0
  89. package/src/browser/editor/debug-hover.module.less +29 -0
  90. package/src/browser/editor/debug-hover.view.tsx +147 -0
  91. package/src/browser/editor/debug-model-manager.ts +220 -0
  92. package/src/browser/editor/debug-model.ts +853 -0
  93. package/src/browser/editor/debug-run-to-cursor.service.ts +180 -0
  94. package/src/browser/editor/debug-styles.ts +66 -0
  95. package/src/browser/editor/evaluatable-expression.ts +47 -0
  96. package/src/browser/editor/index.ts +6 -0
  97. package/src/browser/index.ts +121 -0
  98. package/src/browser/markers/index.ts +2 -0
  99. package/src/browser/markers/marker-manager.ts +201 -0
  100. package/src/browser/markers/marker.ts +20 -0
  101. package/src/browser/model/debug-source.ts +144 -0
  102. package/src/browser/model/debug-stack-frame.ts +111 -0
  103. package/src/browser/model/debug-thread.ts +186 -0
  104. package/src/browser/model/debug-watch.ts +130 -0
  105. package/src/browser/model/index.ts +4 -0
  106. package/src/browser/preferences/launch-folder-preference-provider.ts +23 -0
  107. package/src/browser/preferences/launch-preferences-contribution.ts +9 -0
  108. package/src/browser/preferences/launch-preferences.ts +16 -0
  109. package/src/browser/tree/debug-console-tree-node.define.tsx +76 -0
  110. package/src/browser/tree/debug-tree-node.define.ts +768 -0
  111. package/src/browser/tree/index.ts +2 -0
  112. package/src/browser/view/breakpoints/debug-breakpoints.module.less +72 -0
  113. package/src/browser/view/breakpoints/debug-breakpoints.service.ts +217 -0
  114. package/src/browser/view/breakpoints/debug-breakpoints.view.tsx +174 -0
  115. package/src/browser/view/configuration/debug-configuration.module.less +110 -0
  116. package/src/browser/view/configuration/debug-configuration.service.ts +170 -0
  117. package/src/browser/view/configuration/debug-configuration.view.tsx +252 -0
  118. package/src/browser/view/configuration/debug-toolbar.service.ts +167 -0
  119. package/src/browser/view/configuration/debug-toolbar.view.tsx +335 -0
  120. package/src/browser/view/console/debug-console-filter.model.ts +49 -0
  121. package/src/browser/view/console/debug-console-filter.service.ts +81 -0
  122. package/src/browser/view/console/debug-console-filter.view.tsx +78 -0
  123. package/src/browser/view/console/debug-console-model.ts +48 -0
  124. package/src/browser/view/console/debug-console-session.ts +164 -0
  125. package/src/browser/view/console/debug-console-toolbar.view.tsx +28 -0
  126. package/src/browser/view/console/debug-console-tree.model.service.ts +550 -0
  127. package/src/browser/view/console/debug-console.contribution.ts +181 -0
  128. package/src/browser/view/console/debug-console.module.less +373 -0
  129. package/src/browser/view/console/debug-console.service.ts +433 -0
  130. package/src/browser/view/console/debug-console.view.tsx +500 -0
  131. package/src/browser/view/debug-view-model.ts +182 -0
  132. package/src/browser/view/frames/debug-call-stack-frame.view.tsx +224 -0
  133. package/src/browser/view/frames/debug-call-stack-session.view.tsx +237 -0
  134. package/src/browser/view/frames/debug-call-stack-thread.view.tsx +93 -0
  135. package/src/browser/view/frames/debug-call-stack.contribution.ts +88 -0
  136. package/src/browser/view/frames/debug-call-stack.module.less +193 -0
  137. package/src/browser/view/frames/debug-call-stack.operation.tsx +97 -0
  138. package/src/browser/view/frames/debug-call-stack.service.ts +105 -0
  139. package/src/browser/view/frames/debug-call-stack.view.tsx +43 -0
  140. package/src/browser/view/variables/debug-variables-model.ts +38 -0
  141. package/src/browser/view/variables/debug-variables-tree.model.service.ts +467 -0
  142. package/src/browser/view/variables/debug-variables.contribution.ts +244 -0
  143. package/src/browser/view/variables/debug-variables.module.less +149 -0
  144. package/src/browser/view/variables/debug-variables.view.tsx +303 -0
  145. package/src/browser/view/watch/debug-watch-model.ts +38 -0
  146. package/src/browser/view/watch/debug-watch-tree.model.service.ts +567 -0
  147. package/src/browser/view/watch/debug-watch.contribution.ts +167 -0
  148. package/src/browser/view/watch/debug-watch.module.less +189 -0
  149. package/src/browser/view/watch/debug-watch.view.tsx +337 -0
  150. package/src/common/constants.ts +81 -0
  151. package/src/common/debug-breakpoint.ts +43 -0
  152. package/src/common/debug-configuration.ts +68 -0
  153. package/src/common/debug-editor.ts +4 -0
  154. package/src/common/debug-hover.ts +31 -0
  155. package/src/common/debug-model.ts +247 -0
  156. package/src/common/debug-progress.ts +8 -0
  157. package/src/common/debug-schema-updater.ts +1 -0
  158. package/src/common/debug-service.ts +176 -0
  159. package/src/common/debug-session-options.ts +19 -0
  160. package/src/common/debug-session.ts +200 -0
  161. package/src/common/evaluatable-expression.ts +43 -0
  162. package/src/common/index.ts +14 -0
  163. package/src/common/inline-values.ts +77 -0
  164. package/src/common/terminal.ts +163 -0
  165. package/src/common/types.ts +86 -0
  166. package/src/index.ts +1 -0
@@ -0,0 +1,224 @@
1
+ import cls from 'classnames';
2
+ import { observer } from 'mobx-react-lite';
3
+ import React from 'react';
4
+
5
+ import { RecycleList } from '@opensumi/ide-components';
6
+ import {
7
+ ViewState,
8
+ isUndefined,
9
+ useInjectable,
10
+ localize,
11
+ DisposableCollection,
12
+ getIcon,
13
+ } from '@opensumi/ide-core-browser';
14
+
15
+ import { IDebugSessionManager } from '../../../common';
16
+ import { DebugSession } from '../../debug-session';
17
+ import { DebugSessionManager } from '../../debug-session-manager';
18
+ import { DebugStackFrame } from '../../model';
19
+ import { DebugThread } from '../../model/debug-thread';
20
+
21
+ import styles from './debug-call-stack.module.less';
22
+ import { DebugCallStackService } from './debug-call-stack.service';
23
+
24
+
25
+ export interface DebugStackSessionViewProps {
26
+ frames: DebugStackFrame[];
27
+ session: DebugSession;
28
+ thread: DebugThread;
29
+ viewState: ViewState;
30
+ indent?: number;
31
+ }
32
+
33
+ export const DebugStackFramesView = observer((props: DebugStackSessionViewProps) => {
34
+ const { viewState, frames: rawFrames, thread, indent = 0, session } = props;
35
+ const [selected, setSelected] = React.useState<number | undefined>();
36
+ const [isLoading, setIsLoading] = React.useState<boolean>(false);
37
+ const [frames, setFrames] = React.useState<DebugStackFrame[]>([]);
38
+ const [framesErrorMessage, setFramesErrorMessage] = React.useState<string>('');
39
+ const [canLoadMore, setCanLoadMore] = React.useState<boolean>(false);
40
+ const manager = useInjectable<DebugSessionManager>(IDebugSessionManager);
41
+ const debugCallStackService = useInjectable<DebugCallStackService>(DebugCallStackService);
42
+
43
+ const loadMore = async () => {
44
+ if (!thread) {
45
+ return;
46
+ }
47
+ const remainingFramesCount =
48
+ typeof thread.stoppedDetails?.totalFrames === 'number'
49
+ ? thread.stoppedDetails?.totalFrames - thread.frameCount
50
+ : undefined;
51
+ const frames = await thread.fetchFrames(remainingFramesCount);
52
+ setFrames(frames);
53
+ };
54
+
55
+ const frameOpenSource = (frame: DebugStackFrame) => {
56
+ if (frame && frame.source) {
57
+ frame.source.open({}, frame);
58
+ }
59
+ };
60
+
61
+ React.useEffect(() => {
62
+ setFrames([...rawFrames]);
63
+
64
+ const disposable = new DisposableCollection();
65
+
66
+ disposable.push(
67
+ manager.onDidChangeActiveDebugSession(({ previous }) => {
68
+ if (previous && previous !== thread.session) {
69
+ setSelected(undefined);
70
+ }
71
+ }),
72
+ );
73
+
74
+ if (session) {
75
+ disposable.push(
76
+ session.onDidChangeCallStack(() => {
77
+ setFrames([...thread.frames]);
78
+ }),
79
+ );
80
+ }
81
+
82
+ return () => {
83
+ disposable.dispose();
84
+ };
85
+ }, []);
86
+
87
+ React.useEffect(() => {
88
+ if (thread) {
89
+ const hasSourceFrame = thread.frames.find((e: DebugStackFrame) => !!e.source);
90
+ if (hasSourceFrame) {
91
+ setSelected(hasSourceFrame.raw.id);
92
+ frameOpenSource(hasSourceFrame);
93
+ }
94
+ }
95
+ }, [thread.frameCount]);
96
+
97
+ React.useEffect(() => {
98
+ if (thread) {
99
+ if (thread.stoppedDetails) {
100
+ const { framesErrorMessage, totalFrames } = thread.stoppedDetails;
101
+ setFramesErrorMessage(framesErrorMessage || '');
102
+ if (totalFrames && totalFrames > thread.frameCount) {
103
+ setCanLoadMore(true);
104
+ } else {
105
+ setCanLoadMore(false);
106
+ }
107
+ } else {
108
+ setCanLoadMore(false);
109
+ }
110
+ } else {
111
+ setCanLoadMore(false);
112
+ }
113
+ }, [frames]);
114
+
115
+ const template = ({ data }) => {
116
+ const frame: DebugStackFrame = data;
117
+ const isLabel = frame.raw.presentationHint === 'label';
118
+ const isSubtle = frame.raw.presentationHint === 'subtle';
119
+ const clickHandler = () => {
120
+ if (isLabel || isSubtle) {
121
+ return;
122
+ }
123
+ manager.updateCurrentSession(frame.session);
124
+
125
+ frame.session.currentThread = frame.thread;
126
+ setSelected(frame.raw.id);
127
+ frameOpenSource(frame);
128
+ };
129
+
130
+ const restartFrame = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
131
+ event.preventDefault();
132
+ event.stopPropagation();
133
+
134
+ if (frame.canRestart) {
135
+ frame.restart();
136
+ }
137
+ };
138
+
139
+ return (
140
+ <div
141
+ style={{ paddingLeft: `${indent}px` }}
142
+ className={cls(
143
+ styles.debug_stack_frames_item,
144
+ selected === frame.raw.id && styles.selected,
145
+ !(frame.raw && frame.raw.source && frame.raw.source.name) && styles.debug_stack_frames_item_hidden,
146
+ )}
147
+ onClick={clickHandler}
148
+ onContextMenu={(event: React.MouseEvent<HTMLDivElement, MouseEvent>) =>
149
+ debugCallStackService.handleContextMenu(event, data)
150
+ }
151
+ >
152
+ <span className={cls(styles.debug_stack_frames_item_label, isLabel && styles.label, isSubtle && styles.subtle)}>
153
+ {frame.raw && frame.raw.name}
154
+ </span>
155
+ <span className={styles.debug_stack_frames_item_description}>
156
+ {(frame.raw && frame.raw.source && frame.raw.source.name) || localize('debug.stack.frame.noSource')}
157
+ </span>
158
+ <>
159
+ <a
160
+ title=''
161
+ onClick={(event) => restartFrame(event)}
162
+ className={cls(styles.debug_restart_frame_icon, getIcon('debug-restart-frame'))}
163
+ ></a>
164
+ <div className={cls(!isUndefined(frame.raw.line) && styles.debug_stack_frames_item_badge)}>
165
+ {frame.raw && frame.raw.line}
166
+ {!isUndefined(frame.raw.line) && ':'}
167
+ {frame.raw && frame.raw.column}
168
+ </div>
169
+ </>
170
+ </div>
171
+ );
172
+ };
173
+
174
+ const renderLoadMoreStackFrames = () => {
175
+ const clickHandler = async () => {
176
+ setIsLoading(true);
177
+ await loadMore();
178
+ setIsLoading(false);
179
+ };
180
+ return (
181
+ <div className={styles.debug_stack_frames_item} onClick={clickHandler}>
182
+ <span className={styles.debug_stack_frames_load_more}>{localize('debug.stack.loadMore')}</span>
183
+ </div>
184
+ );
185
+ };
186
+
187
+ const renderLoading = () => (
188
+ <div className={styles.debug_stack_frames_item}>
189
+ <span className={styles.debug_stack_frames_load_more}>{localize('debug.stack.loading')}</span>
190
+ </div>
191
+ );
192
+
193
+ const renderFramesErrorMessage = (message: string) => (
194
+ <div className={styles.debug_stack_frames_item}>
195
+ <span className={styles.debug_stack_frames_error_message} title={message}>
196
+ {message}
197
+ </span>
198
+ </div>
199
+ );
200
+
201
+ if (framesErrorMessage) {
202
+ return <div className={styles.debug_stack_frames}>{renderFramesErrorMessage(framesErrorMessage)}</div>;
203
+ }
204
+
205
+ const footer = () => {
206
+ if (isLoading) {
207
+ return renderLoading();
208
+ } else if (canLoadMore) {
209
+ return renderLoadMoreStackFrames();
210
+ }
211
+ return null;
212
+ };
213
+
214
+ return (
215
+ <RecycleList
216
+ data={frames}
217
+ template={template}
218
+ itemHeight={22}
219
+ width={viewState.width}
220
+ height={isLoading || canLoadMore ? (frames.length + 1) * 22 : frames.length * 22}
221
+ footer={isLoading || canLoadMore ? footer : undefined}
222
+ />
223
+ );
224
+ });
@@ -0,0 +1,237 @@
1
+ import cls from 'classnames';
2
+ import React from 'react';
3
+
4
+ import { ViewState, getIcon, useInjectable, DisposableCollection } from '@opensumi/ide-core-browser';
5
+
6
+ import { DebugState, IDebugSessionManager } from '../../../common';
7
+ import { DebugSession } from '../../debug-session';
8
+ import { DebugSessionManager } from '../../debug-session-manager';
9
+ import { DebugThread } from '../../model/debug-thread';
10
+
11
+ import { DebugStackThreadView } from './debug-call-stack-thread.view';
12
+ import styles from './debug-call-stack.module.less';
13
+ import { DebugStackOperationView } from './debug-call-stack.operation';
14
+ import { DebugCallStackService } from './debug-call-stack.service';
15
+
16
+ export interface DebugStackSessionViewProps {
17
+ session: DebugSession;
18
+ viewState: ViewState;
19
+ indent: number;
20
+ }
21
+
22
+ export const DebugStackSessionView = (props: DebugStackSessionViewProps) => {
23
+ const { session, viewState, indent } = props;
24
+ const manager = useInjectable<DebugSessionManager>(IDebugSessionManager);
25
+ const debugCallStackService = useInjectable<DebugCallStackService>(DebugCallStackService);
26
+ const [threads, setThreads] = React.useState<DebugThread[]>([]);
27
+ const [otherThreads, setOtherThreads] = React.useState<DebugThread[]>([]);
28
+ const [multipleThreadPaused, setMultipleThreadPaused] = React.useState<DebugThread[]>([]);
29
+ const [subSession, setSubSession] = React.useState<DebugSession[]>([]);
30
+ const [unfold, setUnfold] = React.useState<boolean>(true);
31
+ const [hover, setHover] = React.useState<boolean>(false);
32
+ const [loading, setLoading] = React.useState<boolean>(true);
33
+ // 多 session 调试
34
+ const mutipleSession = manager.sessions.length > 1;
35
+ const supportsThreadIdCorrespond = session.supportsThreadIdCorrespond;
36
+
37
+ // 从 manager.sessions 中找出 parentSession id 是当前 session id 的 session
38
+ const findSubSessions = () => {
39
+ const hasParentSessions = manager.sessions.filter((s) => s.parentSession);
40
+ const subSession: DebugSession[] = [];
41
+ while (hasParentSessions[0]) {
42
+ if (manager.getSession(hasParentSessions[0].parentSession?.id)?.id === session.id) {
43
+ subSession.push(hasParentSessions[0]);
44
+ }
45
+ hasParentSessions.shift();
46
+ }
47
+
48
+ return subSession;
49
+ };
50
+
51
+ // 加载更多线程信息
52
+ const fetchOtherThreads = async () => {
53
+ setLoading(true);
54
+ const _threads = await session.fetchThreads();
55
+ setLoading(false);
56
+ setOtherThreads(_threads);
57
+ };
58
+
59
+ React.useEffect(() => {
60
+ const createDispose = manager.onDidCreateDebugSession(() => {
61
+ const sub = findSubSessions();
62
+ setSubSession(sub);
63
+ });
64
+
65
+ const destroyDispose = manager.onDidDestroyDebugSession(() => {
66
+ const sub = findSubSessions();
67
+ setSubSession(sub);
68
+ });
69
+
70
+ return () => {
71
+ createDispose.dispose();
72
+ destroyDispose.dispose();
73
+ setSubSession([]);
74
+ };
75
+ }, []);
76
+
77
+ React.useEffect(() => {
78
+ setThreads(Array.from(session.threads));
79
+
80
+ const disposable = new DisposableCollection();
81
+
82
+ disposable.push(
83
+ session.onDidChange(() => {
84
+ setThreads([...session.threads]);
85
+ }),
86
+ );
87
+
88
+ disposable.push(
89
+ session.onDidThread(async ({ body: { reason } }) => {
90
+ if (!session.supportsThreadIdCorrespond) {
91
+ return;
92
+ }
93
+
94
+ if (session.state === DebugState.Stopped && reason === 'started') {
95
+ await fetchOtherThreads();
96
+ }
97
+ }),
98
+ );
99
+
100
+ disposable.push(
101
+ session.onDidStop(async () => {
102
+ if (!session.supportsThreadIdCorrespond) {
103
+ return;
104
+ }
105
+
106
+ const multipleThreads = Array.from(session.multipleThreadPaused.values());
107
+ setMultipleThreadPaused(multipleThreads);
108
+
109
+ await fetchOtherThreads();
110
+ }),
111
+ );
112
+
113
+ disposable.push(
114
+ session.onDidContinued(async () => {
115
+ if (!session.supportsThreadIdCorrespond) {
116
+ return;
117
+ }
118
+
119
+ const multipleThreads = Array.from(session.multipleThreadPaused.values());
120
+ setMultipleThreadPaused(multipleThreads);
121
+ }),
122
+ );
123
+
124
+ return () => {
125
+ disposable.dispose();
126
+ };
127
+ }, []);
128
+
129
+ // 渲染 "加载更多线程"
130
+ const renderLoadMoreThread = () => {
131
+ if (session.state !== DebugState.Stopped) {
132
+ return null;
133
+ }
134
+
135
+ if (supportsThreadIdCorrespond && unfold) {
136
+ return loading ? (
137
+ <div className={styles.debug_stack_item_loading}>
138
+ <span>正在加载线程...</span>
139
+ </div>
140
+ ) : (
141
+ otherThreads.map(
142
+ (thread) =>
143
+ !session.hasInMultipleThreadPaused(thread.raw.id) && (
144
+ <DebugStackThreadView
145
+ key={thread.id}
146
+ indent={mutipleSession ? 16 : 0}
147
+ viewState={viewState}
148
+ thread={thread}
149
+ session={session}
150
+ />
151
+ ),
152
+ )
153
+ );
154
+ }
155
+ };
156
+
157
+ const isIncompressible = (stat: DebugSession) => {
158
+ if (stat.threads.some((t) => t.frameCount > 0)) {
159
+ return false;
160
+ }
161
+
162
+ const sub = findSubSessions();
163
+ if (sub.length !== 1) {
164
+ return false;
165
+ }
166
+
167
+ if (!sub[0].compact) {
168
+ return false;
169
+ }
170
+
171
+ return true;
172
+ };
173
+
174
+ if (isIncompressible(session)) {
175
+ const sub = findSubSessions();
176
+ return (
177
+ <div className={styles.debug_stack_item}>
178
+ {sub.map((s) => (
179
+ <DebugStackSessionView key={s.id} viewState={viewState} session={s} indent={1} />
180
+ ))}
181
+ </div>
182
+ );
183
+ }
184
+
185
+ return (
186
+ <div
187
+ className={styles.debug_stack_item}
188
+ onContextMenu={(event: React.MouseEvent<HTMLDivElement, MouseEvent>) =>
189
+ debugCallStackService.handleContextMenu(event, session)
190
+ }
191
+ >
192
+ {mutipleSession && (
193
+ <div
194
+ className={styles.debug_stack_item_label}
195
+ onMouseEnter={() => setHover(true)}
196
+ onMouseLeave={() => setHover(false)}
197
+ >
198
+ {(supportsThreadIdCorrespond || threads.length > 0) && (
199
+ <>
200
+ <div className={unfold ? getIcon('down') : getIcon('right')} onClick={() => setUnfold(!unfold)}></div>
201
+ <div className={cls([getIcon('debug'), styles.debug_session_icon])}></div>
202
+ </>
203
+ )}
204
+ <div className={styles.debug_stack_item_label_title}>{session.label}</div>
205
+ {hover && <DebugStackOperationView session={session} />}
206
+ </div>
207
+ )}
208
+ {supportsThreadIdCorrespond && unfold
209
+ ? multipleThreadPaused.map((t) => (
210
+ <DebugStackThreadView
211
+ key={t.id}
212
+ indent={mutipleSession ? 16 : 0}
213
+ viewState={viewState}
214
+ thread={t}
215
+ session={session}
216
+ />
217
+ ))
218
+ : null}
219
+ {!supportsThreadIdCorrespond &&
220
+ (!mutipleSession || unfold) &&
221
+ threads.map((thread) => (
222
+ <DebugStackThreadView
223
+ key={thread.id}
224
+ indent={mutipleSession ? 16 : 0}
225
+ viewState={viewState}
226
+ thread={thread}
227
+ session={session}
228
+ />
229
+ ))}
230
+ {subSession.length > 0 &&
231
+ subSession.map(
232
+ (s) => unfold && <DebugStackSessionView key={s.id} viewState={viewState} session={s} indent={1} />,
233
+ )}
234
+ {renderLoadMoreThread()}
235
+ </div>
236
+ );
237
+ };
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+
3
+ import { ViewState, getIcon, useInjectable, localize, DisposableCollection } from '@opensumi/ide-core-browser';
4
+
5
+ import { IDebugSessionManager } from '../../../common';
6
+ import { DebugSession } from '../../debug-session';
7
+ import { DebugSessionManager } from '../../debug-session-manager';
8
+ import { DebugThread } from '../../model/debug-thread';
9
+
10
+ import { DebugStackFramesView } from './debug-call-stack-frame.view';
11
+ import styles from './debug-call-stack.module.less';
12
+ import { DebugStackOperationView } from './debug-call-stack.operation';
13
+ import { DebugCallStackService } from './debug-call-stack.service';
14
+
15
+ export interface DebugStackThreadViewProps {
16
+ session: DebugSession;
17
+ viewState: ViewState;
18
+ thread: DebugThread;
19
+ indent?: number;
20
+ }
21
+
22
+ export const DebugStackThreadView = (props: DebugStackThreadViewProps) => {
23
+ const { thread, viewState, indent, session } = props;
24
+ const manager = useInjectable<DebugSessionManager>(IDebugSessionManager);
25
+ const debugCallStackService = useInjectable<DebugCallStackService>(DebugCallStackService);
26
+ const [unfold, setUnfold] = React.useState<boolean>(true);
27
+
28
+ const mutipleS = manager.sessions.length > 1;
29
+ const mutiple = manager.currentSession?.supportsThreadIdCorrespond
30
+ ? true
31
+ : manager.sessions.length > 1 || (manager.sessions[0] && manager.sessions[0].threadCount > 1);
32
+
33
+ React.useEffect(() => {
34
+ const disposable = new DisposableCollection();
35
+
36
+ disposable.push(
37
+ session.onDidChangeCallStack(() => {
38
+ if (thread.stopped && manager.currentThread && manager.currentThread.id === thread.id) {
39
+ setUnfold(true);
40
+ } else {
41
+ setUnfold(false);
42
+ }
43
+ }),
44
+ );
45
+
46
+ return () => {
47
+ disposable.dispose();
48
+ };
49
+ }, []);
50
+
51
+ return (
52
+ <div
53
+ className={styles.debug_stack_item}
54
+ onContextMenu={(event: React.MouseEvent<HTMLDivElement, MouseEvent>) =>
55
+ debugCallStackService.handleContextMenu(event, thread)
56
+ }
57
+ >
58
+ {mutiple && (
59
+ <div style={{ paddingLeft: `${indent}px` }} className={styles.debug_stack_item_label}>
60
+ {thread.frames.length > 0 ? (
61
+ <div className={unfold ? getIcon('down') : getIcon('right')} onClick={() => setUnfold(!unfold)}></div>
62
+ ) : (
63
+ <div style={{ width: 14 }}></div>
64
+ )}
65
+ <div className={styles.debug_threads_item}>{thread.raw.name}</div>
66
+ <>
67
+ <div className={styles.debug_threads_operation}>
68
+ <DebugStackOperationView thread={thread} />
69
+ </div>
70
+ <span className={styles.debug_threads_description}>
71
+ {thread.stopped && thread.stoppedDetails
72
+ ? thread.raw.id === thread.stoppedDetails.threadId
73
+ ? `${localize('debug.stack.frame.because')} ${thread.stoppedDetails.reason} ${localize(
74
+ 'debug.stack.frame.stopped',
75
+ )}`
76
+ : localize('debug.stack.frame.stopped')
77
+ : localize('debug.stack.frame.running')}
78
+ </span>
79
+ </>
80
+ </div>
81
+ )}
82
+ {(!mutiple || unfold) && thread.frames.length > 0 && (
83
+ <DebugStackFramesView
84
+ indent={mutiple ? (mutipleS ? 24 + 14 : 16 + 14) : 8}
85
+ viewState={viewState}
86
+ thread={thread}
87
+ frames={thread.frames}
88
+ session={session}
89
+ />
90
+ )}
91
+ </div>
92
+ );
93
+ };
@@ -0,0 +1,88 @@
1
+ import { Autowired } from '@opensumi/di';
2
+ import { Domain, CommandContribution, CommandRegistry, localize, IClipboardService } from '@opensumi/ide-core-browser';
3
+ import { MenuContribution, IMenuRegistry, MenuId } from '@opensumi/ide-core-browser/lib/menu/next';
4
+
5
+ import { DEBUG_COMMANDS } from '../../debug-contribution';
6
+
7
+ import {
8
+ CONTEXT_CALLSTACK_ITEM_TYPE,
9
+ CONTEXT_RESTART_FRAME_SUPPORTED,
10
+ CONTEXT_STACK_FRAME_SUPPORTS_RESTART,
11
+ } from './../../../common/constants';
12
+ import { IDebugSessionManager } from './../../../common/debug-session';
13
+ import { CallStackContext } from './../../../common/types';
14
+ import { DebugSessionManager } from './../../debug-session-manager';
15
+ import { DebugStackFrame } from './../../model/debug-stack-frame';
16
+ import { DebugThread } from './../../model/debug-thread';
17
+
18
+ function isStackFrameContext(obj: any): obj is CallStackContext {
19
+ return (
20
+ obj && typeof obj.sessionId === 'string' && typeof obj.threadId === 'string' && typeof obj.frameId === 'string'
21
+ );
22
+ }
23
+
24
+ function getFrame(debugService: DebugSessionManager, context: CallStackContext | unknown): DebugStackFrame | undefined {
25
+ if (isStackFrameContext(context)) {
26
+ const session = debugService.getSession(context.sessionId);
27
+ if (session) {
28
+ const thread = [session.currentThread, ...session.threads].find((t: DebugThread) => t.id === context.threadId);
29
+ if (thread) {
30
+ return thread.frames.find((sf: DebugStackFrame) => sf.id === context.frameId);
31
+ }
32
+ }
33
+ }
34
+
35
+ return undefined;
36
+ }
37
+
38
+ @Domain(MenuContribution, CommandContribution)
39
+ export class DebugCallStackContribution implements MenuContribution, CommandContribution {
40
+ @Autowired(IDebugSessionManager)
41
+ protected readonly debugSessionManager: DebugSessionManager;
42
+
43
+ @Autowired(IClipboardService)
44
+ private readonly clipboardService: IClipboardService;
45
+
46
+ registerCommands(registry: CommandRegistry) {
47
+ registry.registerCommand(DEBUG_COMMANDS.RESTART_FRAME, {
48
+ execute: async (_: string, context: CallStackContext) => {
49
+ const frame = getFrame(this.debugSessionManager, context);
50
+ if (frame) {
51
+ await frame.restart();
52
+ }
53
+ },
54
+ });
55
+ registry.registerCommand(DEBUG_COMMANDS.COPY_STACK_TRACE, {
56
+ execute: async (_: string, context: CallStackContext) => {
57
+ const frame = getFrame(this.debugSessionManager, context);
58
+ if (frame) {
59
+ const callStacks = frame.thread.frames.map(
60
+ (e: DebugStackFrame) =>
61
+ `${e.raw && e.raw.name} (${e.raw && e.raw.source && e.raw.source.path}:${e.raw && e.raw.line})`,
62
+ );
63
+ this.clipboardService.writeText(callStacks.join('\n'));
64
+ }
65
+ },
66
+ });
67
+ }
68
+
69
+ registerMenus(registry: IMenuRegistry) {
70
+ registry.registerMenuItem(MenuId.DebugCallStackContext, {
71
+ command: {
72
+ id: DEBUG_COMMANDS.RESTART_FRAME.id,
73
+ label: localize('debugger.menu.restartFrame'),
74
+ },
75
+ when: `${CONTEXT_CALLSTACK_ITEM_TYPE.equalsTo('stackFrame')} && ${CONTEXT_RESTART_FRAME_SUPPORTED.raw}`,
76
+ enabledWhen: CONTEXT_STACK_FRAME_SUPPORTS_RESTART.raw,
77
+ order: 10,
78
+ });
79
+ registry.registerMenuItem(MenuId.DebugCallStackContext, {
80
+ command: {
81
+ id: DEBUG_COMMANDS.COPY_STACK_TRACE.id,
82
+ label: localize('debugger.menu.copyCallstack'),
83
+ },
84
+ when: CONTEXT_CALLSTACK_ITEM_TYPE.equalsTo('stackFrame'),
85
+ order: 20,
86
+ });
87
+ }
88
+ }