Introduce a cache object for styling per semantic coloring provider

上级 1c98b5ec
......@@ -441,12 +441,14 @@ export interface ILineSequence {
class SemanticColoringFeature extends Disposable {
private _watchers: Record<string, ModelSemanticColoring>;
private _semanticStyling: SemanticStyling;
constructor(modelService: IModelService, themeService: IThemeService) {
super();
this._watchers = Object.create(null);
this._semanticStyling = new SemanticStyling(themeService);
this._register(modelService.onModelAdded((model) => {
this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, themeService);
this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, themeService, this._semanticStyling);
}));
this._register(modelService.onModelRemoved((model) => {
this._watchers[model.uri.toString()].dispose();
......@@ -455,24 +457,72 @@ class SemanticColoringFeature extends Disposable {
}
}
class SemanticStyling {
private readonly _caches: WeakMap<SemanticColoringProvider, SemanticColoringProviderStyling>;
constructor(
private readonly _themeService: IThemeService
) {
this._caches = new WeakMap<SemanticColoringProvider, SemanticColoringProviderStyling>();
}
public get(provider: SemanticColoringProvider): SemanticColoringProviderStyling {
if (!this._caches.has(provider)) {
this._caches.set(provider, new SemanticColoringProviderStyling(provider.getLegend(), this._themeService));
}
return this._caches.get(provider)!;
}
}
const enum Constants {
NO_STYLING = 0b01111111111111111111111111111111
}
class SemanticColoringProviderStyling {
constructor(
private readonly _legend: SemanticColoringLegend,
private readonly _themeService: IThemeService
) {
}
public getMetadata(tokenTypeIndex: number, tokenModifierSet: number): number {
const tokenType = this._legend.tokenTypes[tokenTypeIndex];
const tokenModifiers: string[] = [];
for (let modifierIndex = 0; tokenModifierSet !== 0 && modifierIndex < this._legend.tokenModifiers.length; modifierIndex++) {
if (tokenModifierSet & 1) {
tokenModifiers.push(this._legend.tokenModifiers[modifierIndex]);
}
tokenModifierSet = tokenModifierSet >> 1;
}
const metadata = this._themeService.getTheme().getTokenStyleMetadata(tokenType, tokenModifiers);
if (typeof metadata === 'undefined') {
return Constants.NO_STYLING;
}
return metadata;
}
}
class ModelSemanticColoring extends Disposable {
private _isDisposed: boolean;
private readonly _model: ITextModel;
private readonly _semanticStyling: SemanticStyling;
private readonly _fetchSemanticTokens: RunOnceScheduler;
private _currentResponse: SemanticColoring | null;
private _currentRequestCancellationTokenSource: CancellationTokenSource | null;
private _themeService: IThemeService;
constructor(model: ITextModel, themeService: IThemeService) {
constructor(model: ITextModel, themeService: IThemeService, stylingProvider: SemanticStyling) {
super();
this._isDisposed = false;
this._model = model;
this._semanticStyling = stylingProvider;
this._fetchSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchSemanticTokensNow(), 500));
this._currentResponse = null;
this._currentRequestCancellationTokenSource = null;
this._themeService = themeService;
this._register(this._model.onDidChangeContent(e => this._fetchSemanticTokens.schedule()));
this._register(SemanticColoringProviderRegistry.onDidChange(e => this._fetchSemanticTokens.schedule()));
......@@ -509,22 +559,22 @@ class ModelSemanticColoring extends Disposable {
pendingChanges.push(e);
});
const legend = provider.getLegend();
const styling = this._semanticStyling.get(provider);
const request = Promise.resolve(provider.provideSemanticColoring(this._model, this._currentRequestCancellationTokenSource.token));
request.then((res) => {
this._currentRequestCancellationTokenSource = null;
contentChangeListener.dispose();
this._setSemanticTokens(res || null, legend, pendingChanges);
this._setSemanticTokens(res || null, styling, pendingChanges);
}, (err) => {
errors.onUnexpectedError(err);
this._currentRequestCancellationTokenSource = null;
contentChangeListener.dispose();
this._setSemanticTokens(null, legend, pendingChanges);
this._setSemanticTokens(null, styling, pendingChanges);
});
}
private _setSemanticTokens(tokens: SemanticColoring | null, legend: SemanticColoringLegend, pendingChanges: IModelContentChangedEvent[]): void {
private _setSemanticTokens(tokens: SemanticColoring | null, styling: SemanticColoringProviderStyling, pendingChanges: IModelContentChangedEvent[]): void {
if (this._currentResponse) {
this._currentResponse.dispose();
this._currentResponse = null;
......@@ -554,19 +604,9 @@ class ModelSemanticColoring extends Disposable {
const startCharacter = srcTokens[srcOffset + 1];
const endCharacter = srcTokens[srcOffset + 2];
const tokenTypeIndex = srcTokens[srcOffset + 3];
const tokenType = legend.tokenTypes[tokenTypeIndex];
let tokenModifierSet = srcTokens[srcOffset + 4];
let tokenModifiers: string[] = [];
for (let modifierIndex = 0; tokenModifierSet !== 0 && modifierIndex < legend.tokenModifiers.length; modifierIndex++) {
if (tokenModifierSet & 1) {
tokenModifiers.push(legend.tokenModifiers[modifierIndex]);
}
tokenModifierSet = tokenModifierSet >> 1;
}
const metadata = this._themeService.getTheme().getTokenStyleMetadata(tokenType, tokenModifiers);
if (metadata !== undefined) {
const tokenModifierSet = srcTokens[srcOffset + 4];
const metadata = styling.getMetadata(tokenTypeIndex, tokenModifierSet);
if (metadata !== Constants.NO_STYLING) {
destTokens[destOffset] = deltaLine;
destTokens[destOffset + 1] = startCharacter;
destTokens[destOffset + 2] = endCharacter;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册