提交 412ee9ac 编写于 作者: M Martin Aeschlimann

Make editor.tokenColorCustomizationsExperimental offical. Fixes #96267

上级 696dca78
......@@ -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;
}
......
......@@ -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(' '))}<br><code class="tiw-theme-selector">${strScopes}\n${JSON.stringify(matchingRule.settings, null, '\t')}</code>`;
}
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)}`;
......
......@@ -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) {
......
......@@ -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<ProbeScope>[] | undefined;
private customTokenScopeMatchers: Matcher<ProbeScope>[] | 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<any> {
async function _loadColorTheme(extensionResourceLoaderService: IExtensionResourceLoaderService, themeLocation: URI, result: { textMateRules: ITextMateThemingRule[], colors: IColorMap, semanticTokenRules: SemanticTokenRule[], semanticHighlighting: boolean }): Promise<any> {
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<ProbeScope> {
};
}
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));
......
......@@ -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<ITokenColorCustomizations>(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS) || {};
}
public get tokenStylesCustomizations(): IExperimentalTokenStyleCustomizations {
return this.configurationService.getValue<IExperimentalTokenStyleCustomizations>(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL) || {};
public get semanticTokenColorCustomizations(): ISemanticTokenColorCustomizations | undefined {
return this.configurationService.getValue<ISemanticTokenColorCustomizations>(ThemeSettings.SEMANTIC_TOKEN_COLOR_CUSTOMIZATIONS);
}
public get experimentalSemanticTokenColorCustomizations(): IExperimentalSemanticTokenColorCustomizations | undefined {
return this.configurationService.getValue<IExperimentalSemanticTokenColorCustomizations>(ThemeSettings.TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL);
}
public async setColorTheme(theme: IWorkbenchColorTheme, settingsTarget: ConfigurationTarget | undefined | 'auto'): Promise<IWorkbenchColorTheme> {
......
......@@ -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 {
......
......@@ -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');
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册