提交 b9fc2c1c 编写于 作者: A Andre Weinand

debug api: add workspacefolder to DebugSession

上级 06a6d539
......@@ -566,6 +566,16 @@ declare module 'vscode' {
//#region André: debug
/**
* A debug session.
*/
export interface DebugSession {
/**
* The workspace folder of this DebugSession or undefined for a folderless setup.
*/
readonly workspaceFolder: WorkspaceFolder | undefined;
}
/**
* Represents a debug adapter executable and optional arguments passed to it.
*/
......@@ -638,25 +648,10 @@ declare module 'vscode' {
export type DebugAdapterDescriptor = DebugAdapterExecutable | DebugAdapterServer | DebugAdapterImplementation;
/**
* A Debug Adapter Tracker is a means to track the communication between VS Code and a Debug Adapter.
*/
export interface DebugAdapterTracker {
// VS Code -> Debug Adapter
startDebugAdapter?(): void;
toDebugAdapter?(message: any): void;
stopDebugAdapter?(): void;
// Debug Adapter -> VS Code
fromDebugAdapter?(message: any): void;
debugAdapterError?(error: Error): void;
debugAdapterExit?(code?: number, signal?: string): void;
}
export interface DebugConfigurationProvider {
/**
* Deprecated, use DebugConfigurationProvider.provideDebugAdapter instead.
* @deprecated Use DebugConfigurationProvider.provideDebugAdapter instead
* Deprecated, use DebugAdapterProvider.provideDebugAdapter instead.
* @deprecated Use DebugAdapterProvider.provideDebugAdapter instead
*/
debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult<DebugAdapterExecutable>;
......@@ -667,7 +662,7 @@ declare module 'vscode' {
* @param config The resolved debug configuration.
* @param token A cancellation token.
*/
provideDebugAdapterTracker?(session: DebugSession, folder: WorkspaceFolder | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugAdapterTracker>;
provideDebugAdapterTracker?(session: DebugSession, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugAdapterTracker>;
}
export interface DebugAdapterProvider {
......@@ -685,21 +680,35 @@ declare module 'vscode' {
* return executable;
* }
* @param session The [debug session](#DebugSession) for which the debug adapter will be used.
* @param folder The workspace folder from which the configuration originates from or undefined for a folderless setup.
* @param executable The debug adapter's executable information as specified in the package.json (or undefined if no such information exists).
* @param config The resolved debug configuration.
* @param token A cancellation token.
* @return a [debug adapter's descriptor](#DebugAdapterDescriptor) or undefined.
*/
provideDebugAdapter(session: DebugSession, folder: WorkspaceFolder | undefined, executable: DebugAdapterExecutable | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugAdapterDescriptor>;
provideDebugAdapter(session: DebugSession, executable: DebugAdapterExecutable | undefined, config: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugAdapterDescriptor>;
}
/**
* A Debug Adapter Tracker is a means to track the communication between VS Code and a Debug Adapter.
*/
export interface DebugAdapterTracker {
// VS Code -> Debug Adapter
startDebugAdapter?(): void;
toDebugAdapter?(message: any): void;
stopDebugAdapter?(): void;
// Debug Adapter -> VS Code
fromDebugAdapter?(message: any): void;
debugAdapterError?(error: Error): void;
debugAdapterExit?(code?: number, signal?: string): void;
}
export namespace debug {
/**
* Register a [debug adapter provider](#DebugConfigurationProvider) for a specific debug type.
* Register a [debug adapter provider](#DebugAdapterProvider) for a specific debug type.
* Only one provider can be registered for the same type.
* An extension is only allowed to register a DebugAdapterProvider with if the extension defines the debug type. Otherwise an error is thrown.
* Registering more than one DebugAdapterProvider for a type results in an error.
* An extension is only allowed to register a DebugAdapterProvider for the debug type 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.
......
......@@ -58,9 +58,9 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
// interface IDebugAdapterProvider
createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter {
createDebugAdapter(session: IDebugSession, config: IConfig): IDebugAdapter {
const handle = this._debugAdaptersHandleCounter++;
const da = new ExtensionHostDebugAdapter(handle, this._proxy, this.getSessionDto(session), folder, config);
const da = new ExtensionHostDebugAdapter(handle, this._proxy, this.getSessionDto(session), config);
this._debugAdapters.set(handle, da);
return da;
}
......@@ -185,8 +185,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
const provider = <IDebugAdapterProvider>{
type: debugType,
provideDebugAdapter: (session, folder, config) => {
return Promise.resolve(this._proxy.$provideDebugAdapter(handle, this.getSessionDto(session), folder, config));
provideDebugAdapter: (session, config) => {
return Promise.resolve(this._proxy.$provideDebugAdapter(handle, this.getSessionDto(session), config));
}
};
this._debugAdapterProviders.set(handle, provider);
......@@ -203,7 +203,6 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
}
}
public $startDebugging(_folderUri: uri | undefined, nameOrConfiguration: string | IConfig): Thenable<boolean> {
const folderUri = _folderUri ? uri.revive(_folderUri) : undefined;
const launch = this.debugService.getConfigurationManager().getLaunch(folderUri);
......@@ -256,7 +255,8 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return {
id: <DebugSessionUUID>session.getId(),
type: session.configuration.type,
name: session.configuration.name
name: session.configuration.name,
folderUri: session.root ? session.root.uri : undefined
};
}
return undefined;
......@@ -298,7 +298,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
*/
class ExtensionHostDebugAdapter extends AbstractDebugAdapter {
constructor(private _handle: number, private _proxy: ExtHostDebugServiceShape, private _sessionDto: IDebugSessionDto, private folder: IWorkspaceFolder, private config: IConfig) {
constructor(private _handle: number, private _proxy: ExtHostDebugServiceShape, private _sessionDto: IDebugSessionDto, private config: IConfig) {
super();
}
......@@ -311,7 +311,7 @@ class ExtensionHostDebugAdapter extends AbstractDebugAdapter {
}
public startSession(): Promise<void> {
return Promise.resolve(this._proxy.$startDASession(this._handle, this._sessionDto, this.folder ? this.folder.uri : undefined, this.config));
return Promise.resolve(this._proxy.$startDASession(this._handle, this._sessionDto, this.config));
}
public sendMessage(message: DebugProtocol.ProtocolMessage): void {
......
......@@ -968,18 +968,19 @@ export interface IDebugSessionDto {
id: DebugSessionUUID;
type: string;
name: string;
folderUri: UriComponents | undefined;
}
export interface ExtHostDebugServiceShape {
$substituteVariables(folder: UriComponents | undefined, config: IConfig): Thenable<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Thenable<void>;
$startDASession(handle: number, session: IDebugSessionDto, folder: UriComponents | undefined, debugConfiguration: IConfig): Thenable<void>;
$startDASession(handle: number, session: IDebugSessionDto, debugConfiguration: IConfig): Thenable<void>;
$stopDASession(handle: number): Thenable<void>;
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig): Thenable<IConfig>;
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined): Thenable<IConfig[]>;
$legacyDebugAdapterExecutable(handle: number, folderUri: UriComponents | undefined): Thenable<IAdapterDescriptor>; // TODO@AW legacy
$provideDebugAdapter(handle: number, session: IDebugSessionDto, folderUri: UriComponents | undefined, debugConfiguration: IConfig): Thenable<IAdapterDescriptor>;
$provideDebugAdapter(handle: number, session: IDebugSessionDto, debugConfiguration: IConfig): Thenable<IAdapterDescriptor>;
$acceptDebugSessionStarted(session: IDebugSessionDto): void;
$acceptDebugSessionTerminated(session: IDebugSessionDto): void;
$acceptDebugSessionActiveChanged(session: IDebugSessionDto): void;
......
......@@ -364,10 +364,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return Promise.resolve(this._variableResolver.resolveAny(ws, config));
}
public $startDASession(handle: number, sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): Thenable<void> {
public $startDASession(handle: number, sessionDto: IDebugSessionDto, config: vscode.DebugConfiguration): Thenable<void> {
const mythis = this;
return this.getAdapterDescriptor(this.getAdapterProviderByType(config.type), sessionDto, folderUri, config).then(x => {
return this.getAdapterDescriptor(this.getAdapterProviderByType(config.type), sessionDto, config).then(x => {
const adapter = this.convertToDto(x);
let da: AbstractDebugAdapter | undefined = undefined;
......@@ -393,7 +393,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (da) {
this._debugAdapters.set(handle, da);
return this.getDebugAdapterTrackers(sessionDto, folderUri, config).then(tracker => {
return this.getDebugAdapterTrackers(sessionDto, config).then(tracker => {
if (tracker) {
this._debugAdaptersTrackers.set(handle, tracker);
......@@ -565,12 +565,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return asThenable(() => provider.debugAdapterExecutable(this.getFolder(folderUri), CancellationToken.None)).then(x => this.convertToDto(x));
}
public $provideDebugAdapter(handle: number, sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): Thenable<IAdapterDescriptor> {
public $provideDebugAdapter(handle: number, sessionDto: IDebugSessionDto, config: vscode.DebugConfiguration): Thenable<IAdapterDescriptor> {
let adapterProvider = this.getAdapterProviderByHandle(handle);
if (!adapterProvider) {
return Promise.reject(new Error('no handler found'));
}
return this.getAdapterDescriptor(adapterProvider, sessionDto, folderUri, config).then(x => this.convertToDto(x));
return this.getAdapterDescriptor(adapterProvider, sessionDto, config).then(x => this.convertToDto(x));
}
public $acceptDebugSessionStarted(sessionDto: IDebugSessionDto): void {
......@@ -668,15 +668,14 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return false;
}
private getDebugAdapterTrackers(sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): Promise<vscode.DebugAdapterTracker> {
private getDebugAdapterTrackers(sessionDto: IDebugSessionDto, config: vscode.DebugConfiguration): Promise<vscode.DebugAdapterTracker> {
const session = this.getSession(sessionDto);
const folder = this.getFolder(folderUri);
const type = config.type;
const promises = this._configProviders
.filter(pair => pair.provider.provideDebugAdapterTracker && (pair.type === type || pair.type === '*'))
.map(pair => asThenable(() => pair.provider.provideDebugAdapterTracker(session, folder, config, CancellationToken.None)).then(p => p).catch(err => null));
.map(pair => asThenable(() => pair.provider.provideDebugAdapterTracker(session, config, CancellationToken.None)).then(p => p).catch(err => null));
return Promise.race([
Promise.all(promises).then(trackers => {
......@@ -698,30 +697,34 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
});
}
private getAdapterDescriptor(adapterProvider: vscode.DebugAdapterProvider, sessionDto: IDebugSessionDto, folderUri: UriComponents | undefined, config: vscode.DebugConfiguration): Thenable<vscode.DebugAdapterDescriptor> {
private getAdapterDescriptor(adapterProvider: vscode.DebugAdapterProvider, sessionDto: IDebugSessionDto, config: vscode.DebugConfiguration): Thenable<vscode.DebugAdapterDescriptor> {
// a "debugServer" attribute in the launch config takes precedence
if (typeof config.debugServer === 'number') {
return Promise.resolve(new DebugAdapterServer(config.debugServer));
}
const session = this.getSession(sessionDto);
// TODO@AW legacy
const pairs = this._configProviders.filter(p => p.type === config.type);
if (pairs.length > 0) {
if (pairs[0].provider.debugAdapterExecutable) {
return asThenable(() => pairs[0].provider.debugAdapterExecutable(this.getFolder(folderUri), CancellationToken.None));
return asThenable(() => pairs[0].provider.debugAdapterExecutable(session.workspaceFolder, CancellationToken.None));
}
}
if (adapterProvider) {
const adapterExecutable = ExecutableDebugAdapter.platformAdapterExecutable(this._extensionService.getAllExtensionDescriptions(), config.type);
return asThenable(() => adapterProvider.provideDebugAdapter(this.getSession(sessionDto), this.getFolder(folderUri), adapterExecutable, config, CancellationToken.None));
return asThenable(() => adapterProvider.provideDebugAdapter(session, adapterExecutable, config, CancellationToken.None));
}
// try deprecated command based extension API "adapterExecutableCommand" to determine the executable
// TODO@AW legacy
const aex = this._aexCommands.get(config.type);
if (aex) {
const rootFolder = folderUri ? URI.revive(folderUri).toString() : undefined;
const folder = session.workspaceFolder;
const rootFolder = folder ? folder.uri.toString() : undefined;
return this._commandService.executeCommand(aex, rootFolder).then((ae: { command: string, args: string[] }) => {
return new DebugAdapterExecutable(ae.command, ae.args || []);
});
......@@ -752,7 +755,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (dto) {
let debugSession = this._debugSessions.get(dto.id);
if (!debugSession) {
debugSession = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name);
debugSession = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name, this.getFolder(dto.folderUri));
this._debugSessions.set(dto.id, debugSession);
}
return debugSession;
......@@ -771,17 +774,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
export class ExtHostDebugSession implements vscode.DebugSession {
private _debugServiceProxy: MainThreadDebugServiceShape;
private _id: DebugSessionUUID;
private _type: string;
private _name: string;
constructor(proxy: MainThreadDebugServiceShape, id: DebugSessionUUID, type: string, name: string) {
this._debugServiceProxy = proxy;
this._id = id;
this._type = type;
this._name = name;
constructor(
private _debugServiceProxy: MainThreadDebugServiceShape,
private _id: DebugSessionUUID,
private _type: string,
private _name: string,
private _workspaceFolder: vscode.WorkspaceFolder | undefined) {
}
public get id(): string {
......@@ -796,6 +794,10 @@ export class ExtHostDebugSession implements vscode.DebugSession {
return this._name;
}
public get workspaceFolder(): vscode.WorkspaceFolder | undefined {
return this._workspaceFolder;
}
public customRequest(command: string, args: any): Thenable<any> {
return this._debugServiceProxy.$customDebugAdapterRequest(this._id, command, args);
}
......
......@@ -110,7 +110,7 @@ export interface IExpression extends IReplElement, IExpressionContainer {
}
export interface IDebugger {
createDebugAdapter(session: IDebugSession, root: IWorkspaceFolder, config: IConfig, outputService: IOutputService): Promise<IDebugAdapter>;
createDebugAdapter(session: IDebugSession, config: IConfig, outputService: IOutputService): Promise<IDebugAdapter>;
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise<void>;
getCustomTelemetryService(): Thenable<TelemetryService>;
}
......@@ -468,7 +468,7 @@ export interface IDebugAdapter extends IDisposable {
}
export interface IDebugAdapterFactory extends ITerminalLauncher {
createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter;
createDebugAdapter(session: IDebugSession, config: IConfig): IDebugAdapter;
substituteVariables(folder: IWorkspaceFolder, config: IConfig): Promise<IConfig>;
}
......@@ -535,7 +535,7 @@ export interface IDebugConfigurationProvider {
export interface IDebugAdapterProvider {
readonly type: string;
provideDebugAdapter(session: IDebugSession, folderUri: uri | undefined, config: IConfig): Promise<IAdapterDescriptor>;
provideDebugAdapter(session: IDebugSession, config: IConfig): Promise<IAdapterDescriptor>;
}
export interface ITerminalLauncher {
......@@ -592,10 +592,10 @@ export interface IConfigurationManager {
unregisterDebugAdapterProvider(debugConfigurationProvider: IDebugAdapterProvider): void;
resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: any): Thenable<any>;
provideDebugAdapter(session: IDebugSession, folderUri: uri | undefined, config: IConfig): Promise<IAdapterDescriptor | undefined>;
provideDebugAdapter(session: IDebugSession, config: IConfig): Promise<IAdapterDescriptor | undefined>;
registerDebugAdapterFactory(debugTypes: string[], debugAdapterFactory: IDebugAdapterFactory): IDisposable;
createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter;
createDebugAdapter(session: IDebugSession, config: IConfig): IDebugAdapter;
substituteVariables(debugType: string, folder: IWorkspaceFolder, config: IConfig): Promise<IConfig>;
runInTerminal(debugType: string, args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise<void>;
......
......@@ -92,10 +92,10 @@ export class ConfigurationManager implements IConfigurationManager {
};
}
public createDebugAdapter(session: IDebugSession, folder: IWorkspaceFolder, config: IConfig): IDebugAdapter {
public createDebugAdapter(session: IDebugSession, config: IConfig): IDebugAdapter {
let dap = this.debugAdapterFactories.get(config.type);
if (dap) {
return dap.createDebugAdapter(session, folder, config);
return dap.createDebugAdapter(session, config);
}
return undefined;
}
......@@ -137,12 +137,12 @@ export class ConfigurationManager implements IConfigurationManager {
}
}
public provideDebugAdapter(session: IDebugSession, folderUri: uri | undefined, config: IConfig): Promise<IAdapterDescriptor | undefined> {
public provideDebugAdapter(session: IDebugSession, config: IConfig): Promise<IAdapterDescriptor | undefined> {
// first try legacy proposed API: DebugConfigurationProvider.debugAdapterExecutable
const providers0 = this.configProviders.filter(p => p.type === config.type && p.debugAdapterExecutable);
if (providers0.length === 1) {
return providers0[0].debugAdapterExecutable(folderUri);
return providers0[0].debugAdapterExecutable(session.root ? session.root.uri : undefined);
} else {
// TODO@AW handle n > 1 case
}
......@@ -150,7 +150,7 @@ export class ConfigurationManager implements IConfigurationManager {
// try new proposed API
const providers = this.adapterProviders.filter(p => p.type === config.type && p.provideDebugAdapter);
if (providers.length === 1) {
return providers[0].provideDebugAdapter(session, folderUri, config);
return providers[0].provideDebugAdapter(session, config);
} else {
// TODO@AW handle n > 1 case
}
......
......@@ -144,7 +144,7 @@ export class DebugSession implements IDebugSession {
return dbgr.getCustomTelemetryService().then(customTelemetryService => {
return dbgr.createDebugAdapter(this, this.root, this._configuration.resolved, this.outputService).then(debugAdapter => {
return dbgr.createDebugAdapter(this, this._configuration.resolved, this.outputService).then(debugAdapter => {
this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService);
......
......@@ -42,11 +42,11 @@ export class Debugger implements IDebugger {
}
createDebugAdapter(session: IDebugSession, root: IWorkspaceFolder, config: IConfig, outputService: IOutputService): Promise<IDebugAdapter> {
createDebugAdapter(session: IDebugSession, config: IConfig, outputService: IOutputService): Promise<IDebugAdapter> {
if (this.inExtHost()) {
return Promise.resolve(this.configurationManager.createDebugAdapter(session, root, config));
return Promise.resolve(this.configurationManager.createDebugAdapter(session, config));
} else {
return this.getAdapterDescriptor(session, root, config).then(adapterDescriptor => {
return this.getAdapterDescriptor(session, config).then(adapterDescriptor => {
switch (adapterDescriptor.type) {
case 'executable':
return new ExecutableDebugAdapter(adapterDescriptor, this.type, outputService);
......@@ -54,7 +54,7 @@ export class Debugger implements IDebugger {
return new SocketDebugAdapter(adapterDescriptor);
case 'implementation':
// TODO@AW: this.inExtHost() should now return true
return Promise.resolve(this.configurationManager.createDebugAdapter(session, root, config));
return Promise.resolve(this.configurationManager.createDebugAdapter(session, config));
default:
throw new Error('Cannot create debug adapter.');
}
......@@ -62,7 +62,7 @@ export class Debugger implements IDebugger {
}
}
private getAdapterDescriptor(session: IDebugSession, root: IWorkspaceFolder, config: IConfig): Promise<IAdapterDescriptor> {
private getAdapterDescriptor(session: IDebugSession, config: IConfig): Promise<IAdapterDescriptor> {
// a "debugServer" attribute in the launch config takes precedence
if (typeof config.debugServer === 'number') {
......@@ -73,7 +73,7 @@ export class Debugger implements IDebugger {
}
// try the proposed and the deprecated "provideDebugAdapter" API
return this.configurationManager.provideDebugAdapter(session, root ? root.uri : undefined, config).then(adapter => {
return this.configurationManager.provideDebugAdapter(session, config).then(adapter => {
if (adapter) {
return adapter;
......@@ -81,7 +81,7 @@ export class Debugger implements IDebugger {
// try deprecated command based extension API "adapterExecutableCommand" to determine the executable
if (this.debuggerContribution.adapterExecutableCommand) {
const rootFolder = root ? root.uri.toString() : undefined;
const rootFolder = session.root ? session.root.uri.toString() : undefined;
return this.commandService.executeCommand<IDebugAdapterExecutable>(this.debuggerContribution.adapterExecutableCommand, rootFolder).then((ae: { command: string, args: string[] }) => {
return <IAdapterDescriptor>{
type: 'executable',
......
......@@ -117,7 +117,7 @@ suite('Debug - Debugger', () => {
const configurationManager = <IConfigurationManager>{
provideDebugAdapter(session: IDebugSession, folderUri: URI | undefined, config: IConfig): Promise<IDebugAdapterExecutable | undefined> {
provideDebugAdapter(session: IDebugSession, config: IConfig): Promise<IDebugAdapterExecutable | undefined> {
return Promise.resolve(undefined);
}
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册