mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 1ec43773e37997841c5af42b33ddb180e9735bf2
This commit is contained in:
@@ -92,6 +92,7 @@ export class MenuId {
|
||||
static readonly MenubarSwitchGroupMenu = new MenuId('MenubarSwitchGroupMenu');
|
||||
static readonly MenubarTerminalMenu = new MenuId('MenubarTerminalMenu');
|
||||
static readonly MenubarViewMenu = new MenuId('MenubarViewMenu');
|
||||
static readonly MenubarWebNavigationMenu = new MenuId('MenubarWebNavigationMenu');
|
||||
static readonly OpenEditorsContext = new MenuId('OpenEditorsContext');
|
||||
static readonly ProblemsPanelContext = new MenuId('ProblemsPanelContext');
|
||||
static readonly SCMChangeContext = new MenuId('SCMChangeContext');
|
||||
@@ -127,7 +128,6 @@ export class MenuId {
|
||||
static readonly TimelineTitle = new MenuId('TimelineTitle');
|
||||
static readonly TimelineTitleContext = new MenuId('TimelineTitleContext');
|
||||
static readonly AccountsContext = new MenuId('AccountsContext');
|
||||
static readonly WebMenuActions = new MenuId('MenubarWebMenu');
|
||||
|
||||
readonly id: number;
|
||||
readonly _debugName: string;
|
||||
|
||||
@@ -265,8 +265,12 @@ export function addToValueTree(settingsTreeRoot: any, key: string, value: any, c
|
||||
curr = obj;
|
||||
}
|
||||
|
||||
if (typeof curr === 'object') {
|
||||
curr[last] = value; // workaround https://github.com/Microsoft/vscode/issues/13606
|
||||
if (typeof curr === 'object' && curr !== null) {
|
||||
try {
|
||||
curr[last] = value; // workaround https://github.com/Microsoft/vscode/issues/13606
|
||||
} catch (e) {
|
||||
conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);
|
||||
}
|
||||
} else {
|
||||
conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
|
||||
fileService: IFileService
|
||||
) {
|
||||
super();
|
||||
this._register(fileService.watch(settingsResource));
|
||||
this.userConfiguration = this._register(new UserSettings(this.settingsResource, undefined, fileService));
|
||||
this.configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel());
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
suite('ConfigurationService - Node', () => {
|
||||
|
||||
@@ -110,10 +111,10 @@ suite('ConfigurationService - Node', () => {
|
||||
|
||||
test('trigger configuration change event when file does not exist', async () => {
|
||||
const res = await testFile('config', 'config.json');
|
||||
|
||||
const service = new ConfigurationService(URI.file(res.testFile), fileService);
|
||||
const settingsFile = URI.file(res.testFile);
|
||||
const service = new ConfigurationService(settingsFile, fileService);
|
||||
await service.initialize();
|
||||
return new Promise((c, e) => {
|
||||
return new Promise(async (c, e) => {
|
||||
const disposable = Event.filter(service.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => {
|
||||
disposable.dispose();
|
||||
assert.equal(service.getValue('foo'), 'bar');
|
||||
@@ -121,7 +122,7 @@ suite('ConfigurationService - Node', () => {
|
||||
await res.cleanUp();
|
||||
c();
|
||||
});
|
||||
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
|
||||
await fileService.writeFile(settingsFile, VSBuffer.fromString('{ "foo": "bar" }'));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -56,7 +56,7 @@ export interface ParsedArgs {
|
||||
'open-url'?: boolean;
|
||||
'skip-getting-started'?: boolean;
|
||||
'skip-release-notes'?: boolean;
|
||||
'sticky-quickopen'?: boolean;
|
||||
'sticky-quickinput'?: boolean;
|
||||
'disable-restore-windows'?: boolean;
|
||||
'disable-telemetry'?: boolean;
|
||||
'export-default-configuration'?: string;
|
||||
|
||||
@@ -90,7 +90,7 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
|
||||
'logExtensionHostCommunication': { type: 'boolean' },
|
||||
'skip-getting-started': { type: 'boolean' },
|
||||
'skip-release-notes': { type: 'boolean' },
|
||||
'sticky-quickopen': { type: 'boolean' },
|
||||
'sticky-quickinput': { type: 'boolean' },
|
||||
'disable-restore-windows': { type: 'boolean' },
|
||||
'disable-telemetry': { type: 'boolean' },
|
||||
'disable-updates': { type: 'boolean' },
|
||||
|
||||
@@ -395,6 +395,8 @@ export function toFileOperationResult(error: Error): FileOperationResult {
|
||||
return FileOperationResult.FILE_NOT_FOUND;
|
||||
case FileSystemProviderErrorCode.FileIsADirectory:
|
||||
return FileOperationResult.FILE_IS_DIRECTORY;
|
||||
case FileSystemProviderErrorCode.FileNotADirectory:
|
||||
return FileOperationResult.FILE_NOT_DIRECTORY;
|
||||
case FileSystemProviderErrorCode.NoPermissions:
|
||||
return FileOperationResult.FILE_PERMISSION_DENIED;
|
||||
case FileSystemProviderErrorCode.FileExists:
|
||||
@@ -763,6 +765,7 @@ export const enum FileOperationResult {
|
||||
FILE_TOO_LARGE,
|
||||
FILE_INVALID_PATH,
|
||||
FILE_EXCEEDS_MEMORY_LIMIT,
|
||||
FILE_NOT_DIRECTORY,
|
||||
FILE_OTHER_ERROR
|
||||
}
|
||||
|
||||
|
||||
@@ -668,6 +668,9 @@ export class DiskFileSystemProvider extends Disposable implements
|
||||
case 'EISDIR':
|
||||
code = FileSystemProviderErrorCode.FileIsADirectory;
|
||||
break;
|
||||
case 'ENOTDIR':
|
||||
code = FileSystemProviderErrorCode.FileNotADirectory;
|
||||
break;
|
||||
case 'EEXIST':
|
||||
code = FileSystemProviderErrorCode.FileExists;
|
||||
break;
|
||||
|
||||
@@ -1409,6 +1409,24 @@ suite('Disk File Service', function () {
|
||||
assert.equal(error!.fileOperationResult, FileOperationResult.FILE_IS_DIRECTORY);
|
||||
});
|
||||
|
||||
test('readFile - FILE_NOT_DIRECTORY', async () => {
|
||||
if (isWindows) {
|
||||
return; // error code does not seem to be supported on windows
|
||||
}
|
||||
|
||||
const resource = URI.file(join(testDir, 'lorem.txt', 'file.txt'));
|
||||
|
||||
let error: FileOperationError | undefined = undefined;
|
||||
try {
|
||||
await service.readFile(resource);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
assert.ok(error);
|
||||
assert.equal(error!.fileOperationResult, FileOperationResult.FILE_NOT_DIRECTORY);
|
||||
});
|
||||
|
||||
test('readFile - FILE_NOT_FOUND', async () => {
|
||||
const resource = URI.file(join(testDir, '404.html'));
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ if (isWeb) {
|
||||
// Running out of sources
|
||||
if (Object.keys(product).length === 0) {
|
||||
assign(product, {
|
||||
version: '1.16.0-dev',
|
||||
vscodeVersion: '1.43.0-dev',
|
||||
version: '1.17.0-dev',
|
||||
vscodeVersion: '1.44.0-dev',
|
||||
nameLong: 'Azure Data Studio Web Dev',
|
||||
nameShort: 'Azure Data Studio Web Dev',
|
||||
urlProtocol: 'azuredatastudio-oss'
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IQuickNavigateConfiguration, IAutoFocus } from 'vs/base/parts/quickopen/common/quickOpen';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export interface IShowOptions {
|
||||
quickNavigateConfiguration?: IQuickNavigateConfiguration;
|
||||
inputSelection?: { start: number; end: number; };
|
||||
autoFocus?: IAutoFocus;
|
||||
}
|
||||
|
||||
export const IQuickOpenService = createDecorator<IQuickOpenService>('quickOpenService');
|
||||
|
||||
export interface IQuickOpenService {
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
/**
|
||||
* Asks the container to show the quick open control with the optional prefix set. If the optional parameter
|
||||
* is set for quick navigation mode, the quick open control will quickly navigate when the quick navigate
|
||||
* key is pressed and will run the selection after the ctrl key is released.
|
||||
*
|
||||
* The returned promise completes when quick open is closing.
|
||||
*/
|
||||
show(prefix?: string, options?: IShowOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Allows to navigate from the outside in an opened picker.
|
||||
*/
|
||||
navigate(next: boolean, quickNavigate?: IQuickNavigateConfiguration): void;
|
||||
|
||||
/**
|
||||
* Accepts the selected value in quick open if visible.
|
||||
*/
|
||||
accept(): void;
|
||||
|
||||
/**
|
||||
* Focus into the quick open if visible.
|
||||
*/
|
||||
focus(): void;
|
||||
|
||||
/**
|
||||
* Closes any opened quick open.
|
||||
*/
|
||||
close(): void;
|
||||
|
||||
/**
|
||||
* Allows to register on the event that quick open is showing
|
||||
*/
|
||||
onShow: Event<void>;
|
||||
|
||||
/**
|
||||
* Allows to register on the event that quick open is hiding
|
||||
*/
|
||||
onHide: Event<void>;
|
||||
}
|
||||
@@ -115,15 +115,27 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
const picksToken = picksCts.token;
|
||||
const providedPicks = this.getPicks(picker.value.substr(this.prefix.length).trim(), picksDisposables, picksToken);
|
||||
|
||||
function applyPicks(picks: Picks<T>): void {
|
||||
function applyPicks(picks: Picks<T>, skipEmpty?: boolean): boolean {
|
||||
let items: ReadonlyArray<Pick<T>>;
|
||||
let activeItem: T | undefined = undefined;
|
||||
|
||||
if (isPicksWithActive(picks)) {
|
||||
picker.items = picks.items;
|
||||
if (picks.active) {
|
||||
picker.activeItems = [picks.active];
|
||||
}
|
||||
items = picks.items;
|
||||
activeItem = picks.active;
|
||||
} else {
|
||||
picker.items = picks;
|
||||
items = picks;
|
||||
}
|
||||
|
||||
if (items.length === 0 && skipEmpty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
picker.items = items;
|
||||
if (activeItem) {
|
||||
picker.activeItems = [activeItem];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// No Picks
|
||||
@@ -133,8 +145,8 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
|
||||
// Fast and Slow Picks
|
||||
else if (isFastAndSlowPicks(providedPicks)) {
|
||||
let fastPicksHandlerDone = false;
|
||||
let slowPicksHandlerDone = false;
|
||||
let fastPicksApplied = false;
|
||||
let slowPicksApplied = false;
|
||||
|
||||
await Promise.all([
|
||||
|
||||
@@ -143,17 +155,13 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
// If the slow picks are faster, we reduce the flicker by
|
||||
// only setting the items once.
|
||||
(async () => {
|
||||
try {
|
||||
await timeout(PickerQuickAccessProvider.FAST_PICKS_RACE_DELAY);
|
||||
if (picksToken.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
await timeout(PickerQuickAccessProvider.FAST_PICKS_RACE_DELAY);
|
||||
if (picksToken.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!slowPicksHandlerDone) {
|
||||
applyPicks(providedPicks.picks);
|
||||
}
|
||||
} finally {
|
||||
fastPicksHandlerDone = true;
|
||||
if (!slowPicksApplied) {
|
||||
fastPicksApplied = applyPicks(providedPicks.picks, true /* skip over empty to reduce flicker */);
|
||||
}
|
||||
})(),
|
||||
|
||||
@@ -186,7 +194,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
additionalPicks = awaitedAdditionalPicks;
|
||||
}
|
||||
|
||||
if (additionalPicks.length > 0 || !fastPicksHandlerDone) {
|
||||
if (additionalPicks.length > 0 || !fastPicksApplied) {
|
||||
applyPicks({
|
||||
items: [...picks, ...additionalPicks],
|
||||
active: activePick as T || additionalActivePick as T // {{SQL CARBON EDIT}} strict-null-checks
|
||||
@@ -197,7 +205,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
picker.busy = false;
|
||||
}
|
||||
|
||||
slowPicksHandlerDone = true;
|
||||
slowPicksApplied = true;
|
||||
}
|
||||
})()
|
||||
]);
|
||||
|
||||
@@ -52,7 +52,7 @@ export class QuickInputService extends Themable implements IQuickInputService {
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IContextKeyService protected readonly contextKeyService: IContextKeyService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
|
||||
@ILayoutService protected readonly layoutService: ILayoutService
|
||||
@@ -166,10 +166,6 @@ export class QuickInputService extends Themable implements IQuickInputService {
|
||||
return this.controller.cancel();
|
||||
}
|
||||
|
||||
hide(focusLost?: boolean): void {
|
||||
return this.controller.hide(focusLost);
|
||||
}
|
||||
|
||||
protected updateStyles() {
|
||||
this.controller.applyStyles(this.computeStyles());
|
||||
}
|
||||
|
||||
@@ -94,7 +94,4 @@ export interface IQuickInputService {
|
||||
* Cancels quick input and closes it.
|
||||
*/
|
||||
cancel(): Promise<void>;
|
||||
|
||||
// TODO@Ben remove once quick open is gone
|
||||
hide(focusLost?: boolean): void;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IWorkspaceStorageChangeEvent, IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason, logStorage } from 'vs/platform/storage/common/storage';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
|
||||
@@ -189,8 +189,8 @@ export class BrowserStorageService extends Disposable implements IStorageService
|
||||
|
||||
export class FileStorageDatabase extends Disposable implements IStorageDatabase {
|
||||
|
||||
private readonly _onDidChangeItemsExternal: Emitter<IStorageItemsChangeEvent> = this._register(new Emitter<IStorageItemsChangeEvent>());
|
||||
readonly onDidChangeItemsExternal: Event<IStorageItemsChangeEvent> = this._onDidChangeItemsExternal.event;
|
||||
private readonly _onDidChangeItemsExternal = this._register(new Emitter<IStorageItemsChangeEvent>());
|
||||
readonly onDidChangeItemsExternal = this._onDidChangeItemsExternal.event;
|
||||
|
||||
private cache: Map<string, string> | undefined;
|
||||
|
||||
|
||||
@@ -125,8 +125,8 @@ export const enum StorageScope {
|
||||
}
|
||||
|
||||
export interface IWorkspaceStorageChangeEvent {
|
||||
key: string;
|
||||
scope: StorageScope;
|
||||
readonly key: string;
|
||||
readonly scope: StorageScope;
|
||||
}
|
||||
|
||||
export class InMemoryStorageService extends Disposable implements IStorageService {
|
||||
@@ -139,8 +139,8 @@ export class InMemoryStorageService extends Disposable implements IStorageServic
|
||||
protected readonly _onWillSaveState = this._register(new Emitter<IWillSaveStateEvent>());
|
||||
readonly onWillSaveState = this._onWillSaveState.event;
|
||||
|
||||
private globalCache: Map<string, string> = new Map<string, string>();
|
||||
private workspaceCache: Map<string, string> = new Map<string, string>();
|
||||
private readonly globalCache = new Map<string, string>();
|
||||
private readonly workspaceCache = new Map<string, string>();
|
||||
|
||||
private getCache(scope: StorageScope): Map<string, string> {
|
||||
return scope === StorageScope.GLOBAL ? this.globalCache : this.workspaceCache;
|
||||
|
||||
@@ -23,8 +23,8 @@ interface ISerializableUpdateRequest {
|
||||
}
|
||||
|
||||
interface ISerializableItemsChangeEvent {
|
||||
changed?: Item[];
|
||||
deleted?: Key[];
|
||||
readonly changed?: Item[];
|
||||
readonly deleted?: Key[];
|
||||
}
|
||||
|
||||
export class GlobalStorageDatabaseChannel extends Disposable implements IServerChannel {
|
||||
@@ -34,15 +34,13 @@ export class GlobalStorageDatabaseChannel extends Disposable implements IServerC
|
||||
private readonly _onDidChangeItems = this._register(new Emitter<ISerializableItemsChangeEvent>());
|
||||
readonly onDidChangeItems = this._onDidChangeItems.event;
|
||||
|
||||
private whenReady: Promise<void>;
|
||||
private readonly whenReady = this.init();
|
||||
|
||||
constructor(
|
||||
private logService: ILogService,
|
||||
private storageMainService: IStorageMainService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.whenReady = this.init();
|
||||
}
|
||||
|
||||
private async init(): Promise<void> {
|
||||
@@ -166,8 +164,8 @@ export class GlobalStorageDatabaseChannelClient extends Disposable implements IS
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
private readonly _onDidChangeItemsExternal: Emitter<IStorageItemsChangeEvent> = this._register(new Emitter<IStorageItemsChangeEvent>());
|
||||
readonly onDidChangeItemsExternal: Event<IStorageItemsChangeEvent> = this._onDidChangeItemsExternal.event;
|
||||
private readonly _onDidChangeItemsExternal = this._register(new Emitter<IStorageItemsChangeEvent>());
|
||||
readonly onDidChangeItemsExternal = this._onDidChangeItemsExternal.event;
|
||||
|
||||
private onDidChangeItemsOnMainListener: IDisposable | undefined;
|
||||
|
||||
|
||||
@@ -48,6 +48,11 @@ export class NativeStorageService extends Disposable implements IStorageService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Global Storage change events
|
||||
this._register(this.globalStorage.onDidChangeStorage(key => this.handleDidChangeStorage(key, StorageScope.GLOBAL)));
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ export function attachFindReplaceInputBoxStyler(widget: IThemable, themeService:
|
||||
} as IInputBoxStyleOverrides, widget);
|
||||
}
|
||||
|
||||
export interface IQuickOpenStyleOverrides extends IListStyleOverrides, IInputBoxStyleOverrides, IProgressBarStyleOverrides {
|
||||
export interface IQuickInputStyleOverrides extends IListStyleOverrides, IInputBoxStyleOverrides, IProgressBarStyleOverrides {
|
||||
foreground?: ColorIdentifier;
|
||||
background?: ColorIdentifier;
|
||||
borderColor?: ColorIdentifier;
|
||||
@@ -163,7 +163,7 @@ export interface IQuickOpenStyleOverrides extends IListStyleOverrides, IInputBox
|
||||
pickerGroupBorder?: ColorIdentifier;
|
||||
}
|
||||
|
||||
export function attachQuickOpenStyler(widget: IThemable, themeService: IThemeService, style?: IQuickOpenStyleOverrides): IDisposable {
|
||||
export function attachQuickInputStyler(widget: IThemable, themeService: IThemeService, style?: IQuickInputStyleOverrides): IDisposable {
|
||||
return attachStyler(themeService, {
|
||||
foreground: (style && style.foreground) || foreground,
|
||||
background: (style && style.background) || editorBackground,
|
||||
@@ -199,7 +199,7 @@ export function attachQuickOpenStyler(widget: IThemable, themeService: IThemeSer
|
||||
listFocusOutline: (style && style.listFocusOutline) || activeContrastBorder,
|
||||
listSelectionOutline: (style && style.listSelectionOutline) || activeContrastBorder,
|
||||
listHoverOutline: (style && style.listHoverOutline) || activeContrastBorder
|
||||
} as IQuickOpenStyleOverrides, widget);
|
||||
} as IQuickInputStyleOverrides, widget);
|
||||
}
|
||||
|
||||
export interface IListStyleOverrides extends IStyleOverrides {
|
||||
|
||||
@@ -106,7 +106,7 @@ export interface IColorTheme {
|
||||
/**
|
||||
* Returns the token style for a given classification. The result uses the <code>MetadataConsts</code> format
|
||||
*/
|
||||
getTokenStyleMetadata(type: string, modifiers: string[]): ITokenStyle | undefined;
|
||||
getTokenStyleMetadata(type: string, modifiers: string[], modelLanguage: string): ITokenStyle | undefined;
|
||||
|
||||
/**
|
||||
* List of all colors used with tokens. <code>getTokenStyleMetadata</code> references the colors by index into this list.
|
||||
|
||||
@@ -13,15 +13,21 @@ import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema';
|
||||
|
||||
export const TOKEN_TYPE_WILDCARD = '*';
|
||||
export const TOKEN_CLASSIFIER_LANGUAGE_SEPARATOR = ':';
|
||||
export const CLASSIFIER_MODIFIER_SEPARATOR = '.';
|
||||
|
||||
// qualified string [type|*](.modifier)*
|
||||
// qualified string [type|*](.modifier)*(/language)!
|
||||
export type TokenClassificationString = string;
|
||||
|
||||
export const typeAndModifierIdPattern = '^\\w+[-_\\w+]*$';
|
||||
export const idPattern = '\\w+[-_\\w+]*';
|
||||
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 interface TokenSelector {
|
||||
match(type: string, modifiers: string[]): number;
|
||||
match(type: string, modifiers: string[], language: string): number;
|
||||
readonly selectorString: string;
|
||||
}
|
||||
|
||||
@@ -52,7 +58,36 @@ export class TokenStyle implements Readonly<TokenStyleData> {
|
||||
}
|
||||
|
||||
export namespace TokenStyle {
|
||||
export function fromData(data: { foreground?: Color, bold?: boolean, underline?: boolean, italic?: boolean }) {
|
||||
export function toJSONObject(style: TokenStyle): any {
|
||||
return {
|
||||
_foreground: style.foreground === undefined ? null : Color.Format.CSS.formatHexA(style.foreground, true),
|
||||
_bold: style.bold === undefined ? null : style.bold,
|
||||
_underline: style.underline === undefined ? null : style.underline,
|
||||
_italic: style.italic === undefined ? null : style.italic,
|
||||
};
|
||||
}
|
||||
export function fromJSONObject(obj: any): TokenStyle | undefined {
|
||||
if (obj) {
|
||||
const boolOrUndef = (b: any) => (typeof b === 'boolean') ? b : undefined;
|
||||
const colorOrUndef = (s: any) => (typeof s === 'string') ? Color.fromHex(s) : undefined;
|
||||
return new TokenStyle(colorOrUndef(obj._foreground), boolOrUndef(obj._bold), boolOrUndef(obj._underline), boolOrUndef(obj._italic));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
export function equals(s1: any, s2: any): boolean {
|
||||
if (s1 === s2) {
|
||||
return true;
|
||||
}
|
||||
return s1 !== undefined && s2 !== undefined
|
||||
&& (s1.foreground instanceof Color ? s1.foreground.equals(s2.foreground) : s2.foreground === undefined)
|
||||
&& s1.bold === s2.bold
|
||||
&& s1.underline === s2.underline
|
||||
&& s1.italic === s2.italic;
|
||||
}
|
||||
export function is(s: any): s is TokenStyle {
|
||||
return s instanceof TokenStyle;
|
||||
}
|
||||
export function fromData(data: { foreground?: Color, bold?: boolean, underline?: boolean, italic?: boolean }): TokenStyle {
|
||||
return new TokenStyle(data.foreground, data.bold, data.underline, data.italic);
|
||||
}
|
||||
export function fromSettings(foreground: string | undefined, fontStyle: string | undefined): TokenStyle {
|
||||
@@ -105,6 +140,38 @@ export interface TokenStylingRule {
|
||||
selector: TokenSelector;
|
||||
}
|
||||
|
||||
export namespace TokenStylingRule {
|
||||
export function fromJSONObject(registry: ITokenClassificationRegistry, o: any): TokenStylingRule | undefined {
|
||||
if (o && typeof o._selector === 'string' && o._style) {
|
||||
const style = TokenStyle.fromJSONObject(o._style);
|
||||
if (style) {
|
||||
try {
|
||||
return { selector: registry.parseTokenSelector(o._selector), style };
|
||||
} catch (_ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
export function toJSONObject(rule: TokenStylingRule): any {
|
||||
return {
|
||||
_selector: rule.selector.selectorString,
|
||||
_style: TokenStyle.toJSONObject(rule.style)
|
||||
};
|
||||
}
|
||||
export function equals(r1: TokenStylingRule | undefined, r2: TokenStylingRule | undefined) {
|
||||
if (r1 === r2) {
|
||||
return true;
|
||||
}
|
||||
return r1 !== undefined && r2 !== undefined
|
||||
&& r1.selector && r2.selector && r1.selector.selectorString === r2.selector.selectorString
|
||||
&& TokenStyle.equals(r1.style, r2.style);
|
||||
}
|
||||
export function is(r: any): r is TokenStylingRule {
|
||||
return r && r.selector && typeof r.selector.selectorString === 'string' && TokenStyle.is(r.style);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A TokenStyle Value is either a token style literal, or a TokenClassificationString
|
||||
*/
|
||||
@@ -269,9 +336,9 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
|
||||
}
|
||||
|
||||
public parseTokenSelector(selectorString: string): TokenSelector {
|
||||
const [selectorType, ...selectorModifiers] = selectorString.split('.');
|
||||
const selector = parseClassifierString(selectorString);
|
||||
|
||||
if (!selectorType) {
|
||||
if (!selector.type) {
|
||||
return {
|
||||
match: () => -1,
|
||||
selectorString
|
||||
@@ -279,23 +346,29 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
|
||||
}
|
||||
|
||||
return {
|
||||
match: (type: string, modifiers: string[]) => {
|
||||
match: (type: string, modifiers: string[], language: string) => {
|
||||
let score = 0;
|
||||
if (selectorType !== TOKEN_TYPE_WILDCARD) {
|
||||
if (selector.language !== undefined) {
|
||||
if (selector.language !== language) {
|
||||
return -1;
|
||||
}
|
||||
score += 100;
|
||||
}
|
||||
if (selector.type !== TOKEN_TYPE_WILDCARD) {
|
||||
const hierarchy = this.getTypeHierarchy(type);
|
||||
const level = hierarchy.indexOf(selectorType);
|
||||
const level = hierarchy.indexOf(selector.type);
|
||||
if (level === -1) {
|
||||
return -1;
|
||||
}
|
||||
score = 100 - level;
|
||||
score += (100 - level);
|
||||
}
|
||||
// all selector modifiers must be present
|
||||
for (const selectorModifier of selectorModifiers) {
|
||||
for (const selectorModifier of selector.modifiers) {
|
||||
if (modifiers.indexOf(selectorModifier) === -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return score + selectorModifiers.length * 100;
|
||||
return score + selector.modifiers.length * 100;
|
||||
},
|
||||
selectorString
|
||||
};
|
||||
@@ -366,15 +439,41 @@ class TokenClassificationRegistry implements ITokenClassificationRegistry {
|
||||
|
||||
}
|
||||
|
||||
const CHAR_LANGUAGE = TOKEN_CLASSIFIER_LANGUAGE_SEPARATOR.charCodeAt(0);
|
||||
const CHAR_MODIFIER = CLASSIFIER_MODIFIER_SEPARATOR.charCodeAt(0);
|
||||
|
||||
const tokenClassificationRegistry = new TokenClassificationRegistry();
|
||||
export function parseClassifierString(s: string): { type: string, modifiers: string[], language: string | undefined; } {
|
||||
let k = s.length;
|
||||
let language: string | undefined = undefined;
|
||||
const modifiers = [];
|
||||
|
||||
for (let i = k - 1; i >= 0; i--) {
|
||||
const ch = s.charCodeAt(i);
|
||||
if (ch === CHAR_LANGUAGE || ch === CHAR_MODIFIER) {
|
||||
const segment = s.substring(i + 1, k);
|
||||
k = i;
|
||||
if (ch === CHAR_LANGUAGE) {
|
||||
language = segment;
|
||||
} else {
|
||||
modifiers.push(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
const type = s.substring(0, k);
|
||||
return { type, modifiers, language };
|
||||
}
|
||||
|
||||
|
||||
let tokenClassificationRegistry = createDefaultTokenClassificationRegistry();
|
||||
platform.Registry.add(Extensions.TokenClassificationContribution, tokenClassificationRegistry);
|
||||
|
||||
registerDefaultClassifications();
|
||||
|
||||
function registerDefaultClassifications(): void {
|
||||
function createDefaultTokenClassificationRegistry(): TokenClassificationRegistry {
|
||||
|
||||
const registry = new TokenClassificationRegistry();
|
||||
|
||||
function registerTokenType(id: string, description: string, scopesToProbe: ProbeScope[] = [], superType?: string, deprecationMessage?: string): string {
|
||||
tokenClassificationRegistry.registerTokenType(id, description, superType, deprecationMessage);
|
||||
registry.registerTokenType(id, description, superType, deprecationMessage);
|
||||
if (scopesToProbe) {
|
||||
registerTokenStyleDefault(id, scopesToProbe);
|
||||
}
|
||||
@@ -383,8 +482,8 @@ function registerDefaultClassifications(): void {
|
||||
|
||||
function registerTokenStyleDefault(selectorString: string, scopesToProbe: ProbeScope[]) {
|
||||
try {
|
||||
const selector = tokenClassificationRegistry.parseTokenSelector(selectorString);
|
||||
tokenClassificationRegistry.registerTokenStyleDefault(selector, { scopesToProbe });
|
||||
const selector = registry.parseTokenSelector(selectorString);
|
||||
registry.registerTokenStyleDefault(selector, { scopesToProbe });
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
@@ -422,18 +521,28 @@ function registerDefaultClassifications(): void {
|
||||
|
||||
// default token modifiers
|
||||
|
||||
tokenClassificationRegistry.registerTokenModifier('declaration', nls.localize('declaration', "Style for all symbol declarations."), undefined);
|
||||
tokenClassificationRegistry.registerTokenModifier('documentation', nls.localize('documentation', "Style to use for references in documentation."), undefined);
|
||||
tokenClassificationRegistry.registerTokenModifier('static', nls.localize('static', "Style to use for symbols that are static."), undefined);
|
||||
tokenClassificationRegistry.registerTokenModifier('abstract', nls.localize('abstract', "Style to use for symbols that are abstract."), undefined);
|
||||
tokenClassificationRegistry.registerTokenModifier('deprecated', nls.localize('deprecated', "Style to use for symbols that are deprecated."), undefined);
|
||||
tokenClassificationRegistry.registerTokenModifier('modification', nls.localize('modification', "Style to use for write accesses."), undefined);
|
||||
tokenClassificationRegistry.registerTokenModifier('async', nls.localize('async', "Style to use for symbols that are async."), undefined);
|
||||
tokenClassificationRegistry.registerTokenModifier('readonly', nls.localize('readonly', "Style to use for symbols that are readonly."), undefined);
|
||||
registry.registerTokenModifier('declaration', nls.localize('declaration', "Style for all symbol declarations."), undefined);
|
||||
registry.registerTokenModifier('documentation', nls.localize('documentation', "Style to use for references in documentation."), undefined);
|
||||
registry.registerTokenModifier('static', nls.localize('static', "Style to use for symbols that are static."), undefined);
|
||||
registry.registerTokenModifier('abstract', nls.localize('abstract', "Style to use for symbols that are abstract."), undefined);
|
||||
registry.registerTokenModifier('deprecated', nls.localize('deprecated', "Style to use for symbols that are deprecated."), undefined);
|
||||
registry.registerTokenModifier('modification', nls.localize('modification', "Style to use for write accesses."), undefined);
|
||||
registry.registerTokenModifier('async', nls.localize('async', "Style to use for symbols that are async."), undefined);
|
||||
registry.registerTokenModifier('readonly', nls.localize('readonly', "Style to use for symbols that are readonly."), undefined);
|
||||
|
||||
|
||||
registerTokenStyleDefault('variable.readonly', [['variable.other.constant']]);
|
||||
registerTokenStyleDefault('property.readonly', [['variable.other.constant.property']]);
|
||||
registerTokenStyleDefault('type.defaultLibrary', [['support.type']]);
|
||||
registerTokenStyleDefault('class.defaultLibrary', [['support.class']]);
|
||||
registerTokenStyleDefault('interface.defaultLibrary', [['support.class']]);
|
||||
registerTokenStyleDefault('variable.defaultLibrary', [['support.variable'], ['support.other.variable']]);
|
||||
registerTokenStyleDefault('variable.defaultLibrary.readonly', [['support.constant']]);
|
||||
registerTokenStyleDefault('property.defaultLibrary', [['support.variable.property']]);
|
||||
registerTokenStyleDefault('property.defaultLibrary.readonly', [['support.constant.property']]);
|
||||
registerTokenStyleDefault('function.defaultLibrary', [['support.function']]);
|
||||
registerTokenStyleDefault('member.defaultLibrary', [['support.function']]);
|
||||
return registry;
|
||||
}
|
||||
|
||||
export function getTokenClassificationRegistry(): ITokenClassificationRegistry {
|
||||
|
||||
@@ -24,7 +24,7 @@ export class TestColorTheme implements IColorTheme {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
getTokenStyleMetadata(type: string, modifiers: string[]): ITokenStyle | undefined {
|
||||
getTokenStyleMetadata(type: string, modifiers: string[], modelLanguage: string): ITokenStyle | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user