diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 43d17fb0609..1f0a242b31f 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1652,6 +1652,10 @@ export interface RenameProvider { resolveRenameLocation?(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult; } +export interface NewSymbolNamesProvider { + provideNewSymbolNames(model: model.ITextModel, range: IRange, token: CancellationToken): ProviderResult; +} + export interface Command { id: string; title: string; diff --git a/src/vs/editor/common/services/languageFeatures.ts b/src/vs/editor/common/services/languageFeatures.ts index 760e6e6e22a..92f7e271f1a 100644 --- a/src/vs/editor/common/services/languageFeatures.ts +++ b/src/vs/editor/common/services/languageFeatures.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { LanguageFeatureRegistry, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; -import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentPasteEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, MappedEditsProvider, MultiDocumentHighlightProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; +import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentPasteEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, MappedEditsProvider, MultiDocumentHighlightProvider, NewSymbolNamesProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const ILanguageFeaturesService = createDecorator('ILanguageFeaturesService'); @@ -29,6 +29,8 @@ export interface ILanguageFeaturesService { readonly renameProvider: LanguageFeatureRegistry; + readonly newSymbolNamesProvider: LanguageFeatureRegistry; + readonly documentFormattingEditProvider: LanguageFeatureRegistry; readonly documentRangeFormattingEditProvider: LanguageFeatureRegistry; diff --git a/src/vs/editor/common/services/languageFeaturesService.ts b/src/vs/editor/common/services/languageFeaturesService.ts index c6504614ce3..4e414b34b36 100644 --- a/src/vs/editor/common/services/languageFeaturesService.ts +++ b/src/vs/editor/common/services/languageFeaturesService.ts @@ -5,7 +5,7 @@ import { URI } from 'vs/base/common/uri'; import { LanguageFeatureRegistry, NotebookInfo, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry'; -import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, MultiDocumentHighlightProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, MappedEditsProvider } from 'vs/editor/common/languages'; +import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, MultiDocumentHighlightProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider, MappedEditsProvider, NewSymbolNamesProvider } from 'vs/editor/common/languages'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -15,6 +15,7 @@ export class LanguageFeaturesService implements ILanguageFeaturesService { readonly referenceProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly renameProvider = new LanguageFeatureRegistry(this._score.bind(this)); + readonly newSymbolNamesProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly codeActionProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly definitionProvider = new LanguageFeatureRegistry(this._score.bind(this)); readonly typeDefinitionProvider = new LanguageFeatureRegistry(this._score.bind(this)); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index ed1b548900f..dc6e5fb74e9 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -7766,6 +7766,10 @@ declare namespace monaco.languages { resolveRenameLocation?(model: editor.ITextModel, position: Position, token: CancellationToken): ProviderResult; } + export interface NewSymbolNamesProvider { + provideNewSymbolNames(model: editor.ITextModel, range: IRange, token: CancellationToken): ProviderResult; + } + export interface Command { id: string; title: string; diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 497fc46663b..b9d86e64edf 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -479,7 +479,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread // --- rename $registerRenameSupport(handle: number, selector: IDocumentFilterDto[], supportResolveLocation: boolean): void { - this._registrations.set(handle, this._languageFeaturesService.renameProvider.register(selector, { + this._registrations.set(handle, this._languageFeaturesService.renameProvider.register(selector, { provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken) => { return this._proxy.$provideRenameEdits(handle, model.uri, position, newName, token).then(data => reviveWorkspaceEditDto(data, this._uriIdentService)); }, @@ -489,6 +489,14 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread })); } + $registerNewSymbolNamesProvider(handle: number, selector: IDocumentFilterDto[]): void { + this._registrations.set(handle, this._languageFeaturesService.newSymbolNamesProvider.register(selector, { + provideNewSymbolNames: (model: ITextModel, range: IRange, token: CancellationToken): Promise => { + return this._proxy.$provideNewSymbolNames(handle, model.uri, range, token); + } + } satisfies languages.NewSymbolNamesProvider)); + } + // --- semantic tokens $registerDocumentSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: languages.SemanticTokensLegend, eventHandle: number | undefined): void { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index c0569540c2e..db680538d6b 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -582,6 +582,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable { return extHostLanguageFeatures.registerRenameProvider(extension, checkSelector(selector), provider); }, + registerNewSymbolNamesProvider(selector: vscode.DocumentSelector, provider: vscode.NewSymbolNamesProvider): vscode.Disposable { + checkProposedApiEnabled(extension, 'newSymbolNamesProvider'); + return extHostLanguageFeatures.registerNewSymbolNamesProvider(extension, checkSelector(selector), provider); + }, registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider, metadata?: vscode.DocumentSymbolProviderMetadata): vscode.Disposable { return extHostLanguageFeatures.registerDocumentSymbolProvider(extension, checkSelector(selector), provider, metadata); }, diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 676cf530dcf..e8b75cbceba 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -416,6 +416,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable { $registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void; $registerNavigateTypeSupport(handle: number, supportsResolve: boolean): void; $registerRenameSupport(handle: number, selector: IDocumentFilterDto[], supportsResolveInitialValues: boolean): void; + $registerNewSymbolNamesProvider(handle: number, selector: IDocumentFilterDto[]): void; $registerDocumentSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: languages.SemanticTokensLegend, eventHandle: number | undefined): void; $emitDocumentSemanticTokensEvent(eventHandle: number): void; $registerDocumentRangeSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: languages.SemanticTokensLegend): void; @@ -2103,6 +2104,7 @@ export interface ExtHostLanguageFeaturesShape { $releaseWorkspaceSymbols(handle: number, id: number): void; $provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise; $resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise; + $provideNewSymbolNames(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise; $provideDocumentSemanticTokens(handle: number, resource: UriComponents, previousResultId: number, token: CancellationToken): Promise; $releaseDocumentSemanticTokens(handle: number, semanticColoringResultId: number): void; $provideDocumentRangeSemanticTokens(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise; diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index b0a8742c349..90bf9b20469 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -816,6 +816,44 @@ class RenameAdapter { } } +class NewSymbolNamesAdapter { + + constructor( + private readonly _documents: ExtHostDocuments, + private readonly _provider: vscode.NewSymbolNamesProvider, + private readonly _logService: ILogService + ) { } + + async provideNewSymbolNames(resource: URI, range: IRange, token: CancellationToken): Promise { + + const doc = this._documents.getDocument(resource); + const pos = typeConvert.Range.to(range); + + try { + const value = await this._provider.provideNewSymbolNames(doc, pos, token); + if (!value) { + return undefined; + } + return value; + + } catch (err: unknown) { + this._logService.error(NewSymbolNamesAdapter._asMessage(err) ?? JSON.stringify(err, null, '\t') /* @ulugbekna: assuming `err` doesn't have circular references that could result in an exception when converting to JSON */); + return undefined; + } + } + + // @ulugbekna: this method is also defined in RenameAdapter but seems OK to be duplicated + private static _asMessage(err: any): string | undefined { + if (typeof err === 'string') { + return err; + } else if (err instanceof Error && typeof err.message === 'string') { + return err.message; + } else { + return undefined; + } + } +} + class SemanticTokensPreviousResult { constructor( readonly resultId: string | undefined, @@ -1905,7 +1943,7 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter | EvaluatableExpressionAdapter | InlineValuesAdapter | LinkedEditingRangeAdapter | InlayHintsAdapter | InlineCompletionAdapter - | DocumentOnDropEditAdapter | MappedEditsAdapter; + | DocumentOnDropEditAdapter | MappedEditsAdapter | NewSymbolNamesAdapter; class AdapterData { constructor( @@ -2287,6 +2325,16 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position, token), undefined, token); } + registerNewSymbolNamesProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.NewSymbolNamesProvider): vscode.Disposable { + const handle = this._addNewAdapter(new NewSymbolNamesAdapter(this._documents, provider, this._logService), extension); + this._proxy.$registerNewSymbolNamesProvider(handle, this._transformDocumentSelector(selector, extension)); + return this._createDisposable(handle); + } + + $provideNewSymbolNames(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise { + return this._withAdapter(handle, NewSymbolNamesAdapter, adapter => adapter.provideNewSymbolNames(URI.revive(resource), range, token), undefined, token); + } + //#region semantic coloring registerDocumentSemanticTokensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable { diff --git a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts index 15df9887466..0edc713a74c 100644 --- a/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts +++ b/src/vs/workbench/services/extensions/common/extensionsApiProposals.ts @@ -70,6 +70,7 @@ export const allApiProposals = Object.freeze({ languageStatusText: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.languageStatusText.d.ts', mappedEditsProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.mappedEditsProvider.d.ts', multiDocumentHighlightProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.multiDocumentHighlightProvider.d.ts', + newSymbolNamesProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.newSymbolNamesProvider.d.ts', notebookCellExecutionState: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookCellExecutionState.d.ts', notebookControllerAffinityHidden: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookControllerAffinityHidden.d.ts', notebookDeprecated: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookDeprecated.d.ts', diff --git a/src/vscode-dts/vscode.proposed.newSymbolNamesProvider.d.ts b/src/vscode-dts/vscode.proposed.newSymbolNamesProvider.d.ts new file mode 100644 index 00000000000..5f2c994d283 --- /dev/null +++ b/src/vscode-dts/vscode.proposed.newSymbolNamesProvider.d.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// https://github.com/microsoft/vscode/issues/204345 @ulugbekna + +declare module 'vscode' { + + export interface NewSymbolNamesProvider { + /** + * Provide possible new names for the symbol at the given range. + * + * @param document The document in which the symbol is defined. + * @param range The range that spans the symbol being renamed. + * @param token A cancellation token. + * @return A list of new symbol names. + */ + provideNewSymbolNames(document: TextDocument, range: Range, token: CancellationToken): ProviderResult; + } + + export namespace languages { + export function registerNewSymbolNamesProvider(selector: DocumentSelector, provider: NewSymbolNamesProvider): Disposable; + } +}