@theia/debug 1.18.0-next.0f7dec1a → 1.18.0-next.104

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 (97) hide show
  1. package/LICENSE +642 -0
  2. package/lib/browser/console/debug-console-items.d.ts +2 -1
  3. package/lib/browser/console/debug-console-items.d.ts.map +1 -1
  4. package/lib/browser/console/debug-console-items.js +4 -1
  5. package/lib/browser/console/debug-console-items.js.map +1 -1
  6. package/lib/browser/console/debug-console-session.d.ts +1 -1
  7. package/lib/browser/debug-configuration-manager.d.ts +7 -0
  8. package/lib/browser/debug-configuration-manager.d.ts.map +1 -1
  9. package/lib/browser/debug-configuration-manager.js +20 -8
  10. package/lib/browser/debug-configuration-manager.js.map +1 -1
  11. package/lib/browser/debug-frontend-application-contribution.d.ts +1 -0
  12. package/lib/browser/debug-frontend-application-contribution.d.ts.map +1 -1
  13. package/lib/browser/debug-frontend-application-contribution.js +3 -0
  14. package/lib/browser/debug-frontend-application-contribution.js.map +1 -1
  15. package/lib/browser/debug-preferences.d.ts +1 -0
  16. package/lib/browser/debug-preferences.d.ts.map +1 -1
  17. package/lib/browser/debug-preferences.js +10 -0
  18. package/lib/browser/debug-preferences.js.map +1 -1
  19. package/lib/browser/debug-prefix-configuration.d.ts +1 -1
  20. package/lib/browser/debug-prefix-configuration.d.ts.map +1 -1
  21. package/lib/browser/debug-prefix-configuration.js +20 -3
  22. package/lib/browser/debug-prefix-configuration.js.map +1 -1
  23. package/lib/browser/debug-session-connection.d.ts +1 -1
  24. package/lib/browser/debug-session-connection.d.ts.map +1 -1
  25. package/lib/browser/debug-session-contribution.d.ts +1 -1
  26. package/lib/browser/debug-session-contribution.d.ts.map +1 -1
  27. package/lib/browser/debug-session-contribution.js +1 -1
  28. package/lib/browser/debug-session-contribution.js.map +1 -1
  29. package/lib/browser/view/debug-configuration-widget.d.ts +1 -1
  30. package/lib/browser/view/debug-configuration-widget.d.ts.map +1 -1
  31. package/lib/browser/view/debug-configuration-widget.js +2 -3
  32. package/lib/browser/view/debug-configuration-widget.js.map +1 -1
  33. package/lib/browser/view/debug-session-widget.d.ts +2 -1
  34. package/lib/browser/view/debug-session-widget.d.ts.map +1 -1
  35. package/lib/browser/view/debug-session-widget.js +12 -6
  36. package/lib/browser/view/debug-session-widget.js.map +1 -1
  37. package/lib/common/debug-configuration.d.ts +2 -0
  38. package/lib/common/debug-configuration.d.ts.map +1 -1
  39. package/lib/common/debug-configuration.js.map +1 -1
  40. package/lib/common/debug-service.d.ts +8 -0
  41. package/lib/common/debug-service.d.ts.map +1 -1
  42. package/lib/common/debug-service.js.map +1 -1
  43. package/lib/node/debug-adapter-contribution-registry.d.ts +1 -1
  44. package/lib/node/debug-adapter-contribution-registry.d.ts.map +1 -1
  45. package/lib/node/debug-adapter-contribution-registry.js +1 -1
  46. package/lib/node/debug-adapter-contribution-registry.js.map +1 -1
  47. package/lib/node/debug-adapter-factory.d.ts +1 -1
  48. package/lib/node/debug-adapter-factory.d.ts.map +1 -1
  49. package/lib/node/debug-adapter-factory.js +8 -10
  50. package/lib/node/debug-adapter-factory.js.map +1 -1
  51. package/lib/node/debug-adapter-session-manager.d.ts +1 -1
  52. package/lib/node/debug-adapter-session-manager.d.ts.map +1 -1
  53. package/lib/node/debug-adapter-session-manager.js +1 -1
  54. package/lib/node/debug-adapter-session-manager.js.map +1 -1
  55. package/lib/node/debug-adapter-session.d.ts +1 -7
  56. package/lib/node/debug-adapter-session.d.ts.map +1 -1
  57. package/lib/node/debug-adapter-session.js +4 -48
  58. package/lib/node/debug-adapter-session.js.map +1 -1
  59. package/lib/node/debug-backend-module.js +1 -1
  60. package/lib/node/debug-backend-module.js.map +1 -1
  61. package/lib/{common → node}/debug-model.d.ts +6 -5
  62. package/lib/node/debug-model.d.ts.map +1 -0
  63. package/lib/{common → node}/debug-model.js +0 -0
  64. package/lib/node/debug-model.js.map +1 -0
  65. package/lib/node/inline-communication-provider.d.ts +33 -0
  66. package/lib/node/inline-communication-provider.d.ts.map +1 -0
  67. package/lib/node/inline-communication-provider.js +43 -0
  68. package/lib/node/inline-communication-provider.js.map +1 -0
  69. package/lib/node/stream-communication-provider.d.ts +38 -0
  70. package/lib/node/stream-communication-provider.d.ts.map +1 -0
  71. package/lib/node/stream-communication-provider.js +88 -0
  72. package/lib/node/stream-communication-provider.js.map +1 -0
  73. package/lib/node/vscode/vscode-debug-adapter-contribution.d.ts +1 -1
  74. package/lib/node/vscode/vscode-debug-adapter-contribution.d.ts.map +1 -1
  75. package/package.json +22 -20
  76. package/src/browser/console/debug-console-items.tsx +6 -2
  77. package/src/browser/debug-configuration-manager.ts +26 -9
  78. package/src/browser/debug-frontend-application-contribution.ts +6 -2
  79. package/src/browser/debug-preferences.ts +11 -0
  80. package/src/browser/debug-prefix-configuration.ts +24 -3
  81. package/src/browser/debug-session-connection.ts +1 -1
  82. package/src/browser/debug-session-contribution.ts +1 -1
  83. package/src/browser/view/debug-configuration-widget.tsx +1 -2
  84. package/src/browser/view/debug-session-widget.ts +12 -6
  85. package/src/common/debug-configuration.ts +3 -0
  86. package/src/common/debug-service.ts +6 -0
  87. package/src/node/debug-adapter-contribution-registry.ts +1 -1
  88. package/src/node/debug-adapter-factory.ts +10 -11
  89. package/src/node/debug-adapter-session-manager.ts +1 -1
  90. package/src/node/debug-adapter-session.ts +8 -57
  91. package/src/node/debug-backend-module.ts +1 -1
  92. package/src/{common → node}/debug-model.ts +6 -4
  93. package/src/node/inline-communication-provider.ts +44 -0
  94. package/src/node/stream-communication-provider.ts +93 -0
  95. package/src/node/vscode/vscode-debug-adapter-contribution.ts +1 -1
  96. package/lib/common/debug-model.d.ts.map +0 -1
  97. package/lib/common/debug-model.js.map +0 -1
