diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index b3167bf60cc..9e6dfecd6a4 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -55,6 +55,7 @@ "./vs/vscode.d.ts", "./vs/vscode.proposed.d.ts", "./vs/workbench/api/browser/viewsExtensionPoint.ts", + "./vs/workbench/api/browser/mainThreadDebugService.ts", "./vs/workbench/api/common/extHostCustomers.ts", "./vs/workbench/api/common/configurationExtensionPoint.ts", "./vs/workbench/api/common/jsonValidationExtensionPoint.ts", @@ -63,7 +64,6 @@ "./vs/workbench/api/electron-browser/mainThreadCommands.ts", "./vs/workbench/api/electron-browser/mainThreadConfiguration.ts", "./vs/workbench/api/electron-browser/mainThreadConsole.ts", - "./vs/workbench/api/electron-browser/mainThreadDebugService.ts", "./vs/workbench/api/electron-browser/mainThreadDecorations.ts", "./vs/workbench/api/electron-browser/mainThreadDiagnostics.ts", "./vs/workbench/api/electron-browser/mainThreadDialogs.ts", diff --git a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts b/src/vs/workbench/api/browser/mainThreadDebugService.ts similarity index 99% rename from src/vs/workbench/api/electron-browser/mainThreadDebugService.ts rename to src/vs/workbench/api/browser/mainThreadDebugService.ts index b7783b208db..3b727aa3f6f 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/browser/mainThreadDebugService.ts @@ -12,7 +12,7 @@ import { } from 'vs/workbench/api/common/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import severity from 'vs/base/common/severity'; -import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter'; +import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/contrib/debug/common/debugUtils'; @@ -150,7 +150,6 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb return Promise.resolve(); } - public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasProvideDebugAdapter: boolean, handle: number): Promise { const provider = { diff --git a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts index 6484ec367cc..ad49c1dcd65 100644 --- a/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/electron-browser/extensionHost.contribution.ts @@ -19,7 +19,7 @@ import './mainThreadClipboard'; import './mainThreadCommands'; import './mainThreadConfiguration'; import './mainThreadConsole'; -import './mainThreadDebugService'; +import '../browser/mainThreadDebugService'; import './mainThreadDecorations'; import './mainThreadDiagnostics'; import './mainThreadDialogs'; diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index aab9899ac45..e4f5d8dafb7 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -15,7 +15,8 @@ import { } from 'vs/workbench/api/common/extHost.protocol'; import * as vscode from 'vscode'; import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable } from 'vs/workbench/api/node/extHostTypes'; -import { ExecutableDebugAdapter, SocketDebugAdapter, AbstractDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter'; +import { ExecutableDebugAdapter, SocketDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter'; +import { AbstractDebugAdapter } from 'vs/workbench/contrib/debug/common/abstractDebugAdapter'; import { IExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace'; import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors'; diff --git a/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts b/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts new file mode 100644 index 00000000000..53c93567d91 --- /dev/null +++ b/src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts @@ -0,0 +1,161 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter, Event } from 'vs/base/common/event'; +import { IDebugAdapter } from 'vs/workbench/contrib/debug/common/debug'; + +/** + * Abstract implementation of the low level API for a debug adapter. + * Missing is how this API communicates with the debug adapter. + */ +export abstract class AbstractDebugAdapter implements IDebugAdapter { + + private sequence: number; + private pendingRequests: Map void>; + private requestCallback: (request: DebugProtocol.Request) => void; + private eventCallback: (request: DebugProtocol.Event) => void; + private messageCallback: (message: DebugProtocol.ProtocolMessage) => void; + protected readonly _onError: Emitter; + protected readonly _onExit: Emitter; + + constructor() { + this.sequence = 1; + this.pendingRequests = new Map(); + this._onError = new Emitter(); + this._onExit = new Emitter(); + } + + abstract startSession(): Promise; + + abstract stopSession(): Promise; + + abstract sendMessage(message: DebugProtocol.ProtocolMessage): void; + + get onError(): Event { + return this._onError.event; + } + + get onExit(): Event { + return this._onExit.event; + } + + onMessage(callback: (message: DebugProtocol.ProtocolMessage) => void): void { + if (this.eventCallback) { + this._onError.fire(new Error(`attempt to set more than one 'Message' callback`)); + } + this.messageCallback = callback; + } + + onEvent(callback: (event: DebugProtocol.Event) => void): void { + if (this.eventCallback) { + this._onError.fire(new Error(`attempt to set more than one 'Event' callback`)); + } + this.eventCallback = callback; + } + + onRequest(callback: (request: DebugProtocol.Request) => void): void { + if (this.requestCallback) { + this._onError.fire(new Error(`attempt to set more than one 'Request' callback`)); + } + this.requestCallback = callback; + } + + sendResponse(response: DebugProtocol.Response): void { + if (response.seq > 0) { + this._onError.fire(new Error(`attempt to send more than one response for command ${response.command}`)); + } + else { + this.internalSend('response', response); + } + } + + sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void { + const request: any = { + command: command + }; + if (args && Object.keys(args).length > 0) { + request.arguments = args; + } + this.internalSend('request', request); + if (typeof timeout === 'number') { + const timer = setTimeout(() => { + clearTimeout(timer); + const clb = this.pendingRequests.get(request.seq); + if (clb) { + this.pendingRequests.delete(request.seq); + const err: DebugProtocol.Response = { + type: 'response', + seq: 0, + request_seq: request.seq, + success: false, + command, + message: `timeout after ${timeout} ms` + }; + clb(err); + } + }, timeout); + } + if (clb) { + // store callback for this request + this.pendingRequests.set(request.seq, clb); + } + } + + acceptMessage(message: DebugProtocol.ProtocolMessage): void { + if (this.messageCallback) { + this.messageCallback(message); + } + else { + switch (message.type) { + case 'event': + if (this.eventCallback) { + this.eventCallback(message); + } + break; + case 'request': + if (this.requestCallback) { + this.requestCallback(message); + } + break; + case 'response': + const response = message; + const clb = this.pendingRequests.get(response.request_seq); + if (clb) { + this.pendingRequests.delete(response.request_seq); + clb(response); + } + break; + } + } + } + + private internalSend(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void { + message.type = typ; + message.seq = this.sequence++; + this.sendMessage(message); + } + + protected cancelPending() { + const pending = this.pendingRequests; + this.pendingRequests = new Map(); + setTimeout(_ => { + pending.forEach((callback, request_seq) => { + const err: DebugProtocol.Response = { + type: 'response', + seq: 0, + request_seq, + success: false, + command: 'canceled', + message: 'canceled' + }; + callback(err); + }); + }, 1000); + } + + dispose(): void { + this.cancelPending(); + } +} diff --git a/src/vs/workbench/contrib/debug/node/debugAdapter.ts b/src/vs/workbench/contrib/debug/node/debugAdapter.ts index b98c5d5355e..360a27a9329 100644 --- a/src/vs/workbench/contrib/debug/node/debugAdapter.ts +++ b/src/vs/workbench/contrib/debug/node/debugAdapter.ts @@ -12,170 +12,11 @@ import * as path from 'vs/base/common/path'; import * as strings from 'vs/base/common/strings'; import * as objects from 'vs/base/common/objects'; import * as platform from 'vs/base/common/platform'; -import { Emitter, Event } from 'vs/base/common/event'; import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IOutputService } from 'vs/workbench/contrib/output/common/output'; -import { IDebugAdapter, IDebugAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IDebugAdapterServer } from 'vs/workbench/contrib/debug/common/debug'; +import { IDebugAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IDebugAdapterServer } from 'vs/workbench/contrib/debug/common/debug'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; - -/** - * Abstract implementation of the low level API for a debug adapter. - * Missing is how this API communicates with the debug adapter. - */ -export abstract class AbstractDebugAdapter implements IDebugAdapter { - - private sequence: number; - private pendingRequests: Map void>; - private requestCallback: (request: DebugProtocol.Request) => void; - private eventCallback: (request: DebugProtocol.Event) => void; - private messageCallback: (message: DebugProtocol.ProtocolMessage) => void; - - protected readonly _onError: Emitter; - protected readonly _onExit: Emitter; - - constructor() { - this.sequence = 1; - this.pendingRequests = new Map(); - - this._onError = new Emitter(); - this._onExit = new Emitter(); - } - - abstract startSession(): Promise; - abstract stopSession(): Promise; - - abstract sendMessage(message: DebugProtocol.ProtocolMessage): void; - - get onError(): Event { - return this._onError.event; - } - - get onExit(): Event { - return this._onExit.event; - } - - onMessage(callback: (message: DebugProtocol.ProtocolMessage) => void): void { - if (this.eventCallback) { - this._onError.fire(new Error(`attempt to set more than one 'Message' callback`)); - } - this.messageCallback = callback; - } - - onEvent(callback: (event: DebugProtocol.Event) => void): void { - if (this.eventCallback) { - this._onError.fire(new Error(`attempt to set more than one 'Event' callback`)); - } - this.eventCallback = callback; - } - - onRequest(callback: (request: DebugProtocol.Request) => void): void { - if (this.requestCallback) { - this._onError.fire(new Error(`attempt to set more than one 'Request' callback`)); - } - this.requestCallback = callback; - } - - sendResponse(response: DebugProtocol.Response): void { - if (response.seq > 0) { - this._onError.fire(new Error(`attempt to send more than one response for command ${response.command}`)); - } else { - this.internalSend('response', response); - } - } - - sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): void { - - const request: any = { - command: command - }; - if (args && Object.keys(args).length > 0) { - request.arguments = args; - } - - this.internalSend('request', request); - - if (typeof timeout === 'number') { - const timer = setTimeout(() => { - clearTimeout(timer); - const clb = this.pendingRequests.get(request.seq); - if (clb) { - this.pendingRequests.delete(request.seq); - const err: DebugProtocol.Response = { - type: 'response', - seq: 0, - request_seq: request.seq, - success: false, - command, - message: `timeout after ${timeout} ms` - }; - clb(err); - } - }, timeout); - } - - if (clb) { - // store callback for this request - this.pendingRequests.set(request.seq, clb); - } - } - - acceptMessage(message: DebugProtocol.ProtocolMessage): void { - if (this.messageCallback) { - this.messageCallback(message); - } else { - switch (message.type) { - case 'event': - if (this.eventCallback) { - this.eventCallback(message); - } - break; - case 'request': - if (this.requestCallback) { - this.requestCallback(message); - } - break; - case 'response': - const response = message; - const clb = this.pendingRequests.get(response.request_seq); - if (clb) { - this.pendingRequests.delete(response.request_seq); - clb(response); - } - break; - } - } - } - - private internalSend(typ: 'request' | 'response' | 'event', message: DebugProtocol.ProtocolMessage): void { - - message.type = typ; - message.seq = this.sequence++; - - this.sendMessage(message); - } - - protected cancelPending() { - const pending = this.pendingRequests; - this.pendingRequests = new Map(); - setTimeout(_ => { - pending.forEach((callback, request_seq) => { - const err: DebugProtocol.Response = { - type: 'response', - seq: 0, - request_seq, - success: false, - command: 'canceled', - message: 'canceled' - }; - callback(err); - }); - }, 1000); - } - - dispose(): void { - this.cancelPending(); - } -} +import { AbstractDebugAdapter } from '../common/abstractDebugAdapter'; /** * An implementation that communicates via two streams with the debug adapter.