Skip to content

Commit f75c9b8

Browse files
committed
connect ModelSemanticColoring to Theme
1 parent 1837853 commit f75c9b8

10 files changed

Lines changed: 88 additions & 49 deletions

File tree

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

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { Range } from 'vs/editor/common/core/range';
1414
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions } from 'vs/editor/common/model';
1515
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
1616
import { IModelLanguageChangedEvent, IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
17-
import { LanguageIdentifier, SemanticColoringProviderRegistry, SemanticColoringProvider, SemanticColoring, FontStyle, MetadataConsts } from 'vs/editor/common/modes';
17+
import { LanguageIdentifier, SemanticColoringProviderRegistry, SemanticColoringProvider, SemanticColoring, SemanticColoringLegend } from 'vs/editor/common/modes';
1818
import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry';
1919
import { ILanguageSelection } from 'vs/editor/common/services/modeService';
2020
import { IModelService } from 'vs/editor/common/services/modelService';
@@ -23,6 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
2323
import { RunOnceScheduler } from 'vs/base/common/async';
2424
import { CancellationTokenSource } from 'vs/base/common/cancellation';
2525
import { SparseEncodedTokens, MultilineTokens2 } from 'vs/editor/common/model/tokensStore';
26+
import { IThemeService } from 'vs/platform/theme/common/themeService';
2627

2728
function MODEL_ID(resource: URI): string {
2829
return resource.toString();
@@ -118,7 +119,8 @@ export class ModelServiceImpl extends Disposable implements IModelService {
118119

119120
constructor(
120121
@IConfigurationService configurationService: IConfigurationService,
121-
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService
122+
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService,
123+
@IThemeService themeService: IThemeService
122124
) {
123125
super();
124126
this._configurationService = configurationService;
@@ -129,7 +131,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
129131
this._configurationServiceSubscription = this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions());
130132
this._updateModelOptions();
131133

132-
this._register(new SemanticColoringFeature(this));
134+
this._register(new SemanticColoringFeature(this, themeService));
133135
}
134136

135137
private static _readModelOptions(config: IRawConfig, isForSimpleWidget: boolean): ITextModelCreationOptions {
@@ -440,11 +442,11 @@ export interface ILineSequence {
440442
class SemanticColoringFeature extends Disposable {
441443
private _watchers: Record<string, ModelSemanticColoring>;
442444

443-
constructor(modelService: IModelService) {
445+
constructor(modelService: IModelService, themeService: IThemeService) {
444446
super();
445447
this._watchers = Object.create(null);
446448
this._register(modelService.onModelAdded((model) => {
447-
this._watchers[model.uri.toString()] = new ModelSemanticColoring(model);
449+
this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, themeService);
448450
}));
449451
this._register(modelService.onModelRemoved((model) => {
450452
this._watchers[model.uri.toString()].dispose();
@@ -460,15 +462,17 @@ class ModelSemanticColoring extends Disposable {
460462
private readonly _fetchSemanticTokens: RunOnceScheduler;
461463
private _currentResponse: SemanticColoring | null;
462464
private _currentRequestCancellationTokenSource: CancellationTokenSource | null;
465+
private _themeService: IThemeService;
463466

464-
constructor(model: ITextModel) {
467+
constructor(model: ITextModel, themeService: IThemeService) {
465468
super();
466469

467470
this._isDisposed = false;
468471
this._model = model;
469472
this._fetchSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchSemanticTokensNow(), 500));
470473
this._currentResponse = null;
471474
this._currentRequestCancellationTokenSource = null;
475+
this._themeService = themeService;
472476

473477
this._register(this._model.onDidChangeContent(e => this._fetchSemanticTokens.schedule()));
474478
this._register(SemanticColoringProviderRegistry.onDidChange(e => this._fetchSemanticTokens.schedule()));
@@ -509,16 +513,16 @@ class ModelSemanticColoring extends Disposable {
509513
request.then((res) => {
510514
this._currentRequestCancellationTokenSource = null;
511515
contentChangeListener.dispose();
512-
this._setSemanticTokens(res || null, pendingChanges);
516+
this._setSemanticTokens(res || null, provider.getLegend(), pendingChanges);
513517
}, (err) => {
514518
errors.onUnexpectedError(err);
515519
this._currentRequestCancellationTokenSource = null;
516520
contentChangeListener.dispose();
517-
this._setSemanticTokens(null, pendingChanges);
521+
this._setSemanticTokens(null, provider.getLegend(), pendingChanges);
518522
});
519523
}
520524

521-
private _setSemanticTokens(tokens: SemanticColoring | null, pendingChanges: IModelContentChangedEvent[]): void {
525+
private _setSemanticTokens(tokens: SemanticColoring | null, legend: SemanticColoringLegend, pendingChanges: IModelContentChangedEvent[]): void {
522526
if (this._currentResponse) {
523527
this._currentResponse.dispose();
524528
this._currentResponse = null;
@@ -540,30 +544,37 @@ class ModelSemanticColoring extends Disposable {
540544
for (const area of this._currentResponse.areas) {
541545
const srcTokens = area.data;
542546
const tokenCount = srcTokens.length / 5;
543-
const destTokens = new Uint32Array(4 * tokenCount);
547+
let destTokens = new Uint32Array(4 * tokenCount);
548+
let destOffset = 0;
544549
for (let i = 0; i < tokenCount; i++) {
545550
const srcOffset = 5 * i;
546551
const deltaLine = srcTokens[srcOffset];
547552
const startCharacter = srcTokens[srcOffset + 1];
548553
const endCharacter = srcTokens[srcOffset + 2];
549-
// const tokenType = srcTokens[srcOffset + 3];
550-
// const tokenModifiers = srcTokens[srcOffset + 4];
551-
// TODO@semantic: map here tokenType and tokenModifiers to metadata
552-
553-
const fontStyle = FontStyle.Italic | FontStyle.Bold | FontStyle.Underline;
554-
const foregroundColorId = 3;
555-
const metadata = (
556-
(fontStyle << MetadataConsts.FONT_STYLE_OFFSET)
557-
| (foregroundColorId << MetadataConsts.FOREGROUND_OFFSET)
558-
) >>> 0;
559-
560-
const destOffset = 4 * i;
561-
destTokens[destOffset] = deltaLine;
562-
destTokens[destOffset + 1] = startCharacter;
563-
destTokens[destOffset + 2] = endCharacter;
564-
destTokens[destOffset + 3] = metadata;
554+
const tokenTypeIndex = srcTokens[srcOffset + 3];
555+
const tokenType = legend.tokenTypes[tokenTypeIndex];
556+
557+
const tokenModifierSet = srcTokens[srcOffset + 4];
558+
let tokenModifiers: string[] = [];
559+
for (let modifierIndex = 0; tokenModifierSet !== 0 && modifierIndex < legend.tokenModifiers.length; modifierIndex++) {
560+
if (tokenModifierSet & 1) {
561+
tokenModifiers.push(legend.tokenTypes[modifierIndex]);
562+
}
563+
}
564+
565+
const metadata = this._themeService.getTheme().getTokenStyleMetadata(tokenType, tokenModifiers);
566+
if (metadata !== undefined) {
567+
destTokens[destOffset] = deltaLine;
568+
destTokens[destOffset + 1] = startCharacter;
569+
destTokens[destOffset + 2] = endCharacter;
570+
destTokens[destOffset + 3] = metadata;
571+
destOffset += 4;
572+
}
565573
}
566574

575+
if (destOffset !== destTokens.length) {
576+
destTokens = destTokens.subarray(0, destOffset);
577+
}
567578
const tokens = new MultilineTokens2(area.line, new SparseEncodedTokens(destTokens));
568579
result.push(tokens);
569580
}

src/vs/editor/standalone/browser/standaloneServices.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,11 @@ export module StaticServices {
144144

145145
export const modeService = define(IModeService, (o) => new ModeServiceImpl());
146146

147-
export const modelService = define(IModelService, (o) => new ModelServiceImpl(configurationService.get(o), resourcePropertiesService.get(o)));
147+
export const standaloneThemeService = define(IStandaloneThemeService, () => new StandaloneThemeServiceImpl());
148148

149-
export const markerDecorationsService = define(IMarkerDecorationsService, (o) => new MarkerDecorationsService(modelService.get(o), markerService.get(o)));
149+
export const modelService = define(IModelService, (o) => new ModelServiceImpl(configurationService.get(o), resourcePropertiesService.get(o), standaloneThemeService.get(o)));
150150

151-
export const standaloneThemeService = define(IStandaloneThemeService, () => new StandaloneThemeServiceImpl());
151+
export const markerDecorationsService = define(IMarkerDecorationsService, (o) => new MarkerDecorationsService(modelService.get(o), markerService.get(o)));
152152

153153
export const codeEditorService = define(ICodeEditorService, (o) => new StandaloneCodeEditorServiceImpl(standaloneThemeService.get(o)));
154154

src/vs/editor/standalone/browser/standaloneThemeServiceImpl.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ class StandaloneTheme implements IStandaloneTheme {
129129
}
130130
return this._tokenTheme;
131131
}
132+
133+
public getTokenStyleMetadata(type: string, modifiers: string[]): number | undefined {
134+
return undefined;
135+
}
136+
137+
public get tokenColorMap(): string[] {
138+
return [];
139+
}
132140
}
133141

134142
function isBuiltinTheme(themeName: string): themeName is BuiltinTheme {

src/vs/editor/standalone/test/browser/standaloneLanguages.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,13 @@ suite('TokenizationSupport2Adapter', () => {
5454

5555
defines: (color: ColorIdentifier): boolean => {
5656
throw new Error('Not implemented');
57-
}
57+
},
58+
59+
getTokenStyleMetadata: (type: string, modifiers: string[]): number | undefined => {
60+
return undefined;
61+
},
62+
63+
tokenColorMap: []
5864
};
5965
}
6066

src/vs/platform/theme/common/themeService.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ export interface ITheme {
5959
* default color will be used.
6060
*/
6161
defines(color: ColorIdentifier): boolean;
62+
63+
/**
64+
* Returns the token style for a given classification. The result uses the <code>MetadataConsts</code> format
65+
*/
66+
getTokenStyleMetadata(type: string, modifiers: string[]): number | undefined;
67+
68+
/**
69+
* List of all colors used with tokens. <code>getTokenStyleMetadata</code> references the colors by index into this list.
70+
*/
71+
readonly tokenColorMap: string[];
6272
}
6373

6474
export interface IIconTheme {

src/vs/platform/theme/test/common/testThemeService.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ export class TestTheme implements ITheme {
2323
defines(color: string): boolean {
2424
throw new Error('Method not implemented.');
2525
}
26+
27+
getTokenStyleMetadata(type: string, modifiers: string[]): number | undefined {
28+
return undefined;
29+
}
30+
31+
get tokenColorMap(): string[] {
32+
return [];
33+
}
2634
}
2735

2836
export class TestIconTheme implements IIconTheme {

src/vs/workbench/contrib/terminal/test/electron-browser/terminalColorRegistry.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ function getMockTheme(type: ThemeType): ITheme {
2020
type: type,
2121
getColor: (colorId: ColorIdentifier): Color | undefined => themingRegistry.resolveDefaultColor(colorId, theme),
2222
defines: () => true,
23-
getTokenStyle: () => undefined,
24-
resolveScopes: () => undefined
23+
getTokenStyleMetadata: () => undefined,
24+
tokenColorMap: []
2525

2626
};
2727
return theme;

src/vs/workbench/services/themes/common/colorThemeData.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,11 @@ export class ColorThemeData implements IColorTheme {
229229
return this.getTokenColorIndex().asArray();
230230
}
231231

232-
public getTokenStyleMetadata(classification: TokenClassification, useDefault?: boolean): number {
232+
public getTokenStyleMetadata(type: string, modifiers: string[], useDefault?: boolean): number | undefined {
233+
const classification = tokenClassificationRegistry.getTokenClassification(type, modifiers);
234+
if (!classification) {
235+
return undefined;
236+
}
233237
const style = this.getTokenStyle(classification, useDefault);
234238
let fontStyle = FontStyle.None;
235239
let foreground = 0;

src/vs/workbench/services/themes/common/workbenchThemeService.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { Event } from 'vs/base/common/event';
88
import { Color } from 'vs/base/common/color';
99
import { ITheme, IThemeService, IIconTheme } from 'vs/platform/theme/common/themeService';
1010
import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
11-
import { TokenClassification } from 'vs/platform/theme/common/tokenClassificationRegistry';
1211

1312
export const IWorkbenchThemeService = createDecorator<IWorkbenchThemeService>('themeService');
1413

@@ -33,16 +32,6 @@ export interface IColorTheme extends ITheme {
3332
readonly description?: string;
3433
readonly isLoaded: boolean;
3534
readonly tokenColors: ITextMateThemingRule[];
36-
37-
/**
38-
* Returns the token style for a given classification. The result uses the <code>MetadataConsts</code> format
39-
*/
40-
getTokenStyleMetadata(classification: TokenClassification): number;
41-
42-
/**
43-
* List of all colors used with tokens. <code>getTokenStyleMetadata</code> references the colors by index into this list.
44-
*/
45-
readonly tokenColorMap: string[];
4635
}
4736

4837
export interface IColorMap {

src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ function assertTokenStyle(actual: TokenStyle | undefined | null, expected: Token
4949
assert.equal(tokenStyleAsString(actual), tokenStyleAsString(expected), message);
5050
}
5151

52-
function assertTokenStyleMetaData(colorIndex: string[], actual: number, expected: TokenStyle | undefined | null, message?: string) {
53-
if (!expected) {
54-
assert.equal(actual, 0);
52+
function assertTokenStyleMetaData(colorIndex: string[], actual: number | undefined, expected: TokenStyle | undefined | null, message?: string) {
53+
if (!expected || !actual) {
54+
assert.equal(actual, expected);
5555
return;
5656
}
5757
const actualFontStyle = TokenMetadata.getFontStyle(actual);
@@ -74,14 +74,17 @@ function assertTokenStyles(themeData: ColorThemeData, expected: { [qualifiedClas
7474
const colorIndex = themeData.tokenColorMap;
7575

7676
for (let qualifiedClassifier in expected) {
77-
const classification = tokenClassificationRegistry.getTokenClassificationFromString(qualifiedClassifier);
77+
const modifiers = qualifiedClassifier.split('.');
78+
const type = modifiers.shift()!;
79+
80+
const classification = tokenClassificationRegistry.getTokenClassification(type, modifiers);
7881
assert.ok(classification, 'Classification not found');
7982

8083
const tokenStyle = themeData.getTokenStyle(classification!);
8184
const expectedTokenStyle = expected[qualifiedClassifier];
8285
assertTokenStyle(tokenStyle, expectedTokenStyle, qualifiedClassifier);
8386

84-
const tokenStyleMetaData = themeData.getTokenStyleMetadata(classification!);
87+
const tokenStyleMetaData = themeData.getTokenStyleMetadata(type, modifiers);
8588
assertTokenStyleMetaData(colorIndex, tokenStyleMetaData, expectedTokenStyle);
8689
}
8790
}

0 commit comments

Comments
 (0)