diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 22e3340319f..93761a39bb3 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -1956,7 +1956,7 @@ export class EditorModeContext extends Disposable { this._register(modes.DocumentHighlightProviderRegistry.onDidChange(update)); this._register(modes.DocumentSymbolProviderRegistry.onDidChange(update)); this._register(_languageFeaturesService.referenceProvider.onDidChange(update)); - this._register(modes.RenameProviderRegistry.onDidChange(update)); + this._register(_languageFeaturesService.renameProvider.onDidChange(update)); this._register(modes.DocumentFormattingEditProviderRegistry.onDidChange(update)); this._register(modes.DocumentRangeFormattingEditProviderRegistry.onDidChange(update)); this._register(modes.SignatureHelpProviderRegistry.onDidChange(update)); @@ -2010,7 +2010,7 @@ export class EditorModeContext extends Disposable { this._hasDocumentHighlightProvider.set(modes.DocumentHighlightProviderRegistry.has(model)); this._hasDocumentSymbolProvider.set(modes.DocumentSymbolProviderRegistry.has(model)); this._hasReferenceProvider.set(this._languageFeaturesService.referenceProvider.has(model)); - this._hasRenameProvider.set(modes.RenameProviderRegistry.has(model)); + this._hasRenameProvider.set(this._languageFeaturesService.renameProvider.has(model)); this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model)); this._hasInlayHintsProvider.set(modes.InlayHintsProviderRegistry.has(model)); this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model)); diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 3e410f3d169..77e968b4560 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1887,12 +1887,6 @@ export interface DocumentRangeSemanticTokensProvider { // --- feature registries ------ - -/** - * @internal - */ -export const RenameProviderRegistry = new LanguageFeatureRegistry(); - /** * @internal */ diff --git a/src/vs/editor/common/services/languageFeatures.ts b/src/vs/editor/common/services/languageFeatures.ts index 3eaf7df80ce..d916be67e46 100644 --- a/src/vs/editor/common/services/languageFeatures.ts +++ b/src/vs/editor/common/services/languageFeatures.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry'; -import { ReferenceProvider } from 'vs/editor/common/languages'; +import { ReferenceProvider, RenameProvider } from 'vs/editor/common/languages'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const ILanguageFeaturesService = createDecorator('ILanguageFeaturesService'); @@ -14,4 +14,6 @@ export interface ILanguageFeaturesService { readonly _serviceBrand: undefined; readonly referenceProvider: LanguageFeatureRegistry; + + readonly renameProvider: LanguageFeatureRegistry; } diff --git a/src/vs/editor/common/services/languageFeaturesService.ts b/src/vs/editor/common/services/languageFeaturesService.ts index 869ee492c8a..89e84c505f0 100644 --- a/src/vs/editor/common/services/languageFeaturesService.ts +++ b/src/vs/editor/common/services/languageFeaturesService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry'; -import { ReferenceProvider } from 'vs/editor/common/languages'; +import { ReferenceProvider, RenameProvider } from 'vs/editor/common/languages'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -13,6 +13,8 @@ export class LanguageFeatureService implements ILanguageFeaturesService { declare _serviceBrand: undefined; readonly referenceProvider = new LanguageFeatureRegistry(); + + readonly renameProvider = new LanguageFeatureRegistry(); } registerSingleton(ILanguageFeaturesService, LanguageFeatureService, true); diff --git a/src/vs/editor/contrib/rename/browser/rename.ts b/src/vs/editor/contrib/rename/browser/rename.ts index 0cae004d2a7..80a86dac88e 100644 --- a/src/vs/editor/contrib/rename/browser/rename.ts +++ b/src/vs/editor/contrib/rename/browser/rename.ts @@ -21,7 +21,7 @@ import { Range } from 'vs/editor/common/core/range'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { ITextModel } from 'vs/editor/common/model'; -import { Rejection, RenameLocation, RenameProvider, RenameProviderRegistry, WorkspaceEdit } from 'vs/editor/common/languages'; +import { Rejection, RenameLocation, RenameProvider, WorkspaceEdit } from 'vs/editor/common/languages'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration'; import { MessageController } from 'vs/editor/contrib/message/browser/messageController'; import * as nls from 'vs/nls'; @@ -34,6 +34,8 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { IEditorProgressService } from 'vs/platform/progress/common/progress'; import { Registry } from 'vs/platform/registry/common/platform'; import { CONTEXT_RENAME_INPUT_VISIBLE, RenameInputField } from './renameInputField'; +import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; class RenameSkeleton { @@ -42,9 +44,10 @@ class RenameSkeleton { constructor( private readonly model: ITextModel, - private readonly position: Position + private readonly position: Position, + registry: LanguageFeatureRegistry ) { - this._providers = RenameProviderRegistry.ordered(model); + this._providers = registry.ordered(model); } hasProvider() { @@ -109,8 +112,8 @@ class RenameSkeleton { } } -export async function rename(model: ITextModel, position: Position, newName: string): Promise { - const skeleton = new RenameSkeleton(model, position); +export async function rename(registry: LanguageFeatureRegistry, model: ITextModel, position: Position, newName: string): Promise { + const skeleton = new RenameSkeleton(model, position, registry); const loc = await skeleton.resolveRenameLocation(CancellationToken.None); if (loc?.rejectReason) { return { edits: [], rejectReason: loc.rejectReason }; @@ -140,6 +143,7 @@ class RenameController implements IEditorContribution { @IEditorProgressService private readonly _progressService: IEditorProgressService, @ILogService private readonly _logService: ILogService, @ITextResourceConfigurationService private readonly _configService: ITextResourceConfigurationService, + @ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService, ) { this._renameInputField = this._dispoableStore.add(new IdleValue(() => this._dispoableStore.add(this._instaService.createInstance(RenameInputField, this.editor, ['acceptRenameInput', 'acceptRenameInputWithPreview'])))); } @@ -158,7 +162,7 @@ class RenameController implements IEditorContribution { } const position = this.editor.getPosition(); - const skeleton = new RenameSkeleton(this.editor.getModel(), position); + const skeleton = new RenameSkeleton(this.editor.getModel(), position, this._languageFeaturesService.renameProvider); if (!skeleton.hasProvider()) { return undefined; @@ -354,14 +358,16 @@ registerEditorCommand(new RenameCommand({ // ---- api bridge command -registerModelAndPositionCommand('_executeDocumentRenameProvider', function (_accessor, model, position, ...args) { +registerModelAndPositionCommand('_executeDocumentRenameProvider', function (accessor, model, position, ...args) { const [newName] = args; assertType(typeof newName === 'string'); - return rename(model, position, newName); + const { renameProvider } = accessor.get(ILanguageFeaturesService); + return rename(renameProvider, model, position, newName); }); -registerModelAndPositionCommand('_executePrepareRename', async function (_accessor, model, position) { - const skeleton = new RenameSkeleton(model, position); +registerModelAndPositionCommand('_executePrepareRename', async function (accessor, model, position) { + const { renameProvider } = accessor.get(ILanguageFeaturesService); + const skeleton = new RenameSkeleton(model, position, renameProvider); const loc = await skeleton.resolveRenameLocation(CancellationToken.None); if (loc?.rejectReason) { throw new Error(loc.rejectReason); diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index 71016c552e3..55a9f578dee 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -421,7 +421,8 @@ export function registerReferenceProvider(languageId: string, provider: language * Register a rename provider (used by e.g. rename symbol). */ export function registerRenameProvider(languageId: string, provider: languages.RenameProvider): IDisposable { - return languages.RenameProviderRegistry.register(languageId, provider); + const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService); + return languageFeaturesService.renameProvider.register(languageId, provider); } /** diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index f94b3506822..697b93d7184 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -419,7 +419,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha // --- rename $registerRenameSupport(handle: number, selector: IDocumentFilterDto[], supportResolveLocation: boolean): void { - this._registrations.set(handle, modes.RenameProviderRegistry.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(reviveWorkspaceEditDto); }, diff --git a/src/vs/workbench/api/test/browser/extHostApiCommands.test.ts b/src/vs/workbench/api/test/browser/extHostApiCommands.test.ts index 15359a78bd6..49c0b32822f 100644 --- a/src/vs/workbench/api/test/browser/extHostApiCommands.test.ts +++ b/src/vs/workbench/api/test/browser/extHostApiCommands.test.ts @@ -55,6 +55,8 @@ import 'vs/editor/contrib/smartSelect/browser/smartSelect'; import 'vs/editor/contrib/suggest/browser/suggest'; import 'vs/editor/contrib/rename/browser/rename'; import 'vs/editor/contrib/inlayHints/browser/inlayHintsController'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; +import { LanguageFeatureService } from 'vs/editor/common/services/languageFeaturesService'; function assertRejects(fn: () => Promise, message: string = 'Expected rejection') { return fn().then(() => assert.ok(false, message), _err => assert.ok(true)); @@ -74,6 +76,7 @@ suite('ExtHostLanguageFeatureCommands', function () { let mainThread: MainThreadLanguageFeatures; let commands: ExtHostCommands; let disposables: vscode.Disposable[] = []; + let originalErrorHandler: (e: any) => any; suiteSetup(() => { @@ -93,6 +96,7 @@ suite('ExtHostLanguageFeatureCommands', function () { let insta: IInstantiationService; rpcProtocol = new TestRPCProtocol(); const services = new ServiceCollection(); + services.set(ILanguageFeaturesService, new SyncDescriptor(LanguageFeatureService)); services.set(IExtensionService, new class extends mock() { override async activateByEvent() { diff --git a/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts b/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts index 5c2014a7d50..29f9ee3bea7 100644 --- a/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts @@ -766,7 +766,7 @@ suite('ExtHostLanguageFeatures', function () { await rpcProtocol.sync(); try { - await rename(model, new EditorPosition(1, 1), 'newName'); + await rename(languageFeaturesService.renameProvider, model, new EditorPosition(1, 1), 'newName'); throw Error(); } catch (err) { @@ -783,7 +783,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await rename(model, new EditorPosition(1, 1), 'newName'); + const value = await rename(languageFeaturesService.renameProvider, model, new EditorPosition(1, 1), 'newName'); assert.strictEqual(value.rejectReason, 'evil'); }); @@ -804,7 +804,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await rename(model, new EditorPosition(1, 1), 'newName'); + const value = await rename(languageFeaturesService.renameProvider, model, new EditorPosition(1, 1), 'newName'); assert.strictEqual(value.edits.length, 1); }); @@ -826,7 +826,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - const value = await rename(model, new EditorPosition(1, 1), 'newName'); + const value = await rename(languageFeaturesService.renameProvider, model, new EditorPosition(1, 1), 'newName'); // least relevant rename provider assert.strictEqual(value.edits.length, 2); }); @@ -860,7 +860,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - await rename(model, new EditorPosition(1, 1), 'newName'); + await rename(languageFeaturesService.renameProvider, model, new EditorPosition(1, 1), 'newName'); assert.deepStrictEqual(called, [true, true, true, false]); }); @@ -891,7 +891,7 @@ suite('ExtHostLanguageFeatures', function () { })); await rpcProtocol.sync(); - await rename(model, new EditorPosition(1, 1), 'newName'); + await rename(languageFeaturesService.renameProvider, model, new EditorPosition(1, 1), 'newName'); // first provider has NO prepare which means it is taken by default assert.deepStrictEqual(called, [false, false, true]);