diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index da05c098834..76ee48e81f1 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -619,6 +619,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostQuickOpen.showWorkspaceFolderPick(options); }, showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken) { + if (options?.validateInput2) { + checkProposedApiEnabled(extension, 'inputBoxSeverity'); + options.validateInput = options.validateInput2 as any; + } return extHostQuickOpen.showInput(options, token); }, showOpenDialog(options) { @@ -702,7 +706,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostQuickOpen.createQuickPick(extension); }, createInputBox(): vscode.InputBox { - return extHostQuickOpen.createInputBox(extension.identifier); + return extHostQuickOpen.createInputBox(extension); }, get activeColorTheme(): vscode.ColorTheme { return extHostTheming.activeColorTheme; @@ -1328,6 +1332,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I WorkspaceTrustState: extHostTypes.WorkspaceTrustState, LanguageStatusSeverity: extHostTypes.LanguageStatusSeverity, QuickPickItemKind: extHostTypes.QuickPickItemKind, + InputBoxValidationSeverity: extHostTypes.InputBoxValidationSeverity, TextTabInput: extHostTypes.TextTabInput, TextDiffTabInput: extHostTypes.TextDiffTabInput, CustomEditorTabInput: extHostTypes.CustomEditorTabInput, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index ea2deffb974..74e9add6a55 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1712,7 +1712,7 @@ export interface ExtHostLanguageFeaturesShape { export interface ExtHostQuickOpenShape { $onItemSelected(handle: number): void; - $validateInput(input: string): Promise; + $validateInput(input: string): Promise; $onDidChangeActive(sessionId: number, handles: number[]): void; $onDidChangeSelection(sessionId: number, handles: number[]): void; $onDidAccept(sessionId: number): void; diff --git a/src/vs/workbench/api/common/extHostQuickOpen.ts b/src/vs/workbench/api/common/extHostQuickOpen.ts index a2f6efd3cbc..0df03b79137 100644 --- a/src/vs/workbench/api/common/extHostQuickOpen.ts +++ b/src/vs/workbench/api/common/extHostQuickOpen.ts @@ -9,7 +9,7 @@ import { Emitter } from 'vs/base/common/event'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands'; import { IExtHostWorkspaceProvider } from 'vs/workbench/api/common/extHostWorkspace'; -import type { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickItemButtonEvent, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode'; +import type { InputBox, InputBoxOptions, InputBoxValidationSeverity, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickItemButtonEvent, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode'; import { ExtHostQuickOpenShape, IMainContext, MainContext, TransferQuickInput, TransferQuickInputButton, TransferQuickPickItemOrSeparator } from './extHost.protocol'; import { URI } from 'vs/base/common/uri'; import { ThemeIcon, QuickInputButtons, QuickPickItemKind } from 'vs/workbench/api/common/extHostTypes'; @@ -18,6 +18,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio import { coalesce } from 'vs/base/common/arrays'; import Severity from 'vs/base/common/severity'; import { ThemeIcon as ThemeIconUtils } from 'vs/platform/theme/common/themeService'; +import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; export type Item = string | QuickPickItem; @@ -31,9 +32,9 @@ export interface ExtHostQuickOpen { showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token?: CancellationToken): Promise; - createQuickPick(extensionId: IExtensionDescription): QuickPick; + createQuickPick(extension: IExtensionDescription): QuickPick; - createInputBox(extensionId: ExtensionIdentifier): InputBox; + createInputBox(extension: IExtensionDescription): InputBox; } export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IExtHostWorkspaceProvider, commands: ExtHostCommands): ExtHostQuickOpenShape & ExtHostQuickOpen { @@ -45,7 +46,7 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx private _commands: ExtHostCommands; private _onDidSelectItem?: (handle: number) => void; - private _validateInput?: (input: string) => string | undefined | null | Thenable; + private _validateInput?: (input: string) => string | { content: string; severity: Severity } | undefined | null | Thenable; private _sessions = new Map(); @@ -159,7 +160,7 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx }); } - $validateInput(input: string): Promise { + $validateInput(input: string): Promise { if (this._validateInput) { return asPromise(() => this._validateInput!(input)); } @@ -188,8 +189,8 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx return session; } - createInputBox(extensionId: ExtensionIdentifier): InputBox { - const session: ExtHostInputBox = new ExtHostInputBox(extensionId, () => this._sessions.delete(session._id)); + createInputBox(extension: IExtensionDescription): InputBox { + const session: ExtHostInputBox = new ExtHostInputBox(extension, () => this._sessions.delete(session._id)); this._sessions.set(session._id, session); return session; } @@ -674,9 +675,10 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx private _password = false; private _prompt: string | undefined; private _validationMessage: string | undefined; + private _validationMessage2: string | { content: string; severity: InputBoxValidationSeverity } | undefined; - constructor(extensionId: ExtensionIdentifier, onDispose: () => void) { - super(extensionId, onDispose); + constructor(private readonly extension: IExtensionDescription, onDispose: () => void) { + super(extension.identifier, onDispose); this.update({ type: 'inputBox' }); } @@ -706,6 +708,22 @@ export function createExtHostQuickOpen(mainContext: IMainContext, workspace: IEx this._validationMessage = validationMessage; this.update({ validationMessage, severity: validationMessage ? Severity.Error : Severity.Ignore }); } + + get validationMessage2() { + return this._validationMessage2; + } + + set validationMessage2(validationMessage: string | { content: string; severity: InputBoxValidationSeverity } | undefined) { + checkProposedApiEnabled(this.extension, 'inputBoxSeverity'); + this._validationMessage2 = validationMessage; + if (!validationMessage) { + this.update({ validationMessage: undefined, severity: Severity.Ignore }); + } else if (typeof validationMessage === 'string') { + this.update({ validationMessage, severity: Severity.Error }); + } else { + this.update({ validationMessage: validationMessage.content, severity: validationMessage.severity ?? Severity.Error }); + } + } } return new ExtHostQuickOpenImpl(workspace, commands); diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 3ecc45731b5..584f7dfc14e 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3022,6 +3022,12 @@ export enum QuickPickItemKind { Default = 0, } +export enum InputBoxValidationSeverity { + Info = 1, + Warning = 2, + Error = 3 +} + export enum ExtensionKind { UI = 1, Workspace = 2 diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index a5c03b15f6e..0a1e93cded5 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -27,6 +27,7 @@ export const allApiProposals = Object.freeze({ inlineCompletions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inlineCompletions.d.ts', inlineCompletionsAdditions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts', inlineCompletionsNew: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inlineCompletionsNew.d.ts', + inputBoxSeverity: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.inputBoxSeverity.d.ts', ipc: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.ipc.d.ts', notebookCellExecutionState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookCellExecutionState.d.ts', notebookConcatTextDocument: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookConcatTextDocument.d.ts', diff --git a/src/vscode-dts/vscode.proposed.inputBoxSeverity.d.ts b/src/vscode-dts/vscode.proposed.inputBoxSeverity.d.ts new file mode 100644 index 00000000000..aca62dc70ba --- /dev/null +++ b/src/vscode-dts/vscode.proposed.inputBoxSeverity.d.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'vscode' { + + // https://github.com/microsoft/vscode/issues/144944 + + export enum InputBoxValidationSeverity { + Info = 1, + Warning = 2, + Error = 3 + } + + export interface InputBoxOptions { + /** + * The validation message to display. This will become the new {@link InputBoxOptions#validateInput} upon finalization. + */ + validateInput2?(value: string): string | { content: string; severity: InputBoxValidationSeverity } | undefined | null | + Thenable; + } + + export interface InputBox { + /** + * The validation message to display. This will become the new {@link InputBox#validationMessage} upon finalization. + */ + validationMessage2: string | { content: string; severity: InputBoxValidationSeverity } | undefined; + } +}