From 4573042ac91861b28de55203d44acca1e27fde7b Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 7 Feb 2019 23:25:05 +0100 Subject: [PATCH] properly merge debugger contributions --- .../workbench/api/node/extHostDebugService.ts | 5 +-- .../contrib/debug/common/debugUtils.ts | 7 ++- .../debugConfigurationManager.ts | 6 +-- .../debug/electron-browser/debugService.ts | 2 +- .../workbench/contrib/debug/node/debugger.ts | 45 ++++++++++++------- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index a1c246eab34..31a45f7dd27 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -24,7 +24,7 @@ import { getTerminalLauncher, hasChildProcesses, prepareCommand } from 'vs/workb import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/node/variableResolver'; import { ExtHostConfiguration, ExtHostConfigProvider } from './extHostConfiguration'; -import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/contrib/debug/common/debugUtils'; +import { convertToVSCPaths, convertToDAPaths, isDebuggerMainContribution } from 'vs/workbench/contrib/debug/common/debugUtils'; import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; @@ -128,8 +128,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape { const debuggers = ed.contributes['debuggers']; if (debuggers && debuggers.length > 0) { for (const dbg of debuggers) { - // only debugger contributions with a label, program, or runtime attribute are considered a "defining" debugger contribution - if (dbg.type && (dbg.label || dbg.program || dbg.runtime)) { + if (isDebuggerMainContribution(dbg)) { debugTypes.push(dbg.type); if (dbg.adapterExecutableCommand) { this._aexCommands.set(dbg.type, dbg.adapterExecutableCommand); diff --git a/src/vs/workbench/contrib/debug/common/debugUtils.ts b/src/vs/workbench/contrib/debug/common/debugUtils.ts index fccd81a0add..7bd7849ceb1 100644 --- a/src/vs/workbench/contrib/debug/common/debugUtils.ts +++ b/src/vs/workbench/contrib/debug/common/debugUtils.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { equalsIgnoreCase } from 'vs/base/common/strings'; -import { IConfig } from 'vs/workbench/contrib/debug/common/debug'; +import { IConfig, IDebuggerContribution } from 'vs/workbench/contrib/debug/common/debug'; import { URI as uri } from 'vs/base/common/uri'; import { isAbsolute_posix, isAbsolute_win32 } from 'vs/base/common/paths'; import { deepClone } from 'vs/base/common/objects'; @@ -27,6 +27,11 @@ export function isExtensionHostDebugging(config: IConfig) { return config.type && equalsIgnoreCase(config.type === 'vslsShare' ? (config).adapterProxy.configuration.type : config.type, 'extensionhost'); } +// only a debugger contributions with a label, program, or runtime attribute is considered a "defining" or "main" debugger contribution +export function isDebuggerMainContribution(dbg: IDebuggerContribution) { + return dbg.type && (dbg.label || dbg.program || dbg.runtime); +} + export function getExactExpressionStartAndEnd(lineContent: string, looseStart: number, looseEnd: number): { start: number, end: number } { let matchingExpression: string | undefined = undefined; let startOffset = 0; diff --git a/src/vs/workbench/contrib/debug/electron-browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/electron-browser/debugConfigurationManager.ts index 90d5cbeeeb9..4fda9f76074 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debugConfigurationManager.ts @@ -249,9 +249,9 @@ export class ConfigurationManager implements IConfigurationManager { }); } - const duplicate = this.getDebugger(rawAdapter.type); - if (duplicate) { - duplicate.merge(rawAdapter, added.description); + const existing = this.getDebugger(rawAdapter.type); + if (existing) { + existing.merge(rawAdapter, added.description); } else { this.debuggers.push(this.instantiationService.createInstance(Debugger, this, rawAdapter, added.description)); } diff --git a/src/vs/workbench/contrib/debug/electron-browser/debugService.ts b/src/vs/workbench/contrib/debug/electron-browser/debugService.ts index 5aac6bdf13c..4828acaa6eb 100644 --- a/src/vs/workbench/contrib/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/electron-browser/debugService.ts @@ -1016,7 +1016,7 @@ export class DebugService implements IDebugService { //---- telemetry private telemetryDebugSessionStart(root: IWorkspaceFolder, type: string): Promise { - const extension = this.configurationManager.getDebugger(type).extensionDescription; + const extension = this.configurationManager.getDebugger(type).getMainExtensionDescriptor(); /* __GDPR__ "debugSessionStart" : { "type": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, diff --git a/src/vs/workbench/contrib/debug/node/debugger.ts b/src/vs/workbench/contrib/debug/node/debugger.ts index 01f5edd2451..93e37f35d61 100644 --- a/src/vs/workbench/contrib/debug/node/debugger.ts +++ b/src/vs/workbench/contrib/debug/node/debugger.ts @@ -26,19 +26,36 @@ import { getPathFromAmdModule } from 'vs/base/common/amd'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; +import { isDebuggerMainContribution } from 'vs/workbench/contrib/debug/common/debugUtils'; export class Debugger implements IDebugger { - private mergedExtensionDescriptions: IExtensionDescription[]; + private debuggerContribution: IDebuggerContribution = {}; + private mergedExtensionDescriptions: IExtensionDescription[] = []; + private mainExtensionDescription: IExtensionDescription | undefined; - constructor(private configurationManager: IConfigurationManager, private debuggerContribution: IDebuggerContribution, public extensionDescription: IExtensionDescription, + constructor(private configurationManager: IConfigurationManager, dbgContribution: IDebuggerContribution, extensionDescription: IExtensionDescription, @IConfigurationService private readonly configurationService: IConfigurationService, @ITextResourcePropertiesService private readonly resourcePropertiesService: ITextResourcePropertiesService, @ICommandService private readonly commandService: ICommandService, @IConfigurationResolverService private readonly configurationResolverService: IConfigurationResolverService, @ITelemetryService private readonly telemetryService: ITelemetryService, ) { - this.mergedExtensionDescriptions = [extensionDescription]; + this.merge(dbgContribution, extensionDescription); + } + + public merge(otherDebuggerContribution: IDebuggerContribution, extensionDescription: IExtensionDescription): void { + + // remember all extensions that are merged for this debugger + this.mergedExtensionDescriptions.push(extensionDescription); + + // merge debugger contributions + objects.mixin(this.debuggerContribution, otherDebuggerContribution, extensionDescription.isBuiltin); + + // remember the extension that has the "main" debugger contribution + if (isDebuggerMainContribution(otherDebuggerContribution)) { + this.mainExtensionDescription = extensionDescription; + } } public createDebugAdapter(session: IDebugSession, outputService: IOutputService): Promise { @@ -129,7 +146,9 @@ export class Debugger implements IDebugger { private inExtHost(): boolean { const debugConfigs = this.configurationService.getValue('debug'); - return debugConfigs.extensionHostDebugAdapter || this.configurationManager.needsToRunInExtHost(this.type) || this.extensionDescription.extensionLocation.scheme !== 'file'; + return debugConfigs.extensionHostDebugAdapter + || this.configurationManager.needsToRunInExtHost(this.type) + || (this.mainExtensionDescription && this.mainExtensionDescription.extensionLocation.scheme !== 'file'); } get label(): string { @@ -152,18 +171,6 @@ export class Debugger implements IDebugger { return this.debuggerContribution.languages; } - merge(secondRawAdapter: IDebuggerContribution, extensionDescription: IExtensionDescription): void { - - // remember all ext descriptions that are the source of this debugger - this.mergedExtensionDescriptions.push(extensionDescription); - - // Give priority to built in debug adapters - if (extensionDescription.isBuiltin) { - this.extensionDescription = extensionDescription; - } - objects.mixin(this.debuggerContribution, secondRawAdapter, extensionDescription.isBuiltin); - } - hasInitialConfiguration(): boolean { return !!this.debuggerContribution.initialConfigurations; } @@ -204,6 +211,10 @@ export class Debugger implements IDebugger { return Promise.resolve(content); } + public getMainExtensionDescriptor(): IExtensionDescription { + return this.mainExtensionDescription || this.mergedExtensionDescriptions[0]; + } + @memoize getCustomTelemetryService(): Promise { if (!this.debuggerContribution.aiKey) { @@ -221,7 +232,7 @@ export class Debugger implements IDebugger { { serverName: 'Debug Telemetry', timeout: 1000 * 60 * 5, - args: [`${this.extensionDescription.publisher}.${this.type}`, JSON.stringify(data), this.debuggerContribution.aiKey], + args: [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), this.debuggerContribution.aiKey], env: { ELECTRON_RUN_AS_NODE: 1, PIPE_LOGGING: 'true', -- GitLab