Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/common/tokenizationRegistry.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Color } from '../../base/common/color.js';
7
import { Emitter, Event } from '../../base/common/event.js';
8
import { Disposable, IDisposable, toDisposable } from '../../base/common/lifecycle.js';
9
import { ITokenizationRegistry, ITokenizationSupportChangedEvent, ILazyTokenizationSupport } from './languages.js';
10
import { ColorId } from './encodedTokenAttributes.js';
11
12
export class TokenizationRegistry<TSupport> implements ITokenizationRegistry<TSupport> {
13
14
private readonly _tokenizationSupports = new Map<string, TSupport>();
15
private readonly _factories = new Map<string, TokenizationSupportFactoryData<TSupport>>();
16
17
private readonly _onDidChange = new Emitter<ITokenizationSupportChangedEvent>();
18
public readonly onDidChange: Event<ITokenizationSupportChangedEvent> = this._onDidChange.event;
19
20
private _colorMap: Color[] | null;
21
22
constructor() {
23
this._colorMap = null;
24
}
25
26
public handleChange(languageIds: string[]): void {
27
this._onDidChange.fire({
28
changedLanguages: languageIds,
29
changedColorMap: false
30
});
31
}
32
33
public register(languageId: string, support: TSupport): IDisposable {
34
this._tokenizationSupports.set(languageId, support);
35
this.handleChange([languageId]);
36
return toDisposable(() => {
37
if (this._tokenizationSupports.get(languageId) !== support) {
38
return;
39
}
40
this._tokenizationSupports.delete(languageId);
41
this.handleChange([languageId]);
42
});
43
}
44
45
public get(languageId: string): TSupport | null {
46
return this._tokenizationSupports.get(languageId) || null;
47
}
48
49
public registerFactory(languageId: string, factory: ILazyTokenizationSupport<TSupport>): IDisposable {
50
this._factories.get(languageId)?.dispose();
51
const myData = new TokenizationSupportFactoryData(this, languageId, factory);
52
this._factories.set(languageId, myData);
53
return toDisposable(() => {
54
const v = this._factories.get(languageId);
55
if (!v || v !== myData) {
56
return;
57
}
58
this._factories.delete(languageId);
59
v.dispose();
60
});
61
}
62
63
public async getOrCreate(languageId: string): Promise<TSupport | null> {
64
// check first if the support is already set
65
const tokenizationSupport = this.get(languageId);
66
if (tokenizationSupport) {
67
return tokenizationSupport;
68
}
69
70
const factory = this._factories.get(languageId);
71
if (!factory || factory.isResolved) {
72
// no factory or factory.resolve already finished
73
return null;
74
}
75
76
await factory.resolve();
77
78
return this.get(languageId);
79
}
80
81
public isResolved(languageId: string): boolean {
82
const tokenizationSupport = this.get(languageId);
83
if (tokenizationSupport) {
84
return true;
85
}
86
87
const factory = this._factories.get(languageId);
88
if (!factory || factory.isResolved) {
89
return true;
90
}
91
92
return false;
93
}
94
95
public setColorMap(colorMap: Color[]): void {
96
this._colorMap = colorMap;
97
this._onDidChange.fire({
98
changedLanguages: Array.from(this._tokenizationSupports.keys()),
99
changedColorMap: true
100
});
101
}
102
103
public getColorMap(): Color[] | null {
104
return this._colorMap;
105
}
106
107
public getDefaultBackground(): Color | null {
108
if (this._colorMap && this._colorMap.length > ColorId.DefaultBackground) {
109
return this._colorMap[ColorId.DefaultBackground];
110
}
111
return null;
112
}
113
}
114
115
class TokenizationSupportFactoryData<TSupport> extends Disposable {
116
117
private _isDisposed: boolean = false;
118
private _resolvePromise: Promise<void> | null = null;
119
private _isResolved: boolean = false;
120
121
public get isResolved(): boolean {
122
return this._isResolved;
123
}
124
125
constructor(
126
private readonly _registry: TokenizationRegistry<TSupport>,
127
private readonly _languageId: string,
128
private readonly _factory: ILazyTokenizationSupport<TSupport>,
129
) {
130
super();
131
}
132
133
public override dispose(): void {
134
this._isDisposed = true;
135
super.dispose();
136
}
137
138
public async resolve(): Promise<void> {
139
if (!this._resolvePromise) {
140
this._resolvePromise = this._create();
141
}
142
return this._resolvePromise;
143
}
144
145
private async _create(): Promise<void> {
146
const value = await this._factory.tokenizationSupport;
147
this._isResolved = true;
148
if (value && !this._isDisposed) {
149
this._register(this._registry.register(this._languageId, value));
150
}
151
}
152
}
153
154