@@ -49,6 +49,16 @@ export const debugPreferencesSchema: PreferenceSchema = {
49
49
  enum: ['never', 'always', 'onFirstSessionStart'],
50
50
  description: 'Controls when the debug status bar should be visible.',
51
51
  default: 'onFirstSessionStart'
52
+ },
53
+ 'debug.confirmOnExit': {
54
+ description: 'Controls whether to confirm when the window closes if there are active debug sessions.',
55
+ type: 'string',
56
+ enum: ['never', 'always'],
57
+ enumDescriptions: [
58
+ 'Never confirm.',
59
+ 'Always confirm if there are debug sessions.',
60
+ ],
61
+ default: 'never'
52
62
  }
53
63
  }
54
64
  };
@@ -60,6 +70,7 @@ export class DebugConfiguration {
60
70
  'debug.internalConsoleOptions': 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart';
61
71
  'debug.inlineValues': boolean;
62
72
  'debug.showInStatusBar': 'never' | 'always' | 'onFirstSessionStart';
73
+ 'debug.confirmOnExit': 'never' | 'always';
63
74
  }
64
75
 
65
76
  export const DebugPreferenceContribution = Symbol('DebugPreferenceContribution');
@@ -107,10 +107,11 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan
107
107
  });
108
108
  }
109
109
 
