diff --git a/src/vs/platform/theme/common/tokenClassificationRegistry.ts b/src/vs/platform/theme/common/tokenClassificationRegistry.ts
index 46d85c25fad340ae34bf2c98d0acd7aa2f765d98..14a1b52e4c32c08d68726e503b392187548afa86 100644
--- a/src/vs/platform/theme/common/tokenClassificationRegistry.ts
+++ b/src/vs/platform/theme/common/tokenClassificationRegistry.ts
@@ -24,7 +24,7 @@ export const typeAndModifierIdPattern = `^${idPattern}$`;
export const selectorPattern = `^(${idPattern}|\\*)(\\${CLASSIFIER_MODIFIER_SEPARATOR}${idPattern})*(\\${TOKEN_CLASSIFIER_LANGUAGE_SEPARATOR}${idPattern})?$`;
-export const fontStylePattern = '^(\\s*(-?italic|-?bold|-?underline))*\\s*$';
+export const fontStylePattern = '^(\\s*(italic|bold|underline))*\\s*$';
export interface TokenSelector {
match(type: string, modifiers: string[], language: string): number;
@@ -124,18 +124,18 @@ export interface TokenStyleDefaults {
hc?: TokenStyleValue;
}
-export interface TokenStylingDefaultRule {
+export interface SemanticTokenDefaultRule {
selector: TokenSelector;
defaults: TokenStyleDefaults;
}
-export interface TokenStylingRule {
+export interface SemanticTokenRule {
style: TokenStyle;
selector: TokenSelector;
}
-export namespace TokenStylingRule {
- export function fromJSONObject(registry: ITokenClassificationRegistry, o: any): TokenStylingRule | undefined {
+export namespace SemanticTokenRule {
+ export function fromJSONObject(registry: ITokenClassificationRegistry, o: any): SemanticTokenRule | undefined {
if (o && typeof o._selector === 'string' && o._style) {
const style = TokenStyle.fromJSONObject(o._style);
if (style) {
@@ -147,13 +147,13 @@ export namespace TokenStylingRule {
}
return undefined;
}
- export function toJSONObject(rule: TokenStylingRule): any {
+ export function toJSONObject(rule: SemanticTokenRule): any {
return {
_selector: rule.selector.id,
_style: TokenStyle.toJSONObject(rule.style)
};
}
- export function equals(r1: TokenStylingRule | undefined, r2: TokenStylingRule | undefined) {
+ export function equals(r1: SemanticTokenRule | undefined, r2: SemanticTokenRule | undefined) {
if (r1 === r2) {
return true;
}
@@ -161,7 +161,7 @@ export namespace TokenStylingRule {
&& r1.selector && r2.selector && r1.selector.id === r2.selector.id
&& TokenStyle.equals(r1.style, r2.style);
}
- export function is(r: any): r is TokenStylingRule {
+ export function is(r: any): r is SemanticTokenRule {
return r && r.selector && typeof r.selector.selectorString === 'string' && TokenStyle.is(r.style);
}
}
@@ -239,7 +239,7 @@ export interface ITokenClassificationRegistry {
/**
* The styling rules to used when a schema does not define any styling rules.
*/
- getTokenStylingDefaultRules(): TokenStylingDefaultRule[];
+ getTokenStylingDefaultRules(): SemanticTokenDefaultRule[];
/**
* JSON schema for an object to assign styling to token classifications
@@ -258,14 +258,18 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
private tokenTypeById: { [key: string]: TokenTypeOrModifierContribution };
private tokenModifierById: { [key: string]: TokenTypeOrModifierContribution };
- private tokenStylingDefaultRules: TokenStylingDefaultRule[] = [];
+ private tokenStylingDefaultRules: SemanticTokenDefaultRule[] = [];
private typeHierarchy: { [id: string]: string[] };
- private tokenStylingSchema: IJSONSchema & { properties: IJSONSchemaMap } = {
+ private tokenStylingSchema: IJSONSchema & { properties: IJSONSchemaMap, patternProperties: IJSONSchemaMap } = {
type: 'object',
properties: {},
- additionalProperties: getStylingSchemeEntry(),
+ patternProperties: {
+ [selectorPattern]: getStylingSchemeEntry()
+ },
+ //errorMessage: nls.localize('schema.token.errors', 'Valid token selectors have the form (*|tokenType)(.tokenModifier)*(:tokenLanguage)?.'),
+ additionalProperties: false,
definitions: {
style: {
type: 'object',
@@ -325,7 +329,8 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
let tokenStyleContribution: TokenTypeOrModifierContribution = { num, id, superType, description, deprecationMessage };
this.tokenTypeById[id] = tokenStyleContribution;
- this.tokenStylingSchema.properties[id] = getStylingSchemeEntry(description, deprecationMessage);
+ const stylingSchemeEntry = getStylingSchemeEntry(description, deprecationMessage);
+ this.tokenStylingSchema.properties[id] = stylingSchemeEntry;
this.typeHierarchy = {};
}
@@ -413,7 +418,7 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
return this.tokenStylingSchema;
}
- public getTokenStylingDefaultRules(): TokenStylingDefaultRule[] {
+ public getTokenStylingDefaultRules(): SemanticTokenDefaultRule[] {
return this.tokenStylingDefaultRules;
}
diff --git a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts
index 133f4febc65ca3121b5fc17f178c9eb1f04796b9..3f5ac4d934ee57439613badc40e1f8c5021d67e3 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts
@@ -27,7 +27,7 @@ import { ITextMateService, IGrammar, IToken, StackElement } from 'vs/workbench/s
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { ColorThemeData, TokenStyleDefinitions, TokenStyleDefinition, TextMateThemingRuleDefinitions } from 'vs/workbench/services/themes/common/colorThemeData';
-import { TokenStylingRule, TokenStyleData, TokenStyle } from 'vs/platform/theme/common/tokenClassificationRegistry';
+import { SemanticTokenRule, TokenStyleData, TokenStyle } from 'vs/platform/theme/common/tokenClassificationRegistry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export interface IEditorSemanticHighlightingOptions {
@@ -557,7 +557,7 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
return `${escape(scopesDefinition.scope.join(' '))}
${strScopes}\n${JSON.stringify(matchingRule.settings, null, '\t')}
`;
}
return '';
- } else if (TokenStylingRule.is(definition)) {
+ } else if (SemanticTokenRule.is(definition)) {
const scope = theme.getTokenStylingRuleScope(definition);
if (scope === 'setting') {
return `User settings: ${definition.selector.id} - ${this._renderStyleProperty(definition.style, property)}`;
diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts
index f98a3dd8b3472a9e963de0f8e643bc423c8defd1..5097ebc2918d1af18fe2f61bf1d088f31b509ce5 100644
--- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts
+++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts
@@ -218,8 +218,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
this.currentColorTheme.setCustomTokenColors(this.settings.tokenColorCustomizations);
hasColorChanges = true;
}
- if (e.affectsConfiguration(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL)) {
- this.currentColorTheme.setCustomTokenStyleRules(this.settings.tokenStylesCustomizations);
+ if (e.affectsConfiguration(ThemeSettings.SEMANTIC_TOKEN_COLOR_CUSTOMIZATIONS) || e.affectsConfiguration(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL)) {
+ this.currentColorTheme.setCustomSemanticTokenColors(this.settings.semanticTokenColorCustomizations, this.settings.experimentalSemanticTokenColorCustomizations);
hasColorChanges = true;
}
if (hasColorChanges) {
diff --git a/src/vs/workbench/services/themes/common/colorThemeData.ts b/src/vs/workbench/services/themes/common/colorThemeData.ts
index 37c7efb72ba248fb16caf5d3ed85c111f3e7a712..df2c0f3c4bcbaebd4bf4f1bb04096aa747375de0 100644
--- a/src/vs/workbench/services/themes/common/colorThemeData.ts
+++ b/src/vs/workbench/services/themes/common/colorThemeData.ts
@@ -6,7 +6,7 @@
import { basename } from 'vs/base/common/path';
import * as Json from 'vs/base/common/json';
import { Color } from 'vs/base/common/color';
-import { ExtensionData, ITokenColorCustomizations, ITextMateThemingRule, IWorkbenchColorTheme, IColorMap, IThemeExtensionPoint, VS_LIGHT_THEME, VS_HC_THEME, IColorCustomizations, IExperimentalTokenStyleCustomizations, ISemanticTokenColorizationSetting } from 'vs/workbench/services/themes/common/workbenchThemeService';
+import { ExtensionData, ITokenColorCustomizations, ITextMateThemingRule, IWorkbenchColorTheme, IColorMap, IThemeExtensionPoint, VS_LIGHT_THEME, VS_HC_THEME, IColorCustomizations, ISemanticTokenRules, ISemanticTokenColorizationSetting, ISemanticTokenColorCustomizations, IExperimentalSemanticTokenColorCustomizations } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { convertSettings } from 'vs/workbench/services/themes/common/themeCompatibility';
import * as nls from 'vs/nls';
import * as types from 'vs/base/common/types';
@@ -20,7 +20,7 @@ import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages';
import { URI } from 'vs/base/common/uri';
import { parse as parsePList } from 'vs/workbench/services/themes/common/plistParser';
import { startsWith } from 'vs/base/common/strings';
-import { TokenStyle, ProbeScope, TokenStylingRule, getTokenClassificationRegistry, TokenStyleValue, TokenStyleData, parseClassifierString } from 'vs/platform/theme/common/tokenClassificationRegistry';
+import { TokenStyle, SemanticTokenRule, ProbeScope, getTokenClassificationRegistry, TokenStyleValue, TokenStyleData, parseClassifierString } from 'vs/platform/theme/common/tokenClassificationRegistry';
import { MatcherWithPriority, Matcher, createMatchers } from 'vs/workbench/services/themes/common/textMateScopeMatcher';
import { IExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader';
import { CharCode } from 'vs/base/common/charCode';
@@ -42,7 +42,7 @@ const tokenGroupToScopesMap = {
};
-export type TokenStyleDefinition = TokenStylingRule | ProbeScope[] | TokenStyleValue;
+export type TokenStyleDefinition = SemanticTokenRule | ProbeScope[] | TokenStyleValue;
export type TokenStyleDefinitions = { [P in keyof TokenStyleData]?: TokenStyleDefinition | undefined };
export type TextMateThemingRuleDefinitions = { [P in keyof TokenStyleData]?: ITextMateThemingRule | undefined; } & { scope?: ProbeScope; };
@@ -62,14 +62,15 @@ export class ColorThemeData implements IWorkbenchColorTheme {
private themeSemanticHighlighting: boolean | undefined;
private customSemanticHighlighting: boolean | undefined;
+ private customSemanticHighlightingDeprecated: boolean | undefined;
private themeTokenColors: ITextMateThemingRule[] = [];
private customTokenColors: ITextMateThemingRule[] = [];
private colorMap: IColorMap = {};
private customColorMap: IColorMap = {};
- private tokenStylingRules: TokenStylingRule[] = [];
- private customTokenStylingRules: TokenStylingRule[] = [];
+ private semanticTokenRules: SemanticTokenRule[] = [];
+ private customSemanticTokenRules: SemanticTokenRule[] = [];
private themeTokenScopeMatchers: Matcher[] | undefined;
private customTokenScopeMatchers: Matcher[] | undefined;
@@ -85,7 +86,13 @@ export class ColorThemeData implements IWorkbenchColorTheme {
}
get semanticHighlighting(): boolean {
- return this.customSemanticHighlighting !== undefined ? this.customSemanticHighlighting : !!this.themeSemanticHighlighting;
+ if (this.customSemanticHighlighting !== undefined) {
+ return this.customSemanticHighlighting;
+ }
+ if (this.customSemanticHighlightingDeprecated !== undefined) {
+ return this.customSemanticHighlightingDeprecated;
+ }
+ return !!this.themeSemanticHighlighting;
}
get tokenColors(): ITextMateThemingRule[] {
@@ -170,18 +177,16 @@ export class ColorThemeData implements IWorkbenchColorTheme {
}
}
}
- for (const rule of this.tokenStylingRules) {
- const matchScore = rule.selector.match(type, modifiers, language);
- if (matchScore >= 0) {
- _processStyle(matchScore, rule.style, rule);
- }
- }
- for (const rule of this.customTokenStylingRules) {
+ function _processSemanticTokenRule(rule: SemanticTokenRule) {
const matchScore = rule.selector.match(type, modifiers, language);
if (matchScore >= 0) {
_processStyle(matchScore, rule.style, rule);
}
}
+
+ this.semanticTokenRules.forEach(_processSemanticTokenRule);
+ this.customSemanticTokenRules.forEach(_processSemanticTokenRule);
+
let hasUndefinedStyleProperty = false;
for (let k in score) {
const key = k as keyof TokenStyle;
@@ -240,14 +245,14 @@ export class ColorThemeData implements IWorkbenchColorTheme {
index.add(rule.settings.background);
});
- this.tokenStylingRules.forEach(r => index.add(r.style.foreground));
+ this.semanticTokenRules.forEach(r => index.add(r.style.foreground));
tokenClassificationRegistry.getTokenStylingDefaultRules().forEach(r => {
const defaultColor = r.defaults[this.type];
if (defaultColor && typeof defaultColor === 'object') {
index.add(defaultColor.foreground);
}
});
- this.customTokenStylingRules.forEach(r => index.add(r.style.foreground));
+ this.customSemanticTokenRules.forEach(r => index.add(r.style.foreground));
this.tokenColorIndex = index;
}
@@ -273,11 +278,11 @@ export class ColorThemeData implements IWorkbenchColorTheme {
};
}
- public getTokenStylingRuleScope(rule: TokenStylingRule): 'setting' | 'theme' | undefined {
- if (this.customTokenStylingRules.indexOf(rule) !== -1) {
+ public getTokenStylingRuleScope(rule: SemanticTokenRule): 'setting' | 'theme' | undefined {
+ if (this.customSemanticTokenRules.indexOf(rule) !== -1) {
return 'setting';
}
- if (this.tokenStylingRules.indexOf(rule) !== -1) {
+ if (this.semanticTokenRules.indexOf(rule) !== -1) {
return 'theme';
}
return undefined;
@@ -346,7 +351,7 @@ export class ColorThemeData implements IWorkbenchColorTheme {
public setCustomizations(settings: ThemeConfiguration) {
this.setCustomColors(settings.colorCustomizations);
this.setCustomTokenColors(settings.tokenColorCustomizations);
- this.setCustomTokenStyleRules(settings.tokenStylesCustomizations);
+ this.setCustomSemanticTokenColors(settings.semanticTokenColorCustomizations, settings.experimentalSemanticTokenColorCustomizations);
}
public setCustomColors(colors: IColorCustomizations) {
@@ -374,7 +379,7 @@ export class ColorThemeData implements IWorkbenchColorTheme {
public setCustomTokenColors(customTokenColors: ITokenColorCustomizations) {
this.customTokenColors = [];
- this.customSemanticHighlighting = undefined;
+ this.customSemanticHighlightingDeprecated = undefined;
// first add the non-theme specific settings
this.addCustomTokenColors(customTokenColors);
@@ -390,19 +395,53 @@ export class ColorThemeData implements IWorkbenchColorTheme {
this.customTokenScopeMatchers = undefined;
}
- public setCustomTokenStyleRules(tokenStylingRules: IExperimentalTokenStyleCustomizations) {
- this.customTokenStylingRules = [];
- readCustomTokenStyleRules(tokenStylingRules, this.customTokenStylingRules);
+ public setCustomSemanticTokenColors(semanticTokenColors: ISemanticTokenColorCustomizations | undefined, experimental?: IExperimentalSemanticTokenColorCustomizations) {
+ this.customSemanticTokenRules = [];
+ this.customSemanticHighlighting = undefined;
- const themeSpecificColors = tokenStylingRules[`[${this.settingsId}]`] as IExperimentalTokenStyleCustomizations;
- if (types.isObject(themeSpecificColors)) {
- readCustomTokenStyleRules(themeSpecificColors, this.customTokenStylingRules);
+ if (experimental) { // apply deprecated settings first
+ this.readSemanticTokenRules(experimental);
+ const themeSpecificColors = experimental[`[${this.settingsId}]`] as IExperimentalSemanticTokenColorCustomizations;
+ if (types.isObject(themeSpecificColors)) {
+ this.readSemanticTokenRules(themeSpecificColors);
+ }
+ }
+ if (semanticTokenColors) {
+ this.customSemanticHighlighting = semanticTokenColors.enabled;
+ if (semanticTokenColors.rules) {
+ this.readSemanticTokenRules(semanticTokenColors.rules);
+ }
+ const themeSpecificColors = semanticTokenColors[`[${this.settingsId}]`] as ISemanticTokenColorCustomizations;
+ if (types.isObject(themeSpecificColors)) {
+ if (themeSpecificColors.enabled !== undefined) {
+ this.customSemanticHighlighting = themeSpecificColors.enabled;
+ }
+ if (themeSpecificColors.rules) {
+ this.readSemanticTokenRules(themeSpecificColors.rules);
+ }
+ }
}
this.tokenColorIndex = undefined;
this.textMateThemingRules = undefined;
}
+
+ private readSemanticTokenRules(tokenStylingRuleSection: ISemanticTokenRules) {
+ for (let key in tokenStylingRuleSection) {
+ if (key[0] !== '[') { // still do this test until experimental settings are gone
+ try {
+ const rule = readSemanticTokenRule(key, tokenStylingRuleSection[key]);
+ if (rule) {
+ this.customSemanticTokenRules.push(rule);
+ }
+ } catch (e) {
+ // invalid selector, ignore
+ }
+ }
+ }
+ }
+
private addCustomTokenColors(customTokenColors: ITokenColorCustomizations) {
// Put the general customizations such as comments, strings, etc. first so that
// they can be overridden by specific customizations like "string.interpolated"
@@ -427,7 +466,7 @@ export class ColorThemeData implements IWorkbenchColorTheme {
}
}
if (customTokenColors.semanticHighlighting !== undefined) {
- this.customSemanticHighlighting = customTokenColors.semanticHighlighting;
+ this.customSemanticHighlightingDeprecated = customTokenColors.semanticHighlighting;
}
}
@@ -449,12 +488,12 @@ export class ColorThemeData implements IWorkbenchColorTheme {
const result = {
colors: {},
textMateRules: [],
- stylingRules: [],
+ semanticTokenRules: [],
semanticHighlighting: false
};
return _loadColorTheme(extensionResourceLoaderService, this.location, result).then(_ => {
this.isLoaded = true;
- this.tokenStylingRules = result.stylingRules;
+ this.semanticTokenRules = result.semanticTokenRules;
this.colorMap = result.colors;
this.themeTokenColors = result.textMateRules;
this.themeSemanticHighlighting = result.semanticHighlighting;
@@ -480,7 +519,7 @@ export class ColorThemeData implements IWorkbenchColorTheme {
settingsId: this.settingsId,
selector: this.id.split(' ').join('.'), // to not break old clients
themeTokenColors: this.themeTokenColors,
- tokenStylingRules: this.tokenStylingRules.map(TokenStylingRule.toJSONObject),
+ semanticTokenRules: this.semanticTokenRules.map(SemanticTokenRule.toJSONObject),
extensionData: ExtensionData.toJSONObject(this.extensionData),
location: this.location?.toJSON(),
themeSemanticHighlighting: this.themeSemanticHighlighting,
@@ -493,7 +532,7 @@ export class ColorThemeData implements IWorkbenchColorTheme {
hasEqualData(other: ColorThemeData) {
return objects.equals(this.colorMap, other.colorMap)
&& objects.equals(this.themeTokenColors, other.themeTokenColors)
- && arrays.equals(this.tokenStylingRules, other.tokenStylingRules, TokenStylingRule.equals)
+ && arrays.equals(this.semanticTokenRules, other.semanticTokenRules, SemanticTokenRule.equals)
&& this.themeSemanticHighlighting === other.themeSemanticHighlighting;
}
@@ -547,13 +586,13 @@ export class ColorThemeData implements IWorkbenchColorTheme {
case 'id': case 'label': case 'settingsId': case 'watch': case 'themeSemanticHighlighting':
(theme as any)[key] = data[key];
break;
- case 'tokenStylingRules':
+ case 'semanticTokenRules':
const rulesData = data[key];
if (Array.isArray(rulesData)) {
for (let d of rulesData) {
- const rule = TokenStylingRule.fromJSONObject(tokenClassificationRegistry, d);
+ const rule = SemanticTokenRule.fromJSONObject(tokenClassificationRegistry, d);
if (rule) {
- theme.tokenStylingRules.push(rule);
+ theme.semanticTokenRules.push(rule);
}
}
}
@@ -605,7 +644,7 @@ function toCSSSelector(extensionId: string, path: string) {
return str;
}
-async function _loadColorTheme(extensionResourceLoaderService: IExtensionResourceLoaderService, themeLocation: URI, result: { textMateRules: ITextMateThemingRule[], colors: IColorMap, stylingRules: TokenStylingRule[], semanticHighlighting: boolean }): Promise {
+async function _loadColorTheme(extensionResourceLoaderService: IExtensionResourceLoaderService, themeLocation: URI, result: { textMateRules: ITextMateThemingRule[], colors: IColorMap, semanticTokenRules: SemanticTokenRule[], semanticHighlighting: boolean }): Promise {
if (resources.extname(themeLocation) === '.json') {
const content = await extensionResourceLoaderService.readExtensionResource(themeLocation);
let errors: Json.ParseError[] = [];
@@ -650,9 +689,9 @@ async function _loadColorTheme(extensionResourceLoaderService: IExtensionResourc
if (semanticTokenColors && typeof semanticTokenColors === 'object') {
for (let key in semanticTokenColors) {
try {
- const rule = readCustomTokenStyleRule(key, semanticTokenColors[key]);
+ const rule = readSemanticTokenRule(key, semanticTokenColors[key]);
if (rule) {
- result.stylingRules.push(rule);
+ result.semanticTokenRules.push(rule);
}
} catch (e) {
return Promise.reject(new Error(nls.localize({ key: 'error.invalidformat.semanticTokenColors', comment: ['{0} will be replaced by a path. Values in quotes should not be translated.'] }, "Problem parsing color theme file: {0}. Property 'semanticTokenColors' conatains a invalid selector", themeLocation.toString())));
@@ -770,7 +809,7 @@ function getScopeMatcher(rule: ITextMateThemingRule): Matcher {
};
}
-function readCustomTokenStyleRule(selectorString: string, settings: ISemanticTokenColorizationSetting | string | undefined): TokenStylingRule | undefined {
+function readSemanticTokenRule(selectorString: string, settings: ISemanticTokenColorizationSetting | string | boolean | undefined): SemanticTokenRule | undefined {
const selector = tokenClassificationRegistry.parseTokenSelector(selectorString);
let style: TokenStyle | undefined;
if (typeof settings === 'string') {
@@ -784,22 +823,6 @@ function readCustomTokenStyleRule(selectorString: string, settings: ISemanticTok
return undefined;
}
-function readCustomTokenStyleRules(tokenStylingRuleSection: IExperimentalTokenStyleCustomizations, result: TokenStylingRule[] = []) {
- for (let key in tokenStylingRuleSection) {
- if (key[0] !== '[') {
- try {
- const rule = readCustomTokenStyleRule(key, tokenStylingRuleSection[key]);
- if (rule) {
- result.push(rule);
- }
- } catch (e) {
- // invalid selector, ignore
- }
- }
- }
- return result;
-}
-
function isSemanticTokenColorizationSetting(style: any): style is ISemanticTokenColorizationSetting {
return style && (types.isString(style.foreground) || types.isString(style.fontStyle) || types.isBoolean(style.italic)
|| types.isBoolean(style.underline) || types.isBoolean(style.bold));
diff --git a/src/vs/workbench/services/themes/common/themeConfiguration.ts b/src/vs/workbench/services/themes/common/themeConfiguration.ts
index 23d689a28506d376e0bfb70751771fa3ef931bb8..5e5665b01e780ad81511435b36b021d9a166baa1 100644
--- a/src/vs/workbench/services/themes/common/themeConfiguration.ts
+++ b/src/vs/workbench/services/themes/common/themeConfiguration.ts
@@ -12,9 +12,8 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { textmateColorsSchemaId, textmateColorGroupSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema';
import { workbenchColorsSchemaId } from 'vs/platform/theme/common/colorRegistry';
import { tokenStylingSchemaId } from 'vs/platform/theme/common/tokenClassificationRegistry';
-import { ThemeSettings, IWorkbenchColorTheme, IWorkbenchFileIconTheme, IColorCustomizations, ITokenColorCustomizations, IExperimentalTokenStyleCustomizations, IWorkbenchProductIconTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
+import { ThemeSettings, IWorkbenchColorTheme, IWorkbenchFileIconTheme, IColorCustomizations, ITokenColorCustomizations, IWorkbenchProductIconTheme, ISemanticTokenColorCustomizations, IExperimentalSemanticTokenColorCustomizations } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
-
const DEFAULT_THEME_SETTING_VALUE = 'Default Dark+';
const DEFAULT_THEME_DARK_SETTING_VALUE = 'Default Dark+';
const DEFAULT_THEME_LIGHT_SETTING_VALUE = 'Default Light+';
@@ -134,19 +133,43 @@ const tokenColorSchema: IJSONSchema = {
},
semanticHighlighting: {
description: nls.localize('editorColors.semanticHighlighting', 'Whether semantic highlighting should be enabled for this theme.'),
+ deprecationMessage: nls.localize('editorColors.semanticHighlighting.deprecationMessage', 'Use `enabled` in `editor.semanticTokenColorCustomizations` setting instead.'),
type: 'boolean'
}
}
};
+
const tokenColorCustomizationSchema: IConfigurationPropertySchema = {
- description: nls.localize('editorColors', "Overrides editor colors and font style from the currently selected color theme."),
+ description: nls.localize('editorColors', "Overrides editor syntax colors and font style from the currently selected color theme."),
default: {},
allOf: [tokenColorSchema]
};
+
+const semanticTokenColorSchema: IJSONSchema = {
+ type: 'object',
+ properties: {
+ enabled: {
+ type: 'boolean',
+ description: nls.localize('editorColors.semanticHighlighting.enabled', 'Whether semantic highlighting is enabled or disabled for this theme')
+ },
+ rules: {
+ $ref: tokenStylingSchemaId,
+ description: nls.localize('editorColors.semanticHighlighting.rules', 'Semantic token styling rules for this theme.')
+ }
+ },
+ additionalProperties: false
+};
+
+const semanticTokenColorCustomizationSchema: IConfigurationPropertySchema = {
+ description: nls.localize('semanticTokenColors', "Overrides editor semantic token color and styles from the currently selected color theme."),
+ default: {},
+ allOf: [{ ...semanticTokenColorSchema, patternProperties: { '^\\[': {} } }]
+};
+
const experimentalTokenStylingCustomizationSchema: IConfigurationPropertySchema = {
- description: nls.localize('editorColorsTokenStyles', "Overrides token color and styles from the currently selected color theme."),
+ deprecationMessage: nls.localize('editorColors.experimentalTokenStyling.deprecationMessage', 'Use `editor.semanticTokenColorCustomizations` instead.'),
default: {},
- allOf: [{ $ref: tokenStylingSchemaId }]
+ allOf: [{ $ref: tokenStylingSchemaId }],
};
const tokenColorCustomizationConfiguration: IConfigurationNode = {
id: 'editor',
@@ -154,6 +177,7 @@ const tokenColorCustomizationConfiguration: IConfigurationNode = {
type: 'object',
properties: {
[ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS]: tokenColorCustomizationSchema,
+ [ThemeSettings.SEMANTIC_TOKEN_COLOR_CUSTOMIZATIONS]: semanticTokenColorCustomizationSchema,
[ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL]: experimentalTokenStylingCustomizationSchema
}
};
@@ -167,22 +191,24 @@ export function updateColorThemeConfigurationSchemas(themes: IWorkbenchColorThem
const themeSpecificWorkbenchColors: IJSONSchema = { properties: {} };
const themeSpecificTokenColors: IJSONSchema = { properties: {} };
- const themeSpecificTokenStyling: IJSONSchema = { properties: {} };
+ const themeSpecificSemanticTokenColors: IJSONSchema = { properties: {} };
+ const experimentalThemeSpecificSemanticTokenColors: IJSONSchema = { properties: {} };
const workbenchColors = { $ref: workbenchColorsSchemaId, additionalProperties: false };
const tokenColors = { properties: tokenColorSchema.properties, additionalProperties: false };
- const tokenStyling = { $ref: tokenStylingSchemaId, additionalProperties: false };
for (let t of themes) {
// add theme specific color customization ("[Abyss]":{ ... })
const themeId = `[${t.settingsId}]`;
themeSpecificWorkbenchColors.properties![themeId] = workbenchColors;
themeSpecificTokenColors.properties![themeId] = tokenColors;
- themeSpecificTokenStyling.properties![themeId] = tokenStyling;
+ themeSpecificSemanticTokenColors.properties![themeId] = semanticTokenColorSchema;
+ experimentalThemeSpecificSemanticTokenColors.properties![themeId] = { $ref: tokenStylingSchemaId, additionalProperties: false };
}
colorCustomizationsSchema.allOf![1] = themeSpecificWorkbenchColors;
tokenColorCustomizationSchema.allOf![1] = themeSpecificTokenColors;
- experimentalTokenStylingCustomizationSchema.allOf![1] = themeSpecificTokenStyling;
+ semanticTokenColorCustomizationSchema.allOf![1] = themeSpecificSemanticTokenColors;
+ experimentalTokenStylingCustomizationSchema.allOf![1] = experimentalThemeSpecificSemanticTokenColors;
configurationRegistry.notifyConfigurationSchemaUpdated(themeSettingsConfiguration, tokenColorCustomizationConfiguration);
}
@@ -226,8 +252,12 @@ export class ThemeConfiguration {
return this.configurationService.getValue(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS) || {};
}
- public get tokenStylesCustomizations(): IExperimentalTokenStyleCustomizations {
- return this.configurationService.getValue(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL) || {};
+ public get semanticTokenColorCustomizations(): ISemanticTokenColorCustomizations | undefined {
+ return this.configurationService.getValue(ThemeSettings.SEMANTIC_TOKEN_COLOR_CUSTOMIZATIONS);
+ }
+
+ public get experimentalSemanticTokenColorCustomizations(): IExperimentalSemanticTokenColorCustomizations | undefined {
+ return this.configurationService.getValue(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL);
}
public async setColorTheme(theme: IWorkbenchColorTheme, settingsTarget: ConfigurationTarget | undefined | 'auto'): Promise {
diff --git a/src/vs/workbench/services/themes/common/workbenchThemeService.ts b/src/vs/workbench/services/themes/common/workbenchThemeService.ts
index bc37417470ff682a5a9b0da5f9685e6b94b9ce4d..c1409abd2a8ebbb5d16554098b89d3815cbfb8f1 100644
--- a/src/vs/workbench/services/themes/common/workbenchThemeService.ts
+++ b/src/vs/workbench/services/themes/common/workbenchThemeService.ts
@@ -25,6 +25,7 @@ export enum ThemeSettings {
PRODUCT_ICON_THEME = 'workbench.productIconTheme',
COLOR_CUSTOMIZATIONS = 'workbench.colorCustomizations',
TOKEN_COLOR_CUSTOMIZATIONS = 'editor.tokenColorCustomizations',
+ SEMANTIC_TOKEN_COLOR_CUSTOMIZATIONS = 'editor.semanticTokenColorCustomizations',
TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL = 'editor.tokenColorCustomizationsExperimental',
PREFERRED_DARK_THEME = 'workbench.preferredDarkColorTheme',
@@ -93,11 +94,21 @@ export interface ITokenColorCustomizations {
functions?: string | ITokenColorizationSetting;
variables?: string | ITokenColorizationSetting;
textMateRules?: ITextMateThemingRule[];
- semanticHighlighting?: boolean;
+ semanticHighlighting?: boolean; // deprecated, use ISemanticTokenColorCustomizations.enabled instead
}
-export interface IExperimentalTokenStyleCustomizations {
- [styleRuleOrThemeSettingsId: string]: string | ISemanticTokenColorizationSetting | IExperimentalTokenStyleCustomizations | undefined;
+export interface ISemanticTokenColorCustomizations {
+ enabled?: boolean;
+ rules?: ISemanticTokenRules;
+ [styleRuleOrThemeSettingsId: string]: ISemanticTokenRules | ISemanticTokenColorCustomizations | boolean | undefined;
+}
+
+export interface IExperimentalSemanticTokenColorCustomizations {
+ [styleRuleOrThemeSettingsId: string]: ISemanticTokenRules | IExperimentalSemanticTokenColorCustomizations | undefined;
+}
+
+export interface ISemanticTokenRules {
+ [selector: string]: string | ISemanticTokenColorizationSetting | undefined;
}
export interface ITextMateThemingRule {
diff --git a/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts b/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts
index cf8fc36547df8651295ceb6b26a90af8c0d80ffc..15422f0975f736efc2934cbf1b7dab67008a0cf1 100644
--- a/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts
+++ b/src/vs/workbench/services/themes/test/electron-browser/tokenStyleResolving.test.ts
@@ -326,13 +326,16 @@ suite('Themes - TokenStyleResolving', () => {
test('rule matching', async () => {
const themeData = ColorThemeData.createLoadedEmptyTheme('test', 'test');
themeData.setCustomColors({ 'editor.foreground': '#000000' });
- themeData.setCustomTokenStyleRules({
- 'type': '#ff0000',
- 'class': { foreground: '#0000ff', italic: true },
- '*.static': { bold: true },
- '*.declaration': { italic: true },
- '*.async.static': { italic: true, underline: true },
- '*.async': { foreground: '#000fff', underline: true }
+ themeData.setCustomSemanticTokenColors({
+ enabled: true,
+ rules: {
+ 'type': '#ff0000',
+ 'class': { foreground: '#0000ff', italic: true },
+ '*.static': { bold: true },
+ '*.declaration': { italic: true },
+ '*.async.static': { italic: true, underline: true },
+ '*.async': { foreground: '#000fff', underline: true }
+ }
});
assertTokenStyles(themeData, {
@@ -357,18 +360,24 @@ suite('Themes - TokenStyleResolving', () => {
try {
const themeData = ColorThemeData.createLoadedEmptyTheme('test', 'test');
themeData.setCustomColors({ 'editor.foreground': '#000000' });
- themeData.setCustomTokenStyleRules({
- 'interface': '#ff0000',
- 'myTestInterface': { italic: true },
- 'interface.static': { bold: true }
+ themeData.setCustomSemanticTokenColors({
+ enabled: true,
+ rules: {
+ 'interface': '#ff0000',
+ 'myTestInterface': { italic: true },
+ 'interface.static': { bold: true }
+ }
});
assertTokenStyles(themeData, { 'myTestSubInterface': ts('#ff0000', { italic: true }) });
assertTokenStyles(themeData, { 'myTestSubInterface.static': ts('#ff0000', { italic: true, bold: true }) });
- themeData.setCustomTokenStyleRules({
- 'interface': '#ff0000',
- 'myTestInterface': { foreground: '#ff00ff', italic: true }
+ themeData.setCustomSemanticTokenColors({
+ enabled: true,
+ rules: {
+ 'interface': '#ff0000',
+ 'myTestInterface': { foreground: '#ff00ff', italic: true }
+ }
});
assertTokenStyles(themeData, { 'myTestSubInterface': ts('#ff00ff', { italic: true }) });
} finally {
@@ -381,11 +390,14 @@ suite('Themes - TokenStyleResolving', () => {
try {
const themeData = ColorThemeData.createLoadedEmptyTheme('test', 'test');
themeData.setCustomColors({ 'editor.foreground': '#000000' });
- themeData.setCustomTokenStyleRules({
- 'interface': '#fff000',
- 'interface:java': '#ff0000',
- 'interface.static': { bold: true },
- 'interface.static:typescript': { italic: true }
+ themeData.setCustomSemanticTokenColors({
+ enabled: true,
+ rules: {
+ 'interface': '#fff000',
+ 'interface:java': '#ff0000',
+ 'interface.static': { bold: true },
+ 'interface.static:typescript': { italic: true }
+ }
});
assertTokenStyles(themeData, { 'interface': ts('#ff0000', undefined) }, 'java');