@opensumi/ide-debug 2.21.13 → 2.22.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.
- package/lib/browser/breakpoint/breakpoint-manager.js.map +1 -1
- package/lib/browser/breakpoint/breakpoint-marker.d.ts +1 -1
- package/lib/browser/breakpoint/breakpoint-marker.d.ts.map +1 -1
- package/lib/browser/breakpoint/breakpoint-marker.js +3 -2
- package/lib/browser/breakpoint/breakpoint-marker.js.map +1 -1
- package/lib/browser/contextkeys/debug-call-stack-item-type-key.d.ts +1 -1
- package/lib/browser/contextkeys/debug-call-stack-item-type-key.d.ts.map +1 -1
- package/lib/browser/contextkeys/debug-contextkey.service.js.map +1 -1
- package/lib/browser/debug-configuration-manager.d.ts +2 -2
- package/lib/browser/debug-configuration-manager.d.ts.map +1 -1
- package/lib/browser/debug-configuration-manager.js +2 -2
- package/lib/browser/debug-configuration-manager.js.map +1 -1
- package/lib/browser/debug-contribution.d.ts +2 -147
- package/lib/browser/debug-contribution.d.ts.map +1 -1
- package/lib/browser/debug-contribution.js +50 -200
- package/lib/browser/debug-contribution.js.map +1 -1
- package/lib/browser/debug-exception-widget.js.map +1 -1
- package/lib/browser/debug-link-detector.js.map +1 -1
- package/lib/browser/debug-memory.js +4 -4
- package/lib/browser/debug-memory.js.map +1 -1
- package/lib/browser/debug-preferences.d.ts +1 -1
- package/lib/browser/debug-preferences.d.ts.map +1 -1
- package/lib/browser/debug-progress.service.js.map +1 -1
- package/lib/browser/debug-schema-updater.js.map +1 -1
- package/lib/browser/debug-service.js.map +1 -1
- package/lib/browser/debug-session-connection.d.ts +2 -3
- package/lib/browser/debug-session-connection.d.ts.map +1 -1
- package/lib/browser/debug-session-connection.js.map +1 -1
- package/lib/browser/debug-session-contribution.js.map +1 -1
- package/lib/browser/debug-session-manager.d.ts +3 -4
- package/lib/browser/debug-session-manager.d.ts.map +1 -1
- package/lib/browser/debug-session-manager.js +7 -8
- package/lib/browser/debug-session-manager.js.map +1 -1
- package/lib/browser/debug-session.d.ts +3 -4
- package/lib/browser/debug-session.d.ts.map +1 -1
- package/lib/browser/debug-session.js +15 -11
- package/lib/browser/debug-session.js.map +1 -1
- package/lib/browser/debugUtils.js +4 -4
- package/lib/browser/debugUtils.js.map +1 -1
- package/lib/browser/editor/debug-breakpoint-widget.js.map +1 -1
- package/lib/browser/editor/debug-breakpoint-zone-widget.js +7 -7
- package/lib/browser/editor/debug-breakpoint-zone-widget.js.map +1 -1
- package/lib/browser/editor/debug-breakpoint.module.less +3 -4
- package/lib/browser/editor/debug-editor-contribution.d.ts +2 -2
- package/lib/browser/editor/debug-editor-contribution.d.ts.map +1 -1
- package/lib/browser/editor/debug-editor-contribution.js +3 -4
- package/lib/browser/editor/debug-editor-contribution.js.map +1 -1
- package/lib/browser/editor/debug-expression-provider.js.map +1 -1
- package/lib/browser/editor/debug-hover-model.js.map +1 -1
- package/lib/browser/editor/debug-hover-source.d.ts +1 -1
- package/lib/browser/editor/debug-hover-source.d.ts.map +1 -1
- package/lib/browser/editor/debug-hover-source.js.map +1 -1
- package/lib/browser/editor/debug-hover-tree.model.service.js.map +1 -1
- package/lib/browser/editor/debug-hover-widget.js.map +1 -1
- package/lib/browser/editor/debug-model-manager.d.ts +2 -9
- package/lib/browser/editor/debug-model-manager.d.ts.map +1 -1
- package/lib/browser/editor/debug-model-manager.js +8 -15
- package/lib/browser/editor/debug-model-manager.js.map +1 -1
- package/lib/browser/editor/debug-model.d.ts +2 -2
- package/lib/browser/editor/debug-model.d.ts.map +1 -1
- package/lib/browser/editor/debug-model.js +27 -27
- package/lib/browser/editor/debug-model.js.map +1 -1
- package/lib/browser/editor/debug-run-to-cursor.service.js +7 -7
- package/lib/browser/editor/debug-run-to-cursor.service.js.map +1 -1
- package/lib/browser/editor/evaluatable-expression.js.map +1 -1
- package/lib/browser/index.d.ts +0 -14
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +8 -24
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/markers/marker-manager.js.map +1 -1
- package/lib/browser/model/debug-source.d.ts +3 -3
- package/lib/browser/model/debug-source.d.ts.map +1 -1
- package/lib/browser/model/debug-source.js.map +1 -1
- package/lib/browser/model/debug-thread.d.ts +1 -1
- package/lib/browser/model/debug-thread.d.ts.map +1 -1
- package/lib/browser/model/debug-watch.d.ts.map +1 -1
- package/lib/browser/model/debug-watch.js +1 -2
- package/lib/browser/model/debug-watch.js.map +1 -1
- package/lib/browser/preferences/launch-folder-preference-provider.d.ts +2 -2
- package/lib/browser/preferences/launch-folder-preference-provider.d.ts.map +1 -1
- package/lib/browser/preferences/launch-folder-preference-provider.js +2 -2
- package/lib/browser/preferences/launch-folder-preference-provider.js.map +1 -1
- package/lib/browser/preferences/launch-preferences-contribution.js.map +1 -1
- package/lib/browser/tree/debug-console-tree-node.define.js +6 -6
- package/lib/browser/tree/debug-console-tree-node.define.js.map +1 -1
- package/lib/browser/tree/debug-tree-node.define.js +18 -18
- package/lib/browser/tree/debug-tree-node.define.js.map +1 -1
- package/lib/browser/view/breakpoints/debug-breakpoints.service.js +3 -3
- package/lib/browser/view/breakpoints/debug-breakpoints.service.js.map +1 -1
- package/lib/browser/view/configuration/debug-configuration.module.less +5 -5
- package/lib/browser/view/configuration/debug-configuration.service.d.ts +1 -2
- package/lib/browser/view/configuration/debug-configuration.service.d.ts.map +1 -1
- package/lib/browser/view/configuration/debug-configuration.service.js.map +1 -1
- package/lib/browser/view/configuration/debug-configuration.view.d.ts.map +1 -1
- package/lib/browser/view/configuration/debug-configuration.view.js +1 -1
- package/lib/browser/view/configuration/debug-configuration.view.js.map +1 -1
- package/lib/browser/view/configuration/debug-toolbar.service.js.map +1 -1
- package/lib/browser/view/configuration/debug-toolbar.view.js +2 -2
- package/lib/browser/view/configuration/debug-toolbar.view.js.map +1 -1
- package/lib/browser/view/console/debug-console-filter.model.js.map +1 -1
- package/lib/browser/view/console/debug-console-filter.service.js.map +1 -1
- package/lib/browser/view/console/debug-console-model.js.map +1 -1
- package/lib/browser/view/console/debug-console-session.d.ts +3 -2
- package/lib/browser/view/console/debug-console-session.d.ts.map +1 -1
- package/lib/browser/view/console/debug-console-session.js.map +1 -1
- package/lib/browser/view/console/debug-console-tree.model.service.d.ts +1 -1
- package/lib/browser/view/console/debug-console-tree.model.service.d.ts.map +1 -1
- package/lib/browser/view/console/debug-console-tree.model.service.js +5 -3
- package/lib/browser/view/console/debug-console-tree.model.service.js.map +1 -1
- package/lib/browser/view/console/debug-console.contribution.d.ts.map +1 -1
- package/lib/browser/view/console/debug-console.contribution.js +21 -23
- package/lib/browser/view/console/debug-console.contribution.js.map +1 -1
- package/lib/browser/view/console/debug-console.module.less +2 -3
- package/lib/browser/view/console/debug-console.service.js +7 -7
- package/lib/browser/view/console/debug-console.service.js.map +1 -1
- package/lib/browser/view/console/debug-console.view.d.ts +1 -1
- package/lib/browser/view/console/debug-console.view.d.ts.map +1 -1
- package/lib/browser/view/console/debug-console.view.js +15 -3
- package/lib/browser/view/console/debug-console.view.js.map +1 -1
- package/lib/browser/view/debug-view-model.js.map +1 -1
- package/lib/browser/view/frames/debug-call-stack-frame.view.d.ts.map +1 -1
- package/lib/browser/view/frames/debug-call-stack-frame.view.js +25 -24
- package/lib/browser/view/frames/debug-call-stack-frame.view.js.map +1 -1
- package/lib/browser/view/frames/debug-call-stack-session.view.d.ts.map +1 -1
- package/lib/browser/view/frames/debug-call-stack-session.view.js +8 -5
- package/lib/browser/view/frames/debug-call-stack-session.view.js.map +1 -1
- package/lib/browser/view/frames/debug-call-stack-thread.view.d.ts.map +1 -1
- package/lib/browser/view/frames/debug-call-stack-thread.view.js +12 -7
- package/lib/browser/view/frames/debug-call-stack-thread.view.js.map +1 -1
- package/lib/browser/view/frames/debug-call-stack.contribution.js +5 -5
- package/lib/browser/view/frames/debug-call-stack.contribution.js.map +1 -1
- package/lib/browser/view/frames/debug-call-stack.service.js.map +1 -1
- package/lib/browser/view/variables/debug-variables-model.js.map +1 -1
- package/lib/browser/view/variables/debug-variables-tree.model.service.d.ts +1 -1
- package/lib/browser/view/variables/debug-variables-tree.model.service.d.ts.map +1 -1
- package/lib/browser/view/variables/debug-variables-tree.model.service.js +5 -3
- package/lib/browser/view/variables/debug-variables-tree.model.service.js.map +1 -1
- package/lib/browser/view/variables/debug-variables.contribution.d.ts.map +1 -1
- package/lib/browser/view/variables/debug-variables.contribution.js +13 -14
- package/lib/browser/view/variables/debug-variables.contribution.js.map +1 -1
- package/lib/browser/view/variables/debug-variables.module.less +2 -11
- package/lib/browser/view/variables/debug-variables.view.d.ts +1 -1
- package/lib/browser/view/variables/debug-variables.view.d.ts.map +1 -1
- package/lib/browser/view/variables/debug-variables.view.js +1 -1
- package/lib/browser/view/variables/debug-variables.view.js.map +1 -1
- package/lib/browser/view/watch/debug-watch-model.js.map +1 -1
- package/lib/browser/view/watch/debug-watch-tree.model.service.d.ts +2 -2
- package/lib/browser/view/watch/debug-watch-tree.model.service.d.ts.map +1 -1
- package/lib/browser/view/watch/debug-watch-tree.model.service.js +5 -3
- package/lib/browser/view/watch/debug-watch-tree.model.service.js.map +1 -1
- package/lib/browser/view/watch/debug-watch.contribution.d.ts.map +1 -1
- package/lib/browser/view/watch/debug-watch.contribution.js +21 -19
- package/lib/browser/view/watch/debug-watch.contribution.js.map +1 -1
- package/lib/browser/view/watch/debug-watch.module.less +2 -12
- package/lib/browser/view/watch/debug-watch.view.d.ts +1 -1
- package/lib/browser/view/watch/debug-watch.view.d.ts.map +1 -1
- package/lib/browser/view/watch/debug-watch.view.js +1 -1
- package/lib/browser/view/watch/debug-watch.view.js.map +1 -1
- package/lib/common/commands.d.ts +46 -0
- package/lib/common/commands.d.ts.map +1 -0
- package/lib/common/commands.js +149 -0
- package/lib/common/commands.js.map +1 -0
- package/lib/common/debug-breakpoint.d.ts +3 -3
- package/lib/common/debug-breakpoint.d.ts.map +1 -1
- package/lib/common/debug-configuration.d.ts +1 -1
- package/lib/common/debug-configuration.d.ts.map +1 -1
- package/lib/common/debug-console.d.ts +18 -0
- package/lib/common/debug-console.d.ts.map +1 -0
- package/lib/common/debug-console.js +5 -0
- package/lib/common/debug-console.js.map +1 -0
- package/lib/common/debug-editor.d.ts +1 -1
- package/lib/common/debug-editor.d.ts.map +1 -1
- package/lib/common/debug-model.d.ts +19 -4
- package/lib/common/debug-model.d.ts.map +1 -1
- package/lib/common/debug-model.js +14 -6
- package/lib/common/debug-model.js.map +1 -1
- package/lib/common/debug-schema-updater.d.ts +2 -1
- package/lib/common/debug-schema-updater.d.ts.map +1 -1
- package/lib/common/debug-schema-updater.js +1 -1
- package/lib/common/debug-schema-updater.js.map +1 -1
- package/lib/common/debug-service.d.ts +1 -1
- package/lib/common/debug-service.d.ts.map +1 -1
- package/lib/common/debug-session.d.ts +1 -1
- package/lib/common/debug-session.d.ts.map +1 -1
- package/lib/common/index.d.ts +2 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +2 -0
- package/lib/common/index.js.map +1 -1
- package/lib/common/inline-values.d.ts +1 -1
- package/lib/common/inline-values.d.ts.map +1 -1
- package/lib/common/terminal.js +10 -10
- package/lib/common/terminal.js.map +1 -1
- package/package.json +27 -26
- package/src/browser/assets/breakpoint-conditional-disabled.svg +4 -0
- package/src/browser/assets/breakpoint-conditional-unverified.svg +4 -0
- package/src/browser/assets/breakpoint-conditional.svg +4 -0
- package/src/browser/assets/breakpoint-disabled.svg +4 -0
- package/src/browser/assets/breakpoint-hint.svg +4 -0
- package/src/browser/assets/breakpoint-log-disabled.svg +4 -0
- package/src/browser/assets/breakpoint-log-unverified.svg +4 -0
- package/src/browser/assets/breakpoint-log.svg +4 -0
- package/src/browser/assets/breakpoint-unsupported.svg +4 -0
- package/src/browser/assets/breakpoint-unverified.svg +4 -0
- package/src/browser/assets/breakpoint.svg +4 -0
- package/src/browser/assets/breakpoints-activate-inverse.svg +4 -0
- package/src/browser/assets/breakpoints-activate.svg +4 -0
- package/src/browser/assets/configure-inverse.svg +4 -0
- package/src/browser/assets/configure.svg +4 -0
- package/src/browser/assets/continue-inverse.svg +4 -0
- package/src/browser/assets/current-and-breakpoint.svg +4 -0
- package/src/browser/assets/current-arrow.svg +4 -0
- package/src/browser/assets/remove-all-inverse.svg +4 -0
- package/src/browser/assets/remove-all.svg +4 -0
- package/src/browser/assets/repl-inverse.svg +4 -0
- package/src/browser/assets/repl.svg +4 -0
- package/src/browser/assets/restart-inverse.svg +4 -0
- package/src/browser/assets/stackframe-and-breakpoint.svg +4 -0
- package/src/browser/assets/stackframe-arrow.svg +4 -0
- package/src/browser/assets/start-inverse.svg +4 -0
- package/src/browser/breakpoint/breakpoint-decoration.ts +57 -0
- package/src/browser/breakpoint/breakpoint-manager.ts +348 -0
- package/src/browser/breakpoint/breakpoint-marker.ts +70 -0
- package/src/browser/breakpoint/index.ts +3 -0
- package/src/browser/components/debug-action/index.module.less +73 -0
- package/src/browser/components/debug-action/index.tsx +40 -0
- package/src/browser/components/debug-exception-widget.less +42 -0
- package/src/browser/components/floating-click-widget/index.module.less +5 -0
- package/src/browser/components/floating-click-widget/index.tsx +21 -0
- package/src/browser/components/index.ts +1 -0
- package/src/browser/contextkeys/debug-call-stack-item-type-key.ts +4 -0
- package/src/browser/contextkeys/debug-contextkey.service.ts +54 -0
- package/src/browser/contextkeys/index.ts +1 -0
- package/src/browser/debug-ansi-handle.ts +521 -0
- package/src/browser/debug-configuration-manager.ts +514 -0
- package/src/browser/debug-configuration-model.ts +66 -0
- package/src/browser/debug-contribution.ts +756 -0
- package/src/browser/debug-exception-widget.tsx +89 -0
- package/src/browser/debug-link-detector.ts +234 -0
- package/src/browser/debug-memory.ts +220 -0
- package/src/browser/debug-preferences.ts +70 -0
- package/src/browser/debug-progress.service.ts +122 -0
- package/src/browser/debug-schema-updater.ts +67 -0
- package/src/browser/debug-service.ts +42 -0
- package/src/browser/debug-session-connection.ts +331 -0
- package/src/browser/debug-session-contribution.ts +57 -0
- package/src/browser/debug-session-manager.ts +622 -0
- package/src/browser/debug-session.ts +1181 -0
- package/src/browser/debug-style.less +128 -0
- package/src/browser/debugUtils.ts +110 -0
- package/src/browser/editor/debug-breakpoint-widget.ts +99 -0
- package/src/browser/editor/debug-breakpoint-zone-widget.tsx +262 -0
- package/src/browser/editor/debug-breakpoint.module.less +30 -0
- package/src/browser/editor/debug-editor-contribution.ts +589 -0
- package/src/browser/editor/debug-expression-provider.ts +101 -0
- package/src/browser/editor/debug-hover-model.ts +38 -0
- package/src/browser/editor/debug-hover-source.ts +107 -0
- package/src/browser/editor/debug-hover-tree.model.service.ts +332 -0
- package/src/browser/editor/debug-hover-widget.tsx +200 -0
- package/src/browser/editor/debug-hover.module.less +29 -0
- package/src/browser/editor/debug-hover.view.tsx +147 -0
- package/src/browser/editor/debug-model-manager.ts +219 -0
- package/src/browser/editor/debug-model.ts +853 -0
- package/src/browser/editor/debug-run-to-cursor.service.ts +180 -0
- package/src/browser/editor/debug-styles.ts +66 -0
- package/src/browser/editor/evaluatable-expression.ts +47 -0
- package/src/browser/editor/index.ts +6 -0
- package/src/browser/index.ts +119 -0
- package/src/browser/markers/index.ts +2 -0
- package/src/browser/markers/marker-manager.ts +201 -0
- package/src/browser/markers/marker.ts +20 -0
- package/src/browser/model/debug-source.ts +144 -0
- package/src/browser/model/debug-stack-frame.ts +111 -0
- package/src/browser/model/debug-thread.ts +186 -0
- package/src/browser/model/debug-watch.ts +129 -0
- package/src/browser/model/index.ts +4 -0
- package/src/browser/preferences/launch-folder-preference-provider.ts +23 -0
- package/src/browser/preferences/launch-preferences-contribution.ts +9 -0
- package/src/browser/preferences/launch-preferences.ts +16 -0
- package/src/browser/tree/debug-console-tree-node.define.tsx +76 -0
- package/src/browser/tree/debug-tree-node.define.ts +768 -0
- package/src/browser/tree/index.ts +2 -0
- package/src/browser/view/breakpoints/debug-breakpoints.module.less +72 -0
- package/src/browser/view/breakpoints/debug-breakpoints.service.ts +217 -0
- package/src/browser/view/breakpoints/debug-breakpoints.view.tsx +174 -0
- package/src/browser/view/configuration/debug-configuration.module.less +110 -0
- package/src/browser/view/configuration/debug-configuration.service.ts +170 -0
- package/src/browser/view/configuration/debug-configuration.view.tsx +252 -0
- package/src/browser/view/configuration/debug-toolbar.service.ts +167 -0
- package/src/browser/view/configuration/debug-toolbar.view.tsx +335 -0
- package/src/browser/view/console/debug-console-filter.model.ts +49 -0
- package/src/browser/view/console/debug-console-filter.service.ts +81 -0
- package/src/browser/view/console/debug-console-filter.view.tsx +78 -0
- package/src/browser/view/console/debug-console-model.ts +48 -0
- package/src/browser/view/console/debug-console-session.ts +165 -0
- package/src/browser/view/console/debug-console-toolbar.view.tsx +28 -0
- package/src/browser/view/console/debug-console-tree.model.service.ts +553 -0
- package/src/browser/view/console/debug-console.contribution.ts +179 -0
- package/src/browser/view/console/debug-console.module.less +371 -0
- package/src/browser/view/console/debug-console.service.ts +433 -0
- package/src/browser/view/console/debug-console.view.tsx +511 -0
- package/src/browser/view/debug-view-model.ts +182 -0
- package/src/browser/view/frames/debug-call-stack-frame.view.tsx +230 -0
- package/src/browser/view/frames/debug-call-stack-session.view.tsx +253 -0
- package/src/browser/view/frames/debug-call-stack-thread.view.tsx +103 -0
- package/src/browser/view/frames/debug-call-stack.contribution.ts +88 -0
- package/src/browser/view/frames/debug-call-stack.module.less +193 -0
- package/src/browser/view/frames/debug-call-stack.operation.tsx +97 -0
- package/src/browser/view/frames/debug-call-stack.service.ts +105 -0
- package/src/browser/view/frames/debug-call-stack.view.tsx +43 -0
- package/src/browser/view/variables/debug-variables-model.ts +38 -0
- package/src/browser/view/variables/debug-variables-tree.model.service.ts +470 -0
- package/src/browser/view/variables/debug-variables.contribution.ts +244 -0
- package/src/browser/view/variables/debug-variables.module.less +139 -0
- package/src/browser/view/variables/debug-variables.view.tsx +303 -0
- package/src/browser/view/watch/debug-watch-model.ts +38 -0
- package/src/browser/view/watch/debug-watch-tree.model.service.ts +570 -0
- package/src/browser/view/watch/debug-watch.contribution.ts +170 -0
- package/src/browser/view/watch/debug-watch.module.less +178 -0
- package/src/browser/view/watch/debug-watch.view.tsx +337 -0
- package/src/common/commands.ts +146 -0
- package/src/common/constants.ts +81 -0
- package/src/common/debug-breakpoint.ts +43 -0
- package/src/common/debug-configuration.ts +68 -0
- package/src/common/debug-console.ts +20 -0
- package/src/common/debug-editor.ts +4 -0
- package/src/common/debug-hover.ts +31 -0
- package/src/common/debug-model.ts +272 -0
- package/src/common/debug-progress.ts +8 -0
- package/src/common/debug-schema-updater.ts +3 -0
- package/src/common/debug-service.ts +176 -0
- package/src/common/debug-session-options.ts +19 -0
- package/src/common/debug-session.ts +200 -0
- package/src/common/evaluatable-expression.ts +43 -0
- package/src/common/index.ts +16 -0
- package/src/common/inline-values.ts +77 -0
- package/src/common/terminal.ts +163 -0
- package/src/common/types.ts +86 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,1181 @@
|
|
|
1
|
+
import debounce from 'lodash/debounce';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Emitter,
|
|
5
|
+
Event,
|
|
6
|
+
URI,
|
|
7
|
+
DisposableCollection,
|
|
8
|
+
Deferred,
|
|
9
|
+
IDisposable,
|
|
10
|
+
IPosition,
|
|
11
|
+
Mutable,
|
|
12
|
+
canceled,
|
|
13
|
+
localize,
|
|
14
|
+
} from '@opensumi/ide-core-browser';
|
|
15
|
+
import { LabelService } from '@opensumi/ide-core-browser/lib/services';
|
|
16
|
+
import {
|
|
17
|
+
CancellationTokenSource,
|
|
18
|
+
CancellationToken,
|
|
19
|
+
Disposable,
|
|
20
|
+
Schemes,
|
|
21
|
+
getLanguageId,
|
|
22
|
+
isDefined,
|
|
23
|
+
} from '@opensumi/ide-core-common';
|
|
24
|
+
import { WorkbenchEditorService } from '@opensumi/ide-editor';
|
|
25
|
+
import { IFileServiceClient } from '@opensumi/ide-file-service';
|
|
26
|
+
import { IMessageService } from '@opensumi/ide-overlay';
|
|
27
|
+
import { ITerminalApiService, TerminalOptions } from '@opensumi/ide-terminal-next';
|
|
28
|
+
import { DebugProtocol } from '@opensumi/vscode-debugprotocol';
|
|
29
|
+
|
|
30
|
+
import {
|
|
31
|
+
DebugSessionOptions,
|
|
32
|
+
IDebugSessionDTO,
|
|
33
|
+
IDebugSession,
|
|
34
|
+
IDebugSessionManager,
|
|
35
|
+
DEBUG_REPORT_NAME,
|
|
36
|
+
DebugState,
|
|
37
|
+
DebugEventTypes,
|
|
38
|
+
DebugRequestTypes,
|
|
39
|
+
DebugExitEvent,
|
|
40
|
+
IRuntimeBreakpoint,
|
|
41
|
+
BreakpointsChangeEvent,
|
|
42
|
+
IDebugBreakpoint,
|
|
43
|
+
IMemoryRegion,
|
|
44
|
+
prepareCommand,
|
|
45
|
+
} from '../common';
|
|
46
|
+
import { DebugConfiguration } from '../common';
|
|
47
|
+
|
|
48
|
+
import { DebugEditor } from './../common/debug-editor';
|
|
49
|
+
import { IDebugModel, IDebugModelManager, MemoryRegion } from './../common/debug-model';
|
|
50
|
+
import { BreakpointManager, DebugBreakpoint } from './breakpoint';
|
|
51
|
+
import { DebugSessionConnection } from './debug-session-connection';
|
|
52
|
+
import { DebugSource } from './model/debug-source';
|
|
53
|
+
import { DebugStackFrame } from './model/debug-stack-frame';
|
|
54
|
+
import { StoppedDetails, DebugThread, DebugThreadData } from './model/debug-thread';
|
|
55
|
+
import { ExpressionContainer } from './tree/debug-tree-node.define';
|
|
56
|
+
|
|
57
|
+
export class DebugSession implements IDebugSession {
|
|
58
|
+
protected readonly onDidChangeEmitter = new Emitter<void>();
|
|
59
|
+
readonly onDidChange: Event<void> = this.onDidChangeEmitter.event;
|
|
60
|
+
public fireDidChange(): void {
|
|
61
|
+
this.onDidChangeEmitter.fire(undefined);
|
|
62
|
+
this.onStateChange();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private readonly _onDidChangeCallStack = new Emitter<void>();
|
|
66
|
+
readonly onDidChangeCallStack: Event<void> = this._onDidChangeCallStack.event;
|
|
67
|
+
|
|
68
|
+
private readonly _onVariableChange = new Emitter<void>();
|
|
69
|
+
readonly onVariableChange: Event<void> = this._onVariableChange.event;
|
|
70
|
+
|
|
71
|
+
private readonly _onCurrentThreadChange = new Emitter<DebugThread | undefined>();
|
|
72
|
+
readonly onCurrentThreadChange: Event<DebugThread | undefined> = this._onCurrentThreadChange.event;
|
|
73
|
+
|
|
74
|
+
private readonly _onDidStop = new Emitter<DebugProtocol.StoppedEvent>();
|
|
75
|
+
readonly onDidStop: Event<DebugProtocol.StoppedEvent> = this._onDidStop.event;
|
|
76
|
+
|
|
77
|
+
private readonly _onDidContinued = new Emitter<DebugProtocol.ContinuedEvent>();
|
|
78
|
+
readonly onDidContinued: Event<DebugProtocol.ContinuedEvent> = this._onDidContinued.event;
|
|
79
|
+
|
|
80
|
+
private readonly _onDidThread = new Emitter<DebugProtocol.ThreadEvent>();
|
|
81
|
+
readonly onDidThread: Event<DebugProtocol.ThreadEvent> = this._onDidThread.event;
|
|
82
|
+
|
|
83
|
+
private readonly _onRequest = new Emitter<keyof DebugRequestTypes>();
|
|
84
|
+
readonly onRequest: Event<keyof DebugRequestTypes> = this._onRequest.event;
|
|
85
|
+
|
|
86
|
+
private readonly _onDidExitAdapter = new Emitter<void>();
|
|
87
|
+
readonly onDidExitAdapter: Event<void> = this._onDidExitAdapter.event;
|
|
88
|
+
|
|
89
|
+
private readonly _onDidProgressStart = new Emitter<DebugProtocol.ProgressStartEvent>();
|
|
90
|
+
readonly onDidProgressStart: Event<DebugProtocol.ProgressStartEvent> = this._onDidProgressStart.event;
|
|
91
|
+
|
|
92
|
+
private readonly _onDidProgressUpdate = new Emitter<DebugProtocol.ProgressUpdateEvent>();
|
|
93
|
+
readonly onDidProgressUpdate: Event<DebugProtocol.ProgressUpdateEvent> = this._onDidProgressUpdate.event;
|
|
94
|
+
|
|
95
|
+
private readonly _onDidProgressEnd = new Emitter<DebugProtocol.ProgressEndEvent>();
|
|
96
|
+
readonly onDidProgressEnd: Event<DebugProtocol.ProgressEndEvent> = this._onDidProgressEnd.event;
|
|
97
|
+
|
|
98
|
+
private readonly _onDidInvalidated = new Emitter<DebugProtocol.InvalidatedEvent>();
|
|
99
|
+
readonly onDidInvalidated: Event<DebugProtocol.InvalidatedEvent> = this._onDidInvalidated.event;
|
|
100
|
+
|
|
101
|
+
private readonly _onDidChangeState = new Emitter<DebugState>();
|
|
102
|
+
readonly onDidChangeState: Event<DebugState> = this._onDidChangeState.event;
|
|
103
|
+
|
|
104
|
+
private readonly _onDidInvalidMemory = new Emitter<DebugProtocol.MemoryEvent>();
|
|
105
|
+
readonly onDidInvalidateMemory: Event<DebugProtocol.MemoryEvent> = this._onDidInvalidMemory.event;
|
|
106
|
+
|
|
107
|
+
protected readonly toDispose = new DisposableCollection();
|
|
108
|
+
|
|
109
|
+
protected _capabilities: DebugProtocol.Capabilities = {};
|
|
110
|
+
|
|
111
|
+
get capabilities(): DebugProtocol.Capabilities {
|
|
112
|
+
return this._capabilities;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get supportsThreadIdCorrespond(): boolean {
|
|
116
|
+
return !!this.capabilities.supportsThreadIdCorrespond;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
protected updateDeffered: Deferred<void> | null = null;
|
|
120
|
+
|
|
121
|
+
protected exitDeferred = new Deferred<DebugExitEvent>();
|
|
122
|
+
|
|
123
|
+
protected cancellationMap = new Map<number, CancellationTokenSource[]>();
|
|
124
|
+
protected readonly toDisposeOnCurrentThread = new DisposableCollection();
|
|
125
|
+
protected previousState: DebugState | undefined;
|
|
126
|
+
protected stoppedDetails: StoppedDetails | undefined;
|
|
127
|
+
|
|
128
|
+
constructor(
|
|
129
|
+
readonly id: string,
|
|
130
|
+
readonly options: DebugSessionOptions,
|
|
131
|
+
protected readonly connection: DebugSessionConnection,
|
|
132
|
+
protected readonly terminalService: ITerminalApiService,
|
|
133
|
+
protected readonly workbenchEditorService: WorkbenchEditorService,
|
|
134
|
+
protected readonly breakpointManager: BreakpointManager,
|
|
135
|
+
protected readonly modelManager: IDebugModelManager,
|
|
136
|
+
protected readonly labelProvider: LabelService,
|
|
137
|
+
protected readonly messages: IMessageService,
|
|
138
|
+
protected readonly fileSystem: IFileServiceClient,
|
|
139
|
+
protected readonly sessionManager: IDebugSessionManager,
|
|
140
|
+
) {
|
|
141
|
+
this.connection.onRequest(
|
|
142
|
+
'runInTerminal',
|
|
143
|
+
async (request: DebugProtocol.RunInTerminalRequest) => await this.runInTerminal(request),
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
this.toDispose.pushAll([
|
|
147
|
+
this.onDidChangeEmitter,
|
|
148
|
+
this.connection,
|
|
149
|
+
// 返回调试配置
|
|
150
|
+
this.on('initialized', () => {
|
|
151
|
+
this.configure();
|
|
152
|
+
}),
|
|
153
|
+
// 更新断点
|
|
154
|
+
this.on('breakpoint', ({ body }) => this.onUpdateBreakpoint(body)),
|
|
155
|
+
this.on('continued', async (event: DebugProtocol.ContinuedEvent) => {
|
|
156
|
+
const {
|
|
157
|
+
body: { allThreadsContinued, threadId },
|
|
158
|
+
} = event;
|
|
159
|
+
this.handleCancellation(threadId);
|
|
160
|
+
if (this.supportsThreadIdCorrespond) {
|
|
161
|
+
if (threadId) {
|
|
162
|
+
this._multipleThreadPaused.delete(threadId);
|
|
163
|
+
} else if (allThreadsContinued !== false) {
|
|
164
|
+
this._multipleThreadPaused.clear();
|
|
165
|
+
}
|
|
166
|
+
await this.updateCurrentThread();
|
|
167
|
+
this._onDidContinued.fire(event);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 更新线程
|
|
172
|
+
if (allThreadsContinued !== false) {
|
|
173
|
+
this.clearThreads();
|
|
174
|
+
this._onDidContinued.fire(event);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (isDefined(threadId)) {
|
|
179
|
+
this.clearThread(threadId);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
this.onStateChange();
|
|
183
|
+
this._onDidContinued.fire(event);
|
|
184
|
+
}),
|
|
185
|
+
this.on('stopped', async (event: DebugProtocol.StoppedEvent) => {
|
|
186
|
+
const { body } = event;
|
|
187
|
+
this.stoppedDetails = body;
|
|
188
|
+
|
|
189
|
+
const { threadId } = body;
|
|
190
|
+
const reportTime = this.sessionManager.reportTime(DEBUG_REPORT_NAME.DEBUG_STOPPED, {
|
|
191
|
+
sessionId: this.id,
|
|
192
|
+
threadId,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
if (this.supportsThreadIdCorrespond === true) {
|
|
196
|
+
await this.collectPausedThread(body);
|
|
197
|
+
if (body.threadId && this._multipleThreadPaused.has(body.threadId)) {
|
|
198
|
+
const pauseThread = this._multipleThreadPaused.get(body.threadId);
|
|
199
|
+
await this.updateCurrentThread(pauseThread);
|
|
200
|
+
await this.updateCurrentThreadFramesOnFocus();
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
this.updateDeffered = new Deferred();
|
|
204
|
+
await this.updateThreads(body);
|
|
205
|
+
await this.updateCurrentThreadFramesOnFocus();
|
|
206
|
+
this.updateDeffered.resolve();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
reportTime('stopped');
|
|
210
|
+
// action 结束后需要清除
|
|
211
|
+
const extra = this.sessionManager.getExtra(this.id, threadId);
|
|
212
|
+
if (threadId && extra && extra.action) {
|
|
213
|
+
extra.action = undefined;
|
|
214
|
+
this.sessionManager.setExtra(this.id, `${threadId ?? ''}`, extra);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
this.onStateChange();
|
|
218
|
+
this._onDidStop.fire(event);
|
|
219
|
+
}),
|
|
220
|
+
this.on('thread', (event: DebugProtocol.ThreadEvent) => {
|
|
221
|
+
const {
|
|
222
|
+
body: { reason, threadId },
|
|
223
|
+
} = event;
|
|
224
|
+
|
|
225
|
+
if (this.supportsThreadIdCorrespond) {
|
|
226
|
+
// 当 supportsThreadIdCorrespond 开启的时候,只有在 DebugState 为 Stopped 的时候才发送 thread dap 事件
|
|
227
|
+
if (this.state === DebugState.Stopped) {
|
|
228
|
+
this._onDidThread.fire(event);
|
|
229
|
+
}
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (reason === 'started') {
|
|
234
|
+
// 队列更新线程
|
|
235
|
+
this.scheduleUpdateThreads();
|
|
236
|
+
} else if (reason === 'exited') {
|
|
237
|
+
// 清理线程数据
|
|
238
|
+
this.clearThread(threadId);
|
|
239
|
+
}
|
|
240
|
+
this._onDidThread.fire(event);
|
|
241
|
+
}),
|
|
242
|
+
this.on('terminated', () => {
|
|
243
|
+
this.terminated = true;
|
|
244
|
+
}),
|
|
245
|
+
this.on('exited', (reason) => {
|
|
246
|
+
this.exitDeferred.resolve(reason);
|
|
247
|
+
}),
|
|
248
|
+
this.on('progressStart', (event: DebugProtocol.ProgressStartEvent) => {
|
|
249
|
+
this._onDidProgressStart.fire(event);
|
|
250
|
+
}),
|
|
251
|
+
this.on('progressUpdate', (event: DebugProtocol.ProgressUpdateEvent) => {
|
|
252
|
+
this._onDidProgressUpdate.fire(event);
|
|
253
|
+
}),
|
|
254
|
+
this.on('progressEnd', (event: DebugProtocol.ProgressEndEvent) => {
|
|
255
|
+
this._onDidProgressEnd.fire(event);
|
|
256
|
+
}),
|
|
257
|
+
this.on('memory', (event: DebugProtocol.MemoryEvent) => {
|
|
258
|
+
this._onDidInvalidMemory.fire(event);
|
|
259
|
+
}),
|
|
260
|
+
this.on('invalidated', async (event: DebugProtocol.InvalidatedEvent) => {
|
|
261
|
+
this._onDidInvalidated.fire(event);
|
|
262
|
+
|
|
263
|
+
if (
|
|
264
|
+
!(
|
|
265
|
+
event.body.areas &&
|
|
266
|
+
event.body.areas.length === 1 &&
|
|
267
|
+
(event.body.areas[0] === 'variables' || event.body.areas[0] === 'watch')
|
|
268
|
+
)
|
|
269
|
+
) {
|
|
270
|
+
this.cancelAllRequests();
|
|
271
|
+
this.clearThreads();
|
|
272
|
+
await this.updateThreads(this.stoppedDetails);
|
|
273
|
+
}
|
|
274
|
+
this.fireDidChange();
|
|
275
|
+
}),
|
|
276
|
+
this.on('capabilities', (event) => this.updateCapabilities(event.body.capabilities)),
|
|
277
|
+
this.breakpointManager.onDidChangeBreakpoints((event) => this.runtimeUpdateBreakpoint(event)),
|
|
278
|
+
this.breakpointManager.onDidChangeExceptionsBreakpoints((args) => {
|
|
279
|
+
if (this.breakpointManager.breakpointsEnabled) {
|
|
280
|
+
this.setExceptionBreakpoints(args);
|
|
281
|
+
}
|
|
282
|
+
}),
|
|
283
|
+
Disposable.create(() => {
|
|
284
|
+
// 清除断点的运行时状态
|
|
285
|
+
this.breakpointManager.clearAllStatus(this.id);
|
|
286
|
+
}),
|
|
287
|
+
]);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
getMemory(memoryReference: string): IMemoryRegion {
|
|
291
|
+
return new MemoryRegion(memoryReference, this);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
get configuration(): DebugConfiguration {
|
|
295
|
+
return this.options.configuration;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
get parentSession(): IDebugSession | undefined {
|
|
299
|
+
return this.options.parentSession;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
get lifecycleManagedByParent(): boolean | undefined {
|
|
303
|
+
return this.options.lifecycleManagedByParent;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
get compact(): boolean {
|
|
307
|
+
return !!this.options.compact;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async start(): Promise<void> {
|
|
311
|
+
await this.workbenchEditorService.saveAll();
|
|
312
|
+
await this.initialize();
|
|
313
|
+
await this.launchOrAttach();
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
protected async runInTerminal({
|
|
317
|
+
arguments: { title, cwd, args, env },
|
|
318
|
+
}: DebugProtocol.RunInTerminalRequest): Promise<DebugProtocol.RunInTerminalResponse['body']> {
|
|
319
|
+
return this.doRunInTerminal({ name: title, cwd, env, args });
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
protected async doRunInTerminal(options: TerminalOptions): Promise<DebugProtocol.RunInTerminalResponse['body']> {
|
|
323
|
+
const activeTerminal = this.terminalService.terminals.find(
|
|
324
|
+
(terminal) => terminal.name === options.name && terminal.isActive,
|
|
325
|
+
);
|
|
326
|
+
let processId: number | undefined;
|
|
327
|
+
const shellPath = await this.terminalService.getDefaultShellPath();
|
|
328
|
+
const command = prepareCommand(shellPath, options.args, false, options.cwd?.toString(), options.env);
|
|
329
|
+
// 当存在同名终端并且处于激活状态时,复用该终端
|
|
330
|
+
if (activeTerminal) {
|
|
331
|
+
if (command) {
|
|
332
|
+
this.terminalService.sendText(activeTerminal.id, command);
|
|
333
|
+
}
|
|
334
|
+
processId = await this.terminalService.getProcessId(activeTerminal.id);
|
|
335
|
+
} else {
|
|
336
|
+
const terminal = await this.terminalService.createTerminal(options);
|
|
337
|
+
terminal.show();
|
|
338
|
+
if (command) {
|
|
339
|
+
this.terminalService.sendText(terminal.id, command);
|
|
340
|
+
processId = await this.terminalService.getProcessId(terminal.id);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return { processId };
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
protected async initialize(): Promise<void> {
|
|
347
|
+
const response = await this.connection.sendRequest(
|
|
348
|
+
'initialize',
|
|
349
|
+
{
|
|
350
|
+
clientID: 'OpenSumi',
|
|
351
|
+
clientName: 'OpenSumi IDE',
|
|
352
|
+
adapterID: this.configuration.type,
|
|
353
|
+
locale: getLanguageId(),
|
|
354
|
+
linesStartAt1: true,
|
|
355
|
+
columnsStartAt1: true,
|
|
356
|
+
pathFormat: 'path',
|
|
357
|
+
supportsVariableType: false,
|
|
358
|
+
supportsVariablePaging: false,
|
|
359
|
+
supportsRunInTerminalRequest: true,
|
|
360
|
+
supportsProgressReporting: true,
|
|
361
|
+
supportsInvalidatedEvent: true,
|
|
362
|
+
supportsMemoryEvent: true,
|
|
363
|
+
supportsMemoryReferences: true,
|
|
364
|
+
},
|
|
365
|
+
this.configuration,
|
|
366
|
+
);
|
|
367
|
+
this.updateCapabilities(response.body || {});
|
|
368
|
+
this.onStateChange();
|
|
369
|
+
}
|
|
370
|
+
protected async launchOrAttach(): Promise<void> {
|
|
371
|
+
if (this.parentSession && this.parentSession.state === DebugState.Inactive) {
|
|
372
|
+
throw canceled();
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
if (this.configuration.request === 'attach') {
|
|
377
|
+
await this.sendRequest('attach', this.configuration);
|
|
378
|
+
} else {
|
|
379
|
+
await this.sendRequest('launch', this.configuration);
|
|
380
|
+
}
|
|
381
|
+
} catch (reason) {
|
|
382
|
+
this.fireExited(reason);
|
|
383
|
+
this.messages.error(reason.message || reason.body?.error.format || localize('debug.console.errorMessage'));
|
|
384
|
+
throw reason && reason.message;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
protected initialized = false;
|
|
388
|
+
|
|
389
|
+
protected async configure(): Promise<void> {
|
|
390
|
+
await this.initBreakpoints();
|
|
391
|
+
// 更新exceptionBreakpoint配置
|
|
392
|
+
this.breakpointManager.setExceptionBreakpoints(this.capabilities.exceptionBreakpointFilters || []);
|
|
393
|
+
if (this.capabilities.supportsConfigurationDoneRequest) {
|
|
394
|
+
await this.sendRequest('configurationDone', {});
|
|
395
|
+
}
|
|
396
|
+
this.initialized = true;
|
|
397
|
+
if (!this.supportsThreadIdCorrespond) {
|
|
398
|
+
await this.updateThreads(undefined);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
protected async setExceptionBreakpoints(
|
|
403
|
+
args: DebugProtocol.SetExceptionBreakpointsArguments,
|
|
404
|
+
): Promise<DebugProtocol.SetExceptionBreakpointsResponse> {
|
|
405
|
+
return this.sendRequest('setExceptionBreakpoints', args);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
protected onStateChange(): void {
|
|
409
|
+
const state = this.state;
|
|
410
|
+
if (this.previousState !== state) {
|
|
411
|
+
this.previousState = state;
|
|
412
|
+
this._onDidChangeState.fire(state);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* runtime 时候的临时缓存,每次调试的时候都应该清空,
|
|
418
|
+
* 会等待首次初始化完成
|
|
419
|
+
*/
|
|
420
|
+
protected id2Breakpoint = new Map<number, IDebugBreakpoint>();
|
|
421
|
+
/**
|
|
422
|
+
* 运行时的断点修改
|
|
423
|
+
* TODO:// 待重构 @Ricbet
|
|
424
|
+
* @param body
|
|
425
|
+
*/
|
|
426
|
+
protected async onUpdateBreakpoint(body: DebugProtocol.BreakpointEvent['body']): Promise<void> {
|
|
427
|
+
let breakpoint: IDebugBreakpoint | undefined;
|
|
428
|
+
if (this.settingBreakpoints) {
|
|
429
|
+
await this.settingBreakpoints.promise;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
try {
|
|
433
|
+
const raw = body.breakpoint;
|
|
434
|
+
switch (body.reason) {
|
|
435
|
+
case 'new':
|
|
436
|
+
if (raw.source && typeof raw.line === 'number' && raw.id && !this.id2Breakpoint.has(raw.id)) {
|
|
437
|
+
const uri = DebugSource.toUri(raw.source);
|
|
438
|
+
const bp = DebugBreakpoint.create(uri, { line: raw.line, column: raw.column });
|
|
439
|
+
bp.status.set(this.id, raw);
|
|
440
|
+
this.addBreakpoint(bp);
|
|
441
|
+
}
|
|
442
|
+
break;
|
|
443
|
+
case 'removed':
|
|
444
|
+
if (raw.id) {
|
|
445
|
+
breakpoint = this.id2Breakpoint.get(raw.id);
|
|
446
|
+
if (breakpoint) {
|
|
447
|
+
this.delBreakpoint(breakpoint);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
break;
|
|
451
|
+
case 'changed':
|
|
452
|
+
if (raw.id) {
|
|
453
|
+
breakpoint = this.id2Breakpoint.get(raw.id);
|
|
454
|
+
if (breakpoint) {
|
|
455
|
+
(breakpoint as IRuntimeBreakpoint).status.set(this.id, raw);
|
|
456
|
+
this.breakpointManager.updateBreakpoint(breakpoint, true);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
break;
|
|
460
|
+
default:
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
} finally {
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
private async setBreakpoints(affected: URI[]) {
|
|
468
|
+
const promises: Promise<void>[] = [];
|
|
469
|
+
for (const uri of affected) {
|
|
470
|
+
const source = await this.toSource(uri);
|
|
471
|
+
const enableds = this.breakpointManager
|
|
472
|
+
.getBreakpoints(uri)
|
|
473
|
+
.filter((b) => this.breakpointManager.breakpointsEnabled && b.enabled);
|
|
474
|
+
promises.push(
|
|
475
|
+
this.sendRequest('setBreakpoints', {
|
|
476
|
+
source: source.raw,
|
|
477
|
+
sourceModified: false,
|
|
478
|
+
lines: enableds.map((breakpoint) => breakpoint.raw.line),
|
|
479
|
+
breakpoints: enableds.map((breakpoint) => breakpoint.raw),
|
|
480
|
+
})
|
|
481
|
+
.then((res) => {
|
|
482
|
+
res.body.breakpoints.forEach((status, index) => {
|
|
483
|
+
if (status.id) {
|
|
484
|
+
this.id2Breakpoint.set(status.id, enableds[index]);
|
|
485
|
+
}
|
|
486
|
+
const enabledBp = enableds[index] as IRuntimeBreakpoint;
|
|
487
|
+
enabledBp.raw.line = status.line ?? enabledBp.raw.line;
|
|
488
|
+
enabledBp.raw.column = status.column ?? enabledBp.raw.column;
|
|
489
|
+
enabledBp.status.set(this.id, status);
|
|
490
|
+
});
|
|
491
|
+
this.breakpointManager.updateBreakpoints(enableds, true);
|
|
492
|
+
this.breakpointManager.resolveBpDeffered();
|
|
493
|
+
return Promise.resolve();
|
|
494
|
+
})
|
|
495
|
+
.catch((error) => {
|
|
496
|
+
if (!(error instanceof Error)) {
|
|
497
|
+
const genericMessage = 'Breakpoint not valid for current debug session';
|
|
498
|
+
const message: string = error.message ? `${error.message}` : genericMessage;
|
|
499
|
+
enableds.forEach((breakpoint) => {
|
|
500
|
+
(breakpoint as IRuntimeBreakpoint).status.set(this.id, { verified: false, message });
|
|
501
|
+
this.breakpointManager.updateBreakpoint(breakpoint, true);
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}),
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return await Promise.all(promises);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
public delBreakpoint(breakpoint: IDebugBreakpoint): boolean {
|
|
512
|
+
return this.breakpointManager.delBreakpoint(breakpoint);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
public async addBreakpoint(breakpoint: IDebugBreakpoint, isBpDeferred?: boolean): Promise<void> {
|
|
516
|
+
if (isBpDeferred) {
|
|
517
|
+
this.breakpointManager.setBpDeffered();
|
|
518
|
+
}
|
|
519
|
+
this.breakpointManager.addBreakpoint(breakpoint);
|
|
520
|
+
return this.breakpointManager.promiseBpDeffered();
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* 运行时修改断点信息
|
|
525
|
+
*/
|
|
526
|
+
async runtimeUpdateBreakpoint(event: BreakpointsChangeEvent): Promise<void[] | undefined> {
|
|
527
|
+
const { affected, statusUpdated } = event;
|
|
528
|
+
|
|
529
|
+
if (statusUpdated) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return await this.setBreakpoints(affected);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* 初始化断点信息的锁
|
|
538
|
+
*/
|
|
539
|
+
protected settingBreakpoints: Deferred<void> | null = null;
|
|
540
|
+
/**
|
|
541
|
+
* 初始化加载用户的断点信息
|
|
542
|
+
*/
|
|
543
|
+
protected async initBreakpoints() {
|
|
544
|
+
this.settingBreakpoints = new Deferred();
|
|
545
|
+
this.id2Breakpoint.clear();
|
|
546
|
+
|
|
547
|
+
// 当配置为noDebug时,仅运行程序,不设置断点
|
|
548
|
+
if (!this.configuration.noDebug) {
|
|
549
|
+
await this.setBreakpoints(this.breakpointManager.affected.map((str) => URI.parse(str)));
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
this.settingBreakpoints.resolve();
|
|
553
|
+
this.settingBreakpoints = null;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
protected _currentThread: DebugThread | undefined;
|
|
557
|
+
protected _multipleThreadPaused: Map<number, DebugThread> = new Map();
|
|
558
|
+
|
|
559
|
+
get currentThread(): DebugThread | undefined {
|
|
560
|
+
return this._currentThread;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
set currentThread(thread: DebugThread | undefined) {
|
|
564
|
+
this.toDisposeOnCurrentThread.dispose();
|
|
565
|
+
this._currentThread = thread;
|
|
566
|
+
if (thread) {
|
|
567
|
+
this.toDisposeOnCurrentThread.push(thread.onDidChanged(() => this.fireDidChange()));
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
get multipleThreadPaused(): Map<number, DebugThread> {
|
|
572
|
+
return this._multipleThreadPaused;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
public hasInMultipleThreadPaused(id: number): boolean {
|
|
576
|
+
return this._multipleThreadPaused.has(id);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
protected clearThreads(): void {
|
|
580
|
+
const frontEndTime = this.sessionManager.reportTime(DEBUG_REPORT_NAME.DEBUG_UI_FRONTEND_TIME, {
|
|
581
|
+
sessionId: this.id,
|
|
582
|
+
threadId: this.currentThread?.id,
|
|
583
|
+
threadAmount: this.threadCount,
|
|
584
|
+
});
|
|
585
|
+
this._threads.forEach((thread: DebugThread) => {
|
|
586
|
+
thread.clear();
|
|
587
|
+
});
|
|
588
|
+
this._onDidChangeCallStack.fire();
|
|
589
|
+
this.collocationThread();
|
|
590
|
+
frontEndTime('clearThreads');
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
protected clearThread(threadId: number): void {
|
|
594
|
+
const frontEndTime = this.sessionManager.reportTime(DEBUG_REPORT_NAME.DEBUG_UI_FRONTEND_TIME, {
|
|
595
|
+
sessionId: this.id,
|
|
596
|
+
threadId,
|
|
597
|
+
threadAmount: this.threadCount,
|
|
598
|
+
});
|
|
599
|
+
const thread: DebugThread | undefined = this._threads.get(threadId);
|
|
600
|
+
if (thread) {
|
|
601
|
+
thread.clear();
|
|
602
|
+
this._onDidChangeCallStack.fire();
|
|
603
|
+
}
|
|
604
|
+
this.collocationThread();
|
|
605
|
+
frontEndTime('clearThread');
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
get state(): DebugState {
|
|
609
|
+
if (this.connection.disposed) {
|
|
610
|
+
return DebugState.Inactive;
|
|
611
|
+
}
|
|
612
|
+
if (!this.initialized) {
|
|
613
|
+
return DebugState.Initializing;
|
|
614
|
+
}
|
|
615
|
+
const thread = this.currentThread;
|
|
616
|
+
if (thread) {
|
|
617
|
+
return thread.stopped ? DebugState.Stopped : DebugState.Running;
|
|
618
|
+
} else if (this.supportsThreadIdCorrespond) {
|
|
619
|
+
return DebugState.Running;
|
|
620
|
+
}
|
|
621
|
+
return this.stoppedThreads.next().value ? DebugState.Stopped : DebugState.Running;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
get currentFrame(): DebugStackFrame | undefined {
|
|
625
|
+
return this.currentThread && this.currentThread.currentFrame;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
async getScopes(parent?: ExpressionContainer): Promise<any[]> {
|
|
629
|
+
const { currentFrame } = this;
|
|
630
|
+
return currentFrame ? currentFrame.getScopes(parent) : [];
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
get label(): string {
|
|
634
|
+
if (IDebugSessionDTO.is(this.options) && this.options.id) {
|
|
635
|
+
return this.configuration.name + ' (' + (this.options.id + 1) + ')';
|
|
636
|
+
}
|
|
637
|
+
return this.configuration.name;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
get visible(): boolean {
|
|
641
|
+
return this.state > DebugState.Inactive;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
protected readonly sources = new Map<string, DebugSource>();
|
|
645
|
+
getSource(raw: DebugProtocol.Source): DebugSource {
|
|
646
|
+
const uri = DebugSource.toUri(raw).toString();
|
|
647
|
+
const source =
|
|
648
|
+
this.sources.get(uri) ||
|
|
649
|
+
new DebugSource(this, this.labelProvider, this.modelManager, this.workbenchEditorService, this.fileSystem);
|
|
650
|
+
source.update({ raw });
|
|
651
|
+
this.sources.set(uri, source);
|
|
652
|
+
return source;
|
|
653
|
+
}
|
|
654
|
+
getSourceForUri(uri: URI): DebugSource | undefined {
|
|
655
|
+
return this.sources.get(uri.toString());
|
|
656
|
+
}
|
|
657
|
+
async toSource(uri: URI): Promise<DebugSource> {
|
|
658
|
+
const source = this.getSourceForUri(uri);
|
|
659
|
+
if (source) {
|
|
660
|
+
return source;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
return this.getSource(await this.toDebugSource(uri));
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
async toDebugSource(uri: URI): Promise<DebugProtocol.Source> {
|
|
667
|
+
if (uri.scheme === DebugSource.SCHEME) {
|
|
668
|
+
return {
|
|
669
|
+
name: uri.path.toString(),
|
|
670
|
+
sourceReference: Number(uri.query),
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
const name = uri.displayName;
|
|
674
|
+
let path: string | undefined = uri.toString();
|
|
675
|
+
if (uri.scheme === Schemes.file) {
|
|
676
|
+
path = await this.fileSystem.getFsPath(path);
|
|
677
|
+
}
|
|
678
|
+
return {
|
|
679
|
+
name,
|
|
680
|
+
path,
|
|
681
|
+
adapterData: undefined,
|
|
682
|
+
sourceReference: undefined,
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
protected _threads: Map<number, DebugThread> = new Map();
|
|
687
|
+
get threads(): DebugThread[] {
|
|
688
|
+
return Array.from(this._threads.values());
|
|
689
|
+
}
|
|
690
|
+
get threadCount(): number {
|
|
691
|
+
return this._threads.size;
|
|
692
|
+
}
|
|
693
|
+
*getThreads(filter: (thread: DebugThread) => boolean): IterableIterator<DebugThread> {
|
|
694
|
+
for (const thread of this.threads) {
|
|
695
|
+
if (filter(thread)) {
|
|
696
|
+
yield thread;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
get runningThreads(): IterableIterator<DebugThread> {
|
|
701
|
+
return this.getThreads((thread) => !thread.stopped);
|
|
702
|
+
}
|
|
703
|
+
private get stoppedThreads(): IterableIterator<DebugThread> {
|
|
704
|
+
return this.getThreads((thread) => thread.stopped);
|
|
705
|
+
}
|
|
706
|
+
protected readonly scheduleUpdateThreads = debounce(() => this.updateThreads(undefined), 100);
|
|
707
|
+
protected pendingThreads = Promise.resolve();
|
|
708
|
+
|
|
709
|
+
private async rawFetchThreads(threadId?: number): Promise<DebugProtocol.Thread[]> {
|
|
710
|
+
const arg = typeof threadId === 'undefined' ? null : { threadId };
|
|
711
|
+
const response = await this.sendRequest('threads', arg);
|
|
712
|
+
if (response && response.body && response.body.threads && Array.isArray(response.body.threads)) {
|
|
713
|
+
return Promise.resolve(response.body.threads);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return Promise.resolve([]);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
public async fetchThreads(): Promise<DebugThread[]> {
|
|
720
|
+
const rawThreads = await this.rawFetchThreads();
|
|
721
|
+
const existing = this._threads;
|
|
722
|
+
const threads: DebugThread[] = [];
|
|
723
|
+
for (const raw of rawThreads) {
|
|
724
|
+
const id = raw.id;
|
|
725
|
+
const thread = existing.get(id) || new DebugThread(this);
|
|
726
|
+
threads.push(thread);
|
|
727
|
+
thread.update({ raw });
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
return Promise.resolve(threads);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
private updateThreads(stoppedDetails: StoppedDetails | undefined): Promise<void> {
|
|
734
|
+
return (this.pendingThreads = this.pendingThreads.then(async () => {
|
|
735
|
+
try {
|
|
736
|
+
// java debugger returns an empty body sometimes
|
|
737
|
+
const threads = await this.rawFetchThreads();
|
|
738
|
+
this.doUpdateThreads(threads, stoppedDetails);
|
|
739
|
+
} catch (e) {
|
|
740
|
+
// console.error(e);
|
|
741
|
+
}
|
|
742
|
+
}));
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
protected doUpdateThreads(rawThreads: DebugProtocol.Thread[], stoppedDetails?: StoppedDetails): void {
|
|
746
|
+
const frontEndTime = this.sessionManager.reportTime(DEBUG_REPORT_NAME.DEBUG_UI_FRONTEND_TIME, {
|
|
747
|
+
sessionId: this.id,
|
|
748
|
+
threadId: stoppedDetails?.threadId,
|
|
749
|
+
threadAmount: rawThreads.length,
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
const threadIds: number[] = [];
|
|
753
|
+
rawThreads.forEach((raw: DebugProtocol.Thread) => {
|
|
754
|
+
threadIds.push(raw.id);
|
|
755
|
+
if (!this._threads.has(raw.id)) {
|
|
756
|
+
const thread = new DebugThread(this);
|
|
757
|
+
const data: Partial<Mutable<DebugThreadData>> = { raw };
|
|
758
|
+
thread.update(data);
|
|
759
|
+
this._threads.set(raw.id, thread);
|
|
760
|
+
} else if (raw.name) {
|
|
761
|
+
const oldThread = this._threads.get(raw.id);
|
|
762
|
+
if (oldThread) {
|
|
763
|
+
oldThread.raw.name = raw.name;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
this._threads.forEach((dthread: DebugThread) => {
|
|
769
|
+
const {
|
|
770
|
+
raw: { id },
|
|
771
|
+
} = dthread;
|
|
772
|
+
if (threadIds.indexOf(id) === -1) {
|
|
773
|
+
this._threads.delete(id);
|
|
774
|
+
}
|
|
775
|
+
if (stoppedDetails && (stoppedDetails.allThreadsStopped || stoppedDetails.threadId === id)) {
|
|
776
|
+
this._threads.get(id)?.update({ stoppedDetails });
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
this.collocationThread(stoppedDetails);
|
|
781
|
+
frontEndTime('doUpdateThreads');
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* 两种更新 currentThread 方式
|
|
786
|
+
* 一. collocationThread: 在 threads 列表里查找
|
|
787
|
+
* 二. updateCurrentThread: 发送 threads DAP 给 debug server,由 server 去查找并返回。前提是 supportsThreadIdCorrespond 必须为 true
|
|
788
|
+
*/
|
|
789
|
+
protected collocationThread(stoppedDetails?: StoppedDetails): void {
|
|
790
|
+
const { currentThread } = this;
|
|
791
|
+
let threadId = currentThread && currentThread.raw.id;
|
|
792
|
+
if (stoppedDetails && !stoppedDetails.preserveFocusHint && !!stoppedDetails.threadId) {
|
|
793
|
+
threadId = stoppedDetails.threadId;
|
|
794
|
+
}
|
|
795
|
+
this.currentThread =
|
|
796
|
+
(typeof threadId === 'number' && this._threads.get(threadId)) || this._threads.values().next().value;
|
|
797
|
+
if (this.currentThread?.raw.id !== threadId) {
|
|
798
|
+
this.fireDidChange();
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
protected async updateCurrentThread(thread?: DebugThread): Promise<void> {
|
|
803
|
+
if (thread) {
|
|
804
|
+
this.currentThread = thread;
|
|
805
|
+
this._onCurrentThreadChange.fire(this.currentThread);
|
|
806
|
+
} else {
|
|
807
|
+
this.currentThread = undefined;
|
|
808
|
+
this._onCurrentThreadChange.fire(undefined);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* 收集被暂停的线程 map
|
|
814
|
+
*/
|
|
815
|
+
protected async collectPausedThread(stoppedDetails: StoppedDetails): Promise<Map<number, DebugThread>> {
|
|
816
|
+
const threads = await this.rawFetchThreads(stoppedDetails?.threadId);
|
|
817
|
+
|
|
818
|
+
if (threads.length === 0) {
|
|
819
|
+
return new Map();
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
const debugThread =
|
|
823
|
+
stoppedDetails.threadId && this._multipleThreadPaused.has(stoppedDetails.threadId)
|
|
824
|
+
? this._multipleThreadPaused.get(stoppedDetails.threadId)
|
|
825
|
+
: new DebugThread(this);
|
|
826
|
+
const data: Partial<Mutable<DebugThreadData>> = { raw: threads[0] };
|
|
827
|
+
if (stoppedDetails && (stoppedDetails.allThreadsStopped || stoppedDetails.threadId === threads[0].id)) {
|
|
828
|
+
data.stoppedDetails = stoppedDetails;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
if (debugThread) {
|
|
832
|
+
debugThread.update(data);
|
|
833
|
+
await this.rawFetchFrames(debugThread);
|
|
834
|
+
this._multipleThreadPaused.set(debugThread.raw.id, debugThread);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
return this._multipleThreadPaused;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
protected async updateCurrentThreadFramesOnFocus(): Promise<void> {
|
|
841
|
+
await this.rawFetchFrames(this.currentThread);
|
|
842
|
+
this._onDidChangeCallStack.fire();
|
|
843
|
+
|
|
844
|
+
const editor = this.workbenchEditorService.currentEditor;
|
|
845
|
+
|
|
846
|
+
const focus = (f: DebugStackFrame | undefined) => {
|
|
847
|
+
if (this.stoppedDetails && !this.stoppedDetails.preserveFocusHint) {
|
|
848
|
+
this.currentThread!.currentFrame = f;
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
if (this.currentThread && !this.currentFrame) {
|
|
853
|
+
// 过滤出有效的 frame source 资源
|
|
854
|
+
const frames = this.currentThread.frames.filter(
|
|
855
|
+
(f: DebugStackFrame) => f && f.source && f.source.raw.presentationHint !== 'deemphasize',
|
|
856
|
+
);
|
|
857
|
+
if (frames.length === 0) {
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (editor) {
|
|
862
|
+
const model = editor.monacoEditor.getModel();
|
|
863
|
+
if (model) {
|
|
864
|
+
const uri = URI.parse(model.uri.toString());
|
|
865
|
+
const curFram = frames.filter((f: DebugStackFrame) => f.source!.uri.toString() === uri.toString());
|
|
866
|
+
if (curFram.length > 0) {
|
|
867
|
+
focus(curFram[0]);
|
|
868
|
+
} else {
|
|
869
|
+
// 说明不是因断点而被 pause, 可能是手动点击暂停按钮
|
|
870
|
+
focus(frames[0]);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
} else {
|
|
874
|
+
focus(frames[0]);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
protected async rawFetchFrames(thread?: DebugThread): Promise<void> {
|
|
880
|
+
if (!thread || thread.frameCount) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
if (this.capabilities.supportsDelayedStackTraceLoading) {
|
|
885
|
+
await thread.rawFetchFrames(1);
|
|
886
|
+
await thread.rawFetchFrames(19);
|
|
887
|
+
} else {
|
|
888
|
+
await thread.rawFetchFrames();
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
public terminated = false;
|
|
893
|
+
async terminate(restart?: boolean): Promise<void> {
|
|
894
|
+
this.cancelAllRequests();
|
|
895
|
+
if (this.lifecycleManagedByParent && this.parentSession) {
|
|
896
|
+
await this.parentSession.terminate(restart);
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
if (!this.terminated && this.capabilities.supportsTerminateRequest && this.configuration.request === 'launch') {
|
|
901
|
+
this.terminated = true;
|
|
902
|
+
this.sendRequest('terminate', { restart });
|
|
903
|
+
if (!(await this.exited(1000))) {
|
|
904
|
+
await this.disconnect(restart);
|
|
905
|
+
}
|
|
906
|
+
} else {
|
|
907
|
+
await this.disconnect(restart);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
public async disconnect(restart?: boolean): Promise<void> {
|
|
912
|
+
try {
|
|
913
|
+
if (this.lifecycleManagedByParent && this.parentSession) {
|
|
914
|
+
this.parentSession.disconnect(restart);
|
|
915
|
+
} else {
|
|
916
|
+
this.sendRequest('disconnect', { restart });
|
|
917
|
+
}
|
|
918
|
+
} catch (reason) {
|
|
919
|
+
this.fireExited(reason);
|
|
920
|
+
return;
|
|
921
|
+
} finally {
|
|
922
|
+
this._onDidExitAdapter.fire();
|
|
923
|
+
this.onStateChange();
|
|
924
|
+
}
|
|
925
|
+
const timeout = 500;
|
|
926
|
+
if (!(await this.exited(timeout))) {
|
|
927
|
+
this.fireExited(new Error(`timeout after ${timeout} ms`));
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
protected updateCapabilities(capabilities: DebugProtocol.Capabilities): void {
|
|
932
|
+
Object.assign(this._capabilities, capabilities);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
protected fireExited(reason?: Error): void {
|
|
936
|
+
this.connection.fire('exited', { reason });
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
protected exited(timeout: number): Promise<boolean> {
|
|
940
|
+
return Promise.race([
|
|
941
|
+
this.exitDeferred.promise.then(
|
|
942
|
+
() => true,
|
|
943
|
+
() => false,
|
|
944
|
+
),
|
|
945
|
+
new Promise<boolean>((resolve) => {
|
|
946
|
+
setTimeout(resolve, timeout, false);
|
|
947
|
+
}),
|
|
948
|
+
]);
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
async restart(): Promise<boolean> {
|
|
952
|
+
this.cancelAllRequests();
|
|
953
|
+
if (this.capabilities.supportsRestartRequest) {
|
|
954
|
+
this.terminated = false;
|
|
955
|
+
if (this.lifecycleManagedByParent && this.parentSession) {
|
|
956
|
+
await this.parentSession.restart();
|
|
957
|
+
} else {
|
|
958
|
+
await this.sendRequest('restart', {});
|
|
959
|
+
}
|
|
960
|
+
return true;
|
|
961
|
+
}
|
|
962
|
+
return false;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
dispose(): void {
|
|
966
|
+
this.toDispose.dispose();
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
async evaluate(expression: string, context?: string): Promise<DebugProtocol.EvaluateResponse['body']> {
|
|
970
|
+
// evaluate muse wait for frames updated
|
|
971
|
+
if (this.updateDeffered) {
|
|
972
|
+
await this.updateDeffered?.promise;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
const frameId = this.currentFrame && this.currentFrame.raw.id;
|
|
976
|
+
|
|
977
|
+
// 在 VS Code JavaScript Debugger 中,如果一个表达式取值为 `undefined`, 这里将不会返回结果
|
|
978
|
+
const response = await this.sendRequest('evaluate', { expression, frameId, context });
|
|
979
|
+
return response.body;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
async goto(args: DebugProtocol.GotoArguments): Promise<DebugProtocol.GotoResponse | void> {
|
|
983
|
+
if (this.capabilities.supportsGotoTargetsRequest) {
|
|
984
|
+
const res = await this.sendRequest('goto', args);
|
|
985
|
+
return res;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
async exceptionInfo(
|
|
990
|
+
args: DebugProtocol.ExceptionInfoArguments,
|
|
991
|
+
): Promise<DebugProtocol.ExceptionInfoResponse | undefined> {
|
|
992
|
+
if (this.capabilities.supportsExceptionInfoRequest) {
|
|
993
|
+
return this.sendRequest('exceptionInfo', args);
|
|
994
|
+
}
|
|
995
|
+
return Promise.reject(new Error('exceptionInfo not supported'));
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
async cancel(progressId: string): Promise<DebugProtocol.CancelResponse | undefined> {
|
|
999
|
+
return this.sendRequest('cancel', { progressId });
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
async setVariableValue(args: DebugProtocol.SetVariableArguments): Promise<DebugProtocol.SetVariableResponse | void> {
|
|
1003
|
+
if (this.capabilities.supportsSetVariable) {
|
|
1004
|
+
const res = await this.sendRequest('setVariable', args);
|
|
1005
|
+
this._onVariableChange.fire();
|
|
1006
|
+
return res;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
async breakpointLocations(uri: URI, line: number) {
|
|
1011
|
+
const source = await this.toSource(uri);
|
|
1012
|
+
const response = await this.sendRequest('breakpointLocations', { source: source.raw, line });
|
|
1013
|
+
const positions: IPosition[] = (response.body?.breakpoints || []).map((item) => ({
|
|
1014
|
+
lineNumber: item.line,
|
|
1015
|
+
column: item.column || 1,
|
|
1016
|
+
}));
|
|
1017
|
+
return Object.values<IPosition>(
|
|
1018
|
+
positions.reduce(
|
|
1019
|
+
(obj, p) => ({
|
|
1020
|
+
...obj,
|
|
1021
|
+
[`${p.lineNumber}:${p.column}`]: p,
|
|
1022
|
+
}),
|
|
1023
|
+
{},
|
|
1024
|
+
),
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
async sendRequest<K extends keyof DebugRequestTypes>(
|
|
1029
|
+
command: K,
|
|
1030
|
+
args: DebugRequestTypes[K][0],
|
|
1031
|
+
token?: CancellationToken,
|
|
1032
|
+
): Promise<DebugRequestTypes[K][1]> {
|
|
1033
|
+
if (
|
|
1034
|
+
(!this._capabilities.supportsTerminateRequest && command === 'terminate') ||
|
|
1035
|
+
(!this._capabilities.supportsCompletionsRequest && command === 'completions') ||
|
|
1036
|
+
(!this._capabilities.supportsTerminateThreadsRequest && command === 'terminateThreads')
|
|
1037
|
+
) {
|
|
1038
|
+
throw new Error(`debug: ${command} not supported`);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
let requestToken: CancellationToken | undefined;
|
|
1042
|
+
|
|
1043
|
+
if ((['continue', 'next', 'stepIn', 'stepOut', 'threads'] as K[]).some((c) => command === c)) {
|
|
1044
|
+
this.handleCancellation(this.currentThread?.raw.id);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
if ((['stackTrace', 'scopes', 'variables', 'completions', 'threads'] as K[]).some((c) => command === c)) {
|
|
1048
|
+
requestToken = this.currentThread?.raw.id
|
|
1049
|
+
? this.getNewCancellationToken(this.currentThread?.raw.id, token)
|
|
1050
|
+
: undefined;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
try {
|
|
1054
|
+
return await this.connection.sendRequest(command, args, this.configuration, requestToken);
|
|
1055
|
+
} finally {
|
|
1056
|
+
this._onRequest.fire(command);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
protected async takeCommand(command: string) {
|
|
1061
|
+
return new Promise<void>((resolve) => {
|
|
1062
|
+
const disposable = this.onRequest((e) => {
|
|
1063
|
+
if (e === command) {
|
|
1064
|
+
disposable.dispose();
|
|
1065
|
+
resolve();
|
|
1066
|
+
}
|
|
1067
|
+
});
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
sendCustomRequest<T extends DebugProtocol.Response>(command: string, args?: any): Promise<T> {
|
|
1072
|
+
return this.connection.sendCustomRequest(command, args);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
on<K extends keyof DebugEventTypes>(kind: K, listener: (e: DebugEventTypes[K]) => any): IDisposable {
|
|
1076
|
+
return this.connection.on(kind, listener);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
get onDidCustomEvent(): Event<DebugProtocol.Event> {
|
|
1080
|
+
return this.connection.onDidCustomEvent;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// REPL
|
|
1084
|
+
|
|
1085
|
+
hasSeparateRepl(): boolean {
|
|
1086
|
+
return !this.parentSession || this.options.repl !== 'mergeWithParent';
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
// REPL end
|
|
1090
|
+
|
|
1091
|
+
// report service
|
|
1092
|
+
reportTime(name: string, defaults?: any): (msg: string | undefined, extra?: any) => number {
|
|
1093
|
+
return this.sessionManager.reportTime(name, defaults);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// Cancellation
|
|
1097
|
+
|
|
1098
|
+
private getNewCancellationToken(threadId: number, token?: CancellationToken): CancellationToken {
|
|
1099
|
+
const tokenSource = new CancellationTokenSource(token);
|
|
1100
|
+
const tokens = this.cancellationMap.get(threadId) || [];
|
|
1101
|
+
tokens.push(tokenSource);
|
|
1102
|
+
this.cancellationMap.set(threadId, tokens);
|
|
1103
|
+
|
|
1104
|
+
return tokenSource.token;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
private cancelAllRequests(): void {
|
|
1108
|
+
this.cancellationMap.forEach((tokens) => tokens.forEach((t) => t.cancel()));
|
|
1109
|
+
this.cancellationMap.clear();
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
public handleCancellation(threadId?: number): void {
|
|
1113
|
+
if (threadId) {
|
|
1114
|
+
const tokens = this.cancellationMap.get(threadId);
|
|
1115
|
+
this.cancellationMap.delete(threadId);
|
|
1116
|
+
if (tokens) {
|
|
1117
|
+
tokens.forEach((t) => t.cancel());
|
|
1118
|
+
}
|
|
1119
|
+
} else {
|
|
1120
|
+
this.cancelAllRequests();
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// Cancellation end
|
|
1125
|
+
|
|
1126
|
+
public getDebugProtocolBreakpoint(breakpointId: string): DebugProtocol.Breakpoint | undefined {
|
|
1127
|
+
const data = this.breakpointManager.getBreakpoints().find((bp) => bp.id === breakpointId);
|
|
1128
|
+
if (data) {
|
|
1129
|
+
const status = data.status.get(this.id);
|
|
1130
|
+
const bp: DebugProtocol.Breakpoint = {
|
|
1131
|
+
id: status?.id,
|
|
1132
|
+
verified: !!status?.verified,
|
|
1133
|
+
message: status?.message,
|
|
1134
|
+
source: status?.source,
|
|
1135
|
+
line: status?.line,
|
|
1136
|
+
column: status?.column,
|
|
1137
|
+
endLine: status?.endLine,
|
|
1138
|
+
endColumn: status?.endColumn,
|
|
1139
|
+
instructionReference: status?.instructionReference,
|
|
1140
|
+
offset: status?.offset,
|
|
1141
|
+
};
|
|
1142
|
+
return bp;
|
|
1143
|
+
}
|
|
1144
|
+
return undefined;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
public currentEditor(): DebugEditor | undefined {
|
|
1148
|
+
return this.getModel()?.getEditor();
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
public getModel(): IDebugModel | undefined {
|
|
1152
|
+
return this.modelManager.model;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
// memory
|
|
1156
|
+
|
|
1157
|
+
public async readMemory(
|
|
1158
|
+
memoryReference: string,
|
|
1159
|
+
offset: number,
|
|
1160
|
+
count: number,
|
|
1161
|
+
): Promise<DebugProtocol.ReadMemoryResponse | undefined> {
|
|
1162
|
+
if (this.capabilities.supportsReadMemoryRequest) {
|
|
1163
|
+
return await this.sendRequest('readMemory', { count, memoryReference, offset });
|
|
1164
|
+
}
|
|
1165
|
+
return Promise.resolve(undefined);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
public async writeMemory(
|
|
1169
|
+
memoryReference: string,
|
|
1170
|
+
offset: number,
|
|
1171
|
+
data: string,
|
|
1172
|
+
allowPartial?: boolean,
|
|
1173
|
+
): Promise<DebugProtocol.WriteMemoryResponse | undefined> {
|
|
1174
|
+
if (this.capabilities.supportsWriteMemoryRequest) {
|
|
1175
|
+
return await this.sendRequest('writeMemory', { memoryReference, offset, allowPartial, data });
|
|
1176
|
+
}
|
|
1177
|
+
return Promise.resolve(undefined);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// memory end
|
|
1181
|
+
}
|