110
- getPicks(filter: string, token: CancellationToken): QuickPicks {
110
+ async getPicks(filter: string, token: CancellationToken): Promise<QuickPicks> {
111
111
  const items: QuickPickItem[] = [];
112
112
  const configurations = this.debugConfigurationManager.all;
113
- Array.from(configurations).forEach(config => {
113
+
114
+ for (const config of configurations) {
114
115
  items.push({
115
116
  label: config.configuration.name,
116
117
  description: this.workspaceService.isMultiRootWorkspaceOpened
@@ -118,7 +119,27 @@ export class DebugPrefixConfiguration implements CommandContribution, CommandHan
118
119
  : '',
119
120
  execute: () => this.runConfiguration(config)
120
121
  });
121
- });
122
+ }
123
+
124
+ // Resolve dynamic configurations from providers
125
+ const configurationsByType = await this.debugConfigurationManager.provideDynamicDebugConfigurations();
126
+ for (const typeConfigurations of configurationsByType) {
127
+ const dynamicConfigurations = typeConfigurations.configurations;
128
+ if (dynamicConfigurations.length > 0) {
129
+ items.push({
130
+ label: typeConfigurations.type,
131
+ type: 'separator'
132
+ });
133
+ }
134
+
135
+ for (const configuration of dynamicConfigurations) {
136
+ items.push({
137
+ label: configuration.name,
138
+ execute: () => this.runConfiguration({configuration})
139
+ });
140
+ }
141
+ }
142
+
122
143
  return filterItems(items, filter);
123
144
  }
124
145
 
@@ -19,7 +19,7 @@
19
19
  import { DebugProtocol } from 'vscode-debugprotocol';
20
20
  import { Deferred } from '@theia/core/lib/common/promise-util';
21
21
  import { Event, Emitter, DisposableCollection, Disposable, MaybePromise } from '@theia/core';
22
- import { OutputChannel } from '@theia/output/lib/common/output-channel';
22
+ import { OutputChannel } from '@theia/output/lib/browser/output-channel';
23
23
  import { IWebSocket } from '@theia/core/shared/vscode-ws-jsonrpc';
24
24
 
25
25
  export interface DebugExitEvent {
@@ -23,7 +23,7 @@ import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging/w
23
23
  import { DebugSession } from './debug-session';
24
24
  import { BreakpointManager } from './breakpoint/breakpoint-manager';
25
25
  import { DebugSessionOptions } from './debug-session-options';
26
- import { OutputChannelManager, OutputChannel } from '@theia/output/lib/common/output-channel';
26
+ import { OutputChannelManager, OutputChannel } from '@theia/output/lib/browser/output-channel';
27
27
  import { DebugPreferences } from './debug-preferences';
28
28
  import { DebugSessionConnection } from './debug-session-connection';
29
29
  import { IWebSocket } from '@theia/core/shared/vscode-ws-jsonrpc';
@@ -16,7 +16,7 @@
16
16
 
17
17
  import * as React from '@theia/core/shared/react';
18
18
  import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
19
- import { Disposable } from '@theia/core/lib/common';
19
+ import { CommandRegistry, Disposable } from '@theia/core/lib/common';
20
20
  import URI from '@theia/core/lib/common/uri';
21
21
  import { ReactWidget } from '@theia/core/lib/browser';
22
22
  import { WorkspaceService } from '@theia/workspace/lib/browser';
@@ -27,7 +27,6 @@ import { DebugAction } from './debug-action';
27
27
  import { DebugViewModel } from './debug-view-model';
28
28
  import { DebugSessionOptions } from '../debug-session-options';
29
29
  import { DebugCommands } from '../debug-frontend-application-contribution';
30
- import { CommandRegistry } from '@theia/core/lib/common';
31
30
 
32
31
  @injectable()
33
32
  export class DebugConfigurationWidget extends ReactWidget {
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { inject, injectable, postConstruct, interfaces, Container } from '@theia/core/shared/inversify';
18
18
  import {
19
- Message, ApplicationShell, Widget, BaseWidget, PanelLayout, StatefulWidget, ViewContainer, codicon
19
+ Message, ApplicationShell, Widget, BaseWidget, PanelLayout, StatefulWidget, ViewContainer, codicon, ViewContainerTitleOptions
20
20
  } from '@theia/core/lib/browser';
21
21
  import { DebugThreadsWidget } from './debug-threads-widget';
22
22
  import { DebugStackFramesWidget } from './debug-stack-frames-widget';
@@ -28,6 +28,11 @@ import { DebugWatchWidget } from './debug-watch-widget';
28
28
 
29
29
  export const DebugSessionWidgetFactory = Symbol('DebugSessionWidgetFactory');
30
30
  export type DebugSessionWidgetFactory = (options: DebugViewOptions) => DebugSessionWidget;
31
+ export const DEBUG_VIEW_CONTAINER_TITLE_OPTIONS: ViewContainerTitleOptions = {
32
+ label: 'debug',
33
+ iconClass: codicon('debug-alt'),
34
+ closeable: true
35
+ };
31
36
 
32
37
  @injectable()
33
38
  export class DebugSessionWidget extends BaseWidget implements StatefulWidget, ApplicationShell.TrackableWidgetProvider {
@@ -88,11 +93,12 @@ export class DebugSessionWidget extends BaseWidget implements StatefulWidget, Ap
88
93
  this.viewContainer = this.viewContainerFactory({
89
94
  id: 'debug:view-container:' + this.model.id
90
95
  });
91
- this.viewContainer.addWidget(this.threads, { weight: 30 });
92
- this.viewContainer.addWidget(this.stackFrames, { weight: 20 });
93
- this.viewContainer.addWidget(this.variables, { weight: 10 });
94
- this.viewContainer.addWidget(this.watch, { weight: 10 });
95
- this.viewContainer.addWidget(this.breakpoints, { weight: 10 });
96
+ this.viewContainer.setTitleOptions(DEBUG_VIEW_CONTAINER_TITLE_OPTIONS);
97
+ this.viewContainer.addWidget(this.threads, { weight: 30, disableDraggingToOtherContainers: true });
98
+ this.viewContainer.addWidget(this.stackFrames, { weight: 20, disableDraggingToOtherContainers: true });
99
+ this.viewContainer.addWidget(this.variables, { weight: 10, disableDraggingToOtherContainers: true });
100
+ this.viewContainer.addWidget(this.watch, { weight: 10, disableDraggingToOtherContainers: true });
101
+ this.viewContainer.addWidget(this.breakpoints, { weight: 10, disableDraggingToOtherContainers: true });
96
102
 
97
103
  this.toDispose.pushAll([
98
104
  this.toolbar,
@@ -74,6 +74,9 @@ export interface DebugConfiguration {
74
74
 
75
75
  /** Task to run after debug session ends */
76
76
  postDebugTask?: string | TaskIdentifier;
77
+
78
+ /** Indicates if it's a dynamic debug configuration */
79
+ dynamic?: boolean;
77
80
  }
78
81
  export namespace DebugConfiguration {
79
82
  export function is(arg: DebugConfiguration | any): arg is DebugConfiguration {
@@ -70,6 +70,12 @@ export interface DebugService extends Disposable {
70
70
  */
71
71
  provideDebugConfigurations(debugType: string, workspaceFolderUri: string | undefined): Promise<DebugConfiguration[]>;
72
72
 
73
+ /**
74
+ * Provides dynamic debug configurations by a provider debug type
75
+ * @returns An Array of objects containing the debug type and corresponding dynamic debug configurations array
76
+ */
77
+ provideDynamicDebugConfigurations?(): Promise<{ type: string, configurations: DebugConfiguration[] }[]>;
78
+
73
79
  /**
74
80
  * Resolves a [debug configuration](#DebugConfiguration) by filling in missing values
75
81
  * or by adding/changing/removing attributes before variable substitution.
@@ -19,7 +19,7 @@ import { ContributionProvider } from '@theia/core';
19
19
  import { DebugConfiguration } from '../common/debug-configuration';
20
20
  import { DebuggerDescription, DebugError } from '../common/debug-service';
21
21
 
22
- import { DebugAdapterContribution, DebugAdapterExecutable, DebugAdapterSessionFactory } from '../common/debug-model';
22
+ import { DebugAdapterContribution, DebugAdapterExecutable, DebugAdapterSessionFactory } from './debug-model';
23
23
  import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
24
24
 
25
25
  /**
@@ -37,9 +37,11 @@ import {
37
37
  DebugAdapterSessionFactory,
38
38
  DebugAdapterFactory,
39
39
  DebugAdapterForkExecutable
40
- } from '../common/debug-model';
40
+ } from './debug-model';
41
41
  import { DebugAdapterSessionImpl } from './debug-adapter-session';
42
42
  import { environment } from '@theia/core/shared/@theia/application-package';
43
+ import { StreamCommunicationProvider } from './stream-communication-provider';
44
+ import { Disposable } from '@theia/core/lib/common/disposable';
43
45
 
44
46
  /**
45
47
  * [DebugAdapterFactory](#DebugAdapterFactory) implementation based on
@@ -56,11 +58,9 @@ export class LaunchBasedDebugAdapterFactory implements DebugAdapterFactory {
56
58
  const process = this.childProcess(executable);
57
59
 
58
60
  // FIXME: propagate onError + onExit
59
- return {
60
- input: process.inputStream,
61
- output: process.outputStream,
62
- dispose: () => process.kill()
63
- };
61
+ const provider = new StreamCommunicationProvider(process.outputStream, process.inputStream);
62
+ provider.push(Disposable.create(() => process.kill()));
63
+ return provider;
64
64
  }
65
65
 
66
66
  private childProcess(executable: DebugAdapterExecutable): RawProcess {
@@ -84,11 +84,10 @@ export class LaunchBasedDebugAdapterFactory implements DebugAdapterFactory {
84
84
  connect(debugServerPort: number): CommunicationProvider {
85
85
  const socket = net.createConnection(debugServerPort);
86
86
  // FIXME: propagate socket.on('error', ...) + socket.on('close', ...)
87
- return {
88
- input: socket,
89
- output: socket,
90
- dispose: () => socket.end()
91
- };
87
+
88
+ const provider = new StreamCommunicationProvider(socket, socket);
89
+ provider.push(Disposable.create(() => socket.end()));
90
+ return provider;
92
91
  }
93
92
  }
94
93
 
@@ -20,7 +20,7 @@ import { MessagingService } from '@theia/core/lib/node/messaging/messaging-servi
20
20
 
21
21
  import { DebugAdapterPath } from '../common/debug-service';
22
22
  import { DebugConfiguration } from '../common/debug-configuration';
23
- import { DebugAdapterSession, DebugAdapterSessionFactory, DebugAdapterFactory } from '../common/debug-model';
23
+ import { DebugAdapterSession, DebugAdapterSessionFactory, DebugAdapterFactory } from './debug-model';
24
24
  import { DebugAdapterContributionRegistry } from './debug-adapter-contribution-registry';
25
25
 
26
26
  /**
@@ -23,8 +23,8 @@
23
23
 
24
24
  import {
25
25
  CommunicationProvider,
26
- DebugAdapterSession,
27
- } from '../common/debug-model';
26
+ DebugAdapterSession
27
+ } from './debug-model';
28
28
  import { DebugProtocol } from 'vscode-debugprotocol';
29
29
  import { IWebSocket } from '@theia/core/shared/vscode-ws-jsonrpc';
30
30
  import { DisposableCollection, Disposable } from '@theia/core/lib/common/disposable';
@@ -34,25 +34,23 @@ import { DisposableCollection, Disposable } from '@theia/core/lib/common/disposa
34
34
  */
35
35
  export class DebugAdapterSessionImpl implements DebugAdapterSession {
36
36
 
37
- private static TWO_CRLF = '\r\n\r\n';
38
- private static CONTENT_LENGTH = 'Content-Length';
39
-
40
37
  private readonly toDispose = new DisposableCollection();
41
38
  private channel: IWebSocket | undefined;
42
- private contentLength: number;
43
- private buffer: Buffer;
44
39
 
45
40
  constructor(
46
41
  readonly id: string,
47
42
  protected readonly communicationProvider: CommunicationProvider
48
43
  ) {
49
- this.contentLength = -1;
50
- this.buffer = Buffer.alloc(0);
51
44
  this.toDispose.pushAll([
52
45
  this.communicationProvider,
53
46
  Disposable.create(() => this.write(JSON.stringify({ seq: -1, type: 'request', command: 'disconnect' }))),
54
47
  Disposable.create(() => this.write(JSON.stringify({ seq: -1, type: 'request', command: 'terminate' })))
55
48
  ]);
49
+
50
+ this.communicationProvider.onMessageReceived((message: string) => this.send(message));
51
+ this.communicationProvider.onClose(() => this.onDebugAdapterExit(1, undefined)); // FIXME pass a proper exit code
52
+ this.communicationProvider.onError(error => this.onDebugAdapterError(error));
53
+
56
54
  }
57
55
 
58
56
  async start(channel: IWebSocket): Promise<void> {
@@ -63,10 +61,6 @@ export class DebugAdapterSessionImpl implements DebugAdapterSession {
63
61
  this.channel.onMessage((message: string) => this.write(message));
64
62
  this.channel.onClose(() => this.channel = undefined);
65
63
 
66
- this.communicationProvider.output.on('data', (data: Buffer) => this.handleData(data));
67
- this.communicationProvider.output.on('close', () => this.onDebugAdapterExit(1, undefined)); // FIXME pass a proper exit code
68
- this.communicationProvider.output.on('error', error => this.onDebugAdapterError(error));
69
- this.communicationProvider.input.on('error', error => this.onDebugAdapterError(error));
70
64
  }
71
65
 
72
66
  protected onDebugAdapterExit(exitCode: number, signal: string | undefined): void {
@@ -91,49 +85,6 @@ export class DebugAdapterSessionImpl implements DebugAdapterSession {
91
85
  this.send(JSON.stringify(event));
92
86
  }
93
87
 
94
- protected handleData(data: Buffer): void {
95
- this.buffer = Buffer.concat([this.buffer, data]);
96
-
97
- while (true) {
98
- if (this.contentLength >= 0) {
99
- if (this.buffer.length >= this.contentLength) {
100
- const message = this.buffer.toString('utf8', 0, this.contentLength);
101
- this.buffer = this.buffer.slice(this.contentLength);
102
- this.contentLength = -1;
103
-
104
- if (message.length > 0) {
105
- this.send(message);
106
- }
107
- continue; // there may be more complete messages to process
108
- }
109
- } else {
110
- let idx = this.buffer.indexOf(DebugAdapterSessionImpl.CONTENT_LENGTH);
111
- if (idx > 0) {
112
- // log unrecognized output
113
- const output = this.buffer.slice(0, idx);
114
- console.log(output.toString('utf-8'));
115
-
116
- this.buffer = this.buffer.slice(idx);
117
- }
118
-
119
- idx = this.buffer.indexOf(DebugAdapterSessionImpl.TWO_CRLF);
120
- if (idx !== -1) {
121
- const header = this.buffer.toString('utf8', 0, idx);
122
- const lines = header.split('\r\n');
123
- for (let i = 0; i < lines.length; i++) {
124
- const pair = lines[i].split(/: +/);
125
- if (pair[0] === DebugAdapterSessionImpl.CONTENT_LENGTH) {
126
- this.contentLength = +pair[1];
127
- }
128
- }
129
- this.buffer = this.buffer.slice(idx + DebugAdapterSessionImpl.TWO_CRLF.length);
130
- continue;
131
- }
132
- }
133
- break;
134
- }
135
- }
136
-
137
88
  protected send(message: string): void {
138
89
  if (this.channel) {
139
90
  this.channel.send(message);
@@ -141,7 +92,7 @@ export class DebugAdapterSessionImpl implements DebugAdapterSession {
141
92
  }
142
93
 
143
94
  protected write(message: string): void {
144
- this.communicationProvider.input.write(`Content-Length: ${Buffer.byteLength(message, 'utf8')}\r\n\r\n${message}`, 'utf8');
95
+ this.communicationProvider.send(message);
145
96
  }
146
97
 
147
98
  async stop(): Promise<void> {
@@ -30,7 +30,7 @@ import {
30
30
  DebugAdapterContribution,
31
31
  DebugAdapterSessionFactory,
32
32
  DebugAdapterFactory
33
- } from '../common/debug-model';
33
+ } from './debug-model';
34
34
  import { DebugServiceImpl } from './debug-service-impl';
35
35
  import { DebugAdapterContributionRegistry } from './debug-adapter-contribution-registry';
36
36
  import { DebugAdapterSessionManager } from './debug-adapter-session-manager';
@@ -22,12 +22,12 @@
22
22
  // Some entities copied and modified from https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.d.ts
23
23
  // Some entities copied and modified from https://github.com/Microsoft/vscode/blob/master/src/vs/workbench/parts/debug/common/debug.ts
24
24
 
25
- import * as stream from 'stream';
26
25
  import { WebSocketChannel } from '@theia/core/lib/common/messaging/web-socket-channel';
27
- import { DebugConfiguration } from './debug-configuration';
26
+ import { DebugConfiguration } from '../common/debug-configuration';
28
27
  import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
29
28
  import { Disposable } from '@theia/core/lib/common/disposable';
30
29
  import { MaybePromise } from '@theia/core/lib/common/types';
30
+ import { Event } from '@theia/core/lib/common/event';
31
31
 
32
32
  // FIXME: break down this file to debug adapter and debug adapter contribution (see Theia file naming conventions)
33
33
 
@@ -96,8 +96,10 @@ export type DebugAdapterExecutable = DebugAdapterSpawnExecutable | DebugAdapterF
96
96
  * TODO: the better name is DebugStreamConnection + handling on error and close
97
97
  */
98
98
  export interface CommunicationProvider extends Disposable {
99
- output: stream.Readable;
100
- input: stream.Writable;
99
+ onMessageReceived: Event<string>;
100
+ onError: Event<Error>;
101
+ onClose: Event<void>;
102
+ send(message: string): void;
101
103
  }
102
104
 
103
105
  /**
@@ -0,0 +1,44 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 Red Hat, Inc. and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { Emitter, Event } from '@theia/core/lib/common/event';
18
+ import { CommunicationProvider } from './debug-model';
19
+ import * as theia from '@theia/plugin';
20
+
21
+ /**
22
+ * A communication provider for using the inline implementation of a debug adapter.
23
+ */
24
+ export class InlineCommunicationProvider implements CommunicationProvider {
25
+ private messageReceivedEmitter = new Emitter<string>();
26
+ onMessageReceived: Event<string> = this.messageReceivedEmitter.event;
27
+ onError: Event<Error> = Event.None;
28
+ private closeEmitter = new Emitter<void>();
29
+ onClose: Event<void> = this.closeEmitter.event;
30
+
31
+ constructor(private debugAdapter: theia.DebugAdapter) {
32
+ this.debugAdapter.onDidSendMessage(msg => {
33
+ this.messageReceivedEmitter.fire(JSON.stringify(msg));
34
+ });
35
+ }
36
+
37
+ send(message: string): void {
38
+ this.debugAdapter.handleMessage(JSON.parse(message));
39
+ }
40
+
41
+ dispose(): void {
42
+ this.debugAdapter.dispose();
43
+ }
44
+ }
@@ -0,0 +1,93 @@
1
+ /********************************************************************************
2
+ * Copyright (C) 2021 Red Hat, Inc. and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { DisposableCollection } from '@theia/core/lib/common/disposable';
18
+ import { Emitter, Event } from '@theia/core/lib/common/event';
19
+ import * as stream from 'stream';
20
+ import { CommunicationProvider } from './debug-model';
21
+
22
+ export class StreamCommunicationProvider extends DisposableCollection implements CommunicationProvider {
23
+ private messageReceivedEmitter = new Emitter<string>();
24
+ onMessageReceived: Event<string> = this.messageReceivedEmitter.event;
25
+ private errorEmitter = new Emitter<Error>();
26
+ onError: Event<Error> = this.errorEmitter.event;
27
+ private closeEmitter = new Emitter<void>();
28
+ onClose: Event<void> = this.closeEmitter.event;
29
+
30
+ // these constants are for the message header, see: https://microsoft.github.io/debug-adapter-protocol/overview#header-part
31
+ private static TWO_CRLF = '\r\n\r\n';
32
+ private static CONTENT_LENGTH = 'Content-Length';
33
+ private contentLength: number = -1;
34
+ private buffer: Buffer = Buffer.alloc(0);
35
+
36
+ constructor(private fromAdapter: stream.Readable, private toAdapter: stream.Writable) {
37
+ super();
38
+
39
+ this.fromAdapter.on('data', (data: Buffer) => this.handleData(data));
40
+ this.fromAdapter.on('close', () => this.closeEmitter.fire()); // FIXME pass a proper exit code
41
+ this.fromAdapter.on('error', error => this.errorEmitter.fire(error));
42
+ this.toAdapter.on('error', error => this.errorEmitter.fire(error));
43
+ };
44
+
45
+ send(message: string): void {
46
+ const msg = `${StreamCommunicationProvider.CONTENT_LENGTH}: ${Buffer.byteLength(message, 'utf8')}${StreamCommunicationProvider.TWO_CRLF}${message}`;
47
+
48
+ this.toAdapter.write(msg, 'utf8');
49
+ }
50
+
51
+ protected handleData(data: Buffer): void {
52
+ this.buffer = Buffer.concat([this.buffer, data]);
53
+
54
+ while (true) {
55
+ if (this.contentLength >= 0) {
56
+ if (this.buffer.length >= this.contentLength) {
57
+ const message = this.buffer.toString('utf8', 0, this.contentLength);
58
+ this.buffer = this.buffer.slice(this.contentLength);
59
+ this.contentLength = -1;
60
+
61
+ if (message.length > 0) {
62
+ this.messageReceivedEmitter.fire(message);
63
+ }
64
+ continue; // there may be more complete messages to process
65
+ }
66
+ } else {
67
+ let idx = this.buffer.indexOf(StreamCommunicationProvider.CONTENT_LENGTH);
68
+ if (idx > 0) {
69
+ // log unrecognized output
70
+ const output = this.buffer.slice(0, idx);
71
+ console.log(output.toString('utf-8'));
72
+
73
+ this.buffer = this.buffer.slice(idx);
74
+ }
75
+
76
+ idx = this.buffer.indexOf(StreamCommunicationProvider.TWO_CRLF);
77
+ if (idx !== -1) {
78
+ const header = this.buffer.toString('utf8', 0, idx);
79
+ const lines = header.split('\r\n');
80
+ for (let i = 0; i < lines.length; i++) {
81
+ const pair = lines[i].split(/: +/);
82
+ if (pair[0] === StreamCommunicationProvider.CONTENT_LENGTH) {
83
+ this.contentLength = +pair[1];
84
+ }
85
+ }
86
+ this.buffer = this.buffer.slice(idx + StreamCommunicationProvider.TWO_CRLF.length);
87
+ continue;
88
+ }
89
+ }
90
+ break;
91
+ }
92
+ }
93
+ }
@@ -16,7 +16,7 @@
16
16
 
17
17
  import * as fs from '@theia/core/shared/fs-extra';
18
18
  import * as path from 'path';
19
- import { DebugAdapterExecutable, DebugAdapterContribution } from '../../common/debug-model';
19
+ import { DebugAdapterExecutable, DebugAdapterContribution } from '../debug-model';
20
20
  import { isWindows, isOSX } from '@theia/core/lib/common/os';
21
21
  import { IJSONSchema, IJSONSchemaSnippet } from '@theia/core/lib/common/json-schema';
22
22
  import { deepClone } from '@theia/core/lib/common/objects';
@@ -1 +0,0 @@
1
- {"version":3,"file":"debug-model.d.ts","sourceRoot":"","sources":["../../src/common/debug-model.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"debug-model.js","sourceRoot":"","sources":["../../src/common/debug-model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;kFAckF;;;AAiBlF,kHAAkH;AAElH;;GAEG;AACU,QAAA,mBAAmB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAYjE;;GAEG;AACU,QAAA,0BAA0B,GAAG,MAAM,CAAC,4BAA4B,CAAC,CAAC;AAmD/E;;GAEG;AACU,QAAA,mBAAmB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAUjE;;GAEG;AACU,QAAA,wBAAwB,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC"}