mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode fb5dc0083bfa9a0e3da7ed1f86e1ecb9836fcc8b
This commit is contained in:
@@ -17,7 +17,7 @@ import { IStoredWorkspaceFolder, IWorkspaceIdentifier } from 'vs/platform/worksp
|
||||
import { JSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditingService';
|
||||
import { WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { extname, join } from 'vs/base/common/path';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -30,7 +30,7 @@ export class UserConfiguration extends Disposable {
|
||||
private readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>());
|
||||
readonly onDidChangeConfiguration: Event<ConfigurationModel> = this._onDidChangeConfiguration.event;
|
||||
|
||||
private readonly userConfiguration: MutableDisposable<UserSettings | FileServiceBasedConfigurationWithNames> = this._register(new MutableDisposable<UserSettings | FileServiceBasedConfigurationWithNames>());
|
||||
private readonly userConfiguration: MutableDisposable<UserSettings | FileServiceBasedConfiguration> = this._register(new MutableDisposable<UserSettings | FileServiceBasedConfiguration>());
|
||||
private readonly reloadConfigurationScheduler: RunOnceScheduler;
|
||||
|
||||
constructor(
|
||||
@@ -52,8 +52,10 @@ export class UserConfiguration extends Disposable {
|
||||
}
|
||||
|
||||
async reload(): Promise<ConfigurationModel> {
|
||||
if (!(this.userConfiguration.value instanceof FileServiceBasedConfigurationWithNames)) {
|
||||
this.userConfiguration.value = new FileServiceBasedConfigurationWithNames(resources.dirname(this.userSettingsResource), [FOLDER_SETTINGS_NAME, TASKS_CONFIGURATION_KEY], this.scopes, this.fileService);
|
||||
if (!(this.userConfiguration.value instanceof FileServiceBasedConfiguration)) {
|
||||
const folder = resources.dirname(this.userSettingsResource);
|
||||
const standAloneConfigurationResources: [string, URI][] = [TASKS_CONFIGURATION_KEY].map(name => ([name, resources.joinPath(folder, `${name}.json`)]));
|
||||
this.userConfiguration.value = new FileServiceBasedConfiguration(folder.toString(), [this.userSettingsResource], standAloneConfigurationResources, this.scopes, this.fileService);
|
||||
this._register(this.userConfiguration.value.onDidChange(() => this.reloadConfigurationScheduler.schedule()));
|
||||
}
|
||||
return this.userConfiguration.value!.loadConfiguration();
|
||||
@@ -64,24 +66,27 @@ export class UserConfiguration extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
class FileServiceBasedConfigurationWithNames extends Disposable {
|
||||
class FileServiceBasedConfiguration extends Disposable {
|
||||
|
||||
private readonly allResources: URI[];
|
||||
private _folderSettingsModelParser: ConfigurationModelParser;
|
||||
private _standAloneConfigurations: ConfigurationModel[];
|
||||
private _cache: ConfigurationModel;
|
||||
|
||||
protected readonly configurationResources: URI[];
|
||||
protected changeEventTriggerScheduler: RunOnceScheduler;
|
||||
protected readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
private readonly changeEventTriggerScheduler: RunOnceScheduler;
|
||||
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
constructor(protected readonly configurationFolder: URI,
|
||||
private readonly configurationNames: string[],
|
||||
constructor(
|
||||
name: string,
|
||||
private readonly settingsResources: URI[],
|
||||
private readonly standAloneConfigurationResources: [string, URI][],
|
||||
private readonly scopes: ConfigurationScope[] | undefined,
|
||||
private fileService: IFileService) {
|
||||
private fileService: IFileService
|
||||
) {
|
||||
super();
|
||||
this.configurationResources = this.configurationNames.map(name => resources.joinPath(this.configurationFolder, `${name}.json`));
|
||||
this._folderSettingsModelParser = new ConfigurationModelParser(this.configurationFolder.toString(), this.scopes);
|
||||
this.allResources = [...this.settingsResources, ...this.standAloneConfigurationResources.map(([, resource]) => resource)];
|
||||
this._folderSettingsModelParser = new ConfigurationModelParser(name, this.scopes);
|
||||
this._standAloneConfigurations = [];
|
||||
this._cache = new ConfigurationModel();
|
||||
|
||||
@@ -90,30 +95,37 @@ class FileServiceBasedConfigurationWithNames extends Disposable {
|
||||
}
|
||||
|
||||
async loadConfiguration(): Promise<ConfigurationModel> {
|
||||
const configurationContents = await Promise.all(this.configurationResources.map(async resource => {
|
||||
try {
|
||||
const content = await this.fileService.readFile(resource);
|
||||
return content.value.toString();
|
||||
} catch (error) {
|
||||
if ((<FileOperationError>error).fileOperationResult !== FileOperationResult.FILE_NOT_FOUND) {
|
||||
errors.onUnexpectedError(error);
|
||||
const resolveContents = async (resources: URI[]): Promise<(string | undefined)[]> => {
|
||||
return Promise.all(resources.map(async resource => {
|
||||
try {
|
||||
const content = await this.fileService.readFile(resource);
|
||||
return content.value.toString();
|
||||
} catch (error) {
|
||||
if ((<FileOperationError>error).fileOperationResult !== FileOperationResult.FILE_NOT_FOUND) {
|
||||
errors.onUnexpectedError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}));
|
||||
return undefined;
|
||||
}));
|
||||
};
|
||||
|
||||
const [settingsContents, standAloneConfigurationContents] = await Promise.all([
|
||||
resolveContents(this.settingsResources),
|
||||
resolveContents(this.standAloneConfigurationResources.map(([, resource]) => resource)),
|
||||
]);
|
||||
|
||||
// reset
|
||||
this._standAloneConfigurations = [];
|
||||
this._folderSettingsModelParser.parseContent('');
|
||||
|
||||
// parse
|
||||
if (configurationContents[0]) {
|
||||
this._folderSettingsModelParser.parseContent(configurationContents[0]);
|
||||
if (settingsContents[0]) {
|
||||
this._folderSettingsModelParser.parseContent(settingsContents[0]);
|
||||
}
|
||||
for (let index = 1; index < configurationContents.length; index++) {
|
||||
const contents = configurationContents[index];
|
||||
for (let index = 0; index < standAloneConfigurationContents.length; index++) {
|
||||
const contents = standAloneConfigurationContents[index];
|
||||
if (contents) {
|
||||
const standAloneConfigurationModelParser = new StandaloneConfigurationModelParser(this.configurationResources[index].toString(), this.configurationNames[index]);
|
||||
const standAloneConfigurationModelParser = new StandaloneConfigurationModelParser(this.standAloneConfigurationResources[index][1].toString(), this.standAloneConfigurationResources[index][0]);
|
||||
standAloneConfigurationModelParser.parseContent(contents);
|
||||
this._standAloneConfigurations.push(standAloneConfigurationModelParser.configurationModel);
|
||||
}
|
||||
@@ -139,49 +151,22 @@ class FileServiceBasedConfigurationWithNames extends Disposable {
|
||||
}
|
||||
|
||||
protected async handleFileEvents(event: FileChangesEvent): Promise<void> {
|
||||
const events = event.changes;
|
||||
let affectedByChanges = false;
|
||||
|
||||
// Find changes that affect workspace configuration files
|
||||
for (let i = 0, len = events.length; i < len; i++) {
|
||||
const resource = events[i].resource;
|
||||
const basename = resources.basename(resource);
|
||||
const isJson = extname(basename) === '.json';
|
||||
const isConfigurationFolderDeleted = (events[i].type === FileChangeType.DELETED && resources.isEqual(resource, this.configurationFolder));
|
||||
|
||||
if (!isJson && !isConfigurationFolderDeleted) {
|
||||
continue; // only JSON files or the actual settings folder
|
||||
const isAffectedByChanges = (): boolean => {
|
||||
// One of the resources has changed
|
||||
if (this.allResources.some(resource => event.contains(resource))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const folderRelativePath = this.toFolderRelativePath(resource);
|
||||
if (!folderRelativePath) {
|
||||
continue; // event is not inside folder
|
||||
// One of the resource's parent got deleted
|
||||
if (this.allResources.some(resource => event.contains(resources.dirname(resource), FileChangeType.DELETED))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle case where ".vscode" got deleted
|
||||
if (isConfigurationFolderDeleted) {
|
||||
affectedByChanges = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// only valid workspace config files
|
||||
if (this.configurationResources.some(configurationResource => resources.isEqual(configurationResource, resource))) {
|
||||
affectedByChanges = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (affectedByChanges) {
|
||||
return false;
|
||||
};
|
||||
if (isAffectedByChanges()) {
|
||||
this.changeEventTriggerScheduler.schedule();
|
||||
}
|
||||
}
|
||||
|
||||
private toFolderRelativePath(resource: URI): string | undefined {
|
||||
if (resources.isEqualOrParent(resource, this.configurationFolder)) {
|
||||
return resources.relativePath(this.configurationFolder, resource);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class RemoteUserConfiguration extends Disposable {
|
||||
@@ -667,14 +652,6 @@ export interface IFolderConfiguration extends IDisposable {
|
||||
reprocess(): ConfigurationModel;
|
||||
}
|
||||
|
||||
class FileServiceBasedFolderConfiguration extends FileServiceBasedConfigurationWithNames implements IFolderConfiguration {
|
||||
|
||||
constructor(configurationFolder: URI, workbenchState: WorkbenchState, fileService: IFileService) {
|
||||
super(configurationFolder, [FOLDER_SETTINGS_NAME /*First one should be settings */, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY], WorkbenchState.WORKSPACE === workbenchState ? FOLDER_SCOPES : WORKSPACE_SCOPES, fileService);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CachedFolderConfiguration extends Disposable implements IFolderConfiguration {
|
||||
|
||||
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
@@ -742,13 +719,13 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat
|
||||
this.configurationFolder = resources.joinPath(workspaceFolder.uri, configFolderRelativePath);
|
||||
this.folderConfiguration = this.cachedFolderConfiguration = new CachedFolderConfiguration(workspaceFolder.uri, configFolderRelativePath, configurationCache);
|
||||
if (workspaceFolder.uri.scheme === Schemas.file) {
|
||||
this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.configurationFolder, this.workbenchState, fileService);
|
||||
this.folderConfiguration = this.createFileServiceBasedConfiguration(fileService);
|
||||
} else {
|
||||
whenProviderRegistered(workspaceFolder.uri, fileService)
|
||||
.then(() => {
|
||||
this.folderConfiguration.dispose();
|
||||
this.folderConfigurationDisposable.dispose();
|
||||
this.folderConfiguration = new FileServiceBasedFolderConfiguration(this.configurationFolder, this.workbenchState, fileService);
|
||||
this.folderConfiguration = this.createFileServiceBasedConfiguration(fileService);
|
||||
this._register(this.folderConfiguration.onDidChange(e => this.onDidFolderConfigurationChange()));
|
||||
this.onDidFolderConfigurationChange();
|
||||
});
|
||||
@@ -769,8 +746,14 @@ export class FolderConfiguration extends Disposable implements IFolderConfigurat
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
|
||||
private createFileServiceBasedConfiguration(fileService: IFileService) {
|
||||
const settingsResources = [resources.joinPath(this.configurationFolder, `${FOLDER_SETTINGS_NAME}.json`)];
|
||||
const standAloneConfigurationResources: [string, URI][] = [TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY].map(name => ([name, resources.joinPath(this.configurationFolder, `${name}.json`)]));
|
||||
return new FileServiceBasedConfiguration(this.configurationFolder.toString(), settingsResources, standAloneConfigurationResources, WorkbenchState.WORKSPACE === this.workbenchState ? FOLDER_SCOPES : WORKSPACE_SCOPES, fileService);
|
||||
}
|
||||
|
||||
private updateCache(): Promise<void> {
|
||||
if (this.configurationFolder.scheme !== Schemas.file && this.folderConfiguration instanceof FileServiceBasedFolderConfiguration) {
|
||||
if (this.configurationFolder.scheme !== Schemas.file && this.folderConfiguration instanceof FileServiceBasedConfiguration) {
|
||||
return this.folderConfiguration.loadConfiguration()
|
||||
.then(configurationModel => this.cachedFolderConfiguration.updateConfiguration(configurationModel));
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ export abstract class AbstractFileDialogService implements IFileDialogService {
|
||||
}
|
||||
|
||||
async showSaveConfirm(fileNamesOrResources: (string | URI)[]): Promise<ConfirmResult> {
|
||||
if (this.environmentService.isExtensionDevelopment) {
|
||||
return ConfirmResult.DONT_SAVE; // no veto when we are in extension dev mode because we cannot assume we run interactive (e.g. tests)
|
||||
if (this.environmentService.isExtensionDevelopment && this.environmentService.extensionTestsLocationURI) {
|
||||
return ConfirmResult.DONT_SAVE; // no veto when we are in extension dev testing mode because we cannot assume we run interactive
|
||||
}
|
||||
|
||||
return this.doShowSaveConfirm(fileNamesOrResources);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { SaveDialogOptions, OpenDialogOptions } from 'electron';
|
||||
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService, IDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IPickAndOpenOptions, ISaveDialogOptions, IOpenDialogOptions, IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
@@ -190,16 +190,6 @@ export class FileDialogService extends AbstractFileDialogService implements IFil
|
||||
// Don't allow untitled schema through.
|
||||
return schema === Schemas.untitled ? [Schemas.file] : (schema !== Schemas.file ? [schema, Schemas.file] : [schema]);
|
||||
}
|
||||
|
||||
async showSaveConfirm(fileNamesOrResources: (string | URI)[]): Promise<ConfirmResult> {
|
||||
if (this.environmentService.isExtensionDevelopment) {
|
||||
if (!this.environmentService.args['extension-development-confirm-save']) {
|
||||
return ConfirmResult.DONT_SAVE; // no veto when we are in extension dev mode because we cannot assume we run interactive (e.g. tests)
|
||||
}
|
||||
}
|
||||
|
||||
return super.doShowSaveConfirm(fileNamesOrResources);
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IFileDialogService, FileDialogService, true);
|
||||
|
||||
@@ -146,6 +146,10 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (extensionKind === 'web') {
|
||||
// Web extensions are not yet supported to be disabled by kind
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -490,6 +490,30 @@ suite('ExtensionEnablementService Test', () => {
|
||||
assert.equal(testObject.canChangeEnablement(localWorkspaceExtension), true);
|
||||
});
|
||||
|
||||
test('test web extension on local server is not disabled by kind', async () => {
|
||||
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
|
||||
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: ['web'] }, { location: URI.file(`pub.a`) });
|
||||
testObject = new TestExtensionEnablementService(instantiationService);
|
||||
assert.ok(testObject.isEnabled(localWorkspaceExtension));
|
||||
assert.deepEqual(testObject.getEnablementState(localWorkspaceExtension), EnablementState.EnabledGlobally);
|
||||
});
|
||||
|
||||
test('test web extension on remote server is not disabled by kind', async () => {
|
||||
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
|
||||
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: ['web'] }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
|
||||
testObject = new TestExtensionEnablementService(instantiationService);
|
||||
assert.ok(testObject.isEnabled(localWorkspaceExtension));
|
||||
assert.deepEqual(testObject.getEnablementState(localWorkspaceExtension), EnablementState.EnabledGlobally);
|
||||
});
|
||||
|
||||
test('test web extension with no server is not disabled by kind', async () => {
|
||||
instantiationService.stub(IExtensionManagementServerService, aMultiExtensionManagementServerService(instantiationService));
|
||||
const localWorkspaceExtension = aLocalExtension2('pub.a', { extensionKind: ['web'] }, { location: URI.file(`pub.a`).with({ scheme: Schemas.https }) });
|
||||
testObject = new TestExtensionEnablementService(instantiationService);
|
||||
assert.ok(testObject.isEnabled(localWorkspaceExtension));
|
||||
assert.deepEqual(testObject.getEnablementState(localWorkspaceExtension), EnablementState.EnabledGlobally);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function anExtensionManagementServer(authority: string, instantiationService: TestInstantiationService): IExtensionManagementServer {
|
||||
|
||||
@@ -289,6 +289,11 @@ export const schema: IJSONSchema = {
|
||||
body: 'onUri',
|
||||
description: nls.localize('vscode.extension.activationEvents.onUri', 'An activation event emitted whenever a system-wide Uri directed towards this extension is open.'),
|
||||
},
|
||||
{
|
||||
label: 'onCustomEditor',
|
||||
body: 'onCustomEditor:${9:viewType}',
|
||||
description: nls.localize('vscode.extension.activationEvents.onCustomEditor', 'An activation event emitted whenever the specified custom editor becomes visible.'),
|
||||
},
|
||||
{
|
||||
label: '*',
|
||||
description: nls.localize('vscode.extension.activationEvents.star', 'An activation event emitted on VS Code startup. To ensure a great end user experience, please use this activation event in your extension only when no other activation events combination works in your use-case.'),
|
||||
|
||||
@@ -671,7 +671,7 @@ registerSingleton(IExtensionService, ExtensionService);
|
||||
class RestartExtensionHostAction extends Action {
|
||||
|
||||
public static readonly ID = 'workbench.action.restartExtensionHost';
|
||||
public static readonly LABEL = nls.localize('restartExtensionHost', "Developer: Restart Extension Host");
|
||||
public static readonly LABEL = nls.localize('restartExtensionHost', "Restart Extension Host");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -687,4 +687,4 @@ class RestartExtensionHostAction extends Action {
|
||||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(RestartExtensionHostAction, RestartExtensionHostAction.ID, RestartExtensionHostAction.LABEL), 'Developer: Restart Extension Host');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(RestartExtensionHostAction, RestartExtensionHostAction.ID, RestartExtensionHostAction.LABEL), 'Developer: Restart Extension Host', nls.localize('developer', "Developer"));
|
||||
|
||||
@@ -11,7 +11,6 @@ import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/cont
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IFilesConfiguration, AutoSaveConfiguration, HotExitConfiguration } from 'vs/platform/files/common/files';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
@@ -83,8 +82,7 @@ export class FilesConfigurationService extends Disposable implements IFilesConfi
|
||||
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -203,7 +201,7 @@ export class FilesConfigurationService extends Disposable implements IFilesConfi
|
||||
}
|
||||
|
||||
get isHotExitEnabled(): boolean {
|
||||
return !this.environmentService.isExtensionDevelopment && this.currentHotExitConfig !== HotExitConfiguration.OFF;
|
||||
return this.currentHotExitConfig !== HotExitConfiguration.OFF;
|
||||
}
|
||||
|
||||
get hotExitConfiguration(): string {
|
||||
|
||||
@@ -293,9 +293,11 @@ export class ColorThemeData implements IWorkbenchColorTheme {
|
||||
const settings = tokenColors[i].settings;
|
||||
if (score >= foregroundScore && settings.foreground) {
|
||||
foreground = settings.foreground;
|
||||
foregroundScore = score;
|
||||
}
|
||||
if (score >= fontStyleScore && types.isString(settings.fontStyle)) {
|
||||
fontStyle = settings.fontStyle;
|
||||
fontStyleScore = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -657,7 +659,7 @@ function nameMatcher(identifers: string[], scope: ProbeScope): number {
|
||||
let lastScopeIndex = scope.length - 1;
|
||||
let lastIdentifierIndex = findInIdents(scope[lastScopeIndex--], identifers.length);
|
||||
if (lastIdentifierIndex >= 0) {
|
||||
const score = (lastIdentifierIndex + 1) * 0x10000 + scope.length;
|
||||
const score = (lastIdentifierIndex + 1) * 0x10000 + identifers[lastIdentifierIndex].length;
|
||||
while (lastScopeIndex >= 0) {
|
||||
lastIdentifierIndex = findInIdents(scope[lastScopeIndex--], lastIdentifierIndex);
|
||||
if (lastIdentifierIndex === -1) {
|
||||
|
||||
@@ -289,6 +289,41 @@ suite('Themes - TokenStyleResolving', () => {
|
||||
|
||||
});
|
||||
|
||||
|
||||
test('resolveScopes - match most specific', async () => {
|
||||
const themeData = ColorThemeData.createLoadedEmptyTheme('test', 'test');
|
||||
|
||||
const customTokenColors: ITokenColorCustomizations = {
|
||||
textMateRules: [
|
||||
{
|
||||
scope: 'entity.name.type',
|
||||
settings: {
|
||||
fontStyle: 'underline',
|
||||
foreground: '#A6E22E'
|
||||
}
|
||||
},
|
||||
{
|
||||
scope: 'entity.name.type.class',
|
||||
settings: {
|
||||
foreground: '#FF00FF'
|
||||
}
|
||||
},
|
||||
{
|
||||
scope: 'entity.name',
|
||||
settings: {
|
||||
foreground: '#FFFFFF'
|
||||
}
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
themeData.setCustomTokenColors(customTokenColors);
|
||||
|
||||
const tokenStyle = themeData.resolveScopes([['entity.name.type.class']]);
|
||||
assertTokenStyle(tokenStyle, ts('#FF00FF', { underline: true }), 'entity.name.type.class');
|
||||
|
||||
});
|
||||
|
||||
test('rule matching', async () => {
|
||||
const themeData = ColorThemeData.createLoadedEmptyTheme('test', 'test');
|
||||
themeData.setCustomColors({ 'editor.foreground': '#000000' });
|
||||
|
||||
Reference in New Issue
Block a user