提交 8780c7b4 编写于 作者: A Andre Weinand

finalize DA & Tracker Debug APIs

上级 0f3eefc6
...@@ -592,15 +592,15 @@ declare module 'vscode' { ...@@ -592,15 +592,15 @@ declare module 'vscode' {
export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer | DebugAdapterImplementation; export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer | DebugAdapterImplementation;
export interface DebugAdapterProvider { export interface DebugAdapterDescriptorFactory {
/** /**
* 'provideDebugAdapter' is called at the start of a debug session to provide details about the debug adapter to use. * 'createDebugAdapterDescriptor' is called at the start of a debug session to provide details about the debug adapter to use.
* These details must be returned as objects of type [DebugAdapterDescriptor](#DebugAdapterDescriptor). * These details must be returned as objects of type [DebugAdapterDescriptor](#DebugAdapterDescriptor).
* Currently two types of debug adapters are supported: * Currently two types of debug adapters are supported:
* - a debug adapter executable is specified as a command path and arguments (see [DebugAdapterExecutable](#DebugAdapterExecutable)), * - a debug adapter executable is specified as a command path and arguments (see [DebugAdapterExecutable](#DebugAdapterExecutable)),
* - a debug adapter server reachable via a communication port (see [DebugAdapterServer](#DebugAdapterServer)). * - a debug adapter server reachable via a communication port (see [DebugAdapterServer](#DebugAdapterServer)).
* If the method is not implemented the default behavior is this: * If the method is not implemented the default behavior is this:
* provideDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable) { * createDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable) {
* if (typeof session.configuration.debugServer === 'number') { * if (typeof session.configuration.debugServer === 'number') {
* return new DebugAdapterServer(session.configuration.debugServer); * return new DebugAdapterServer(session.configuration.debugServer);
* } * }
...@@ -610,29 +610,7 @@ declare module 'vscode' { ...@@ -610,29 +610,7 @@ declare module 'vscode' {
* @param executable The debug adapter's executable information as specified in the package.json (or undefined if no such information exists). * @param executable The debug adapter's executable information as specified in the package.json (or undefined if no such information exists).
* @return a [debug adapter descriptor](#DebugAdapterDescriptor) or undefined. * @return a [debug adapter descriptor](#DebugAdapterDescriptor) or undefined.
*/ */
provideDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor>; createDebugAdapterDescriptor(session: DebugSession, executable: DebugAdapterExecutable | undefined): ProviderResult<DebugAdapterDescriptor>;
}
export namespace debug {
/**
* Register a [debug adapter provider](#DebugAdapterProvider) for a specific debug type.
* An extension is only allowed to register a DebugAdapterProvider for the debug type(s) defined by the extension. Otherwise an error is thrown.
* Registering more than one DebugAdapterProvider for a debug type results in an error.
*
* @param type The debug type for which the provider is registered.
* @param provider The [debug adapter provider](#DebugAdapterProvider) to register.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerDebugAdapterProvider(debugType: string, provider: DebugAdapterProvider): Disposable;
/**
* Register a factory callback for the given debug type that is is called at the start of a debug session in order
* to return a "tracker" object that provides read-access to the communication between VS Code and a debug adapter.
*
* @param debugType A specific debug type or '*' for matching all debug types.
* @param callback A factory callback that is called at the start of a debug session to return a tracker object or `undefined`.
*/
export function registerDebugAdapterTracker(debugType: string, callback: (session: DebugSession) => DebugAdapterTracker | undefined): Disposable;
} }
/** /**
...@@ -650,15 +628,51 @@ declare module 'vscode' { ...@@ -650,15 +628,51 @@ declare module 'vscode' {
debugAdapterExit?(code?: number, signal?: string): void; debugAdapterExit?(code?: number, signal?: string): void;
} }
export interface DebugAdapterTrackerFactory {
/**
* The method 'createDebugAdapterTracker' is called at the start of a debug session in order
* to return a "tracker" object that provides read-access to the communication between VS Code and a debug adapter.
*
* @param session The [debug session](#DebugSession) for which the debug adapter tracker will be used.
* @return A [debug adapter tracker](#DebugAdapterTracker) or undefined.
*/
createDebugAdapterTracker(session: DebugSession): ProviderResult<DebugAdapterTracker>;
}
export namespace debug {
/**
* Register a [debug adapter descriptor factory](#DebugAdapterDescriptorFactory) for a specific debug type.
* An extension is only allowed to register a DebugAdapterDescriptorFactory for the debug type(s) defined by the extension. Otherwise an error is thrown.
* Registering more than one DebugAdapterDescriptorFactory for a debug type results in an error.
*
* @param debugType The debug type for which the factory is registered.
* @param factory The [debug adapter descriptor factory](#DebugAdapterDescriptorFactory) to register.
* @return A [disposable](#Disposable) that unregisters this factory when being disposed.
*/
export function registerDebugAdapterDescriptorFactory(debugType: string, factory: DebugAdapterDescriptorFactory): Disposable;
/**
* Register a debug adapter tracker factory for the given debug type.
*
* @param debugType The debug type for which the factory is registered or '*' for matching all debug types.
* @param factory The [debug adapter tracker factory](#DebugAdapterTrackerFactory) to register.
* @return A [disposable](#Disposable) that unregisters this factory when being disposed.
*/
export function registerDebugAdapterTrackerFactory(debugType: string, factory: DebugAdapterTrackerFactory): Disposable;
}
// deprecated
export interface DebugConfigurationProvider { export interface DebugConfigurationProvider {
/** /**
* Deprecated, use DebugAdapterProvider.provideDebugAdapter instead. * Deprecated, use DebugAdapterDescriptorFactory.provideDebugAdapter instead.
* @deprecated Use DebugAdapterProvider.provideDebugAdapter instead * @deprecated Use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead
*/ */
debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>; debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>;
/** /**
* Preliminary API, do not use in production. * Deprecated, use DebugAdapterTrackerFactory.createDebugAdapterTracker instead.
* @deprecated Use DebugAdapterTrackerFactory.createDebugAdapterTracker instead
* *
* The optional method 'provideDebugAdapterTracker' is called at the start of a debug session to provide a tracker that gives access to the communication between VS Code and a Debug Adapter. * The optional method 'provideDebugAdapterTracker' is called at the start of a debug session to provide a tracker that gives access to the communication between VS Code and a Debug Adapter.
* @param session The [debug session](#DebugSession) for which the tracker will be used. * @param session The [debug session](#DebugSession) for which the tracker will be used.
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { URI as uri } from 'vs/base/common/uri'; import { URI as uri } from 'vs/base/common/uri';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider, IDebugSession, IDebugAdapterFactory } from 'vs/workbench/parts/debug/common/debug'; import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, ITerminalSettings, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugSession, IDebugAdapterFactory, IDebugAdapterTrackerFactory } from 'vs/workbench/parts/debug/common/debug';
import { import {
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext, ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto IExtHostContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, ISourceBreakpointDto, IFunctionBreakpointDto, IDebugSessionDto
...@@ -25,7 +25,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb ...@@ -25,7 +25,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
private _debugAdapters: Map<number, ExtensionHostDebugAdapter>; private _debugAdapters: Map<number, ExtensionHostDebugAdapter>;
private _debugAdaptersHandleCounter = 1; private _debugAdaptersHandleCounter = 1;
private _debugConfigurationProviders: Map<number, IDebugConfigurationProvider>; private _debugConfigurationProviders: Map<number, IDebugConfigurationProvider>;
private _debugAdapterProviders: Map<number, IDebugAdapterProvider>; private _debugAdapterDescriptorFactories: Map<number, IDebugAdapterDescriptorFactory>;
private _debugAdapterTrackerFactories: Map<number, IDebugAdapterTrackerFactory>;
private _sessions: Set<DebugSessionUUID>; private _sessions: Set<DebugSessionUUID>;
constructor( constructor(
...@@ -51,7 +52,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb ...@@ -51,7 +52,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
this._debugAdapters = new Map(); this._debugAdapters = new Map();
this._debugConfigurationProviders = new Map(); this._debugConfigurationProviders = new Map();
this._debugAdapterProviders = new Map(); this._debugAdapterDescriptorFactories = new Map();
this._debugAdapterTrackerFactories = new Map();
this._sessions = new Set(); this._sessions = new Set();
} }
...@@ -184,25 +186,43 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb ...@@ -184,25 +186,43 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
} }
} }
public $registerDebugAdapterProvider(debugType: string, handle: number): Thenable<void> { public $registerDebugAdapterDescriptorFactory(debugType: string, handle: number): Thenable<void> {
const provider = <IDebugAdapterProvider>{ const provider = <IDebugAdapterDescriptorFactory>{
type: debugType, type: debugType,
provideDebugAdapter: session => { createDebugAdapterDescriptor: session => {
return Promise.resolve(this._proxy.$provideDebugAdapter(handle, this.getSessionDto(session))); return Promise.resolve(this._proxy.$provideDebugAdapter(handle, this.getSessionDto(session)));
} }
}; };
this._debugAdapterProviders.set(handle, provider); this._debugAdapterDescriptorFactories.set(handle, provider);
this._toDispose.push(this.debugService.getConfigurationManager().registerDebugAdapterProvider(provider)); this._toDispose.push(this.debugService.getConfigurationManager().registerDebugAdapterDescriptorFactory(provider));
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
public $unregisterDebugAdapterProvider(handle: number): void { public $unregisterDebugAdapterDescriptorFactory(handle: number): void {
const provider = this._debugAdapterProviders.get(handle); const provider = this._debugAdapterDescriptorFactories.get(handle);
if (provider) { if (provider) {
this._debugAdapterProviders.delete(handle); this._debugAdapterDescriptorFactories.delete(handle);
this.debugService.getConfigurationManager().unregisterDebugAdapterProvider(provider); this.debugService.getConfigurationManager().unregisterDebugAdapterDescriptorFactory(provider);
}
}
public $registerDebugAdapterTrackerFactory(debugType: string, handle: number) {
const factory = <IDebugAdapterTrackerFactory>{
type: debugType,
};
this._debugAdapterTrackerFactories.set(handle, factory);
this._toDispose.push(this.debugService.getConfigurationManager().registerDebugAdapterTrackerFactory(factory));
return Promise.resolve(undefined);
}
public $unregisterDebugAdapterTrackerFactory(handle: number) {
const factory = this._debugAdapterTrackerFactories.get(handle);
if (factory) {
this._debugAdapterTrackerFactories.delete(handle);
this.debugService.getConfigurationManager().unregisterDebugAdapterTrackerFactory(factory);
} }
} }
......
...@@ -678,11 +678,11 @@ export function createApiFactory( ...@@ -678,11 +678,11 @@ export function createApiFactory(
registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider) { registerDebugConfigurationProvider(debugType: string, provider: vscode.DebugConfigurationProvider) {
return extHostDebugService.registerDebugConfigurationProvider(debugType, provider); return extHostDebugService.registerDebugConfigurationProvider(debugType, provider);
}, },
registerDebugAdapterProvider(debugType: string, provider: vscode.DebugAdapterProvider) { registerDebugAdapterDescriptorFactory(debugType: string, factory: vscode.DebugAdapterDescriptorFactory) {
return extHostDebugService.registerDebugAdapterProvider(extension, debugType, provider); return extHostDebugService.registerDebugAdapterDescriptorFactory(extension, debugType, factory);
}, },
registerDebugAdapterTracker(debugType: string, callback: (session: vscode.DebugSession) => vscode.DebugAdapterTracker | undefined) { registerDebugAdapterTrackerFactory(debugType: string, factory: vscode.DebugAdapterTrackerFactory) {
return extHostDebugService.registerDebugAdapterTracker(debugType, callback); return extHostDebugService.registerDebugAdapterTrackerFactory(debugType, factory);
}, },
startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration) { startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration) {
return extHostDebugService.startDebugging(folder, nameOrConfig); return extHostDebugService.startDebugging(folder, nameOrConfig);
......
...@@ -596,9 +596,11 @@ export interface MainThreadDebugServiceShape extends IDisposable { ...@@ -596,9 +596,11 @@ export interface MainThreadDebugServiceShape extends IDisposable {
$acceptDAError(handle: number, name: string, message: string, stack: string): void; $acceptDAError(handle: number, name: string, message: string, stack: string): void;
$acceptDAExit(handle: number, code: number, signal: string): void; $acceptDAExit(handle: number, code: number, signal: string): void;
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasProvideDaMethod: boolean, hasProvideTrackerMethod: boolean, handle: number): Thenable<void>; $registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasProvideDaMethod: boolean, hasProvideTrackerMethod: boolean, handle: number): Thenable<void>;
$registerDebugAdapterProvider(type: string, handle: number): Thenable<void>; $registerDebugAdapterDescriptorFactory(type: string, handle: number): Thenable<void>;
$registerDebugAdapterTrackerFactory(type: string, handle: number);
$unregisterDebugConfigurationProvider(handle: number): void; $unregisterDebugConfigurationProvider(handle: number): void;
$unregisterDebugAdapterProvider(handle: number): void; $unregisterDebugAdapterDescriptorFactory(handle: number): void;
$unregisterDebugAdapterTrackerFactory(handle: number): void;
$startDebugging(folder: UriComponents | undefined, nameOrConfig: string | vscode.DebugConfiguration): Thenable<boolean>; $startDebugging(folder: UriComponents | undefined, nameOrConfig: string | vscode.DebugConfiguration): Thenable<boolean>;
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Thenable<any>; $customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Thenable<any>;
$appendDebugConsole(value: string): void; $appendDebugConsole(value: string): void;
......
...@@ -36,10 +36,13 @@ import { IExtensionDescription } from 'vs/workbench/services/extensions/common/e ...@@ -36,10 +36,13 @@ import { IExtensionDescription } from 'vs/workbench/services/extensions/common/e
export class ExtHostDebugService implements ExtHostDebugServiceShape { export class ExtHostDebugService implements ExtHostDebugServiceShape {
private _configProviderHandleCounter: number; private _configProviderHandleCounter: number;
private _configProviders: TypeProviderPair[]; private _configProviders: ConfigProviderTuple[];
private _adapterProviderHandleCounter: number; private _adapterFactoryHandleCounter: number;
private _adapterProviders: TypeDaProviderPair[]; private _adapterFactories: DescriptorFactoryTuple[];
private _trackerFactoryHandleCounter: number;
private _trackerFactories: TrackerFactoryTuple[];
private _debugServiceProxy: MainThreadDebugServiceShape; private _debugServiceProxy: MainThreadDebugServiceShape;
private _debugSessions: Map<DebugSessionUUID, ExtHostDebugSession> = new Map<DebugSessionUUID, ExtHostDebugSession>(); private _debugSessions: Map<DebugSessionUUID, ExtHostDebugSession> = new Map<DebugSessionUUID, ExtHostDebugSession>();
...@@ -88,8 +91,11 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { ...@@ -88,8 +91,11 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this._configProviderHandleCounter = 0; this._configProviderHandleCounter = 0;
this._configProviders = []; this._configProviders = [];
this._adapterProviderHandleCounter = 0; this._adapterFactoryHandleCounter = 0;
this._adapterProviders = []; this._adapterFactories = [];
this._trackerFactoryHandleCounter = 0;
this._trackerFactories = [];
this._aexCommands = new Map(); this._aexCommands = new Map();
this._debugAdapters = new Map(); this._debugAdapters = new Map();
...@@ -252,42 +258,48 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { ...@@ -252,42 +258,48 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}); });
} }
public registerDebugAdapterProvider(extension: IExtensionDescription, type: string, provider: vscode.DebugAdapterProvider): vscode.Disposable { public registerDebugAdapterDescriptorFactory(extension: IExtensionDescription, type: string, factory: vscode.DebugAdapterDescriptorFactory): vscode.Disposable {
if (!provider) { if (!factory) {
return new Disposable(() => { }); return new Disposable(() => { });
} }
// a DebugAdapterProvider can only be registered in the extension that contributes the debugger // a DebugAdapterDescriptorFactory can only be registered in the extension that contributes the debugger
if (!this.definesDebugType(extension, type)) { if (!this.definesDebugType(extension, type)) {
throw new Error(`method 'provideDebugAdapter' must only be called from the extension that defines the '${type}' debugger.`); throw new Error(`a DebugAdapterDescriptorFactory can only be registered from the extension that defines the '${type}' debugger.`);
} }
// make sure that only one provider for this type is registered // make sure that only one factory for this type is registered
if (this.getAdapterProviderByType(type)) { if (this.getAdapterFactoryByType(type)) {
throw new Error(`a provider with method 'provideDebugAdapter' can only be registered once per a type.`); throw new Error(`a DebugAdapterDescriptorFactory can only be registered once per a type.`);
} }
let handle = this._adapterProviderHandleCounter++; let handle = this._adapterFactoryHandleCounter++;
this._adapterProviders.push({ type, handle, provider }); this._adapterFactories.push({ type, handle, factory });
this._debugServiceProxy.$registerDebugAdapterProvider(type, handle); this._debugServiceProxy.$registerDebugAdapterDescriptorFactory(type, handle);
return new Disposable(() => { return new Disposable(() => {
this._adapterProviders = this._adapterProviders.filter(p => p.provider !== provider); // remove this._adapterFactories = this._adapterFactories.filter(p => p.factory !== factory); // remove
this._debugServiceProxy.$unregisterDebugAdapterProvider(handle); this._debugServiceProxy.$unregisterDebugAdapterDescriptorFactory(handle);
}); });
} }
public registerDebugAdapterTracker(debugType: string, callback: (session: vscode.DebugSession) => vscode.DebugAdapterTracker | undefined) { public registerDebugAdapterTrackerFactory(type: string, factory: vscode.DebugAdapterTrackerFactory): vscode.Disposable {
const provider: vscode.DebugConfigurationProvider = { if (!factory) {
provideDebugAdapterTracker(session: vscode.DebugSession) { return new Disposable(() => { });
return callback(session); }
}
}; let handle = this._trackerFactoryHandleCounter++;
this._trackerFactories.push({ type, handle, factory });
return this.registerDebugConfigurationProvider(debugType, provider); this._debugServiceProxy.$registerDebugAdapterTrackerFactory(type, handle);
return new Disposable(() => {
this._trackerFactories = this._trackerFactories.filter(p => p.factory !== factory); // remove
this._debugServiceProxy.$unregisterDebugAdapterTrackerFactory(handle);
});
} }
// RPC methods (ExtHostDebugServiceShape) // RPC methods (ExtHostDebugServiceShape)
...@@ -365,7 +377,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { ...@@ -365,7 +377,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
const mythis = this; const mythis = this;
const session = this.getSession(sessionDto); const session = this.getSession(sessionDto);
return this.getAdapterDescriptor(this.getAdapterProviderByType(session.type), session).then(x => { return this.getAdapterDescriptor(this.getAdapterFactoryByType(session.type), session).then(x => {
const adapter = this.convertToDto(x); const adapter = this.convertToDto(x);
let da: AbstractDebugAdapter | undefined = undefined; let da: AbstractDebugAdapter | undefined = undefined;
...@@ -626,18 +638,18 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { ...@@ -626,18 +638,18 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
} }
} }
private getAdapterProviderByType(type: string): vscode.DebugAdapterProvider { private getAdapterFactoryByType(type: string): vscode.DebugAdapterDescriptorFactory {
const results = this._adapterProviders.filter(p => p.type === type); const results = this._adapterFactories.filter(p => p.type === type);
if (results.length > 0) { if (results.length > 0) {
return results[0].provider; return results[0].factory;
} }
return undefined; return undefined;
} }
private getAdapterProviderByHandle(handle: number): vscode.DebugAdapterProvider { private getAdapterProviderByHandle(handle: number): vscode.DebugAdapterDescriptorFactory {
const results = this._adapterProviders.filter(p => p.handle === handle); const results = this._adapterFactories.filter(p => p.handle === handle);
if (results.length > 0) { if (results.length > 0) {
return results[0].provider; return results[0].factory;
} }
return undefined; return undefined;
} }
...@@ -671,9 +683,16 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { ...@@ -671,9 +683,16 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
const config = session.configuration; const config = session.configuration;
const type = config.type; const type = config.type;
const promises = this._configProviders
.filter(pair => pair.provider.provideDebugAdapterTracker && (pair.type === type || pair.type === '*')) const promises1 = this._configProviders
.map(pair => asThenable(() => pair.provider.provideDebugAdapterTracker(session, session.workspaceFolder, session.configuration, CancellationToken.None)).then(p => p).catch(err => null)); .filter(tuple => tuple.provider.provideDebugAdapterTracker && (tuple.type === type || tuple.type === '*'))
.map(tuple => asThenable(() => tuple.provider.provideDebugAdapterTracker(session, session.workspaceFolder, session.configuration, CancellationToken.None)).then(p => p).catch(err => null));
const promises2 = this._trackerFactories
.filter(tuple => tuple.type === type || tuple.type === '*')
.map(tuple => asThenable(() => tuple.factory.createDebugAdapterTracker(session)).then(p => p).catch(err => null));
const promises = promises1.concat(promises2);
return Promise.race([ return Promise.race([
Promise.all(promises).then(trackers => { Promise.all(promises).then(trackers => {
...@@ -695,7 +714,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { ...@@ -695,7 +714,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}); });
} }
private getAdapterDescriptor(adapterProvider: vscode.DebugAdapterProvider, session: ExtHostDebugSession): Thenable<vscode.DebugAdapterDescriptor> { private getAdapterDescriptor(adapterProvider: vscode.DebugAdapterDescriptorFactory, session: ExtHostDebugSession): Thenable<vscode.DebugAdapterDescriptor> {
// a "debugServer" attribute in the launch config takes precedence // a "debugServer" attribute in the launch config takes precedence
const serverPort = session.configuration.debugServer; const serverPort = session.configuration.debugServer;
...@@ -712,7 +731,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { ...@@ -712,7 +731,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
} }
if (adapterProvider) { if (adapterProvider) {
return asThenable(() => adapterProvider.provideDebugAdapter(session, this.daExecutableFromPackage(session))); return asThenable(() => adapterProvider.createDebugAdapterDescriptor(session, this.daExecutableFromPackage(session)));
} }
// try deprecated command based extension API "adapterExecutableCommand" to determine the executable // try deprecated command based extension API "adapterExecutableCommand" to determine the executable
...@@ -879,16 +898,22 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ ...@@ -879,16 +898,22 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ
} }
} }
interface TypeProviderPair { interface ConfigProviderTuple {
type: string; type: string;
handle: number; handle: number;
provider: vscode.DebugConfigurationProvider; provider: vscode.DebugConfigurationProvider;
} }
interface TypeDaProviderPair { interface DescriptorFactoryTuple {
type: string;
handle: number;
factory: vscode.DebugAdapterDescriptorFactory;
}
interface TrackerFactoryTuple {
type: string; type: string;
handle: number; handle: number;
provider: vscode.DebugAdapterProvider; factory: vscode.DebugAdapterTrackerFactory;
} }
class MultiTracker implements vscode.DebugAdapterTracker { class MultiTracker implements vscode.DebugAdapterTracker {
......
...@@ -537,9 +537,13 @@ export interface IDebugConfigurationProvider { ...@@ -537,9 +537,13 @@ export interface IDebugConfigurationProvider {
hasTracker: boolean; hasTracker: boolean;
} }
export interface IDebugAdapterProvider { export interface IDebugAdapterDescriptorFactory {
readonly type: string;
createDebugAdapterDescriptor(session: IDebugSession): Promise<IAdapterDescriptor>;
}
export interface IDebugAdapterTrackerFactory {
readonly type: string; readonly type: string;
provideDebugAdapter(session: IDebugSession): Promise<IAdapterDescriptor>;
} }
export interface ITerminalLauncher { export interface ITerminalLauncher {
...@@ -594,8 +598,11 @@ export interface IConfigurationManager { ...@@ -594,8 +598,11 @@ export interface IConfigurationManager {
registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable; registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable;
unregisterDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): void; unregisterDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): void;
registerDebugAdapterProvider(debugConfigurationProvider: IDebugAdapterProvider): IDisposable; registerDebugAdapterDescriptorFactory(debugAdapterDescriptorFactory: IDebugAdapterDescriptorFactory): IDisposable;
unregisterDebugAdapterProvider(debugConfigurationProvider: IDebugAdapterProvider): void; unregisterDebugAdapterDescriptorFactory(debugAdapterDescriptorFactory: IDebugAdapterDescriptorFactory): void;
registerDebugAdapterTrackerFactory(debugAdapterTrackerFactory: IDebugAdapterTrackerFactory): IDisposable;
unregisterDebugAdapterTrackerFactory(debugAdapterTrackerFactory: IDebugAdapterTrackerFactory): void;
resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: any): Thenable<any>; resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: any): Thenable<any>;
provideDebugAdapter(session: IDebugSession): Promise<IAdapterDescriptor | undefined>; provideDebugAdapter(session: IDebugSession): Promise<IAdapterDescriptor | undefined>;
......
...@@ -21,7 +21,7 @@ import { IFileService } from 'vs/platform/files/common/files'; ...@@ -21,7 +21,7 @@ import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands'; import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterProvider, IDebugAdapter, ITerminalSettings, ITerminalLauncher, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory } from 'vs/workbench/parts/debug/common/debug'; import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, ITerminalSettings, ITerminalLauncher, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory, IDebugAdapterTrackerFactory } from 'vs/workbench/parts/debug/common/debug';
import { Debugger } from 'vs/workbench/parts/debug/node/debugger'; import { Debugger } from 'vs/workbench/parts/debug/node/debugger';
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
...@@ -49,7 +49,8 @@ export class ConfigurationManager implements IConfigurationManager { ...@@ -49,7 +49,8 @@ export class ConfigurationManager implements IConfigurationManager {
private toDispose: IDisposable[]; private toDispose: IDisposable[];
private _onDidSelectConfigurationName = new Emitter<void>(); private _onDidSelectConfigurationName = new Emitter<void>();
private configProviders: IDebugConfigurationProvider[]; private configProviders: IDebugConfigurationProvider[];
private adapterProviders: IDebugAdapterProvider[]; private adapterProviders: IDebugAdapterDescriptorFactory[];
private adapterTrackerFactories: IDebugAdapterTrackerFactory[];
private debugAdapterFactories: Map<string, IDebugAdapterFactory>; private debugAdapterFactories: Map<string, IDebugAdapterFactory>;
private terminalLauncher: ITerminalLauncher; private terminalLauncher: ITerminalLauncher;
private debugConfigurationTypeContext: IContextKey<string>; private debugConfigurationTypeContext: IContextKey<string>;
...@@ -68,6 +69,7 @@ export class ConfigurationManager implements IConfigurationManager { ...@@ -68,6 +69,7 @@ export class ConfigurationManager implements IConfigurationManager {
) { ) {
this.configProviders = []; this.configProviders = [];
this.adapterProviders = []; this.adapterProviders = [];
this.adapterTrackerFactories = [];
this.debuggers = []; this.debuggers = [];
this.toDispose = []; this.toDispose = [];
this.registerListeners(lifecycleService); this.registerListeners(lifecycleService);
...@@ -121,16 +123,16 @@ export class ConfigurationManager implements IConfigurationManager { ...@@ -121,16 +123,16 @@ export class ConfigurationManager implements IConfigurationManager {
// debug adapter // debug adapter
public registerDebugAdapterProvider(debugAdapterProvider: IDebugAdapterProvider): IDisposable { public registerDebugAdapterDescriptorFactory(debugAdapterProvider: IDebugAdapterDescriptorFactory): IDisposable {
this.adapterProviders.push(debugAdapterProvider); this.adapterProviders.push(debugAdapterProvider);
return { return {
dispose: () => { dispose: () => {
this.unregisterDebugAdapterProvider(debugAdapterProvider); this.unregisterDebugAdapterDescriptorFactory(debugAdapterProvider);
} }
}; };
} }
public unregisterDebugAdapterProvider(debugAdapterProvider: IDebugAdapterProvider): void { public unregisterDebugAdapterDescriptorFactory(debugAdapterProvider: IDebugAdapterDescriptorFactory): void {
const ix = this.adapterProviders.indexOf(debugAdapterProvider); const ix = this.adapterProviders.indexOf(debugAdapterProvider);
if (ix >= 0) { if (ix >= 0) {
this.configProviders.splice(ix, 1); this.configProviders.splice(ix, 1);
...@@ -150,15 +152,33 @@ export class ConfigurationManager implements IConfigurationManager { ...@@ -150,15 +152,33 @@ export class ConfigurationManager implements IConfigurationManager {
} }
// try new proposed API // try new proposed API
const providers = this.adapterProviders.filter(p => p.type === config.type && p.provideDebugAdapter); const providers = this.adapterProviders.filter(p => p.type === config.type && p.createDebugAdapterDescriptor);
if (providers.length === 1) { if (providers.length === 1) {
return providers[0].provideDebugAdapter(session); return providers[0].createDebugAdapterDescriptor(session);
} else { } else {
// TODO@AW handle n > 1 case // TODO@AW handle n > 1 case
} }
return Promise.resolve(undefined); return Promise.resolve(undefined);
} }
// debug adapter trackers
public registerDebugAdapterTrackerFactory(debugAdapterTrackerFactory: IDebugAdapterTrackerFactory): IDisposable {
this.adapterTrackerFactories.push(debugAdapterTrackerFactory);
return {
dispose: () => {
this.unregisterDebugAdapterTrackerFactory(debugAdapterTrackerFactory);
}
};
}
public unregisterDebugAdapterTrackerFactory(debugAdapterTrackerFactory: IDebugAdapterTrackerFactory): void {
const ix = this.adapterTrackerFactories.indexOf(debugAdapterTrackerFactory);
if (ix >= 0) {
this.configProviders.splice(ix, 1);
}
}
// debug configurations // debug configurations
public registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable { public registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable {
...@@ -184,9 +204,17 @@ export class ConfigurationManager implements IConfigurationManager { ...@@ -184,9 +204,17 @@ export class ConfigurationManager implements IConfigurationManager {
} }
public needsToRunInExtHost(debugType: string): boolean { public needsToRunInExtHost(debugType: string): boolean {
// if the given debugType matches any registered tracker factory we need to run the DA in the EH
const providers = this.adapterTrackerFactories.filter(p => p.type === debugType || p.type === '*');
if (providers.length > 0) {
return true;
}
// TODO@AW deprecated
// if the given debugType matches any registered provider that has a provideTracker method, we need to run the DA in the EH // if the given debugType matches any registered provider that has a provideTracker method, we need to run the DA in the EH
const providers = this.configProviders.filter(p => p.hasTracker && (p.type === debugType || p.type === '*')); const providers2 = this.configProviders.filter(p => p.hasTracker && (p.type === debugType || p.type === '*'));
return providers.length > 0; return providers2.length > 0;
} }
public resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: IConfig): Thenable<IConfig> { public resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: IConfig): Thenable<IConfig> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册