diff --git a/src/vs/workbench/api/browser/mainThreadTerminalService.ts b/src/vs/workbench/api/browser/mainThreadTerminalService.ts index 1f45d901a32..55c79a987ab 100644 --- a/src/vs/workbench/api/browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/browser/mainThreadTerminalService.ts @@ -20,7 +20,7 @@ import { IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy, ITerminal import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { withNullAsUndefined } from 'vs/base/common/types'; import { OperatingSystem, OS } from 'vs/base/common/platform'; -import { TerminalCommandMatchResult, TerminalCommandSelector, TerminalEditorLocationOptions } from 'vscode'; +import { TerminalCommandMatchResult, TerminalEditorLocationOptions } from 'vscode'; import { Promises } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -246,9 +246,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape this._profileProviders.delete(id); } - public async $registerQuickFixProvider(id: string, extensionId: string, commandSelector: TerminalCommandSelector): Promise { - this._quickFixProviders.set(id, this._terminalQuickFixService.registerQuickFixProvider( - { id, extensionId, ...commandSelector }, + public async $registerQuickFixProvider(id: string): Promise { + this._quickFixProviders.set(id, this._terminalQuickFixService.registerQuickFixProvider(id, { provideTerminalQuickFixes: (matchResult: TerminalCommandMatchResult, token: CancellationToken) => { return this._proxy.$provideTerminalQuickFixes(id, matchResult, token); diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 125182f0140..c2f05b3598d 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -729,9 +729,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerTerminalProfileProvider(id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable { return extHostTerminalService.registerProfileProvider(extension, id, provider); }, - registerTerminalQuickFixProvider(id: string, commandSelector: vscode.TerminalCommandSelector, provider: vscode.TerminalQuickFixProvider): vscode.Disposable { + registerTerminalQuickFixProvider(id: string, provider: vscode.TerminalQuickFixProvider): vscode.Disposable { checkProposedApiEnabled(extension, 'terminalQuickFixProvider'); - return extHostTerminalService.registerTerminalQuickFixProvider(id, extension.identifier.value, commandSelector, provider); + return extHostTerminalService.registerTerminalQuickFixProvider(id, extension.identifier.value, provider); }, registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider): vscode.Disposable { return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, extension); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index bc7fa83e145..23296caaca8 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -70,7 +70,7 @@ import { CandidatePort } from 'vs/workbench/services/remote/common/remoteExplore import { ITextQueryBuilderOptions } from 'vs/workbench/services/search/common/queryBuilder'; import * as search from 'vs/workbench/services/search/common/search'; import { EditSessionIdentityMatch } from 'vs/platform/workspace/common/editSessions'; -import { TerminalCommandMatchResult, TerminalCommandSelector, TerminalQuickFix } from 'vscode'; +import { TerminalCommandMatchResult, TerminalQuickFix } from 'vscode'; export interface IWorkspaceData extends IStaticWorkspaceData { folders: { uri: UriComponents; name: string; index: number }[]; @@ -478,7 +478,7 @@ export interface MainThreadTerminalServiceShape extends IDisposable { $registerProcessSupport(isSupported: boolean): void; $registerProfileProvider(id: string, extensionIdentifier: string): void; $unregisterProfileProvider(id: string): void; - $registerQuickFixProvider(id: string, extensionIdentifier: string, commandSelector: TerminalCommandSelector): void; + $registerQuickFixProvider(id: string, extensionIdentifier: string): void; $unregisterQuickFixProvider(id: string): void; $setEnvironmentVariableCollection(extensionIdentifier: string, persistent: boolean, collection: ISerializableEnvironmentVariableCollection | undefined): void; diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index e59735881fb..acfb3f6345f 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -49,7 +49,7 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID getDefaultShellArgs(useAutomationShell: boolean): string[] | string; registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable; registerProfileProvider(extension: IExtensionDescription, id: string, provider: vscode.TerminalProfileProvider): vscode.Disposable; - registerTerminalQuickFixProvider(id: string, extensionId: string, commandSelector: vscode.TerminalCommandSelector, provider: vscode.TerminalQuickFixProvider): vscode.Disposable; + registerTerminalQuickFixProvider(id: string, extensionId: string, provider: vscode.TerminalQuickFixProvider): vscode.Disposable; getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection; } @@ -362,7 +362,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I private readonly _bufferer: TerminalDataBufferer; private readonly _linkProviders: Set = new Set(); private readonly _profileProviders: Map = new Map(); - private readonly _quickFixProviders: Map = new Map(); + private readonly _quickFixProviders: Map = new Map(); private readonly _terminalLinkCache: Map> = new Map(); private readonly _terminalLinkCancellationSource: Map = new Map(); @@ -667,12 +667,12 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I }); } - public registerTerminalQuickFixProvider(id: string, extensionId: string, selector: vscode.TerminalCommandSelector, provider: vscode.TerminalQuickFixProvider): vscode.Disposable { + public registerTerminalQuickFixProvider(id: string, extensionId: string, provider: vscode.TerminalQuickFixProvider): vscode.Disposable { if (this._quickFixProviders.has(id)) { throw new Error(`Terminal quick fix provider "${id}" is already registered`); } - this._quickFixProviders.set(id, { selector, provider }); - this._proxy.$registerQuickFixProvider(id, extensionId, selector); + this._quickFixProviders.set(id, provider); + this._proxy.$registerQuickFixProvider(id, extensionId); return new VSCodeDisposable(() => { this._quickFixProviders.delete(id); this._proxy.$unregisterQuickFixProvider(id); @@ -688,7 +688,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I if (!provider) { return; } - return provider.provider.provideTerminalQuickFixes(matchResult, token); + return provider.provideTerminalQuickFixes(matchResult, token); } public async $createContributedProfileTerminal(id: string, options: ICreateContributedTerminalProfileOptions): Promise { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalQuickFixService.ts b/src/vs/workbench/contrib/terminal/browser/terminalQuickFixService.ts index 5f9ad3f2ece..88d7e3441cd 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalQuickFixService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalQuickFixService.ts @@ -6,24 +6,33 @@ import { Emitter } from 'vs/base/common/event'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ITerminalCommandSelector, ITerminalQuickFixProvider } from 'vs/platform/terminal/common/terminal'; -import { ITerminalQuickFixSelectorProvider, ITerminalQuickFixService } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalQuickFixProviderSelector, ITerminalQuickFixService } from 'vs/workbench/contrib/terminal/common/terminal'; export class TerminalQuickFixService implements ITerminalQuickFixService { - private readonly _onDidRegisterProvider = new Emitter(); + private readonly _onDidRegisterProvider = new Emitter(); readonly onDidRegisterProvider = this._onDidRegisterProvider.event; - private readonly _onDidUnregisterProvider = new Emitter(); + private readonly _onDidUnregisterProvider = new Emitter(); readonly onDidUnregisterProvider = this._onDidUnregisterProvider.event; _serviceBrand: undefined; - _providers: Map = new Map(); - get providers(): Map { return this._providers; } + _providers: Map = new Map(); + _selectors: Map = new Map(); + get providers(): Map { return this._providers; } + get selectors(): Map { return this._selectors; } - registerQuickFixProvider(selector: ITerminalCommandSelector, provider: ITerminalQuickFixProvider): IDisposable { - const selectorProvider = { id: selector.id, selector, provider }; - this._providers.set(selector.id, selectorProvider); - this._onDidRegisterProvider.fire(selectorProvider); + registerCommandSelector(selector: ITerminalCommandSelector): void { + this.selectors.set(selector.id, selector); + } + + registerQuickFixProvider(id: string, provider: ITerminalQuickFixProvider): IDisposable { + this._providers.set(id, provider); + const selector = this._selectors.get(id); + if (!selector) { + throw new Error(`No registered selector for ID: ${id}`); + } + this._onDidRegisterProvider.fire({ selector, provider }); return toDisposable(() => { - this._onDidUnregisterProvider.fire(selectorProvider); - this._providers.delete(selector.id); + this._onDidUnregisterProvider.fire(selector.id); + this._providers.delete(id); }); } } diff --git a/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts b/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts index 1b895e95f2b..8239cdeff21 100644 --- a/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/xterm/quickFixAddon.ts @@ -14,7 +14,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView import { IOpenerService } from 'vs/platform/opener/common/opener'; import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService'; import { DecorationSelector, TerminalDecorationHoverManager, updateLayout } from 'vs/workbench/contrib/terminal/browser/xterm/decorationStyles'; -import { ITerminalQuickFixSelectorProvider, ITerminalQuickFixService, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalQuickFixProviderSelector, ITerminalQuickFixService, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IDecoration, Terminal } from 'xterm'; @@ -102,8 +102,8 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, for (const commandSelector of this._terminalContributionService.quickFixes) { this.registerCommandSelector(commandSelector); } - this._quickFixService.onDidRegisterProvider(selectorProvider => this.registerCommandFinishedListener(convertToQuickFixOptions(selectorProvider))); - this._quickFixService.onDidUnregisterProvider(selectorProvider => this._commandListeners.delete(selectorProvider.id)); + this._quickFixService.onDidRegisterProvider(result => this.registerCommandFinishedListener(convertToQuickFixOptions(result))); + this._quickFixService.onDidUnregisterProvider(id => this._commandListeners.delete(id)); } activate(terminal: Terminal): void { @@ -116,6 +116,7 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, } registerCommandSelector(selector: ITerminalCommandSelector): void { + this._quickFixService.registerCommandSelector(selector); const matcherKey = selector.commandLineMatcher.toString(); const currentOptions = this._commandListeners.get(matcherKey) || []; currentOptions.push({ @@ -182,12 +183,12 @@ export class TerminalQuickFixAddon extends Disposable implements ITerminalAddon, } const resolver = async (id: string, matchResult: ITerminalCommandMatchResult) => { await this._extensionService.activateByEvent(`onTerminalQuickFixRequest:${id}`); - const selectorProvider = this._quickFixService.providers.get(id); - if (!selectorProvider?.provider) { + const provider = this._quickFixService.providers.get(id); + if (!provider) { this._logService.warn('No provider when trying to resolve terminal quick fix for provider: ', id); return; } - return selectorProvider.provider.provideTerminalQuickFixes(matchResult); + return provider.provideTerminalQuickFixes(matchResult); }; const result = await getQuickFixesForCommand(command, this._commandListeners, this._openerService, this._onDidRequestRerunCommand, resolver); if (!result) { @@ -375,9 +376,9 @@ export async function getQuickFixesForCommand( return fixes.length > 0 ? { fixes, onDidRunQuickFix, expectedCommands } : undefined; } -function convertToQuickFixOptions(selectorProvider: ITerminalQuickFixSelectorProvider): IResolvedExtensionOptions { +function convertToQuickFixOptions(selectorProvider: ITerminalQuickFixProviderSelector): IResolvedExtensionOptions { return { - id: selectorProvider.id, + id: selectorProvider.selector.id, type: 'resolved', commandLineMatcher: selectorProvider.selector.commandLineMatcher, outputMatcher: selectorProvider.selector.outputMatcher, diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 11ef1ac7899..86322dbf242 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -8,7 +8,7 @@ import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform'; import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, TerminalLocationString, IProcessProperty, TitleEventSource, ProcessPropertyType, IFixedTerminalDimensions, IExtensionTerminalProfile, ICreateContributedTerminalProfileOptions, IProcessPropertyMap, ITerminalEnvironment, ITerminalProcessOptions, ITerminalCommandSelector, ITerminalQuickFixProvider } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalIcon, TerminalLocationString, IProcessProperty, TitleEventSource, ProcessPropertyType, IFixedTerminalDimensions, IExtensionTerminalProfile, ICreateContributedTerminalProfileOptions, IProcessPropertyMap, ITerminalEnvironment, ITerminalProcessOptions, ITerminalQuickFixProvider, ITerminalCommandSelector } from 'vs/platform/terminal/common/terminal'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; @@ -88,15 +88,15 @@ export interface ITerminalProfileService { export const ITerminalQuickFixService = createDecorator('terminalQuickFixService'); export interface ITerminalQuickFixService { - onDidRegisterProvider: Event; - onDidUnregisterProvider: Event; + onDidRegisterProvider: Event; + onDidUnregisterProvider: Event; readonly _serviceBrand: undefined; - providers: Map; - registerQuickFixProvider(commandSelector: ITerminalCommandSelector, provider: ITerminalQuickFixProvider): IDisposable; + providers: Map; + registerQuickFixProvider(id: string, provider: ITerminalQuickFixProvider): IDisposable; + registerCommandSelector(selector: ITerminalCommandSelector): void; } -export interface ITerminalQuickFixSelectorProvider { - id: string; +export interface ITerminalQuickFixProviderSelector { selector: ITerminalCommandSelector; provider: ITerminalQuickFixProvider; } diff --git a/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts b/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts index 694dc560893..d0019e22516 100644 --- a/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts +++ b/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts @@ -31,11 +31,10 @@ declare module 'vscode' { export namespace window { /** - * @param commandSelector A selector that defines the commands that this provider is applicable to. * @param provider A terminal quick fix provider * @return A {@link Disposable} that unregisters the provider when being disposed */ - export function registerTerminalQuickFixProvider(id: string, commandSelector: TerminalCommandSelector, provider: TerminalQuickFixProvider): Disposable; + export function registerTerminalQuickFixProvider(id: string, provider: TerminalQuickFixProvider): Disposable; }