colorThemeData.ts ×33

Frontier kind: Code frontier

unlabeled · c_3958684d8add

5 tests · 31755 LOC · 176 files · introduces 0 tests · 242 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
39 ranges242 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
3478 ranges31755 lines · 176 files · Browse complete extent
All tests (intent)
5 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 242 introduced LOC across 39 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/services/themes/common/colorThemeData.ts 212 introduced LOC · 33 ranges

Open complete file

102
103 get tokenColors(): ITextMateThemingRule[] {
104 > if (!this.textMateThemingRules) { colorThemeData.ts
105 > const result: ITextMateThemingRule[] = [];
106 >
107 > // the default rule (scope empty) is always the first rule. Ignore all other default rules.
108 > const foreground = this.getColor(editorForeground) || this.getDefault(editorForeground)!;
109 > const background = this.getColor(editorBackground) || this.getDefault(editorBackground)!;
110 > result.push({
111 > settings: {
112 > foreground: normalizeColor(foreground),
113 > background: normalizeColor(background)
114 > }
115 > });
116 >
117 > let hasDefaultTokens = false;
118 >
119 > function addRule(rule: ITextMateThemingRule) {
120 > if (rule.scope && rule.settings) {
121 > if (rule.scope === 'token.info-token') {
122 > hasDefaultTokens = true;
123 > }
124 > const ruleSettings = rule.settings;
125 > result.push({
126 > scope: rule.scope, settings: {
127 > foreground: normalizeColor(ruleSettings.foreground),
128 > background: normalizeColor(ruleSettings.background),
129 > fontStyle: ruleSettings.fontStyle,
130 > fontSize: ruleSettings.fontSize,
131 > fontFamily: ruleSettings.fontFamily,
132 > lineHeight: ruleSettings.lineHeight
133 > }
134 > });
135 > }
136 > }
137 >
138 > this.themeTokenColors.forEach(addRule);
139 > // Add the custom colors after the theme colors
140 > // so that they will override them
141 > this.customTokenColors.forEach(addRule);
142 >
143 > if (!hasDefaultTokens) {
144 > defaultThemeColors[this.type].forEach(addRule);
145 > }
146 > this.textMateThemingRules = result;
147 > }
148 > return this.textMateThemingRules;
149 > }
150
151 public getColor(colorId: ColorIdentifier, useDefault?: boolean): Color | undefined {
152 > const customColor = this.customColorMap[colorId]; colorThemeData.ts
153 > if (customColor instanceof Color) {
154 return customColor;
155 }
156 > if (customColor === undefined) { /* !== DEFAULT_COLOR_CONFIG_VALUE */ colorThemeData.ts
157 > const color = this.colorMap[colorId];
158 > if (color !== undefined) {
159 return color;
160 }
162 > if (useDefault !== false) {
163 > return this.getDefault(colorId);
164 > }
165 return undefined;
167
168 private getTokenStyle(type: string, modifiers: string[], language: string, useDefault = true, definitions: TokenStyleDefinitions = {}): TokenStyle | undefined {
169 > const result: any = { colorThemeData.ts
170 > foreground: undefined,
171 > bold: undefined,
172 > underline: undefined,
173 > strikethrough: undefined,
174 > italic: undefined
175 > };
176 > const score = {
177 > foreground: -1,
178 > bold: -1,
179 > underline: -1,
180 > strikethrough: -1,
181 > italic: -1,
182 > fontFamily: -1,
183 > fontSize: -1,
184 > lineHeight: -1
185 > };
186 >
187 > function _processStyle(matchScore: number, style: TokenStyle, definition: TokenStyleDefinition) {
188 > if (style.foreground && score.foreground <= matchScore) {
189 > score.foreground = matchScore;
190 > result.foreground = style.foreground;
191 > definitions.foreground = definition;
192 > }
193 > for (const p of ['bold', 'underline', 'strikethrough', 'italic']) {
194 > const property = p as keyof TokenStyle;
195 > const info = style[property];
196 > if (info !== undefined) {
197 if (score[property] <= matchScore) {
198 score[property] = matchScore;
201 }
202 }
204 > }
205 > function _processSemanticTokenRule(rule: SemanticTokenRule) {
206 const matchScore = rule.selector.match(type, modifiers, language);
207 if (matchScore >= 0) {
209 }
210 }
212 > this.semanticTokenRules.forEach(_processSemanticTokenRule);
213 > this.customSemanticTokenRules.forEach(_processSemanticTokenRule);
214 >
215 > let hasUndefinedStyleProperty = false;
216 > for (const k in score) {
217 > const key = k as keyof TokenStyle;
218 > if (score[key] === -1) {
219 > hasUndefinedStyleProperty = true;
220 > } else {
221 score[key] = Number.MAX_VALUE; // set it to the max, so it won't be replaced by a default
222 }
224 > if (hasUndefinedStyleProperty) {
225 > for (const rule of tokenClassificationRegistry.getTokenStylingDefaultRules()) {
226 > const matchScore = rule.selector.match(type, modifiers, language);
227 > if (matchScore >= 0) {
228 > let style: TokenStyle | undefined;
229 > if (rule.defaults.scopesToProbe) {
230 > style = this.resolveScopes(rule.defaults.scopesToProbe);
231 > if (style) {
232 _processStyle(matchScore, style, rule.defaults.scopesToProbe);
233 }
235 > if (!style && useDefault !== false) {
236 const tokenStyleValue = rule.defaults[this.type];
237 style = this.resolveTokenStyleValue(tokenStyleValue);
240 }
241 }
243 > }
244 > }
245 > return TokenStyle.fromData(result);
246 >
247 > }
248
249 /**
263
264 public getTokenColorIndex(): TokenColorIndex {
265 > // collect all colors that tokens can have colorThemeData.ts
266 > if (!this.tokenColorIndex) {
267 > const index = new TokenColorIndex();
268 > this.tokenColors.forEach(rule => {
269 > index.add(rule.settings.foreground);
270 > index.add(rule.settings.background);
271 > });
272 >
273 > this.semanticTokenRules.forEach(r => index.add(r.style.foreground));
274 > tokenClassificationRegistry.getTokenStylingDefaultRules().forEach(r => {
275 > const defaultColor = r.defaults[this.type];
276 > if (defaultColor && typeof defaultColor === 'object') {
277 index.add(defaultColor.foreground);
278 }
279 > }); colorThemeData.ts
280 > this.customSemanticTokenRules.forEach(r => index.add(r.style.foreground));
281 >
282 > this.tokenColorIndex = index;
283 > }
284 > return this.tokenColorIndex;
285 > }
286
287
296
297 public get tokenColorMap(): string[] {
298 > return this.getTokenColorIndex().asArray(); colorThemeData.ts
299 > }
300
301 public get tokenFontMap(): IFontTokenOptions[] {
304
305 public getTokenStyleMetadata(typeWithLanguage: string, modifiers: string[], defaultLanguage: string, useDefault = true, definitions: TokenStyleDefinitions = {}): ITokenStyle | undefined {
306 > const { type, language } = parseClassifierString(typeWithLanguage, defaultLanguage); colorThemeData.ts
307 > const style = this.getTokenStyle(type, modifiers, language, useDefault, definitions);
308 > if (!style) {
309 return undefined;
310 }
312 > return {
313 > foreground: this.getTokenColorIndex().get(style.foreground),
314 > bold: style.bold,
315 > underline: style.underline,
316 > strikethrough: style.strikethrough,
317 > italic: style.italic,
318 > };
319 > }
320
321 public getTokenStylingRuleScope(rule: SemanticTokenRule): 'setting' | 'theme' | undefined {
330
331 public getDefault(colorId: ColorIdentifier): Color | undefined {
332 > return colorRegistry.resolveDefaultColor(colorId, this); colorThemeData.ts
333 > }
334
335
618
619 get themeTypeSelector(): ThemeTypeSelector {
620 > return this.classNames[0] as ThemeTypeSelector; colorThemeData.ts
621 > }
622
623 get classNames(): string[] {
624 > return this.id.split(' '); colorThemeData.ts
625 > }
626
627 get type(): ColorScheme {
628 > switch (this.themeTypeSelector) { colorThemeData.ts
629 > case ThemeTypeSelector.VS: return ColorScheme.LIGHT;
630 > case ThemeTypeSelector.HC_BLACK: return ColorScheme.HIGH_CONTRAST_DARK;
631 > case ThemeTypeSelector.HC_LIGHT: return ColorScheme.HIGH_CONTRAST_LIGHT;
632 > default: return ColorScheme.DARK;
633 > }
634 > }
635
636 // constructors
968
969 constructor() {
970 > this._lastColorId = 0; colorThemeData.ts
971 > this._id2color = [];
972 > this._color2id = Object.create(null);
973 > }
974
975 public add(color: string | Color | undefined): number {
976 > color = normalizeColor(color); colorThemeData.ts
977 > if (color === undefined) {
978 > return 0;
979 > }
980 >
981 > let value = this._color2id[color];
982 > if (value) {
983 return value;
984 }
985 > value = ++this._lastColorId; colorThemeData.ts
986 > this._color2id[color] = value;
987 > this._id2color[value] = color;
988 > return value;
989 > }
990
991 public get(color: string | Color | undefined): number {
992 > color = normalizeColor(color); colorThemeData.ts
993 > if (color === undefined) {
994 return 0;
995 }
996 > const value = this._color2id[color]; colorThemeData.ts
997 > if (value) {
998 > return value;
999 > }
1000 console.log(`Color ${color} not in index.`);
1001 return 0;
1003
1004 public asArray(): string[] {
1005 > return this._id2color.slice(0); colorThemeData.ts
1006 > }
1007 }
1008
1044 }
1045
1046 > function normalizeColor(color: string | Color | undefined | null): string | undefined { colorThemeData.ts
1047 > if (!color) {
1048 > return undefined;
1049 > }
1050 > if (typeof color !== 'string') {
1051 > color = Color.Format.CSS.formatHexA(color, true);
1052 > }
1053 > const len = color.length;
1054 > if (color.charCodeAt(0) !== CharCode.Hash || (len !== 4 && len !== 5 && len !== 7 && len !== 9)) {
1055 return undefined;
1056 }
1057 > const result = [CharCode.Hash]; colorThemeData.ts
1058 >
1059 > for (let i = 1; i < len; i++) {
1060 > const upper = hexUpper(color.charCodeAt(i));
1061 > if (!upper) {
1062 return undefined;
1063 }
1064 > result.push(upper); colorThemeData.ts
1065 > if (len === 4 || len === 5) {
1066 result.push(upper);
1067 }
1069 >
1070 > if (result.length === 9 && result[7] === CharCode.F && result[8] === CharCode.F) {
1071 result.length = 7;
1072 }
1073 > return String.fromCharCode(...result); colorThemeData.ts
1074 > }
1075
1076 > function hexUpper(charCode: CharCode): number { colorThemeData.ts
1077 > if (charCode >= CharCode.Digit0 && charCode <= CharCode.Digit9 || charCode >= CharCode.A && charCode <= CharCode.F) {
1078 > return charCode;
1079 > } else if (charCode >= CharCode.a && charCode <= CharCode.f) {
1080 > return charCode - CharCode.a + CharCode.A;
1081 > }
1082 return 0;
1083 }
src/vs/platform/theme/common/tokenClassificationRegistry.ts 30 introduced LOC · 6 ranges

Open complete file

100 }
101 export function fromData(data: { foreground: Color | undefined; bold: boolean | undefined; underline: boolean | undefined; strikethrough: boolean | undefined; italic: boolean | undefined }): TokenStyle {
102 > return new TokenStyle(data.foreground, data.bold, data.underline, data.strikethrough, data.italic); tokenClassificationRegistry.ts
103 > }
104 export function fromSettings(foreground: string | undefined, fontStyle: string | undefined): TokenStyle;
105 export function fromSettings(foreground: string | undefined, fontStyle: string | undefined, bold: boolean | undefined, underline: boolean | undefined, strikethrough: boolean | undefined, italic: boolean | undefined): TokenStyle;
397 return {
398 match: (type: string, modifiers: string[], language: string) => {
399 > let score = 0; tokenClassificationRegistry.ts
400 > if (selector.language !== undefined) {
401 if (selector.language !== language) {
402 return -1;
404 score += 10;
405 }
406 > if (selector.type !== TOKEN_TYPE_WILDCARD) { tokenClassificationRegistry.ts
407 > const hierarchy = this.getTypeHierarchy(type);
408 > const level = hierarchy.indexOf(selector.type);
409 > if (level === -1) {
410 > return -1;
411 > }
412 > score += (100 - level);
413 > }
414 > // all selector modifiers must be present
415 > for (const selectorModifier of selector.modifiers) {
416 > if (modifiers.indexOf(selectorModifier) === -1) {
417 > return -1;
418 > }
419 > }
420 > return score + selector.modifiers.length * 100;
421 > },
422 id: `${[selector.type, ...selector.modifiers.sort()].join('.')}${selector.language !== undefined ? ':' + selector.language : ''}`
423 };
457
458 public getTokenStylingDefaultRules(): SemanticTokenDefaultRule[] {
459 > return this.tokenStylingDefaultRules; tokenClassificationRegistry.ts
460 > }
461
462 private getTypeHierarchy(typeId: string): string[] {
463 > let hierarchy = this.typeHierarchy[typeId]; tokenClassificationRegistry.ts
464 > if (!hierarchy) {
465 > this.typeHierarchy[typeId] = hierarchy = [typeId];
466 > let type = this.tokenTypeById[typeId];
467 > while (type && type.superType) {
468 hierarchy.push(type.superType);
469 type = this.tokenTypeById[type.superType];
470 }
472 > return hierarchy;
473 > }
474
475