Skip to content

Commit c2a604a

Browse files
committed
Add DocumentSemanticTokensProvider.onDidChangeSemanticTokens
1 parent e8f005a commit c2a604a

File tree

7 files changed

+57
-9
lines changed

7 files changed

+57
-9
lines changed

src/vs/editor/common/modes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,7 @@ export interface SemanticTokensEdits {
15891589
}
15901590

15911591
export interface DocumentSemanticTokensProvider {
1592+
onDidChange?: Event<void>;
15921593
getLegend(): SemanticTokensLegend;
15931594
provideDocumentSemanticTokens(model: model.ITextModel, lastResultId: string | null, token: CancellationToken): ProviderResult<SemanticTokens | SemanticTokensEdits>;
15941595
releaseDocumentSemanticTokens(resultId: string | undefined): void;

src/vs/editor/common/services/modelServiceImpl.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { Emitter, Event } from 'vs/base/common/event';
7-
import { Disposable, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
7+
import { Disposable, IDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
88
import * as platform from 'vs/base/common/platform';
99
import * as errors from 'vs/base/common/errors';
1010
import { URI } from 'vs/base/common/uri';
@@ -724,6 +724,7 @@ class ModelSemanticColoring extends Disposable {
724724
private readonly _fetchSemanticTokens: RunOnceScheduler;
725725
private _currentResponse: SemanticTokensResponse | null;
726726
private _currentRequestCancellationTokenSource: CancellationTokenSource | null;
727+
private _providersChangeListeners: IDisposable[];
727728

728729
constructor(model: ITextModel, themeService: IThemeService, stylingProvider: SemanticStyling) {
729730
super();
@@ -734,13 +735,28 @@ class ModelSemanticColoring extends Disposable {
734735
this._fetchSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchSemanticTokensNow(), 300));
735736
this._currentResponse = null;
736737
this._currentRequestCancellationTokenSource = null;
738+
this._providersChangeListeners = [];
737739

738740
this._register(this._model.onDidChangeContent(e => {
739741
if (!this._fetchSemanticTokens.isScheduled()) {
740742
this._fetchSemanticTokens.schedule();
741743
}
742744
}));
743-
this._register(DocumentSemanticTokensProviderRegistry.onDidChange(e => this._fetchSemanticTokens.schedule()));
745+
const bindChangeListeners = () => {
746+
dispose(this._providersChangeListeners);
747+
this._providersChangeListeners = [];
748+
for (const provider of DocumentSemanticTokensProviderRegistry.all(model)) {
749+
if (typeof provider.onDidChange === 'function') {
750+
this._providersChangeListeners.push(provider.onDidChange(() => this._fetchSemanticTokens.schedule(0)));
751+
}
752+
}
753+
};
754+
bindChangeListeners();
755+
this._register(DocumentSemanticTokensProviderRegistry.onDidChange(e => {
756+
bindChangeListeners();
757+
this._fetchSemanticTokens.schedule();
758+
}));
759+
744760
if (themeService) {
745761
// workaround for tests which use undefined... :/
746762
this._register(themeService.onThemeChange(_ => {

src/vs/monaco.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6183,6 +6183,7 @@ declare namespace monaco.languages {
61836183
}
61846184

61856185
export interface DocumentSemanticTokensProvider {
6186+
onDidChange?: IEvent<void>;
61866187
getLegend(): SemanticTokensLegend;
61876188
provideDocumentSemanticTokens(model: editor.ITextModel, lastResultId: string | null, token: CancellationToken): ProviderResult<SemanticTokens | SemanticTokensEdits>;
61886189
releaseDocumentSemanticTokens(resultId: string | undefined): void;

src/vs/vscode.proposed.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ declare module 'vscode' {
257257
* semantic tokens.
258258
*/
259259
export interface DocumentSemanticTokensProvider {
260+
/**
261+
* An optional event to signal that the semantic tokens from this provider have changed.
262+
*/
263+
onDidChangeSemanticTokens?: Event<void>;
264+
260265
/**
261266
* A file can contain many tokens, perhaps even hundreds of thousands of tokens. Therefore, to improve
262267
* the memory consumption around describing semantic tokens, we have decided to avoid allocating an object

src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { IDisposable } from 'vs/base/common/lifecycle';
7-
import { Emitter } from 'vs/base/common/event';
7+
import { Emitter, Event } from 'vs/base/common/event';
88
import { ITextModel, ISingleEditOperation } from 'vs/editor/common/model';
99
import * as modes from 'vs/editor/common/modes';
1010
import * as search from 'vs/workbench/contrib/search/common/search';
@@ -367,8 +367,21 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
367367

368368
// --- semantic tokens
369369

370-
$registerDocumentSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void {
371-
this._registrations.set(handle, modes.DocumentSemanticTokensProviderRegistry.register(selector, new MainThreadDocumentSemanticTokensProvider(this._proxy, handle, legend)));
370+
$registerDocumentSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend, eventHandle: number | undefined): void {
371+
let event: Event<void> | undefined = undefined;
372+
if (typeof eventHandle === 'number') {
373+
const emitter = new Emitter<void>();
374+
this._registrations.set(eventHandle, emitter);
375+
event = emitter.event;
376+
}
377+
this._registrations.set(handle, modes.DocumentSemanticTokensProviderRegistry.register(selector, new MainThreadDocumentSemanticTokensProvider(this._proxy, handle, legend, event)));
378+
}
379+
380+
$emitDocumentSemanticTokensEvent(eventHandle: number): void {
381+
const obj = this._registrations.get(eventHandle);
382+
if (obj instanceof Emitter) {
383+
obj.fire(undefined);
384+
}
372385
}
373386

374387
$registerDocumentRangeSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void {
@@ -661,6 +674,7 @@ export class MainThreadDocumentSemanticTokensProvider implements modes.DocumentS
661674
private readonly _proxy: ExtHostLanguageFeaturesShape,
662675
private readonly _handle: number,
663676
private readonly _legend: modes.SemanticTokensLegend,
677+
public readonly onDidChange: Event<void> | undefined,
664678
) {
665679
}
666680

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,8 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
367367
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
368368
$registerNavigateTypeSupport(handle: number): void;
369369
$registerRenameSupport(handle: number, selector: IDocumentFilterDto[], supportsResolveInitialValues: boolean): void;
370-
$registerDocumentSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void;
370+
$registerDocumentSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend, eventHandle: number | undefined): void;
371+
$emitDocumentSemanticTokensEvent(eventHandle: number): void;
371372
$registerDocumentRangeSemanticTokensProvider(handle: number, selector: IDocumentFilterDto[], legend: modes.SemanticTokensLegend): void;
372373
$registerSuggestSupport(handle: number, selector: IDocumentFilterDto[], triggerCharacters: string[], supportsResolveDetails: boolean, extensionId: ExtensionIdentifier): void;
373374
$registerSignatureHelpProvider(handle: number, selector: IDocumentFilterDto[], metadata: ISignatureHelpProviderMetadataDto): void;

src/vs/workbench/api/common/extHostLanguageFeatures.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,9 +1702,19 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
17021702
//#region semantic coloring
17031703

17041704
registerDocumentSemanticTokensProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSemanticTokensProvider, legend: vscode.SemanticTokensLegend): vscode.Disposable {
1705-
const handle = this._addNewAdapter(new DocumentSemanticTokensAdapter(this._documents, provider), extension);
1706-
this._proxy.$registerDocumentSemanticTokensProvider(handle, this._transformDocumentSelector(selector), legend);
1707-
return this._createDisposable(handle);
1705+
const handle = this._nextHandle();
1706+
const eventHandle = (typeof provider.onDidChangeSemanticTokens === 'function' ? this._nextHandle() : undefined);
1707+
1708+
this._adapter.set(handle, new AdapterData(new DocumentSemanticTokensAdapter(this._documents, provider), extension));
1709+
this._proxy.$registerDocumentSemanticTokensProvider(handle, this._transformDocumentSelector(selector), legend, eventHandle);
1710+
let result = this._createDisposable(handle);
1711+
1712+
if (eventHandle) {
1713+
const subscription = provider.onDidChangeSemanticTokens!(_ => this._proxy.$emitDocumentSemanticTokensEvent(eventHandle));
1714+
result = Disposable.from(result, subscription);
1715+
}
1716+
1717+
return result;
17081718
}
17091719

17101720
$provideDocumentSemanticTokens(handle: number, resource: UriComponents, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null> {

0 commit comments

Comments
 (0)