提交 b34da611 编写于 作者: M Martin Aeschlimann

Merge branch 'aeschli/tokenClassificationExtPoint'

...@@ -24,5 +24,34 @@ ...@@ -24,5 +24,34 @@
"mocha-junit-reporter": "^1.17.0", "mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7", "mocha-multi-reporters": "^1.1.7",
"vscode": "1.1.5" "vscode": "1.1.5"
},
"contributes": {
"tokenTypes": [
{
"id": "testToken",
"description": "A test token"
}
],
"tokenModifiers": [
{
"id": "testModifier",
"description": "A test modifier"
}
],
"tokenStyleDefaults": [
{
"selector": "testToken.testModifier",
"light": {
"fontStyle": "bold"
},
"dark": {
"fontStyle": "bold"
},
"highContrast": {
"fontStyle": "bold"
}
}
]
} }
} }
...@@ -8,11 +8,13 @@ import * as jsoncParser from 'jsonc-parser'; ...@@ -8,11 +8,13 @@ import * as jsoncParser from 'jsonc-parser';
export function activate(context: vscode.ExtensionContext): any { export function activate(context: vscode.ExtensionContext): any {
const tokenTypes = ['type', 'struct', 'class', 'interface', 'enum', 'parameterType', 'function', 'variable']; const tokenTypes = ['type', 'struct', 'class', 'interface', 'enum', 'parameterType', 'function', 'variable', 'testToken'];
const tokenModifiers = ['static', 'abstract', 'deprecated', 'declaration', 'documentation', 'member', 'async']; const tokenModifiers = ['static', 'abstract', 'deprecated', 'declaration', 'documentation', 'member', 'async', 'testModifier'];
const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers); const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers);
const outputChannel = vscode.window.createOutputChannel('Semantic Tokens Test');
const semanticHighlightProvider: vscode.SemanticTokensProvider = { const semanticHighlightProvider: vscode.SemanticTokensProvider = {
provideSemanticTokens(document: vscode.TextDocument): vscode.ProviderResult<vscode.SemanticTokens> { provideSemanticTokens(document: vscode.TextDocument): vscode.ProviderResult<vscode.SemanticTokens> {
const builder = new vscode.SemanticTokensBuilder(); const builder = new vscode.SemanticTokensBuilder();
...@@ -35,8 +37,13 @@ export function activate(context: vscode.ExtensionContext): any { ...@@ -35,8 +37,13 @@ export function activate(context: vscode.ExtensionContext): any {
builder.push(startLine, startCharacter, length, tokenType, tokenModifiers); builder.push(startLine, startCharacter, length, tokenType, tokenModifiers);
const selectedModifiers = legend.tokenModifiers.filter((_val, bit) => tokenModifiers & (1 << bit)).join(' ');
outputChannel.appendLine(`line: ${startLine}, character: ${startCharacter}, length ${length}, ${legend.tokenTypes[tokenType]} (${tokenType}), ${selectedModifiers} ${tokenModifiers.toString(2)}`);
} }
outputChannel.appendLine('---');
const visitor: jsoncParser.JSONVisitor = { const visitor: jsoncParser.JSONVisitor = {
onObjectProperty: (property: string, _offset: number, _length: number, startLine: number, startCharacter: number) => { onObjectProperty: (property: string, _offset: number, _length: number, startLine: number, startCharacter: number) => {
addToken(property, startLine, startCharacter, property.length + 2); addToken(property, startLine, startCharacter, property.length + 2);
......
{
"editor.tokenColorCustomizationsExperimental": {
"class": "#00b0b0",
"interface": "#845faf",
"function": "#ff00ff",
"*.declaration": {
"fontStyle": "underline"
},
"*.declaration.member": {
"fontStyle": "italic bold",
}
}
}
\ No newline at end of file
[
"class", "function.member.declaration",
"parameterType.declaration", "type", "parameterType.declaration", "type",
"variable.declaration", "parameterNames",
"function.member.declaration",
"interface.declaration",
"function.member.declaration", "testToken.testModifier"
]
...@@ -14,7 +14,7 @@ import { Range } from 'vs/editor/common/core/range'; ...@@ -14,7 +14,7 @@ import { Range } from 'vs/editor/common/core/range';
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions } from 'vs/editor/common/model'; import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions } from 'vs/editor/common/model';
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel'; import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
import { IModelLanguageChangedEvent, IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents'; import { IModelLanguageChangedEvent, IModelContentChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { LanguageIdentifier, SemanticTokensProviderRegistry, SemanticTokensProvider, SemanticTokensLegend, SemanticTokens, SemanticTokensEdits } from 'vs/editor/common/modes'; import { LanguageIdentifier, SemanticTokensProviderRegistry, SemanticTokensProvider, SemanticTokensLegend, SemanticTokens, SemanticTokensEdits, TokenMetadata } from 'vs/editor/common/modes';
import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry'; import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegistry';
import { ILanguageSelection } from 'vs/editor/common/services/modeService'; import { ILanguageSelection } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService'; import { IModelService } from 'vs/editor/common/services/modelService';
...@@ -24,6 +24,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; ...@@ -24,6 +24,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { SparseEncodedTokens, MultilineTokens2 } from 'vs/editor/common/model/tokensStore'; import { SparseEncodedTokens, MultilineTokens2 } from 'vs/editor/common/model/tokensStore';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
function MODEL_ID(resource: URI): string { function MODEL_ID(resource: URI): string {
return resource.toString(); return resource.toString();
...@@ -120,7 +121,8 @@ export class ModelServiceImpl extends Disposable implements IModelService { ...@@ -120,7 +121,8 @@ export class ModelServiceImpl extends Disposable implements IModelService {
constructor( constructor(
@IConfigurationService configurationService: IConfigurationService, @IConfigurationService configurationService: IConfigurationService,
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService, @ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService,
@IThemeService themeService: IThemeService @IThemeService themeService: IThemeService,
@ILogService logService: ILogService
) { ) {
super(); super();
this._configurationService = configurationService; this._configurationService = configurationService;
...@@ -131,7 +133,7 @@ export class ModelServiceImpl extends Disposable implements IModelService { ...@@ -131,7 +133,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
this._configurationServiceSubscription = this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions()); this._configurationServiceSubscription = this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions());
this._updateModelOptions(); this._updateModelOptions();
this._register(new SemanticColoringFeature(this, themeService)); this._register(new SemanticColoringFeature(this, themeService, logService));
} }
private static _readModelOptions(config: IRawConfig, isForSimpleWidget: boolean): ITextModelCreationOptions { private static _readModelOptions(config: IRawConfig, isForSimpleWidget: boolean): ITextModelCreationOptions {
...@@ -443,10 +445,10 @@ class SemanticColoringFeature extends Disposable { ...@@ -443,10 +445,10 @@ class SemanticColoringFeature extends Disposable {
private _watchers: Record<string, ModelSemanticColoring>; private _watchers: Record<string, ModelSemanticColoring>;
private _semanticStyling: SemanticStyling; private _semanticStyling: SemanticStyling;
constructor(modelService: IModelService, themeService: IThemeService) { constructor(modelService: IModelService, themeService: IThemeService, logService: ILogService) {
super(); super();
this._watchers = Object.create(null); this._watchers = Object.create(null);
this._semanticStyling = this._register(new SemanticStyling(themeService)); this._semanticStyling = this._register(new SemanticStyling(themeService, logService));
this._register(modelService.onModelAdded((model) => { this._register(modelService.onModelAdded((model) => {
this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, themeService, this._semanticStyling); this._watchers[model.uri.toString()] = new ModelSemanticColoring(model, themeService, this._semanticStyling);
})); }));
...@@ -462,7 +464,8 @@ class SemanticStyling extends Disposable { ...@@ -462,7 +464,8 @@ class SemanticStyling extends Disposable {
private _caches: WeakMap<SemanticTokensProvider, SemanticColoringProviderStyling>; private _caches: WeakMap<SemanticTokensProvider, SemanticColoringProviderStyling>;
constructor( constructor(
private readonly _themeService: IThemeService private readonly _themeService: IThemeService,
private readonly _logService: ILogService
) { ) {
super(); super();
this._caches = new WeakMap<SemanticTokensProvider, SemanticColoringProviderStyling>(); this._caches = new WeakMap<SemanticTokensProvider, SemanticColoringProviderStyling>();
...@@ -476,7 +479,7 @@ class SemanticStyling extends Disposable { ...@@ -476,7 +479,7 @@ class SemanticStyling extends Disposable {
public get(provider: SemanticTokensProvider): SemanticColoringProviderStyling { public get(provider: SemanticTokensProvider): SemanticColoringProviderStyling {
if (!this._caches.has(provider)) { if (!this._caches.has(provider)) {
this._caches.set(provider, new SemanticColoringProviderStyling(provider.getLegend(), this._themeService)); this._caches.set(provider, new SemanticColoringProviderStyling(provider.getLegend(), this._themeService, this._logService));
} }
return this._caches.get(provider)!; return this._caches.get(provider)!;
} }
...@@ -581,7 +584,8 @@ class SemanticColoringProviderStyling { ...@@ -581,7 +584,8 @@ class SemanticColoringProviderStyling {
constructor( constructor(
private readonly _legend: SemanticTokensLegend, private readonly _legend: SemanticTokensLegend,
private readonly _themeService: IThemeService private readonly _themeService: IThemeService,
private readonly _logService: ILogService
) { ) {
this._hashTable = new HashTable(); this._hashTable = new HashTable();
} }
...@@ -605,6 +609,9 @@ class SemanticColoringProviderStyling { ...@@ -605,6 +609,9 @@ class SemanticColoringProviderStyling {
if (typeof metadata === 'undefined') { if (typeof metadata === 'undefined') {
metadata = Constants.NO_STYLING; metadata = Constants.NO_STYLING;
} }
if (this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`getTokenStyleMetadata(${tokenType}${tokenModifiers.length ? ', ' + tokenModifiers.join(' ') : ''}): foreground: ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
}
this._hashTable.add(tokenTypeIndex, tokenModifierSet, metadata); this._hashTable.add(tokenTypeIndex, tokenModifierSet, metadata);
return metadata; return metadata;
......
...@@ -18,6 +18,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; ...@@ -18,6 +18,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/wordSelections'; import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/wordSelections';
import { TestTextResourcePropertiesService } from 'vs/editor/test/common/services/modelService.test'; import { TestTextResourcePropertiesService } from 'vs/editor/test/common/services/modelService.test';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { NullLogService } from 'vs/platform/log/common/log';
class MockJSMode extends MockMode { class MockJSMode extends MockMode {
...@@ -46,7 +47,7 @@ suite('SmartSelect', () => { ...@@ -46,7 +47,7 @@ suite('SmartSelect', () => {
setup(() => { setup(() => {
const configurationService = new TestConfigurationService(); const configurationService = new TestConfigurationService();
modelService = new ModelServiceImpl(configurationService, new TestTextResourcePropertiesService(configurationService), new TestThemeService()); modelService = new ModelServiceImpl(configurationService, new TestTextResourcePropertiesService(configurationService), new TestThemeService(), new NullLogService());
mode = new MockJSMode(); mode = new MockJSMode();
}); });
......
...@@ -146,7 +146,9 @@ export module StaticServices { ...@@ -146,7 +146,9 @@ export module StaticServices {
export const standaloneThemeService = define(IStandaloneThemeService, () => new StandaloneThemeServiceImpl()); export const standaloneThemeService = define(IStandaloneThemeService, () => new StandaloneThemeServiceImpl());
export const modelService = define(IModelService, (o) => new ModelServiceImpl(configurationService.get(o), resourcePropertiesService.get(o), standaloneThemeService.get(o))); export const logService = define(ILogService, () => new NullLogService());
export const modelService = define(IModelService, (o) => new ModelServiceImpl(configurationService.get(o), resourcePropertiesService.get(o), standaloneThemeService.get(o), logService.get(o)));
export const markerDecorationsService = define(IMarkerDecorationsService, (o) => new MarkerDecorationsService(modelService.get(o), markerService.get(o))); export const markerDecorationsService = define(IMarkerDecorationsService, (o) => new MarkerDecorationsService(modelService.get(o), markerService.get(o)));
...@@ -156,8 +158,6 @@ export module StaticServices { ...@@ -156,8 +158,6 @@ export module StaticServices {
export const storageService = define(IStorageService, () => new InMemoryStorageService()); export const storageService = define(IStorageService, () => new InMemoryStorageService());
export const logService = define(ILogService, () => new NullLogService());
export const editorWorkerService = define(IEditorWorkerService, (o) => new EditorWorkerServiceImpl(modelService.get(o), resourceConfigurationService.get(o), logService.get(o))); export const editorWorkerService = define(IEditorWorkerService, (o) => new EditorWorkerServiceImpl(modelService.get(o), resourceConfigurationService.get(o), logService.get(o)));
} }
......
...@@ -17,6 +17,7 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/resour ...@@ -17,6 +17,7 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/resour
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { NullLogService } from 'vs/platform/log/common/log';
const GENERATE_TESTS = false; const GENERATE_TESTS = false;
...@@ -28,7 +29,7 @@ suite('ModelService', () => { ...@@ -28,7 +29,7 @@ suite('ModelService', () => {
configService.setUserConfiguration('files', { 'eol': '\n' }); configService.setUserConfiguration('files', { 'eol': '\n' });
configService.setUserConfiguration('files', { 'eol': '\r\n' }, URI.file(platform.isWindows ? 'c:\\myroot' : '/myroot')); configService.setUserConfiguration('files', { 'eol': '\r\n' }, URI.file(platform.isWindows ? 'c:\\myroot' : '/myroot'));
modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService()); modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService());
}); });
teardown(() => { teardown(() => {
......
...@@ -12,14 +12,15 @@ import { RunOnceScheduler } from 'vs/base/common/async'; ...@@ -12,14 +12,15 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event'; import { Event, Emitter } from 'vs/base/common/event';
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
// ------ API types
export const TOKEN_TYPE_WILDCARD = '*'; export const TOKEN_TYPE_WILDCARD = '*';
export const TOKEN_TYPE_WILDCARD_NUM = -1; export const TOKEN_TYPE_WILDCARD_NUM = -1;
// qualified string [type|*](.modifier)* // qualified string [type|*](.modifier)*
export type TokenClassificationString = string; export type TokenClassificationString = string;
export const typeAndModifierIdPattern = '^\\w+[-_\\w+]*$';
export const fontStylePattern = '^(\\s*(-?italic|-?bold|-?underline))*\\s*$';
export interface TokenClassification { export interface TokenClassification {
type: number; type: number;
modifiers: number; modifiers: number;
...@@ -54,6 +55,34 @@ export namespace TokenStyle { ...@@ -54,6 +55,34 @@ export namespace TokenStyle {
export function fromData(data: { foreground?: Color, bold?: boolean, underline?: boolean, italic?: boolean }) { export function fromData(data: { foreground?: Color, bold?: boolean, underline?: boolean, italic?: boolean }) {
return new TokenStyle(data.foreground, data.bold, data.underline, data.italic); return new TokenStyle(data.foreground, data.bold, data.underline, data.italic);
} }
export function fromSettings(foreground: string | undefined, fontStyle: string | undefined): TokenStyle {
let foregroundColor = undefined;
if (foreground !== undefined) {
foregroundColor = Color.fromHex(foreground);
}
let bold, underline, italic;
if (fontStyle !== undefined) {
fontStyle = fontStyle.trim();
if (fontStyle.length === 0) {
bold = italic = underline = false;
} else {
const expression = /-?italic|-?bold|-?underline/g;
let match;
while ((match = expression.exec(fontStyle))) {
switch (match[0]) {
case 'bold': bold = true; break;
case '-bold': bold = false; break;
case 'italic': italic = true; break;
case '-italic': italic = false; break;
case 'underline': underline = true; break;
case '-underline': underline = false; break;
}
}
}
}
return new TokenStyle(foregroundColor, bold, underline, italic);
}
} }
export type ProbeScope = string[]; export type ProbeScope = string[];
...@@ -63,10 +92,10 @@ export interface TokenStyleFunction { ...@@ -63,10 +92,10 @@ export interface TokenStyleFunction {
} }
export interface TokenStyleDefaults { export interface TokenStyleDefaults {
scopesToProbe: ProbeScope[]; scopesToProbe?: ProbeScope[];
light: TokenStyleValue | null; light?: TokenStyleValue;
dark: TokenStyleValue | null; dark?: TokenStyleValue;
hc: TokenStyleValue | null; hc?: TokenStyleValue;
} }
export interface TokenStylingDefaultRule { export interface TokenStylingDefaultRule {
...@@ -120,6 +149,12 @@ export interface ITokenClassificationRegistry { ...@@ -120,6 +149,12 @@ export interface ITokenClassificationRegistry {
*/ */
registerTokenStyleDefault(selector: TokenClassification, defaults: TokenStyleDefaults): void; registerTokenStyleDefault(selector: TokenClassification, defaults: TokenStyleDefaults): void;
/**
* Deregister a TokenStyle default to the registry.
* @param selector The rule selector
*/
deregisterTokenStyleDefault(selector: TokenClassification): void;
/** /**
* Deregister a TokenType from the registry. * Deregister a TokenType from the registry.
*/ */
...@@ -186,7 +221,7 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry { ...@@ -186,7 +221,7 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
fontStyle: { fontStyle: {
type: 'string', type: 'string',
description: nls.localize('schema.token.fontStyle', 'Font style of the rule: \'italic\', \'bold\' or \'underline\', \'-italic\', \'-bold\' or \'-underline\'or a combination. The empty string unsets inherited settings.'), description: nls.localize('schema.token.fontStyle', 'Font style of the rule: \'italic\', \'bold\' or \'underline\', \'-italic\', \'-bold\' or \'-underline\'or a combination. The empty string unsets inherited settings.'),
pattern: '^(\\s*(-?italic|-?bold|-?underline))*\\s*$', pattern: fontStylePattern,
patternErrorMessage: nls.localize('schema.fontStyle.error', 'Font style must be \'italic\', \'bold\' or \'underline\' to set a style or \'-italic\', \'-bold\' or \'-underline\' to unset or a combination. The empty string unsets all styles.'), patternErrorMessage: nls.localize('schema.fontStyle.error', 'Font style must be \'italic\', \'bold\' or \'underline\' to set a style or \'-italic\', \'-bold\' or \'-underline\' to unset or a combination. The empty string unsets all styles.'),
defaultSnippets: [{ label: nls.localize('schema.token.fontStyle.none', 'None (clear inherited style)'), bodyText: '""' }, { body: 'italic' }, { body: 'bold' }, { body: 'underline' }, { body: '-italic' }, { body: '-bold' }, { body: '-underline' }, { body: 'italic bold' }, { body: 'italic underline' }, { body: 'bold underline' }, { body: 'italic bold underline' }] defaultSnippets: [{ label: nls.localize('schema.token.fontStyle.none', 'None (clear inherited style)'), bodyText: '""' }, { body: 'italic' }, { body: 'bold' }, { body: 'underline' }, { body: '-italic' }, { body: '-bold' }, { body: '-underline' }, { body: 'italic bold' }, { body: 'italic underline' }, { body: 'bold underline' }, { body: 'italic bold underline' }]
} }
...@@ -205,6 +240,10 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry { ...@@ -205,6 +240,10 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
} }
public registerTokenType(id: string, description: string, deprecationMessage?: string): void { public registerTokenType(id: string, description: string, deprecationMessage?: string): void {
if (!id.match(typeAndModifierIdPattern)) {
throw new Error('Invalid token type id.');
}
const num = this.currentTypeNumber++; const num = this.currentTypeNumber++;
let tokenStyleContribution: TokenTypeOrModifierContribution = { num, id, description, deprecationMessage }; let tokenStyleContribution: TokenTypeOrModifierContribution = { num, id, description, deprecationMessage };
this.tokenTypeById[id] = tokenStyleContribution; this.tokenTypeById[id] = tokenStyleContribution;
...@@ -213,6 +252,10 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry { ...@@ -213,6 +252,10 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
} }
public registerTokenModifier(id: string, description: string, deprecationMessage?: string): void { public registerTokenModifier(id: string, description: string, deprecationMessage?: string): void {
if (!id.match(typeAndModifierIdPattern)) {
throw new Error('Invalid token modifier id.');
}
const num = this.currentModifierBit; const num = this.currentModifierBit;
this.currentModifierBit = this.currentModifierBit * 2; this.currentModifierBit = this.currentModifierBit * 2;
let tokenStyleContribution: TokenTypeOrModifierContribution = { num, id, description, deprecationMessage }; let tokenStyleContribution: TokenTypeOrModifierContribution = { num, id, description, deprecationMessage };
...@@ -244,6 +287,10 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry { ...@@ -244,6 +287,10 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
this.tokenStylingDefaultRules.push({ classification, matchScore: getTokenStylingScore(classification), defaults }); this.tokenStylingDefaultRules.push({ classification, matchScore: getTokenStylingScore(classification), defaults });
} }
public deregisterTokenStyleDefault(classification: TokenClassification): void {
this.tokenStylingDefaultRules = this.tokenStylingDefaultRules.filter(r => !(r.classification.type === classification.type && r.classification.modifiers === classification.modifiers));
}
public deregisterTokenType(id: string): void { public deregisterTokenType(id: string): void {
delete this.tokenTypeById[id]; delete this.tokenTypeById[id];
delete this.tokenStylingSchema.properties[id]; delete this.tokenStylingSchema.properties[id];
...@@ -270,6 +317,7 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry { ...@@ -270,6 +317,7 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
return this.tokenStylingDefaultRules; return this.tokenStylingDefaultRules;
} }
public toString() { public toString() {
let sorter = (a: string, b: string) => { let sorter = (a: string, b: string) => {
let cat1 = a.indexOf('.') === -1 ? 0 : 1; let cat1 = a.indexOf('.') === -1 ? 0 : 1;
...@@ -301,64 +349,62 @@ export function matchTokenStylingRule(themeSelector: TokenStylingRule | TokenSty ...@@ -301,64 +349,62 @@ export function matchTokenStylingRule(themeSelector: TokenStylingRule | TokenSty
const tokenClassificationRegistry = new TokenClassificationRegistry(); const tokenClassificationRegistry = new TokenClassificationRegistry();
platform.Registry.add(Extensions.TokenClassificationContribution, tokenClassificationRegistry); platform.Registry.add(Extensions.TokenClassificationContribution, tokenClassificationRegistry);
export function registerTokenType(id: string, description: string, scopesToProbe: ProbeScope[] = [], extendsTC: string | null = null, deprecationMessage?: string): string { registerDefaultClassifications();
tokenClassificationRegistry.registerTokenType(id, description, deprecationMessage);
if (scopesToProbe || extendsTC) {
const classification = tokenClassificationRegistry.getTokenClassification(id, []);
tokenClassificationRegistry.registerTokenStyleDefault(classification!, { scopesToProbe, light: extendsTC, dark: extendsTC, hc: extendsTC });
}
return id;
}
export function registerTokenModifier(id: string, description: string, deprecationMessage?: string): string { function registerDefaultClassifications(): void {
tokenClassificationRegistry.registerTokenModifier(id, description, deprecationMessage); function registerTokenType(id: string, description: string, scopesToProbe: ProbeScope[] = [], extendsTC?: string, deprecationMessage?: string): string {
return id; tokenClassificationRegistry.registerTokenType(id, description, deprecationMessage);
}
export function getTokenClassificationRegistry(): ITokenClassificationRegistry { if (scopesToProbe || extendsTC) {
return tokenClassificationRegistry; const classification = tokenClassificationRegistry.getTokenClassification(id, []);
} tokenClassificationRegistry.registerTokenStyleDefault(classification!, { scopesToProbe, light: extendsTC, dark: extendsTC, hc: extendsTC });
}
return id;
}
// default token types // default token types
registerTokenType('comment', nls.localize('comment', "Style for comments."), [['comment']]); registerTokenType('comment', nls.localize('comment', "Style for comments."), [['comment']]);
registerTokenType('string', nls.localize('string', "Style for strings."), [['string']]); registerTokenType('string', nls.localize('string', "Style for strings."), [['string']]);
registerTokenType('keyword', nls.localize('keyword', "Style for keywords."), [['keyword.control']]); registerTokenType('keyword', nls.localize('keyword', "Style for keywords."), [['keyword.control']]);
registerTokenType('number', nls.localize('number', "Style for numbers."), [['constant.numeric']]); registerTokenType('number', nls.localize('number', "Style for numbers."), [['constant.numeric']]);
registerTokenType('regexp', nls.localize('regexp', "Style for expressions."), [['constant.regexp']]); registerTokenType('regexp', nls.localize('regexp', "Style for expressions."), [['constant.regexp']]);
registerTokenType('operator', nls.localize('operator', "Style for operators."), [['keyword.operator']]); registerTokenType('operator', nls.localize('operator', "Style for operators."), [['keyword.operator']]);
registerTokenType('namespace', nls.localize('namespace', "Style for namespaces."), [['entity.name.namespace']]); registerTokenType('namespace', nls.localize('namespace', "Style for namespaces."), [['entity.name.namespace']]);
registerTokenType('type', nls.localize('type', "Style for types."), [['entity.name.type'], ['entity.name.class'], ['support.type'], ['support.class']]); registerTokenType('type', nls.localize('type', "Style for types."), [['entity.name.type'], ['entity.name.class'], ['support.type'], ['support.class']]);
registerTokenType('struct', nls.localize('struct', "Style for structs."), [['storage.type.struct']], 'type'); registerTokenType('struct', nls.localize('struct', "Style for structs."), [['storage.type.struct']], 'type');
registerTokenType('class', nls.localize('class', "Style for classes."), [['entity.name.class']], 'type'); registerTokenType('class', nls.localize('class', "Style for classes."), [['entity.name.class']], 'type');
registerTokenType('interface', nls.localize('interface', "Style for interfaces."), undefined, 'type'); registerTokenType('interface', nls.localize('interface', "Style for interfaces."), undefined, 'type');
registerTokenType('enum', nls.localize('enum', "Style for enums."), undefined, 'type'); registerTokenType('enum', nls.localize('enum', "Style for enums."), undefined, 'type');
registerTokenType('parameterType', nls.localize('parameterType', "Style for parameter types."), undefined, 'type'); registerTokenType('parameterType', nls.localize('parameterType', "Style for parameter types."), undefined, 'type');
registerTokenType('function', nls.localize('function', "Style for functions"), [['entity.name.function'], ['support.function']]); registerTokenType('function', nls.localize('function', "Style for functions"), [['entity.name.function'], ['support.function']]);
registerTokenType('macro', nls.localize('macro', "Style for macros."), undefined, 'function'); registerTokenType('macro', nls.localize('macro', "Style for macros."), undefined, 'function');
registerTokenType('variable', nls.localize('variable', "Style for variables."), [['variable'], ['entity.name.variable']]); registerTokenType('variable', nls.localize('variable', "Style for variables."), [['variable'], ['entity.name.variable']]);
registerTokenType('constant', nls.localize('constant', "Style for constants."), undefined, 'variable'); registerTokenType('constant', nls.localize('constant', "Style for constants."), undefined, 'variable');
registerTokenType('parameter', nls.localize('parameter', "Style for parameters."), undefined, 'variable'); registerTokenType('parameter', nls.localize('parameter', "Style for parameters."), undefined, 'variable');
registerTokenType('property', nls.localize('propertie', "Style for properties."), undefined, 'variable'); registerTokenType('property', nls.localize('propertie', "Style for properties."), undefined, 'variable');
registerTokenType('label', nls.localize('labels', "Style for labels. "), undefined); registerTokenType('label', nls.localize('labels', "Style for labels. "), undefined);
// default token modifiers // default token modifiers
registerTokenModifier('declaration', nls.localize('declaration', "Style for all symbol declarations."), undefined); tokenClassificationRegistry.registerTokenModifier('declaration', nls.localize('declaration', "Style for all symbol declarations."), undefined);
registerTokenModifier('documentation', nls.localize('documentation', "Style to use for references in documentation."), undefined); tokenClassificationRegistry.registerTokenModifier('documentation', nls.localize('documentation', "Style to use for references in documentation."), undefined);
registerTokenModifier('member', nls.localize('member', "Style to use for member functions, variables (fields) and types."), undefined); tokenClassificationRegistry.registerTokenModifier('member', nls.localize('member', "Style to use for member functions, variables (fields) and types."), undefined);
registerTokenModifier('static', nls.localize('static', "Style to use for symbols that are static."), undefined); tokenClassificationRegistry.registerTokenModifier('static', nls.localize('static', "Style to use for symbols that are static."), undefined);
registerTokenModifier('abstract', nls.localize('abstract', "Style to use for symbols that are abstract."), undefined); tokenClassificationRegistry.registerTokenModifier('abstract', nls.localize('abstract', "Style to use for symbols that are abstract."), undefined);
registerTokenModifier('deprecated', nls.localize('deprecated', "Style to use for symbols that are deprecated."), undefined); tokenClassificationRegistry.registerTokenModifier('deprecated', nls.localize('deprecated', "Style to use for symbols that are deprecated."), undefined);
registerTokenModifier('modification', nls.localize('modification', "Style to use for write accesses."), undefined); tokenClassificationRegistry.registerTokenModifier('modification', nls.localize('modification', "Style to use for write accesses."), undefined);
registerTokenModifier('async', nls.localize('async', "Style to use for symbols that are async."), undefined); tokenClassificationRegistry.registerTokenModifier('async', nls.localize('async', "Style to use for symbols that are async."), undefined);
}
export function getTokenClassificationRegistry(): ITokenClassificationRegistry {
return tokenClassificationRegistry;
}
function bitCount(u: number) { function bitCount(u: number) {
// https://blogs.msdn.microsoft.com/jeuge/2005/06/08/bit-fiddling-3/ // https://blogs.msdn.microsoft.com/jeuge/2005/06/08/bit-fiddling-3/
......
...@@ -11,6 +11,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; ...@@ -11,6 +11,7 @@ import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
// --- other interested parties // --- other interested parties
import { JSONValidationExtensionPoint } from 'vs/workbench/api/common/jsonValidationExtensionPoint'; import { JSONValidationExtensionPoint } from 'vs/workbench/api/common/jsonValidationExtensionPoint';
import { ColorExtensionPoint } from 'vs/workbench/services/themes/common/colorExtensionPoint'; import { ColorExtensionPoint } from 'vs/workbench/services/themes/common/colorExtensionPoint';
import { TokenClassificationExtensionPoints } from 'vs/workbench/services/themes/common/tokenClassificationExtensionPoint';
import { LanguageConfigurationFileHandler } from 'vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint'; import { LanguageConfigurationFileHandler } from 'vs/workbench/contrib/codeEditor/browser/languageConfigurationExtensionPoint';
// --- mainThread participants // --- mainThread participants
...@@ -67,6 +68,7 @@ export class ExtensionPoints implements IWorkbenchContribution { ...@@ -67,6 +68,7 @@ export class ExtensionPoints implements IWorkbenchContribution {
// Classes that handle extension points... // Classes that handle extension points...
this.instantiationService.createInstance(JSONValidationExtensionPoint); this.instantiationService.createInstance(JSONValidationExtensionPoint);
this.instantiationService.createInstance(ColorExtensionPoint); this.instantiationService.createInstance(ColorExtensionPoint);
this.instantiationService.createInstance(TokenClassificationExtensionPoints);
this.instantiationService.createInstance(LanguageConfigurationFileHandler); this.instantiationService.createInstance(LanguageConfigurationFileHandler);
} }
} }
......
...@@ -27,7 +27,7 @@ import { IFileService, FileChangeType } from 'vs/platform/files/common/files'; ...@@ -27,7 +27,7 @@ import { IFileService, FileChangeType } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import * as resources from 'vs/base/common/resources'; import * as resources from 'vs/base/common/resources';
import { IJSONSchema } from 'vs/base/common/jsonSchema'; import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { textmateColorsSchemaId, registerColorThemeSchemas, textmateColorSettingsSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema'; import { textmateColorsSchemaId, registerColorThemeSchemas, textmateColorGroupSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema';
import { workbenchColorsSchemaId } from 'vs/platform/theme/common/colorRegistry'; import { workbenchColorsSchemaId } from 'vs/platform/theme/common/colorRegistry';
import { tokenStylingSchemaId } from 'vs/platform/theme/common/tokenClassificationRegistry'; import { tokenStylingSchemaId } from 'vs/platform/theme/common/tokenClassificationRegistry';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
...@@ -684,16 +684,7 @@ configurationRegistry.registerConfiguration(themeSettingsConfiguration); ...@@ -684,16 +684,7 @@ configurationRegistry.registerConfiguration(themeSettingsConfiguration);
function tokenGroupSettings(description: string): IJSONSchema { function tokenGroupSettings(description: string): IJSONSchema {
return { return {
description, description,
default: '#FF0000', $ref: textmateColorGroupSchemaId
anyOf: [
{
type: 'string',
format: 'color-hex'
},
{
$ref: textmateColorSettingsSchemaId
}
]
}; };
} }
......
...@@ -155,7 +155,10 @@ export class ColorThemeData implements IColorTheme { ...@@ -155,7 +155,10 @@ export class ColorThemeData implements IColorTheme {
for (const rule of tokenClassificationRegistry.getTokenStylingDefaultRules()) { for (const rule of tokenClassificationRegistry.getTokenStylingDefaultRules()) {
const matchScore = matchTokenStylingRule(rule, classification); const matchScore = matchTokenStylingRule(rule, classification);
if (matchScore >= 0) { if (matchScore >= 0) {
let style = this.resolveScopes(rule.defaults.scopesToProbe); let style: TokenStyle | undefined;
if (rule.defaults.scopesToProbe) {
style = this.resolveScopes(rule.defaults.scopesToProbe);
}
if (!style && useDefault !== false) { if (!style && useDefault !== false) {
style = this.resolveTokenStyleValue(rule.defaults[this.type]); style = this.resolveTokenStyleValue(rule.defaults[this.type]);
} }
...@@ -185,8 +188,8 @@ export class ColorThemeData implements IColorTheme { ...@@ -185,8 +188,8 @@ export class ColorThemeData implements IColorTheme {
/** /**
* @param tokenStyleValue Resolve a tokenStyleValue in the context of a theme * @param tokenStyleValue Resolve a tokenStyleValue in the context of a theme
*/ */
private resolveTokenStyleValue(tokenStyleValue: TokenStyleValue | null): TokenStyle | undefined { private resolveTokenStyleValue(tokenStyleValue: TokenStyleValue | undefined): TokenStyle | undefined {
if (tokenStyleValue === null) { if (tokenStyleValue === undefined) {
return undefined; return undefined;
} else if (typeof tokenStyleValue === 'string') { } else if (typeof tokenStyleValue === 'string') {
const [type, ...modifiers] = tokenStyleValue.split('.'); const [type, ...modifiers] = tokenStyleValue.split('.');
...@@ -289,7 +292,7 @@ export class ColorThemeData implements IColorTheme { ...@@ -289,7 +292,7 @@ export class ColorThemeData implements IColorTheme {
findTokenStyleForScopeInScopes(this.themeTokenScopeMatchers, this.themeTokenColors); findTokenStyleForScopeInScopes(this.themeTokenScopeMatchers, this.themeTokenColors);
findTokenStyleForScopeInScopes(this.customTokenScopeMatchers, this.customTokenColors); findTokenStyleForScopeInScopes(this.customTokenScopeMatchers, this.customTokenColors);
if (foreground !== undefined || fontStyle !== undefined) { if (foreground !== undefined || fontStyle !== undefined) {
return getTokenStyle(foreground, fontStyle); return TokenStyle.fromSettings(foreground, fontStyle);
} }
} }
return undefined; return undefined;
...@@ -682,34 +685,7 @@ function getScopeMatcher(rule: ITextMateThemingRule): Matcher<ProbeScope> { ...@@ -682,34 +685,7 @@ function getScopeMatcher(rule: ITextMateThemingRule): Matcher<ProbeScope> {
}; };
} }
function getTokenStyle(foreground: string | undefined, fontStyle: string | undefined): TokenStyle {
let foregroundColor = undefined;
if (foreground !== undefined) {
foregroundColor = Color.fromHex(foreground);
}
let bold, underline, italic;
if (fontStyle !== undefined) {
fontStyle = fontStyle.trim();
if (fontStyle.length === 0) {
bold = italic = underline = false;
} else {
const expression = /-?italic|-?bold|-?underline/g;
let match;
while ((match = expression.exec(fontStyle))) {
switch (match[0]) {
case 'bold': bold = true; break;
case '-bold': bold = false; break;
case 'italic': italic = true; break;
case '-italic': italic = false; break;
case 'underline': underline = true; break;
case '-underline': underline = false; break;
}
}
}
}
return new TokenStyle(foregroundColor, bold, underline, italic);
}
function readCustomTokenStyleRules(tokenStylingRuleSection: IExperimentalTokenStyleCustomizations, result: TokenStylingRule[] = []) { function readCustomTokenStyleRules(tokenStylingRuleSection: IExperimentalTokenStyleCustomizations, result: TokenStylingRule[] = []) {
for (let key in tokenStylingRuleSection) { for (let key in tokenStylingRuleSection) {
...@@ -720,9 +696,9 @@ function readCustomTokenStyleRules(tokenStylingRuleSection: IExperimentalTokenSt ...@@ -720,9 +696,9 @@ function readCustomTokenStyleRules(tokenStylingRuleSection: IExperimentalTokenSt
const settings = tokenStylingRuleSection[key]; const settings = tokenStylingRuleSection[key];
let style: TokenStyle | undefined; let style: TokenStyle | undefined;
if (typeof settings === 'string') { if (typeof settings === 'string') {
style = getTokenStyle(settings, undefined); style = TokenStyle.fromSettings(settings, undefined);
} else if (isTokenColorizationSetting(settings)) { } else if (isTokenColorizationSetting(settings)) {
style = getTokenStyle(settings.foreground, settings.fontStyle); style = TokenStyle.fromSettings(settings.foreground, settings.fontStyle);
} }
if (style) { if (style) {
result.push(tokenClassificationRegistry.getTokenStylingRule(classification, style)); result.push(tokenClassificationRegistry.getTokenStylingRule(classification, style));
......
...@@ -115,10 +115,23 @@ let textMateScopes = [ ...@@ -115,10 +115,23 @@ let textMateScopes = [
export const textmateColorsSchemaId = 'vscode://schemas/textmate-colors'; export const textmateColorsSchemaId = 'vscode://schemas/textmate-colors';
export const textmateColorSettingsSchemaId = `${textmateColorsSchemaId}#definitions/settings`; export const textmateColorSettingsSchemaId = `${textmateColorsSchemaId}#definitions/settings`;
export const textmateColorGroupSchemaId = `${textmateColorsSchemaId}#definitions/colorGroup`;
const textmateColorSchema: IJSONSchema = { const textmateColorSchema: IJSONSchema = {
type: 'array', type: 'array',
definitions: { definitions: {
colorGroup: {
default: '#FF0000',
anyOf: [
{
type: 'string',
format: 'color-hex'
},
{
$ref: '#definitions/settings'
}
]
},
settings: { settings: {
type: 'object', type: 'object',
description: nls.localize('schema.token.settings', 'Colors and styles for the token.'), description: nls.localize('schema.token.settings', 'Colors and styles for the token.'),
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { getTokenClassificationRegistry, ITokenClassificationRegistry, typeAndModifierIdPattern, TokenStyleDefaults, TokenStyle, fontStylePattern } from 'vs/platform/theme/common/tokenClassificationRegistry';
import { textmateColorSettingsSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema';
interface ITokenTypeExtensionPoint {
id: string;
description: string;
}
interface ITokenModifierExtensionPoint {
id: string;
description: string;
}
interface ITokenStyleDefaultExtensionPoint {
selector: string;
scopes?: string[];
light?: {
foreground?: string;
fontStyle?: string;
};
dark?: {
foreground?: string;
fontStyle?: string;
};
highContrast?: {
foreground?: string;
fontStyle?: string;
};
}
const selectorPattern = '^([-_\\w]+|\\*)(\\.[-_\\w+]+)*$';
const colorPattern = '^#([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$';
const tokenClassificationRegistry: ITokenClassificationRegistry = getTokenClassificationRegistry();
const tokenTypeExtPoint = ExtensionsRegistry.registerExtensionPoint<ITokenTypeExtensionPoint[]>({
extensionPoint: 'tokenTypes',
jsonSchema: {
description: nls.localize('contributes.tokenTypes', 'Contributes semantic token types.'),
type: 'array',
items: {
type: 'object',
properties: {
id: {
type: 'string',
description: nls.localize('contributes.tokenTypes.id', 'The identifier of the token type'),
pattern: typeAndModifierIdPattern,
patternErrorMessage: nls.localize('contributes.tokenTypes.id.format', 'Identifiers should be in the form letterOrDigit[_-letterOrDigit]*'),
},
description: {
type: 'string',
description: nls.localize('contributes.color.description', 'The description of the token type'),
}
}
}
}
});
const tokenModifierExtPoint = ExtensionsRegistry.registerExtensionPoint<ITokenModifierExtensionPoint[]>({
extensionPoint: 'tokenModifiers',
jsonSchema: {
description: nls.localize('contributes.tokenModifiers', 'Contributes semantic token modifiers.'),
type: 'array',
items: {
type: 'object',
properties: {
id: {
type: 'string',
description: nls.localize('contributes.tokenModifiers.id', 'The identifier of the token modifier'),
pattern: typeAndModifierIdPattern,
patternErrorMessage: nls.localize('contributes.tokenModifiers.id.format', 'Identifiers should be in the form letterOrDigit[_-letterOrDigit]*')
},
description: {
description: nls.localize('contributes.tokenModifiers.description', 'The description of the token modifier')
}
}
}
}
});
const tokenStyleDefaultsExtPoint = ExtensionsRegistry.registerExtensionPoint<ITokenStyleDefaultExtensionPoint[]>({
extensionPoint: 'tokenStyleDefaults',
jsonSchema: {
description: nls.localize('contributes.tokenStyleDefaults', 'Contributes semantic token style default.'),
type: 'array',
items: {
type: 'object',
properties: {
selector: {
type: 'string',
description: nls.localize('contributes.tokenStyleDefaults.selector', 'The selector matching token types and modifiers.'),
pattern: selectorPattern,
patternErrorMessage: nls.localize('contributes.tokenStyleDefaults.selector.format', 'Selectors should be in the form (type|*)(.modifier)*'),
},
scopes: {
type: 'array',
description: nls.localize('contributes.scopes.light', 'A list of textmate scopes that are matched against the current color theme to find a default style'),
items: {
type: 'string'
}
},
light: {
description: nls.localize('contributes.tokenStyleDefaults.light', 'The default style used for light themes'),
$ref: textmateColorSettingsSchemaId
},
dark: {
description: nls.localize('contributes.tokenStyleDefaults.dark', 'The default style used for dark themes'),
$ref: textmateColorSettingsSchemaId
},
highContrast: {
description: nls.localize('contributes.tokenStyleDefaults.hc', 'The default style used for high contrast themes'),
$ref: textmateColorSettingsSchemaId
}
}
}
}
});
export class TokenClassificationExtensionPoints {
constructor() {
function validateTypeOrModifier(contribution: ITokenTypeExtensionPoint | ITokenModifierExtensionPoint, extensionPoint: string, collector: ExtensionMessageCollector): boolean {
if (typeof contribution.id !== 'string' || contribution.id.length === 0) {
collector.error(nls.localize('invalid.id', "'configuration.{0}.id' must be defined and can not be empty", extensionPoint));
return false;
}
if (!contribution.id.match(typeAndModifierIdPattern)) {
collector.error(nls.localize('invalid.id.format', "'configuration.{0}.id' must follow the pattern letterOrDigit[-_letterOrDigit]*", extensionPoint));
return false;
}
if (typeof contribution.description !== 'string' || contribution.id.length === 0) {
collector.error(nls.localize('invalid.description', "'configuration.{0}.description' must be defined and can not be empty", extensionPoint));
return false;
}
return true;
}
function validateStyle(style: { foreground?: string; fontStyle?: string; } | undefined, extensionPoint: string, collector: ExtensionMessageCollector): TokenStyle | undefined {
if (!style) {
return undefined;
}
if (style.foreground) {
if (typeof style.foreground !== 'string' || !style.foreground.match(colorPattern)) {
collector.error(nls.localize('invalid.color', "'configuration.{0}.foreground' must follow the pattern #RRGGBB[AA]", extensionPoint));
return undefined;
}
}
if (style.fontStyle) {
if (typeof style.fontStyle !== 'string' || !style.fontStyle.match(fontStylePattern)) {
collector.error(nls.localize('invalid.fontStyle', "'configuration.{0}.fontStyle' must be a one or a compination of \'italic\', \'bold\' or \'underline\' or the empty string", extensionPoint));
return undefined;
}
}
return TokenStyle.fromSettings(style.foreground, style.fontStyle);
}
tokenTypeExtPoint.setHandler((extensions, delta) => {
for (const extension of delta.added) {
const extensionValue = <ITokenTypeExtensionPoint[]>extension.value;
const collector = extension.collector;
if (!extensionValue || !Array.isArray(extensionValue)) {
collector.error(nls.localize('invalid.tokenTypeConfiguration', "'configuration.tokenType' must be a array"));
return;
}
for (const contribution of extensionValue) {
if (validateTypeOrModifier(contribution, 'tokenType', collector)) {
tokenClassificationRegistry.registerTokenType(contribution.id, contribution.description);
}
}
}
for (const extension of delta.removed) {
const extensionValue = <ITokenTypeExtensionPoint[]>extension.value;
for (const contribution of extensionValue) {
tokenClassificationRegistry.deregisterTokenType(contribution.id);
}
}
});
tokenModifierExtPoint.setHandler((extensions, delta) => {
for (const extension of delta.added) {
const extensionValue = <ITokenModifierExtensionPoint[]>extension.value;
const collector = extension.collector;
if (!extensionValue || !Array.isArray(extensionValue)) {
collector.error(nls.localize('invalid.tokenModifierConfiguration', "'configuration.tokenModifier' must be a array"));
return;
}
for (const contribution of extensionValue) {
if (validateTypeOrModifier(contribution, 'tokenModifier', collector)) {
tokenClassificationRegistry.registerTokenModifier(contribution.id, contribution.description);
}
}
}
for (const extension of delta.removed) {
const extensionValue = <ITokenModifierExtensionPoint[]>extension.value;
for (const contribution of extensionValue) {
tokenClassificationRegistry.deregisterTokenModifier(contribution.id);
}
}
});
tokenStyleDefaultsExtPoint.setHandler((extensions, delta) => {
for (const extension of delta.added) {
const extensionValue = <ITokenStyleDefaultExtensionPoint[]>extension.value;
const collector = extension.collector;
if (!extensionValue || !Array.isArray(extensionValue)) {
collector.error(nls.localize('invalid.tokenStyleDefaultConfiguration', "'configuration.tokenStyleDefaults' must be a array"));
return;
}
for (const contribution of extensionValue) {
if (typeof contribution.selector !== 'string' || contribution.selector.length === 0) {
collector.error(nls.localize('invalid.selector', "'configuration.tokenStyleDefaults.selector' must be defined and can not be empty"));
continue;
}
if (!contribution.selector.match(selectorPattern)) {
collector.error(nls.localize('invalid.selector.format', "'configuration.tokenStyleDefaults.selector' must be in the form (type|*)(.modifier)*"));
continue;
}
const tokenStyleDefault: TokenStyleDefaults = {};
if (contribution.scopes) {
if ((!Array.isArray(contribution.scopes) || contribution.scopes.some(s => typeof s !== 'string'))) {
collector.error(nls.localize('invalid.scopes', "If defined, 'configuration.tokenStyleDefaults.scopes' must must be an array or strings"));
continue;
}
tokenStyleDefault.scopesToProbe = [contribution.scopes];
}
tokenStyleDefault.light = validateStyle(contribution.light, 'tokenStyleDefaults.light', collector);
tokenStyleDefault.dark = validateStyle(contribution.dark, 'tokenStyleDefaults.dark', collector);
tokenStyleDefault.hc = validateStyle(contribution.highContrast, 'tokenStyleDefaults.highContrast', collector);
const [type, ...modifiers] = contribution.selector.split('.');
const classification = tokenClassificationRegistry.getTokenClassification(type, modifiers);
if (classification) {
tokenClassificationRegistry.registerTokenStyleDefault(classification, tokenStyleDefault);
}
}
}
for (const extension of delta.removed) {
const extensionValue = <ITokenStyleDefaultExtensionPoint[]>extension.value;
for (const contribution of extensionValue) {
const [type, ...modifiers] = contribution.selector.split('.');
const classification = tokenClassificationRegistry.getTokenClassification(type, modifiers);
if (classification) {
tokenClassificationRegistry.deregisterTokenStyleDefault(classification);
}
}
}
});
}
}
...@@ -21,6 +21,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService ...@@ -21,6 +21,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { NullLogService } from 'vs/platform/log/common/log';
suite('MainThreadDocumentsAndEditors', () => { suite('MainThreadDocumentsAndEditors', () => {
...@@ -43,7 +44,7 @@ suite('MainThreadDocumentsAndEditors', () => { ...@@ -43,7 +44,7 @@ suite('MainThreadDocumentsAndEditors', () => {
deltas.length = 0; deltas.length = 0;
const configService = new TestConfigurationService(); const configService = new TestConfigurationService();
configService.setUserConfiguration('editor', { 'detectIndentation': false }); configService.setUserConfiguration('editor', { 'detectIndentation': false });
modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService()); modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService());
codeEditorService = new TestCodeEditorService(); codeEditorService = new TestCodeEditorService();
textFileService = new class extends mock<ITextFileService>() { textFileService = new class extends mock<ITextFileService>() {
isDirty() { return false; } isDirty() { return false; }
......
...@@ -43,7 +43,7 @@ suite('MainThreadEditors', () => { ...@@ -43,7 +43,7 @@ suite('MainThreadEditors', () => {
setup(() => { setup(() => {
const configService = new TestConfigurationService(); const configService = new TestConfigurationService();
modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService()); modelService = new ModelServiceImpl(configService, new TestTextResourcePropertiesService(configService), new TestThemeService(), new NullLogService());
const codeEditorService = new TestCodeEditorService(); const codeEditorService = new TestCodeEditorService();
movedResources.clear(); movedResources.clear();
......
...@@ -31,6 +31,7 @@ import { IUntitledTextEditorService, UntitledTextEditorService } from 'vs/workbe ...@@ -31,6 +31,7 @@ import { IUntitledTextEditorService, UntitledTextEditorService } from 'vs/workbe
import { TestContextService, TestEditorGroupsService, TestEditorService, TestEnvironmentService, TestTextResourcePropertiesService } from 'vs/workbench/test/workbenchTestServices'; import { TestContextService, TestEditorGroupsService, TestEditorService, TestEnvironmentService, TestTextResourcePropertiesService } from 'vs/workbench/test/workbenchTestServices';
import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings'; import { ClassifiedEvent, StrictPropertyCheck, GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { NullLogService } from 'vs/platform/log/common/log';
namespace Timer { namespace Timer {
export interface ITimerEvent { export interface ITimerEvent {
...@@ -74,7 +75,7 @@ suite.skip('QuickOpen performance (integration)', () => { ...@@ -74,7 +75,7 @@ suite.skip('QuickOpen performance (integration)', () => {
[ITelemetryService, telemetryService], [ITelemetryService, telemetryService],
[IConfigurationService, configurationService], [IConfigurationService, configurationService],
[ITextResourcePropertiesService, textResourcePropertiesService], [ITextResourcePropertiesService, textResourcePropertiesService],
[IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService())], [IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService(), new NullLogService())],
[IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))], [IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))],
[IEditorService, new TestEditorService()], [IEditorService, new TestEditorService()],
[IEditorGroupsService, new TestEditorGroupsService()], [IEditorGroupsService, new TestEditorGroupsService()],
......
...@@ -60,18 +60,19 @@ suite.skip('TextSearch performance (integration)', () => { ...@@ -60,18 +60,19 @@ suite.skip('TextSearch performance (integration)', () => {
const telemetryService = new TestTelemetryService(); const telemetryService = new TestTelemetryService();
const configurationService = new TestConfigurationService(); const configurationService = new TestConfigurationService();
const textResourcePropertiesService = new TestTextResourcePropertiesService(configurationService); const textResourcePropertiesService = new TestTextResourcePropertiesService(configurationService);
const logService = new NullLogService();
const instantiationService = new InstantiationService(new ServiceCollection( const instantiationService = new InstantiationService(new ServiceCollection(
[ITelemetryService, telemetryService], [ITelemetryService, telemetryService],
[IConfigurationService, configurationService], [IConfigurationService, configurationService],
[ITextResourcePropertiesService, textResourcePropertiesService], [ITextResourcePropertiesService, textResourcePropertiesService],
[IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService())], [IModelService, new ModelServiceImpl(configurationService, textResourcePropertiesService, new TestThemeService(), logService)],
[IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))], [IWorkspaceContextService, new TestContextService(testWorkspace(URI.file(testWorkspacePath)))],
[IEditorService, new TestEditorService()], [IEditorService, new TestEditorService()],
[IEditorGroupsService, new TestEditorGroupsService()], [IEditorGroupsService, new TestEditorGroupsService()],
[IEnvironmentService, TestEnvironmentService], [IEnvironmentService, TestEnvironmentService],
[IUntitledTextEditorService, createSyncDescriptor(UntitledTextEditorService)], [IUntitledTextEditorService, createSyncDescriptor(UntitledTextEditorService)],
[ISearchService, createSyncDescriptor(LocalSearchService)], [ISearchService, createSyncDescriptor(LocalSearchService)],
[ILogService, new NullLogService()] [ILogService, logService]
)); ));
const queryOptions: ITextQueryBuilderOptions = { const queryOptions: ITextQueryBuilderOptions = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册