Skip to content

Commit

Permalink
fix eclipse-theia#7690: implement resolveDebugConfigurationWithSubsti…
Browse files Browse the repository at this point in the history
…tutedVariables VS Code API

Signed-off-by: Anton Kosyakov <anton.kosyakov@typefox.io>
  • Loading branch information
akosyakov authored and minyoungyang committed Aug 4, 2020
1 parent 49a6151 commit 704bc22
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 5 deletions.
9 changes: 7 additions & 2 deletions packages/debug/src/browser/debug-session-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,12 @@ export class DebugSessionManager {
return options;
}
const { workspaceFolderUri } = options;
const resolvedConfiguration = await this.resolveDebugConfiguration(options.configuration, workspaceFolderUri);
const configuration = await this.variableResolver.resolve(resolvedConfiguration, {
let configuration = await this.resolveDebugConfiguration(options.configuration, workspaceFolderUri);
configuration = await this.variableResolver.resolve(configuration, {
context: options.workspaceFolderUri ? new URI(options.workspaceFolderUri) : undefined,
configurationSection: 'launch'
});
configuration = await this.resolveDebugConfigurationWithSubstitutedVariables(configuration, workspaceFolderUri);
const key = configuration.name + workspaceFolderUri;
const id = this.configurationIds.has(key) ? this.configurationIds.get(key)! + 1 : 0;
this.configurationIds.set(key, id);
Expand All @@ -229,6 +230,10 @@ export class DebugSessionManager {
await WaitUntilEvent.fire(this.onWillResolveDebugConfigurationEmitter, { debugType });
}

protected async resolveDebugConfigurationWithSubstitutedVariables(configuration: DebugConfiguration, workspaceFolderUri: string | undefined): Promise<DebugConfiguration> {
return this.debug.resolveDebugConfigurationWithSubstitutedVariables(configuration, workspaceFolderUri);
}

protected async doStart(sessionId: string, options: DebugSessionOptions): Promise<DebugSession> {
const contrib = this.sessionContributionRegistry.get(options.configuration.type);
const sessionFactory = contrib ? contrib.debugSessionFactory() : this.debugSessionFactory;
Expand Down
10 changes: 9 additions & 1 deletion packages/debug/src/common/debug-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,17 @@ export interface DebugAdapterContribution {

/**
* Resolves a [debug configuration](#DebugConfiguration) by filling in missing values
* or by adding/changing/removing attributes.
* or by adding/changing/removing attributes before variable substitution.
* @param config The [debug configuration](#DebugConfiguration) to resolve.
* @returns The resolved debug configuration.
*/
resolveDebugConfiguration?(config: DebugConfiguration, workspaceFolderUri?: string): MaybePromise<DebugConfiguration | undefined>;

/**
* Resolves a [debug configuration](#DebugConfiguration) by filling in missing values
* or by adding/changing/removing attributes with substituted variables.
* @param config The [debug configuration](#DebugConfiguration) to resolve.
* @returns The resolved debug configuration.
*/
resolveDebugConfigurationWithSubstitutedVariables?(config: DebugConfiguration, workspaceFolderUri?: string): MaybePromise<DebugConfiguration | undefined>;
}
10 changes: 9 additions & 1 deletion packages/debug/src/common/debug-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,20 @@ export interface DebugService extends Disposable {

/**
* Resolves a [debug configuration](#DebugConfiguration) by filling in missing values
* or by adding/changing/removing attributes.
* or by adding/changing/removing attributes before variable substitution.
* @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve.
* @returns The resolved debug configuration.
*/
resolveDebugConfiguration(config: DebugConfiguration, workspaceFolderUri: string | undefined): Promise<DebugConfiguration>;

/**
* Resolves a [debug configuration](#DebugConfiguration) by filling in missing values
* or by adding/changing/removing attributes with substituted variables.
* @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve.
* @returns The resolved debug configuration.
*/
resolveDebugConfigurationWithSubstitutedVariables(config: DebugConfiguration, workspaceFolderUri: string | undefined): Promise<DebugConfiguration>;

/**
* Creates a new [debug adapter session](#DebugAdapterSession).
* @param config The resolved [debug configuration](#DebugConfiguration).
Expand Down
27 changes: 26 additions & 1 deletion packages/debug/src/node/debug-adapter-contribution-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class DebugAdapterContributionRegistry {

/**
* Resolves a [debug configuration](#DebugConfiguration) by filling in missing values
* or by adding/changing/removing attributes.
* or by adding/changing/removing attributes before variable substitution.
* @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve.
* @returns The resolved debug configuration.
*/
Expand All @@ -115,6 +115,31 @@ export class DebugAdapterContributionRegistry {
return current;
}

/**
* Resolves a [debug configuration](#DebugConfiguration) by filling in missing values
* or by adding/changing/removing attributes with substituted variables.
* @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve.
* @returns The resolved debug configuration.
*/
async resolveDebugConfigurationWithSubstitutedVariables(config: DebugConfiguration, workspaceFolderUri?: string): Promise<DebugConfiguration> {
let current = config;
for (const contribution of this.getContributions(config.type)) {
if (contribution.resolveDebugConfigurationWithSubstitutedVariables) {
try {
const next = await contribution.resolveDebugConfigurationWithSubstitutedVariables(config, workspaceFolderUri);
if (next) {
current = next;
} else {
return current;
}
} catch (e) {
console.error(e);
}
}
}
return current;
}

/**
* Provides schema attributes.
* @param debugType The registered debug type
Expand Down
3 changes: 3 additions & 0 deletions packages/debug/src/node/debug-service-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ export class DebugServiceImpl implements DebugService {
async resolveDebugConfiguration(config: DebugConfiguration, workspaceFolderUri?: string): Promise<DebugConfiguration> {
return this.registry.resolveDebugConfiguration(config, workspaceFolderUri);
}
async resolveDebugConfigurationWithSubstitutedVariables(config: DebugConfiguration, workspaceFolderUri?: string): Promise<DebugConfiguration> {
return this.registry.resolveDebugConfigurationWithSubstitutedVariables(config, workspaceFolderUri);
}

protected readonly sessions = new Set<string>();
async createDebugSession(config: DebugConfiguration): Promise<string> {
Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,8 @@ export interface DebugExt {
$sessionDidChange(sessionId: string | undefined): void;
$provideDebugConfigurations(debugType: string, workspaceFolder: string | undefined): Promise<theia.DebugConfiguration[]>;
$resolveDebugConfigurations(debugConfiguration: theia.DebugConfiguration, workspaceFolder: string | undefined): Promise<theia.DebugConfiguration | undefined>;
$resolveDebugConfigurationWithSubstitutedVariables(debugConfiguration: theia.DebugConfiguration, workspaceFolder: string | undefined):
Promise<theia.DebugConfiguration | undefined>;
$createDebugSession(debugConfiguration: theia.DebugConfiguration): Promise<string>;
$terminateDebugSession(sessionId: string): Promise<void>;
$getTerminalCreationOptions(debugType: string): Promise<TerminalOptionsExt | undefined>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export class PluginDebugAdapterContribution {
return this.debugExt.$resolveDebugConfigurations(config, workspaceFolderUri);
}

async resolveDebugConfigurationWithSubstitutedVariables(config: DebugConfiguration, workspaceFolderUri: string | undefined): Promise<DebugConfiguration | undefined> {
return this.debugExt.$resolveDebugConfigurationWithSubstitutedVariables(config, workspaceFolderUri);
}

async createDebugSession(config: DebugConfiguration): Promise<string> {
await this.pluginService.activateByDebug('onDebugAdapterProtocolTracker', config.type);
return this.debugExt.$createDebugSession(config);
Expand Down
22 changes: 22 additions & 0 deletions packages/plugin-ext/src/main/browser/debug/plugin-debug-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,28 @@ export class PluginDebugService implements DebugService, PluginDebugAdapterContr
return this.delegated.resolveDebugConfiguration(resolved, workspaceFolderUri);
}

async resolveDebugConfigurationWithSubstitutedVariables(config: DebugConfiguration, workspaceFolderUri: string | undefined): Promise<DebugConfiguration> {
let resolved = config;

// we should iterate over all to handle configuration providers for `*`
for (const contributor of this.contributors.values()) {
if (contributor) {
try {
const next = await contributor.resolveDebugConfigurationWithSubstitutedVariables(resolved, workspaceFolderUri);
if (next) {
resolved = next;
} else {
return resolved;
}
} catch (e) {
console.error(e);
}
}
}

return this.delegated.resolveDebugConfigurationWithSubstitutedVariables(resolved, workspaceFolderUri);
}

registerDebugger(contribution: DebuggerContribution): Disposable {
this.debuggers.push(contribution);
return Disposable.create(() => {
Expand Down
26 changes: 26 additions & 0 deletions packages/plugin-ext/src/plugin/node/debug/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,32 @@ export class DebugExtImpl implements DebugExt {
return current;
}

async $resolveDebugConfigurationWithSubstitutedVariables(debugConfiguration: theia.DebugConfiguration, workspaceFolderUri: string | undefined):
Promise<theia.DebugConfiguration | undefined> {
let current = debugConfiguration;

for (const providers of [this.configurationProviders.get(debugConfiguration.type), this.configurationProviders.get('*')]) {
if (providers) {
for (const provider of providers) {
if (provider.resolveDebugConfigurationWithSubstitutedVariables) {
try {
const next = await provider.resolveDebugConfigurationWithSubstitutedVariables(this.toWorkspaceFolder(workspaceFolderUri), current);
if (next) {
current = next;
} else {
return current;
}
} catch (e) {
console.error(e);
}
}
}
}
}

return current;
}

protected async createDebugAdapterTracker(session: theia.DebugSession): Promise<theia.DebugAdapterTracker> {
return PluginDebugAdapterTracker.create(session, this.trackerFactories);
}
Expand Down
15 changes: 15 additions & 0 deletions packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8183,6 +8183,21 @@ declare module '@theia/plugin' {
* @return The resolved debug configuration or undefined or null.
*/
resolveDebugConfiguration?(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration>;

/**
* This hook is directly called after 'resolveDebugConfiguration' but with all variables substituted.
* It can be used to resolve or verify a [debug configuration](#DebugConfiguration) by filling in missing values or by adding/changing/removing attributes.
* If more than one debug configuration provider is registered for the same type, the 'resolveDebugConfigurationWithSubstitutedVariables' calls are chained
* in arbitrary order and the initial debug configuration is piped through the chain.
* Returning the value 'undefined' prevents the debug session from starting.
* Returning the value 'null' prevents the debug session from starting and opens the underlying debug configuration instead.
*
* @param folder The workspace folder from which the configuration originates from or `undefined` for a folderless setup.
* @param debugConfiguration The [debug configuration](#DebugConfiguration) to resolve.
* @param token A cancellation token.
* @return The resolved debug configuration or undefined or null.
*/
resolveDebugConfigurationWithSubstitutedVariables?(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration>;
}

/**
Expand Down

0 comments on commit 704bc22

Please sign in to comment.