diff --git a/extensions/npm/src/npmMain.ts b/extensions/npm/src/npmMain.ts index 26c6412b2d7..a066aac1e96 100644 --- a/extensions/npm/src/npmMain.ts +++ b/extensions/npm/src/npmMain.ts @@ -78,7 +78,7 @@ export async function activate(context: vscode.ExtensionContext): Promise } const lines = outputMatch.regexMatch[1]; - const fixes: vscode.TerminalQuickFixCommand[] = []; + const fixes: vscode.TerminalQuickFixExecuteTerminalCommand[] = []; for (const line of lines.split('\n')) { // search from the second char, since the lines might be prefixed with // "npm ERR!" which comes before the actual command suggestion. diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 383e886c8c1..961372ad4f1 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1475,7 +1475,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I TaskRevealKind: extHostTypes.TaskRevealKind, TaskScope: extHostTypes.TaskScope, TerminalLink: extHostTypes.TerminalLink, - TerminalQuickFixCommand: extHostTypes.TerminalQuickFixCommand, + TerminalQuickFixExecuteTerminalCommand: extHostTypes.TerminalQuickFixCommand, TerminalQuickFixOpener: extHostTypes.TerminalQuickFixOpener, TerminalLocation: extHostTypes.TerminalLocation, TerminalProfile: extHostTypes.TerminalProfile, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index e1c30c60aa7..acf8470a381 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -73,13 +73,9 @@ import { CandidatePort } from 'vs/workbench/services/remote/common/tunnelModel'; import { ITextQueryBuilderOptions } from 'vs/workbench/services/search/common/queryBuilder'; import * as search from 'vs/workbench/services/search/common/search'; import { ISaveProfileResult } from 'vs/workbench/services/userDataProfile/common/userDataProfile'; -import { TerminalCommandMatchResult, TerminalQuickFixCommand, TerminalQuickFixOpener } from 'vscode'; import { IChatMessage, IChatResponseFragment, IChatResponseProviderMetadata } from 'vs/workbench/contrib/chat/common/chatProvider'; import { IChatSlashFragment } from 'vs/workbench/contrib/chat/common/chatSlashCommands'; -export type TerminalQuickFix = TerminalQuickFixCommand | TerminalQuickFixOpener; - - export interface IWorkspaceData extends IStaticWorkspaceData { folders: { uri: UriComponents; name: string; index: number }[]; } @@ -2033,6 +2029,27 @@ export interface ITerminalDimensionsDto { rows: number; } +type SingleOrMany = T[] | T; + +export interface ITerminalQuickFixExecuteTerminalCommandDto { + terminalCommand: string; +} + +export interface ITerminalQuickFixOpenerDto { + uri: UriComponents; +} + +export type TerminalQuickFix = ITerminalQuickFixExecuteTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto; + +export interface TerminalCommandMatchResultDto { + commandLine: string; + commandLineMatch: RegExpMatchArray; + outputMatch?: { + regexMatch: RegExpMatchArray; + outputLines: string[]; + }; +} + export interface ExtHostTerminalServiceShape { $acceptTerminalClosed(id: number, exitCode: number | undefined, exitReason: TerminalExitReason): void; $acceptTerminalOpened(id: number, extHostTerminalId: string | undefined, name: string, shellLaunchConfig: IShellLaunchConfigDto): void; @@ -2057,7 +2074,7 @@ export interface ExtHostTerminalServiceShape { $initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void; $acceptDefaultProfile(profile: ITerminalProfile, automationProfile: ITerminalProfile): void; $createContributedProfileTerminal(id: string, options: ICreateContributedTerminalProfileOptions): Promise; - $provideTerminalQuickFixes(id: string, matchResult: TerminalCommandMatchResult, token: CancellationToken): Promise; + $provideTerminalQuickFixes(id: string, matchResult: TerminalCommandMatchResultDto, token: CancellationToken): Promise | undefined>; } export interface ExtHostSCMShape { diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 40fdcbb2c87..d91e8fe990f 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -5,11 +5,11 @@ import type * as vscode from 'vscode'; import { Event, Emitter } from 'vs/base/common/event'; -import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, ExtHostTerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, ExtHostTerminalIdentifier, ICommandDto, ITerminalQuickFixOpenerDto, ITerminalQuickFixExecuteTerminalCommandDto, TerminalCommandMatchResultDto } from 'vs/workbench/api/common/extHost.protocol'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; -import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, DisposableStore, Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { Disposable as VSCodeDisposable, EnvironmentVariableMutatorType, TerminalExitReason } from './extHostTypes'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { localize } from 'vs/nls'; @@ -23,8 +23,9 @@ import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBu import { ThemeColor } from 'vs/base/common/themables'; import { Promises } from 'vs/base/common/async'; import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; -import { ViewColumn } from 'vs/workbench/api/common/extHostTypeConverters'; +import { TerminalQuickFix, ViewColumn } from 'vs/workbench/api/common/extHostTypeConverters'; import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; +import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable { @@ -365,6 +366,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I protected _environmentVariableCollections: Map = new Map(); private _defaultProfile: ITerminalProfile | undefined; private _defaultAutomationProfile: ITerminalProfile | undefined; + private _lastQuickFixCommands: MutableDisposable = this._register(new MutableDisposable()); private readonly _bufferer: TerminalDataBufferer; private readonly _linkProviders: Set = new Set(); @@ -393,6 +395,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I constructor( supportsProcesses: boolean, + @IExtHostCommands private readonly _extHostCommands: IExtHostCommands, @IExtHostRpcService extHostRpc: IExtHostRpcService ) { super(); @@ -690,7 +693,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I }); } - public async $provideTerminalQuickFixes(id: string, matchResult: vscode.TerminalCommandMatchResult): Promise<(vscode.TerminalQuickFixOpener | vscode.TerminalQuickFixCommand)[] | vscode.TerminalQuickFixOpener | vscode.TerminalQuickFixCommand | undefined> { + public async $provideTerminalQuickFixes(id: string, matchResult: TerminalCommandMatchResultDto): Promise<(ITerminalQuickFixExecuteTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto)[] | ITerminalQuickFixExecuteTerminalCommandDto | ITerminalQuickFixOpenerDto | ICommandDto | undefined> { const token = new CancellationTokenSource().token; if (token.isCancellationRequested) { return; @@ -700,11 +703,27 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I return; } const quickFixes = await provider.provideTerminalQuickFixes(matchResult, token); - if (quickFixes === null) { + if (quickFixes === null || (Array.isArray(quickFixes) && quickFixes.length === 0)) { return undefined; - } else { - return quickFixes; } + + const store = new DisposableStore(); + this._lastQuickFixCommands.value = store; + + // Single + if (!Array.isArray(quickFixes)) { + return quickFixes ? TerminalQuickFix.from(quickFixes, this._extHostCommands.converter, store) : undefined; + } + + // Many + const result = []; + for (const fix of quickFixes) { + const converted = TerminalQuickFix.from(fix, this._extHostCommands.converter, store); + if (converted) { + result.push(converted); + } + } + return result; } public async $createContributedProfileTerminal(id: string, options: ICreateContributedTerminalProfileOptions): Promise { @@ -1110,9 +1129,10 @@ class ScopedEnvironmentVariableCollection implements vscode.EnvironmentVariableC export class WorkerExtHostTerminalService extends BaseExtHostTerminalService { constructor( + @IExtHostCommands extHostCommands: IExtHostCommands, @IExtHostRpcService extHostRpc: IExtHostRpcService ) { - super(false, extHostRpc); + super(false, extHostCommands, extHostRpc); } public createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index b71861cf028..80aeaa6d1f3 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -2197,3 +2197,15 @@ export namespace ChatMessageRole { } } } + +export namespace TerminalQuickFix { + export function from(quickFix: vscode.TerminalQuickFixExecuteTerminalCommand | vscode.TerminalQuickFixOpener | vscode.Command, converter: Command.ICommandsConverter, disposables: DisposableStore): extHostProtocol.ITerminalQuickFixExecuteTerminalCommandDto | extHostProtocol.ITerminalQuickFixOpenerDto | extHostProtocol.ICommandDto | undefined { + if ('terminalCommand' in quickFix) { + return { terminalCommand: quickFix.terminalCommand }; + } + if ('uri' in quickFix) { + return { uri: quickFix.uri }; + } + return converter.toInternal(quickFix, disposables); + } +} diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 3937478922b..fd5ec81368c 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -7,13 +7,15 @@ import { generateUuid } from 'vs/base/common/uuid'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { BaseExtHostTerminalService, ExtHostTerminal, ITerminalInternalOptions } from 'vs/workbench/api/common/extHostTerminalService'; import type * as vscode from 'vscode'; +import { IExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; export class ExtHostTerminalService extends BaseExtHostTerminalService { constructor( + @IExtHostCommands extHostCommands: IExtHostCommands, @IExtHostRpcService extHostRpc: IExtHostRpcService ) { - super(true, extHostRpc); + super(true, extHostCommands, extHostRpc); } public createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal { diff --git a/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts b/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts index 7c88c70f4f7..094d1b969c4 100644 --- a/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts +++ b/src/vscode-dts/vscode.proposed.terminalQuickFixProvider.d.ts @@ -7,6 +7,8 @@ declare module 'vscode' { // https://github.com/microsoft/vscode/issues/162950 + export type SingleOrMany = T[] | T; + export interface TerminalQuickFixProvider { /** * Provides terminal quick fixes @@ -14,7 +16,7 @@ declare module 'vscode' { * @param token A cancellation token indicating the result is no longer needed * @return Terminal quick fix(es) if any */ - provideTerminalQuickFixes(commandMatchResult: TerminalCommandMatchResult, token: CancellationToken): ProviderResult<(TerminalQuickFixCommand | TerminalQuickFixOpener)[] | TerminalQuickFixCommand | TerminalQuickFixOpener>; + provideTerminalQuickFixes(commandMatchResult: TerminalCommandMatchResult, token: CancellationToken): ProviderResult>; } @@ -35,7 +37,7 @@ declare module 'vscode' { export function registerTerminalQuickFixProvider(id: string, provider: TerminalQuickFixProvider): Disposable; } - export class TerminalQuickFixCommand { + export class TerminalQuickFixExecuteTerminalCommand { /** * The terminal command to run */