diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 6a66fc2b09c..d58d093cc96 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1892,11 +1892,6 @@ export interface DocumentRangeSemanticTokensProvider { */ export const CodeActionProviderRegistry = new LanguageFeatureRegistry(); -/** - * @internal - */ -export const DocumentSemanticTokensProviderRegistry = new LanguageFeatureRegistry(); - /** * @internal */ diff --git a/src/vs/editor/common/services/getSemanticTokens.ts b/src/vs/editor/common/services/getSemanticTokens.ts index 2a63663cca0..298da0ce0f6 100644 --- a/src/vs/editor/common/services/getSemanticTokens.ts +++ b/src/vs/editor/common/services/getSemanticTokens.ts @@ -7,7 +7,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { onUnexpectedExternalError } from 'vs/base/common/errors'; import { URI } from 'vs/base/common/uri'; import { ITextModel } from 'vs/editor/common/model'; -import { DocumentSemanticTokensProviderRegistry, DocumentSemanticTokensProvider, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend, DocumentRangeSemanticTokensProvider } from 'vs/editor/common/languages'; +import { DocumentSemanticTokensProvider, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend, DocumentRangeSemanticTokensProvider } from 'vs/editor/common/languages'; import { IModelService } from 'vs/editor/common/services/model'; import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands'; import { assertType } from 'vs/base/common/types'; @@ -33,17 +33,17 @@ export class DocumentSemanticTokensResult { ) { } } -export function hasDocumentSemanticTokensProvider(model: ITextModel): boolean { - return DocumentSemanticTokensProviderRegistry.has(model); +export function hasDocumentSemanticTokensProvider(registry: LanguageFeatureRegistry, model: ITextModel): boolean { + return registry.has(model); } -function getDocumentSemanticTokensProviders(model: ITextModel): DocumentSemanticTokensProvider[] { - const groups = DocumentSemanticTokensProviderRegistry.orderedGroups(model); +function getDocumentSemanticTokensProviders(registry: LanguageFeatureRegistry, model: ITextModel): DocumentSemanticTokensProvider[] { + const groups = registry.orderedGroups(model); return (groups.length > 0 ? groups[0] : []); } -export async function getDocumentSemanticTokens(model: ITextModel, lastProvider: DocumentSemanticTokensProvider | null, lastResultId: string | null, token: CancellationToken): Promise { - const providers = getDocumentSemanticTokensProviders(model); +export async function getDocumentSemanticTokens(registry: LanguageFeatureRegistry, model: ITextModel, lastProvider: DocumentSemanticTokensProvider | null, lastResultId: string | null, token: CancellationToken): Promise { + const providers = getDocumentSemanticTokensProviders(registry, model); // Get tokens from all providers at the same time. const results = await Promise.all(providers.map(async (provider) => { @@ -82,8 +82,8 @@ export async function getDocumentSemanticTokens(model: ITextModel, lastProvider: return null; } -function _getDocumentSemanticTokensProviderHighestGroup(model: ITextModel): DocumentSemanticTokensProvider[] | null { - const result = DocumentSemanticTokensProviderRegistry.orderedGroups(model); +function _getDocumentSemanticTokensProviderHighestGroup(registry: LanguageFeatureRegistry, model: ITextModel): DocumentSemanticTokensProvider[] | null { + const result = registry.orderedGroups(model); return (result.length > 0 ? result[0] : null); } @@ -146,8 +146,9 @@ CommandsRegistry.registerCommand('_provideDocumentSemanticTokensLegend', async ( if (!model) { return undefined; } + const { documentSemanticTokensProvider } = accessor.get(ILanguageFeaturesService); - const providers = _getDocumentSemanticTokensProviderHighestGroup(model); + const providers = _getDocumentSemanticTokensProviderHighestGroup(documentSemanticTokensProvider, model); if (!providers) { // there is no provider => fall back to a document range semantic tokens provider return accessor.get(ICommandService).executeCommand('_provideDocumentRangeSemanticTokensLegend', uri); @@ -164,13 +165,13 @@ CommandsRegistry.registerCommand('_provideDocumentSemanticTokens', async (access if (!model) { return undefined; } - - if (!hasDocumentSemanticTokensProvider(model)) { + const { documentSemanticTokensProvider } = accessor.get(ILanguageFeaturesService); + if (!hasDocumentSemanticTokensProvider(documentSemanticTokensProvider, model)) { // there is no provider => fall back to a document range semantic tokens provider return accessor.get(ICommandService).executeCommand('_provideDocumentRangeSemanticTokens', uri, model.getFullModelRange()); } - const r = await getDocumentSemanticTokens(model, null, null, CancellationToken.None); + const r = await getDocumentSemanticTokens(documentSemanticTokensProvider, model, null, null, CancellationToken.None); if (!r) { return undefined; } diff --git a/src/vs/editor/common/services/languageFeatures.ts b/src/vs/editor/common/services/languageFeatures.ts index 4c60f5ecabc..8a29d088d13 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 { CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; +import { CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; export const ILanguageFeaturesService = createDecorator('ILanguageFeaturesService'); @@ -55,6 +55,8 @@ export interface ILanguageFeaturesService { readonly documentRangeSemanticTokensProvider: LanguageFeatureRegistry; + readonly documentSemanticTokensProvider: LanguageFeatureRegistry; + readonly selectionRangeProvider: LanguageFeatureRegistry; readonly foldingRangeProvider: LanguageFeatureRegistry; diff --git a/src/vs/editor/common/services/languageFeaturesService.ts b/src/vs/editor/common/services/languageFeaturesService.ts index 9cb428ef80f..38ef3779d3e 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 { CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; +import { CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages'; import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -62,6 +62,7 @@ export class LanguageFeaturesService implements ILanguageFeaturesService { readonly documentRangeSemanticTokensProvider = new LanguageFeatureRegistry(); + readonly documentSemanticTokensProvider = new LanguageFeatureRegistry(); } registerSingleton(ILanguageFeaturesService, LanguageFeaturesService, true); diff --git a/src/vs/editor/common/services/modelService.ts b/src/vs/editor/common/services/modelService.ts index b1eef9c5362..66a74e3f2be 100644 --- a/src/vs/editor/common/services/modelService.ts +++ b/src/vs/editor/common/services/modelService.ts @@ -14,7 +14,7 @@ import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, ITextBuffer, import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel'; import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/core/textModelDefaults'; import { IModelLanguageChangedEvent, IModelContentChangedEvent } from 'vs/editor/common/textModelEvents'; -import { DocumentSemanticTokensProviderRegistry, DocumentSemanticTokensProvider, SemanticTokens, SemanticTokensEdits } from 'vs/editor/common/languages'; +import { DocumentSemanticTokensProvider, SemanticTokens, SemanticTokensEdits } from 'vs/editor/common/languages'; import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry'; import { ILanguageSelection, ILanguageService } from 'vs/editor/common/languages/language'; import { IModelService, DocumentTokensProvider } from 'vs/editor/common/services/model'; @@ -34,6 +34,8 @@ import { equals } from 'vs/base/common/objects'; import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry'; import { IFeatureDebounceInformation, ILanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; import { StopWatch } from 'vs/base/common/stopwatch'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; +import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry'; export interface IEditorSemanticHighlightingOptions { enabled: true | false | 'configuredByTheme'; @@ -166,7 +168,8 @@ export class ModelService extends Disposable implements IModelService { @IUndoRedoService private readonly _undoRedoService: IUndoRedoService, @ILanguageService private readonly _languageService: ILanguageService, @ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService, - @ILanguageFeatureDebounceService private readonly _languageFeatureDebounceService: ILanguageFeatureDebounceService + @ILanguageFeatureDebounceService private readonly _languageFeatureDebounceService: ILanguageFeatureDebounceService, + @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService, ) { super(); this._modelCreationOptionsByLanguageAndResource = Object.create(null); @@ -178,7 +181,7 @@ export class ModelService extends Disposable implements IModelService { this._register(this._configurationService.onDidChangeConfiguration(() => this._updateModelOptions())); this._updateModelOptions(); - this._register(new SemanticColoringFeature(this._semanticStyling, this, this._themeService, this._configurationService, this._languageFeatureDebounceService)); + this._register(new SemanticColoringFeature(this._semanticStyling, this, this._themeService, this._configurationService, this._languageFeatureDebounceService, languageFeaturesService)); } private static _readModelOptions(config: IRawConfig, isForSimpleWidget: boolean): ITextModelCreationOptions { @@ -660,14 +663,15 @@ class SemanticColoringFeature extends Disposable { @IModelService modelService: IModelService, @IThemeService themeService: IThemeService, @IConfigurationService configurationService: IConfigurationService, - @ILanguageFeatureDebounceService languageFeatureDebounceService: ILanguageFeatureDebounceService + @ILanguageFeatureDebounceService languageFeatureDebounceService: ILanguageFeatureDebounceService, + @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService, ) { super(); this._watchers = Object.create(null); this._semanticStyling = semanticStyling; const register = (model: ITextModel) => { - this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, this._semanticStyling, themeService, languageFeatureDebounceService); + this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, this._semanticStyling, themeService, languageFeatureDebounceService, languageFeaturesService); }; const deregister = (model: ITextModel, modelSemanticColoring: ModelSemanticColoring) => { modelSemanticColoring.dispose(); @@ -751,6 +755,7 @@ export class ModelSemanticColoring extends Disposable { private _isDisposed: boolean; private readonly _model: ITextModel; private readonly _semanticStyling: SemanticStyling; + private readonly _provider: LanguageFeatureRegistry; private readonly _debounceInformation: IFeatureDebounceInformation; private readonly _fetchDocumentSemanticTokens: RunOnceScheduler; private _currentDocumentResponse: SemanticTokensResponse | null; @@ -761,14 +766,16 @@ export class ModelSemanticColoring extends Disposable { model: ITextModel, stylingProvider: SemanticStyling, @IThemeService themeService: IThemeService, - @ILanguageFeatureDebounceService languageFeatureDebounceService: ILanguageFeatureDebounceService + @ILanguageFeatureDebounceService languageFeatureDebounceService: ILanguageFeatureDebounceService, + @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService, ) { super(); this._isDisposed = false; this._model = model; this._semanticStyling = stylingProvider; - this._debounceInformation = languageFeatureDebounceService.for(DocumentSemanticTokensProviderRegistry, 'DocumentSemanticTokens', { min: ModelSemanticColoring.REQUEST_MIN_DELAY, max: ModelSemanticColoring.REQUEST_MAX_DELAY }); + this._provider = languageFeaturesService.documentSemanticTokensProvider; + this._debounceInformation = languageFeatureDebounceService.for(this._provider, 'DocumentSemanticTokens', { min: ModelSemanticColoring.REQUEST_MIN_DELAY, max: ModelSemanticColoring.REQUEST_MAX_DELAY }); this._fetchDocumentSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchDocumentSemanticTokensNow(), ModelSemanticColoring.REQUEST_MIN_DELAY)); this._currentDocumentResponse = null; this._currentDocumentRequestCancellationTokenSource = null; @@ -796,14 +803,14 @@ export class ModelSemanticColoring extends Disposable { const bindDocumentChangeListeners = () => { dispose(this._documentProvidersChangeListeners); this._documentProvidersChangeListeners = []; - for (const provider of DocumentSemanticTokensProviderRegistry.all(model)) { + for (const provider of this._provider.all(model)) { if (typeof provider.onDidChange === 'function') { this._documentProvidersChangeListeners.push(provider.onDidChange(() => this._fetchDocumentSemanticTokens.schedule(0))); } } }; bindDocumentChangeListeners(); - this._register(DocumentSemanticTokensProviderRegistry.onDidChange(() => { + this._register(this._provider.onDidChange(() => { bindDocumentChangeListeners(); this._fetchDocumentSemanticTokens.schedule(this._debounceInformation.get(this._model)); })); @@ -838,7 +845,7 @@ export class ModelSemanticColoring extends Disposable { return; } - if (!hasDocumentSemanticTokensProvider(this._model)) { + if (!hasDocumentSemanticTokensProvider(this._provider, this._model)) { // there is no provider if (this._currentDocumentResponse) { // there are semantic tokens set @@ -850,7 +857,7 @@ export class ModelSemanticColoring extends Disposable { const cancellationTokenSource = new CancellationTokenSource(); const lastProvider = this._currentDocumentResponse ? this._currentDocumentResponse.provider : null; const lastResultId = this._currentDocumentResponse ? this._currentDocumentResponse.resultId || null : null; - const request = getDocumentSemanticTokens(this._model, lastProvider, lastResultId, cancellationTokenSource.token); + const request = getDocumentSemanticTokens(this._provider, this._model, lastProvider, lastResultId, cancellationTokenSource.token); this._currentDocumentRequestCancellationTokenSource = cancellationTokenSource; const pendingChanges: IModelContentChangedEvent[] = []; diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index e95ecc6bf50..a9c21a6e2ba 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -611,7 +611,8 @@ export function registerSelectionRangeProvider(languageId: string, provider: lan * For the best user experience, register both a semantic tokens provider and a top-down tokenizer. */ export function registerDocumentSemanticTokensProvider(languageId: string, provider: languages.DocumentSemanticTokensProvider): IDisposable { - return languages.DocumentSemanticTokensProviderRegistry.register(languageId, provider); + const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService); + return languageFeaturesService.documentSemanticTokensProvider.register(languageId, provider); } /** diff --git a/src/vs/editor/test/common/services/getSemanticTokens.test.ts b/src/vs/editor/test/common/services/getSemanticTokens.test.ts index f8dec3fa383..aff59d80eea 100644 --- a/src/vs/editor/test/common/services/getSemanticTokens.test.ts +++ b/src/vs/editor/test/common/services/getSemanticTokens.test.ts @@ -8,15 +8,16 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { canceled } from 'vs/base/common/errors'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { ITextModel } from 'vs/editor/common/model'; -import { DocumentSemanticTokensProvider, DocumentSemanticTokensProviderRegistry, ProviderResult, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend } from 'vs/editor/common/languages'; +import { DocumentSemanticTokensProvider, ProviderResult, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend } from 'vs/editor/common/languages'; import { getDocumentSemanticTokens } from 'vs/editor/common/services/getSemanticTokens'; import { createTextModel } from 'vs/editor/test/common/testTextModel'; +import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry'; suite('getSemanticTokens', () => { test('issue #136540: semantic highlighting flickers', async () => { const disposables = new DisposableStore(); - + const registry = new LanguageFeatureRegistry(); const provider = new class implements DocumentSemanticTokensProvider { getLegend(): SemanticTokensLegend { return { tokenTypes: ['test'], tokenModifiers: [] }; @@ -28,11 +29,11 @@ suite('getSemanticTokens', () => { } }; - disposables.add(DocumentSemanticTokensProviderRegistry.register('testLang', provider)); + disposables.add(registry.register('testLang', provider)); const textModel = disposables.add(createTextModel('example', 'testLang')); - await getDocumentSemanticTokens(textModel, null, null, CancellationToken.None).then((res) => { + await getDocumentSemanticTokens(registry, textModel, null, null, CancellationToken.None).then((res) => { assert.fail(); }, (err) => { assert.ok(!!err); diff --git a/src/vs/editor/test/common/services/modelService.test.ts b/src/vs/editor/test/common/services/modelService.test.ts index 8cd75096693..7d89dddc014 100644 --- a/src/vs/editor/test/common/services/modelService.test.ts +++ b/src/vs/editor/test/common/services/modelService.test.ts @@ -22,7 +22,7 @@ import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogSer import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; import { createTextModel } from 'vs/editor/test/common/testTextModel'; import { DisposableStore } from 'vs/base/common/lifecycle'; -import { DocumentSemanticTokensProvider, DocumentSemanticTokensProviderRegistry, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend } from 'vs/editor/common/languages'; +import { DocumentSemanticTokensProvider, SemanticTokens, SemanticTokensEdits, SemanticTokensLegend } from 'vs/editor/common/languages'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Barrier, timeout } from 'vs/base/common/async'; import { LanguageService } from 'vs/editor/common/services/languageService'; @@ -35,6 +35,8 @@ import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/te import { getDocumentSemanticTokens, isSemanticTokens } from 'vs/editor/common/services/getSemanticTokens'; import { LanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler'; +import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; const GENERATE_TESTS = false; @@ -58,7 +60,8 @@ suite('ModelService', () => { new UndoRedoService(dialogService, new TestNotificationService()), disposables.add(new LanguageService()), new TestLanguageConfigurationService(), - new LanguageFeatureDebounceService(logService) + new LanguageFeatureDebounceService(logService), + new LanguageFeaturesService() )); }); @@ -415,12 +418,14 @@ suite('ModelSemanticColoring', () => { const disposables = new DisposableStore(); let modelService: IModelService; let languageService: ILanguageService; + let languageFeaturesService: ILanguageFeaturesService; setup(() => { const configService = new TestConfigurationService({ editor: { semanticHighlighting: true } }); const themeService = new TestThemeService(); themeService.setTheme(new TestColorTheme({}, ColorScheme.DARK, true)); const logService = new NullLogService(); + languageFeaturesService = new LanguageFeaturesService(); modelService = disposables.add(new ModelService( configService, new TestTextResourcePropertiesService(configService), @@ -429,7 +434,8 @@ suite('ModelSemanticColoring', () => { new UndoRedoService(new TestDialogService(), new TestNotificationService()), disposables.add(new LanguageService()), new TestLanguageConfigurationService(), - new LanguageFeatureDebounceService(logService) + new LanguageFeatureDebounceService(logService), + languageFeaturesService )); languageService = disposables.add(new LanguageService(false)); }); @@ -448,7 +454,7 @@ suite('ModelSemanticColoring', () => { const secondResultProvided = new Barrier(); let callCount = 0; - disposables.add(DocumentSemanticTokensProviderRegistry.register('testMode', new class implements DocumentSemanticTokensProvider { + disposables.add(languageFeaturesService.documentSemanticTokensProvider.register('testMode', new class implements DocumentSemanticTokensProvider { getLegend(): SemanticTokensLegend { return { tokenTypes: ['class'], tokenModifiers: [] }; } @@ -497,7 +503,7 @@ suite('ModelSemanticColoring', () => { let callCount = 0; disposables.add(ModesRegistry.registerLanguage({ id: 'testMode2' })); - disposables.add(DocumentSemanticTokensProviderRegistry.register('testMode2', new class implements DocumentSemanticTokensProvider { + disposables.add(languageFeaturesService.documentSemanticTokensProvider.register('testMode2', new class implements DocumentSemanticTokensProvider { getLegend(): SemanticTokensLegend { return { tokenTypes: ['class1'], tokenModifiers: [] }; } @@ -517,7 +523,7 @@ suite('ModelSemanticColoring', () => { releaseDocumentSemanticTokens(resultId: string | undefined): void { } })); - disposables.add(DocumentSemanticTokensProviderRegistry.register('testMode2', new class implements DocumentSemanticTokensProvider { + disposables.add(languageFeaturesService.documentSemanticTokensProvider.register('testMode2', new class implements DocumentSemanticTokensProvider { getLegend(): SemanticTokensLegend { return { tokenTypes: ['class2'], tokenModifiers: [] }; } @@ -539,7 +545,7 @@ suite('ModelSemanticColoring', () => { const textModel = modelService.createModel('Hello world 2', languageService.createById('testMode2')); try { - let result = await getDocumentSemanticTokens(textModel, null, null, CancellationToken.None); + let result = await getDocumentSemanticTokens(languageFeaturesService.documentSemanticTokensProvider, textModel, null, null, CancellationToken.None); assert.ok(result, `We should have tokens (1)`); assert.ok(result.tokens, `Tokens are found from multiple providers (1)`); assert.ok(isSemanticTokens(result.tokens), `Tokens are full (1)`); @@ -549,7 +555,7 @@ suite('ModelSemanticColoring', () => { assert.deepStrictEqual(result.provider.getLegend(), { tokenTypes: ['class1'], tokenModifiers: [] }, `Legend matches the tokens (1)`); // Make a second request. Make sure we get the secondary value - result = await getDocumentSemanticTokens(textModel, result.provider, result.tokens.resultId, CancellationToken.None); + result = await getDocumentSemanticTokens(languageFeaturesService.documentSemanticTokensProvider, textModel, result.provider, result.tokens.resultId, CancellationToken.None); assert.ok(result, `We should have tokens (2)`); assert.ok(result.tokens, `Tokens are found from multiple providers (2)`); assert.ok(isSemanticTokens(result.tokens), `Tokens are full (2)`); diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 86b646c36c4..82f864269f0 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -438,7 +438,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha this._registrations.set(eventHandle, emitter); event = emitter.event; } - this._registrations.set(handle, modes.DocumentSemanticTokensProviderRegistry.register(selector, new MainThreadDocumentSemanticTokensProvider(this._proxy, handle, legend, event))); + this._registrations.set(handle, this._languageFeaturesService.documentSemanticTokensProvider.register(selector, new MainThreadDocumentSemanticTokensProvider(this._proxy, handle, legend, event))); } $emitDocumentSemanticTokensEvent(eventHandle: number): void { diff --git a/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts b/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts index 7a806032e78..cbe44917b29 100644 --- a/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts +++ b/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts @@ -33,6 +33,7 @@ import { TextModel } from 'vs/editor/common/model/textModel'; import { LanguageService } from 'vs/editor/common/services/languageService'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { LanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; +import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService'; suite('MainThreadDocumentsAndEditors', () => { @@ -71,7 +72,8 @@ suite('MainThreadDocumentsAndEditors', () => { undoRedoService, disposables.add(new LanguageService()), new TestLanguageConfigurationService(), - new LanguageFeatureDebounceService(logService) + new LanguageFeatureDebounceService(logService), + new LanguageFeaturesService() ); codeEditorService = new TestCodeEditorService(themeService); textFileService = new class extends mock() { diff --git a/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts b/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts index e8aa953f46a..4e65fc009ee 100644 --- a/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts +++ b/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts @@ -56,6 +56,7 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/testLanguageConfigurationService'; import { LanguageService } from 'vs/editor/common/services/languageService'; import { LanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; +import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService'; suite('MainThreadEditors', () => { @@ -93,10 +94,10 @@ suite('MainThreadEditors', () => { undoRedoService, disposables.add(new LanguageService()), new TestLanguageConfigurationService(), - new LanguageFeatureDebounceService(logService) + new LanguageFeatureDebounceService(logService), + new LanguageFeaturesService() ); - const services = new ServiceCollection(); services.set(IBulkEditService, new SyncDescriptor(BulkEditService)); services.set(ILabelService, new SyncDescriptor(LabelService)); diff --git a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts index 208f0cc42f3..77c4a6b781e 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts @@ -16,7 +16,7 @@ import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; -import { FontStyle, StandardTokenType, TokenMetadata, DocumentSemanticTokensProviderRegistry, SemanticTokensLegend, SemanticTokens, ColorId } from 'vs/editor/common/languages'; +import { FontStyle, StandardTokenType, TokenMetadata, SemanticTokensLegend, SemanticTokens, ColorId } from 'vs/editor/common/languages'; import { ILanguageService } from 'vs/editor/common/languages/language'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { editorHoverBackground, editorHoverBorder } from 'vs/platform/theme/common/colorRegistry'; @@ -535,7 +535,7 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget { return null; } - const tokenProviders = DocumentSemanticTokensProviderRegistry.ordered(this._model); + const tokenProviders = this._languageFeaturesService.documentSemanticTokensProvider.ordered(this._model); if (tokenProviders.length) { const provider = tokenProviders[0]; const tokens = await Promise.resolve(provider.provideDocumentSemanticTokens(this._model, null, this._currentRequestCancellationTokenSource.token)); diff --git a/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts b/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts index 5a618222ae3..d1a74339e79 100644 --- a/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts +++ b/src/vs/workbench/contrib/search/test/electron-browser/textsearch.perf.integrationTest.ts @@ -42,6 +42,7 @@ import { TestEditorGroupsService, TestEditorService } from 'vs/workbench/test/br import { TestContextService, TestTextResourcePropertiesService } from 'vs/workbench/test/common/workbenchTestServices'; import { TestEnvironmentService } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { LanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; +import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService'; // declare var __dirname: string; @@ -89,7 +90,8 @@ suite.skip('TextSearch performance (integration)', () => { undoRedoService, new LanguageService(), new TestLanguageConfigurationService(), - new LanguageFeatureDebounceService(logService) + new LanguageFeatureDebounceService(logService), + new LanguageFeaturesService() ), ], [ diff --git a/src/vs/workbench/services/model/common/modelService.ts b/src/vs/workbench/services/model/common/modelService.ts index 765860491cb..e72f0272a98 100644 --- a/src/vs/workbench/services/model/common/modelService.ts +++ b/src/vs/workbench/services/model/common/modelService.ts @@ -16,6 +16,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { ILanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; +import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures'; export class WorkbenchModelService extends ModelService { constructor( @@ -27,9 +28,10 @@ export class WorkbenchModelService extends ModelService { @ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService, @ILanguageService languageService: ILanguageService, @ILanguageFeatureDebounceService languageFeatureDebounceService: ILanguageFeatureDebounceService, + @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService, @IPathService private readonly _pathService: IPathService, ) { - super(configurationService, resourcePropertiesService, themeService, logService, undoRedoService, languageService, languageConfigurationService, languageFeatureDebounceService); + super(configurationService, resourcePropertiesService, themeService, logService, undoRedoService, languageService, languageConfigurationService, languageFeatureDebounceService, languageFeaturesService); } protected override _schemaShouldMaintainUndoRedoElements(resource: URI) {