diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index fd8ae385b05a1..5ecfb234283cf 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -40,13 +40,13 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { flatten } from 'vs/base/common/arrays'; import { getVisibleAndSorted } from 'vs/workbench/contrib/debug/common/debugUtils'; import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes'; +import * as path from 'vs/base/common/path'; const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); jsonRegistry.registerSchema(launchSchemaId, launchSchema); const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname'; const DEBUG_SELECTED_ROOT = 'debug.selectedroot'; -// Debug type is only stored if a dynamic configuration is used for better restore const DEBUG_SELECTED_TYPE = 'debug.selectedtype'; interface IDynamicPickItem { label: string, launch: ILaunch, config: IConfig } @@ -99,8 +99,6 @@ export class ConfigurationManager implements IConfigurationManager { } } - // debuggers - registerDebugAdapterFactory(debugTypes: string[], debugAdapterLauncher: IDebugAdapterFactory): IDisposable { debugTypes.forEach(debugType => this.debugAdapterFactories.set(debugType, debugAdapterLauncher)); this.debuggersAvailable.set(this.debugAdapterFactories.size > 0); @@ -141,8 +139,6 @@ export class ConfigurationManager implements IConfigurationManager { return Promise.resolve(void 0); } - // debug adapter - registerDebugAdapterDescriptorFactory(debugAdapterProvider: IDebugAdapterDescriptorFactory): IDisposable { this.adapterDescriptorFactories.push(debugAdapterProvider); return { @@ -163,20 +159,16 @@ export class ConfigurationManager implements IConfigurationManager { const config = session.configuration; - // first try legacy proposed API: DebugConfigurationProvider.debugAdapterExecutable const providers0 = this.configProviders.filter(p => p.type === config.type && p.debugAdapterExecutable); if (providers0.length === 1 && providers0[0].debugAdapterExecutable) { return providers0[0].debugAdapterExecutable(session.root ? session.root.uri : undefined); } else { - // TODO@AW handle n > 1 case } - // new API const providers = this.adapterDescriptorFactories.filter(p => p.type === config.type && p.createDebugAdapterDescriptor); if (providers.length === 1) { return providers[0].createDebugAdapterDescriptor(session); } else { - // TODO@AW handle n > 1 case } return Promise.resolve(undefined); } @@ -194,8 +186,6 @@ export class ConfigurationManager implements IConfigurationManager { return this._onDidRegisterDebugger.event; } - // debug configurations - registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable { this.configProviders.push(debugConfigurationProvider); return { @@ -212,27 +202,21 @@ export class ConfigurationManager implements IConfigurationManager { } } - /** - * if scope is not specified,a value of DebugConfigurationProvideTrigger.Initial is assumed. - */ hasDebugConfigurationProvider(debugType: string, triggerKind?: DebugConfigurationProviderTriggerKind): boolean { if (triggerKind === undefined) { triggerKind = DebugConfigurationProviderTriggerKind.Initial; } - // check if there are providers for the given type that contribute a provideDebugConfigurations method const provider = this.configProviders.find(p => p.provideDebugConfigurations && (p.type === debugType) && (p.triggerKind === triggerKind)); return !!provider; } async resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, config: IConfig, token: CancellationToken): Promise { await this.activateDebuggers('onDebugResolve', type); - // pipe the config through the promises sequentially. Append at the end the '*' types const providers = this.configProviders.filter(p => p.type === type && p.resolveDebugConfiguration) .concat(this.configProviders.filter(p => p.type === '*' && p.resolveDebugConfiguration)); let result: IConfig | null | undefined = config; await sequence(providers.map(provider => async () => { - // If any provider returned undefined or null make sure to respect that and do not pass the result to more resolver if (result) { result = await provider.resolveDebugConfiguration!(folderUri, result, token); } @@ -242,13 +226,11 @@ export class ConfigurationManager implements IConfigurationManager { } async resolveDebugConfigurationWithSubstitutedVariables(folderUri: uri | undefined, type: string | undefined, config: IConfig, token: CancellationToken): Promise { - // pipe the config through the promises sequentially. Append at the end the '*' types const providers = this.configProviders.filter(p => p.type === type && p.resolveDebugConfigurationWithSubstitutedVariables) .concat(this.configProviders.filter(p => p.type === '*' && p.resolveDebugConfigurationWithSubstitutedVariables)); let result: IConfig | null | undefined = config; await sequence(providers.map(provider => async () => { - // If any provider returned undefined or null make sure to respect that and do not pass the result to more resolver if (result) { result = await provider.resolveDebugConfigurationWithSubstitutedVariables!(folderUri, result, token); } @@ -314,7 +296,6 @@ export class ConfigurationManager implements IConfigurationManager { resolve(undefined); const { launch, config } = context.item; await launch.openConfigFile(false, config.type); - // Only Launch have a pin trigger button await (launch as Launch).writeConfiguration(config); await this.selectConfiguration(launch, config.name); })); @@ -343,7 +324,6 @@ export class ConfigurationManager implements IConfigurationManager { let chosen: IDynamicPickItem | undefined; - // If there's exactly one item to choose from, pick it automatically if (items.length === 1 && !chosenDidCancel) { chosen = items[0]; } else { @@ -355,7 +335,6 @@ export class ConfigurationManager implements IConfigurationManager { disposables.dispose(); if (!chosen) { - // User canceled quick input we should notify the provider to cancel computing configurations token.cancel(); return; } @@ -404,7 +383,6 @@ export class ConfigurationManager implements IConfigurationManager { }); }); - // take care of all wildcard contributions extensions.forEach(extension => { extension.value.forEach(rawAdapter => { if (rawAdapter.type === '*') { @@ -418,7 +396,6 @@ export class ConfigurationManager implements IConfigurationManager { this.debuggers = this.debuggers.filter(d => removedTypes.indexOf(d.type) === -1); }); - // update the schema to include all attributes, snippets and types from extensions. this.debuggers.forEach(adapter => { const items = (launchSchema.properties!['configurations'].items); const schemaAttributes = adapter.getSchemaAttributes(); @@ -450,7 +427,6 @@ export class ConfigurationManager implements IConfigurationManager { })); this.toDispose.push(this.configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('launch')) { - // A change happen in the launch.json. If there is already a launch configuration selected, do not change the selection. this.selectConfiguration(undefined); this.setCompoundSchemaValues(); } @@ -538,8 +514,6 @@ export class ConfigurationManager implements IConfigurationManager { if ((name && names.indexOf(name) >= 0) || config) { this.setSelectedLaunchName(name); } else if (!this.selectedName || names.indexOf(this.selectedName) === -1) { - // We could not find the previously used name. We should get all dynamic configurations from providers - // And potentially auto select the previously used dynamic configuration #96293 const providers = await this.getDynamicProviders(); const provider = providers.find(p => p.provider && p.provider.type === type); let nameToSet = names.length ? names[0] : undefined; @@ -574,7 +548,6 @@ export class ConfigurationManager implements IConfigurationManager { canSetBreakpointsIn(model: ITextModel): boolean { const modeId = model.getLanguageIdentifier().language; if (!modeId || modeId === 'jsonc' || modeId === 'log') { - // do not allow breakpoints in our settings files and output return false; } if (this.configurationService.getValue('debug').allowBreakpointsEverywhere) { @@ -694,13 +667,21 @@ abstract class AbstractLaunch { } getConfiguration(name: string): IConfig | undefined { - // We need to clone the configuration in order to be able to make changes to it #42198 const config = objects.deepClone(this.getConfig()); if (!config || !config.configurations) { return undefined; } - - return config.configurations.find(config => config && config.name === name); + const configuration = config.configurations.find(config => config && config.name === name); + if (configuration) { + if (this instanceof UserLaunch) { + configuration.__configurationTarget = ConfigurationTarget.USER; + } else if (this instanceof WorkspaceLaunch) { + configuration.__configurationTarget = ConfigurationTarget.WORKSPACE; + } else { + configuration.__configurationTarget = ConfigurationTarget.WORKSPACE_FOLDER; + } + } + return configuration; } async getInitialConfigurationContent(folderUri?: uri, type?: string, token?: CancellationToken): Promise { @@ -751,10 +732,9 @@ class Launch extends AbstractLaunch implements ILaunch { const fileContent = await this.fileService.readFile(resource); content = fileContent.value.toString(); } catch { - // launch.json not found: create one by collecting launch configs from debugConfigProviders content = await this.getInitialConfigurationContent(this.workspace.uri, type, token); if (content) { - created = true; // pin only if config file is created #8727 + created = true; try { await this.textFileService.write(resource, content); } catch (error) { @@ -831,7 +811,6 @@ class WorkspaceLaunch extends AbstractLaunch implements ILaunch { async openConfigFile(preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }> { let launchExistInFile = !!this.getConfig(); if (!launchExistInFile) { - // Launch property in workspace config not found: create one by collecting launch configs from debugConfigProviders let content = await this.getInitialConfigurationContent(undefined, type, token); if (content) { await this.configurationService.updateValue('launch', json.parse(content), ConfigurationTarget.WORKSPACE); @@ -889,4 +868,4 @@ class UserLaunch extends AbstractLaunch implements ILaunch { created: false }); } -} +} \ No newline at end of file diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 4035cc5ba464a..385800998a1b7 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -21,7 +21,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IDisposable } from 'vs/base/common/lifecycle'; import { TaskIdentifier } from 'vs/workbench/contrib/tasks/common/tasks'; import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { CancellationToken } from 'vs/base/common/cancellation'; import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/api/common/extHostTypes'; import { DebugCompoundRoot } from 'vs/workbench/contrib/debug/common/debugCompoundRoot'; @@ -74,8 +74,6 @@ export const INTERNAL_CONSOLE_OPTIONS_SCHEMA = { description: nls.localize('internalConsoleOptions', "Controls when the internal debug console should open.") }; -// raw - export interface IRawModelUpdate { sessionId: string; threads: DebugProtocol.Thread[]; @@ -92,8 +90,6 @@ export interface IRawStoppedDetails { framesErrorMessage?: string; } -// model - export interface ITreeElement { getId(): string; } @@ -206,24 +202,18 @@ export interface IDebugSession extends ITreeElement { appendToRepl(data: string | IExpression, severity: severity, source?: IReplElementSource): void; logToRepl(sev: severity, args: any[], frame?: { uri: uri, line: number, column: number }): void; - // session events readonly onDidEndAdapter: Event; readonly onDidChangeState: Event; readonly onDidChangeReplElements: Event; - // DA capabilities readonly capabilities: DebugProtocol.Capabilities; - // DAP events - readonly onDidLoadedSource: Event; readonly onDidCustomEvent: Event; readonly onDidProgressStart: Event; readonly onDidProgressUpdate: Event; readonly onDidProgressEnd: Event; - // DAP request - initialize(dbgr: IDebugger): Promise; launchOrAttach(config: IConfig): Promise; restart(): Promise; @@ -268,54 +258,25 @@ export interface IDebugSession extends ITreeElement { export interface IThread extends ITreeElement { - /** - * Process the thread belongs to - */ readonly session: IDebugSession; - /** - * Id of the thread generated by the debug adapter backend. - */ readonly threadId: number; - /** - * Name of the thread. - */ readonly name: string; - /** - * Information about the current thread stop event. Undefined if thread is not stopped. - */ readonly stoppedDetails: IRawStoppedDetails | undefined; - /** - * Information about the exception if an 'exception' stopped event raised and DA supports the 'exceptionInfo' request, otherwise undefined. - */ readonly exceptionInfo: Promise; readonly stateLabel: string; - /** - * Gets the callstack if it has already been received from the debug - * adapter. - */ getCallStack(): ReadonlyArray; - /** - * Gets the top stack frame that is not hidden if the callstack has already been received from the debug adapter - */ getTopStackFrame(): IStackFrame | undefined; - /** - * Invalidates the callstack cache - */ clearCallStack(): void; - /** - * Indicates whether this thread is stopped. The callstack for stopped - * threads can be retrieved from the debug adapter. - */ readonly stopped: boolean; next(): Promise; @@ -415,22 +376,11 @@ export interface IExceptionInfo { readonly details?: DebugProtocol.ExceptionDetails; } -// model interfaces - export interface IViewModel extends ITreeElement { - /** - * Returns the focused debug session or undefined if no session is stopped. - */ readonly focusedSession: IDebugSession | undefined; - /** - * Returns the focused thread or undefined if no thread is stopped. - */ readonly focusedThread: IThread | undefined; - /** - * Returns the focused stack frame or undefined if there are no stack frames. - */ readonly focusedStackFrame: IStackFrame | undefined; getSelectedExpression(): IExpression | undefined; @@ -466,9 +416,6 @@ export interface IDebugModel extends ITreeElement { onDidChangeWatchExpressions: Event; } -/** - * An event describing a change to the set of [breakpoints](#debug.Breakpoint). - */ export interface IBreakpointsChangeEvent { added?: Array; removed?: Array; @@ -476,8 +423,6 @@ export interface IBreakpointsChangeEvent { sessionOnly: boolean; } -// Debug configuration interfaces - export interface IDebugConfiguration { allowBreakpointsEverywhere: boolean; openDebug: 'neverOpen' | 'openOnSessionStart' | 'openOnFirstSessionStart' | 'openOnDebugBreak'; @@ -520,431 +465,4 @@ export interface IEnvConfig { } export interface IConfigPresentation { - hidden?: boolean; - group?: string; - order?: number; -} - -export interface IConfig extends IEnvConfig { - - // fundamental attributes - type: string; - request: string; - name: string; - presentation?: IConfigPresentation; - // platform specifics - windows?: IEnvConfig; - osx?: IEnvConfig; - linux?: IEnvConfig; - - // internals - __sessionId?: string; - __restart?: any; - __autoAttach?: boolean; - port?: number; // TODO -} - -export interface ICompound { - name: string; - stopAll?: boolean; - preLaunchTask?: string | TaskIdentifier; - configurations: (string | { name: string, folder: string })[]; - presentation?: IConfigPresentation; -} - -export interface IDebugAdapter extends IDisposable { - readonly onError: Event; - readonly onExit: Event; - onRequest(callback: (request: DebugProtocol.Request) => void): void; - onEvent(callback: (event: DebugProtocol.Event) => void): void; - startSession(): Promise; - sendMessage(message: DebugProtocol.ProtocolMessage): void; - sendResponse(response: DebugProtocol.Response): void; - sendRequest(command: string, args: any, clb: (result: DebugProtocol.Response) => void, timeout?: number): number; - stopSession(): Promise; -} - -export interface IDebugAdapterFactory extends ITerminalLauncher { - createDebugAdapter(session: IDebugSession): IDebugAdapter; - substituteVariables(folder: IWorkspaceFolder | undefined, config: IConfig): Promise; -} - -export interface IDebugAdapterExecutableOptions { - cwd?: string; - env?: { [key: string]: string }; -} - -export interface IDebugAdapterExecutable { - readonly type: 'executable'; - readonly command: string; - readonly args: string[]; - readonly options?: IDebugAdapterExecutableOptions; -} - -export interface IDebugAdapterServer { - readonly type: 'server'; - readonly port: number; - readonly host?: string; -} - -export interface IDebugAdapterNamedPipeServer { - readonly type: 'pipeServer'; - readonly path: string; -} - -export interface IDebugAdapterInlineImpl extends IDisposable { - readonly onDidSendMessage: Event; - handleMessage(message: DebugProtocol.Message): void; -} - -export interface IDebugAdapterImpl { - readonly type: 'implementation'; - readonly implementation: IDebugAdapterInlineImpl; -} - -export type IAdapterDescriptor = IDebugAdapterExecutable | IDebugAdapterServer | IDebugAdapterNamedPipeServer | IDebugAdapterImpl; - -export interface IPlatformSpecificAdapterContribution { - program?: string; - args?: string[]; - runtime?: string; - runtimeArgs?: string[]; -} - -export interface IDebuggerContribution extends IPlatformSpecificAdapterContribution { - type: string; - label?: string; - // debug adapter executable - adapterExecutableCommand?: string; - win?: IPlatformSpecificAdapterContribution; - winx86?: IPlatformSpecificAdapterContribution; - windows?: IPlatformSpecificAdapterContribution; - osx?: IPlatformSpecificAdapterContribution; - linux?: IPlatformSpecificAdapterContribution; - - // internal - aiKey?: string; - - // supported languages - languages?: string[]; - enableBreakpointsFor?: { languageIds: string[] }; - - // debug configuration support - configurationAttributes?: any; - initialConfigurations?: any[]; - configurationSnippets?: IJSONSchemaSnippet[]; - variables?: { [key: string]: string }; -} - -export interface IDebugConfigurationProvider { - readonly type: string; - readonly triggerKind: DebugConfigurationProviderTriggerKind; - resolveDebugConfiguration?(folderUri: uri | undefined, debugConfiguration: IConfig, token: CancellationToken): Promise; - resolveDebugConfigurationWithSubstitutedVariables?(folderUri: uri | undefined, debugConfiguration: IConfig, token: CancellationToken): Promise; - provideDebugConfigurations?(folderUri: uri | undefined, token: CancellationToken): Promise; - debugAdapterExecutable?(folderUri: uri | undefined): Promise; // TODO@AW legacy -} - -export interface IDebugAdapterDescriptorFactory { - readonly type: string; - createDebugAdapterDescriptor(session: IDebugSession): Promise; -} - -export interface IDebugAdapterTrackerFactory { - readonly type: string; -} - -export interface ITerminalLauncher { - runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments): Promise; -} - -export interface IConfigurationManager { - /** - * Returns true if breakpoints can be set for a given editor model. Depends on mode. - */ - canSetBreakpointsIn(model: EditorIModel): boolean; - - /** - * Returns an object containing the selected launch configuration and the selected configuration name. Both these fields can be null (no folder workspace). - */ - readonly selectedConfiguration: { - launch: ILaunch | undefined; - config: IConfig | undefined; - name: string | undefined; - // Type is used when matching dynamic configurations to their corresponding provider - type: string | undefined; - }; - - selectConfiguration(launch: ILaunch | undefined, name?: string, config?: IConfig, type?: string): Promise; - - getLaunches(): ReadonlyArray; - - hasDebuggers(): boolean; - - getLaunch(workspaceUri: uri | undefined): ILaunch | undefined; - - getAllConfigurations(): { launch: ILaunch, name: string, presentation?: IConfigPresentation }[]; - - /** - * Allows to register on change of selected debug configuration. - */ - onDidSelectConfiguration: Event; - - onDidRegisterDebugger: Event; - - activateDebuggers(activationEvent: string, debugType?: string): Promise; - - isDebuggerInterestedInLanguage(language: string): boolean; - hasDebugConfigurationProvider(debugType: string): boolean; - getDynamicProviders(): Promise<{ label: string, provider: IDebugConfigurationProvider | undefined, pick: () => Promise<{ launch: ILaunch, config: IConfig } | undefined> }[]>; - - registerDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): IDisposable; - unregisterDebugConfigurationProvider(debugConfigurationProvider: IDebugConfigurationProvider): void; - - registerDebugAdapterDescriptorFactory(debugAdapterDescriptorFactory: IDebugAdapterDescriptorFactory): IDisposable; - unregisterDebugAdapterDescriptorFactory(debugAdapterDescriptorFactory: IDebugAdapterDescriptorFactory): void; - - resolveConfigurationByProviders(folderUri: uri | undefined, type: string | undefined, debugConfiguration: any, token: CancellationToken): Promise; - getDebugAdapterDescriptor(session: IDebugSession): Promise; - getDebuggerLabel(type: string): string | undefined; - - registerDebugAdapterFactory(debugTypes: string[], debugAdapterFactory: IDebugAdapterFactory): IDisposable; - createDebugAdapter(session: IDebugSession): IDebugAdapter | undefined; - - substituteVariables(debugType: string, folder: IWorkspaceFolder | undefined, config: IConfig): Promise; - runInTerminal(debugType: string, args: DebugProtocol.RunInTerminalRequestArguments): Promise; -} - -export interface ILaunch { - - /** - * Resource pointing to the launch.json this object is wrapping. - */ - readonly uri: uri; - - /** - * Name of the launch. - */ - readonly name: string; - - /** - * Workspace of the launch. Can be undefined. - */ - readonly workspace: IWorkspaceFolder | undefined; - - /** - * Should this launch be shown in the debug dropdown. - */ - readonly hidden: boolean; - - /** - * Returns a configuration with the specified name. - * Returns undefined if there is no configuration with the specified name. - */ - getConfiguration(name: string): IConfig | undefined; - - /** - * Returns a compound with the specified name. - * Returns undefined if there is no compound with the specified name. - */ - getCompound(name: string): ICompound | undefined; - - /** - * Returns the names of all configurations and compounds. - * Ignores configurations which are invalid. - */ - getConfigurationNames(ignoreCompoundsAndPresentation?: boolean): string[]; - - /** - * Opens the launch.json file. Creates if it does not exist. - */ - openConfigFile(preserveFocus: boolean, type?: string, token?: CancellationToken): Promise<{ editor: IEditorPane | null, created: boolean }>; -} - -// Debug service interfaces - -export const IDebugService = createDecorator(DEBUG_SERVICE_ID); - -export interface IDebugService { - readonly _serviceBrand: undefined; - - /** - * Gets the current debug state. - */ - readonly state: State; - - /** - * Allows to register on debug state changes. - */ - onDidChangeState: Event; - - /** - * Allows to register on new session events. - */ - onDidNewSession: Event; - - /** - * Allows to register on sessions about to be created (not yet fully initialised) - */ - onWillNewSession: Event; - - /** - * Allows to register on end session events. - */ - onDidEndSession: Event; - - /** - * Gets the current configuration manager. - */ - getConfigurationManager(): IConfigurationManager; - - /** - * Sets the focused stack frame and evaluates all expressions against the newly focused stack frame, - */ - focusStackFrame(focusedStackFrame: IStackFrame | undefined, thread?: IThread, session?: IDebugSession, explicit?: boolean): Promise; - - /** - * Adds new breakpoints to the model for the file specified with the uri. Notifies debug adapter of breakpoint changes. - */ - addBreakpoints(uri: uri, rawBreakpoints: IBreakpointData[], ariaAnnounce?: boolean): Promise; - - /** - * Updates the breakpoints. - */ - updateBreakpoints(uri: uri, data: Map, sendOnResourceSaved: boolean): Promise; - - /** - * Enables or disables all breakpoints. If breakpoint is passed only enables or disables the passed breakpoint. - * Notifies debug adapter of breakpoint changes. - */ - enableOrDisableBreakpoints(enable: boolean, breakpoint?: IEnablement): Promise; - - /** - * Sets the global activated property for all breakpoints. - * Notifies debug adapter of breakpoint changes. - */ - setBreakpointsActivated(activated: boolean): Promise; - - /** - * Removes all breakpoints. If id is passed only removes the breakpoint associated with that id. - * Notifies debug adapter of breakpoint changes. - */ - removeBreakpoints(id?: string): Promise; - - /** - * Adds a new function breakpoint for the given name. - */ - addFunctionBreakpoint(name?: string, id?: string): void; - - /** - * Renames an already existing function breakpoint. - * Notifies debug adapter of breakpoint changes. - */ - renameFunctionBreakpoint(id: string, newFunctionName: string): Promise; - - /** - * Removes all function breakpoints. If id is passed only removes the function breakpoint with the passed id. - * Notifies debug adapter of breakpoint changes. - */ - removeFunctionBreakpoints(id?: string): Promise; - - /** - * Adds a new data breakpoint. - */ - addDataBreakpoint(label: string, dataId: string, canPersist: boolean, accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined): Promise; - - /** - * Removes all data breakpoints. If id is passed only removes the data breakpoint with the passed id. - * Notifies debug adapter of breakpoint changes. - */ - removeDataBreakpoints(id?: string): Promise; - - /** - * Sends all breakpoints to the passed session. - * If session is not passed, sends all breakpoints to each session. - */ - sendAllBreakpoints(session?: IDebugSession): Promise; - - /** - * Adds a new watch expression and evaluates it against the debug adapter. - */ - addWatchExpression(name?: string): void; - - /** - * Renames a watch expression and evaluates it against the debug adapter. - */ - renameWatchExpression(id: string, newName: string): void; - - /** - * Moves a watch expression to a new possition. Used for reordering watch expressions. - */ - moveWatchExpression(id: string, position: number): void; - - /** - * Removes all watch expressions. If id is passed only removes the watch expression with the passed id. - */ - removeWatchExpressions(id?: string): void; - - /** - * Starts debugging. If the configOrName is not passed uses the selected configuration in the debug dropdown. - * Also saves all files, manages if compounds are present in the configuration - * and resolveds configurations via DebugConfigurationProviders. - * - * Returns true if the start debugging was successfull. For compound launches, all configurations have to start successfuly for it to return success. - * On errors the startDebugging will throw an error, however some error and cancelations are handled and in that case will simply return false. - */ - startDebugging(launch: ILaunch | undefined, configOrName?: IConfig | string, options?: IDebugSessionOptions): Promise; - - /** - * Restarts a session or creates a new one if there is no active session. - */ - restartSession(session: IDebugSession, restartData?: any): Promise; - - /** - * Stops the session. If no session is specified then all sessions are stopped. - */ - stopSession(session: IDebugSession | undefined): Promise; - - /** - * Makes unavailable all sources with the passed uri. Source will appear as grayed out in callstack view. - */ - sourceIsNotAvailable(uri: uri): void; - - /** - * Gets the current debug model. - */ - getModel(): IDebugModel; - - /** - * Gets the current view model. - */ - getViewModel(): IViewModel; -} - -// Editor interfaces -export const enum BreakpointWidgetContext { - CONDITION = 0, - HIT_COUNT = 1, - LOG_MESSAGE = 2 -} - -export interface IDebugEditorContribution extends editorCommon.IEditorContribution { - showHover(range: Range, focus: boolean): Promise; - addLaunchConfiguration(): Promise; -} - -export interface IBreakpointEditorContribution extends editorCommon.IEditorContribution { - showBreakpointWidget(lineNumber: number, column: number | undefined, context?: BreakpointWidgetContext): void; - closeBreakpointWidget(): void; -} - -// temporary debug helper service - -export const DEBUG_HELPER_SERVICE_ID = 'debugHelperService'; -export const IDebugHelperService = createDecorator(DEBUG_HELPER_SERVICE_ID); - -export interface IDebugHelperService { - readonly _serviceBrand: undefined; - - createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined; -} + hidden?: boolean; \ No newline at end of file diff --git a/src/vs/workbench/contrib/debug/common/debugger.ts b/src/vs/workbench/contrib/debug/common/debugger.ts index 6f0a211b3bdb1..ae8bc52db80ae 100644 --- a/src/vs/workbench/contrib/debug/common/debugger.ts +++ b/src/vs/workbench/contrib/debug/common/debugger.ts @@ -108,7 +108,7 @@ export class Debugger implements IDebugger { substituteVariables(folder: IWorkspaceFolder | undefined, config: IConfig): Promise { return this.configurationManager.substituteVariables(this.type, folder, config).then(config => { - return this.configurationResolverService.resolveWithInteractionReplace(folder, config, 'launch', this.variables); + return this.configurationResolverService.resolveWithInteractionReplace(folder, config, 'launch', this.variables, config.__configurationTarget); }); } diff --git a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts index cbea77efa042f..a40d034ec7f3f 100644 --- a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts @@ -10,7 +10,7 @@ import { Schemas } from 'vs/base/common/network'; import { SideBySideEditor, EditorResourceAccessor } from 'vs/workbench/common/editor'; import { IStringDictionary, forEach, fromMap } from 'vs/base/common/collections'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { IConfigurationService, IConfigurationOverrides, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IWorkspaceFolder, IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -146,8 +146,9 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR // get all "inputs" let inputs: ConfiguredInput[] = []; - if (folder && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && section) { - let result = this.configurationService.inspect(section, { resource: folder.uri }); + if (this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && section) { + const overrides: IConfigurationOverrides = folder ? { resource: folder.uri } : {}; + let result = this.configurationService.inspect(section, overrides); if (result && (result.userValue || result.workspaceValue || result.workspaceFolderValue)) { switch (target) { case ConfigurationTarget.USER: inputs = (result.userValue)?.inputs; break; @@ -155,7 +156,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR default: inputs = (result.workspaceFolderValue)?.inputs; } } else { - const valueResult = this.configurationService.getValue(section, { resource: folder.uri }); + const valueResult = this.configurationService.getValue(section, overrides); if (valueResult) { inputs = valueResult.inputs; }