mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 2f984aad710215f4e4684a035bb02f55d1a9e2cc (#9819)
This commit is contained in:
@@ -14,7 +14,7 @@ import { IResolvedBackup, IBackupFileService } from 'vs/workbench/services/backu
|
||||
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||
import { ITextSnapshot } from 'vs/editor/common/model';
|
||||
import { createTextBufferFactoryFromStream, createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel';
|
||||
import { keys, ResourceMap } from 'vs/base/common/map';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
@@ -434,7 +434,7 @@ export class InMemoryBackupFileService implements IBackupFileService {
|
||||
}
|
||||
|
||||
async getBackups(): Promise<URI[]> {
|
||||
return keys(this.backups).map(key => URI.parse(key));
|
||||
return Array.from(this.backups.keys()).map(key => URI.parse(key));
|
||||
}
|
||||
|
||||
async discardBackup(resource: URI): Promise<void> {
|
||||
|
||||
@@ -203,7 +203,7 @@ export class WorkspaceService extends Disposable implements IConfigurationServic
|
||||
return;
|
||||
}
|
||||
} catch (e) { /* Ignore */ }
|
||||
storedFoldersToAdd.push(getStoredWorkspaceFolder(folderURI, folderToAdd.name, workspaceConfigFolder, slashForPath));
|
||||
storedFoldersToAdd.push(getStoredWorkspaceFolder(folderURI, false, folderToAdd.name, workspaceConfigFolder, slashForPath));
|
||||
}));
|
||||
|
||||
// Apply to array of newStoredFolders
|
||||
|
||||
@@ -20,7 +20,7 @@ import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, Gr
|
||||
import { IResourceEditorInputType, SIDE_GROUP, IResourceEditorReplacement, IOpenEditorOverrideHandler, IEditorService, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE, ISaveEditorsOptions, ISaveAllEditorsOptions, IRevertAllEditorsOptions, IBaseSaveRevertAllEditorOptions } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { Disposable, IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { coalesce, distinct } from 'vs/base/common/arrays';
|
||||
import { coalesce, distinct, insert } from 'vs/base/common/arrays';
|
||||
import { isCodeEditor, isDiffEditor, ICodeEditor, IDiffEditor, isCompositeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { IEditorGroupView, IEditorOpeningEvent, EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
@@ -476,14 +476,9 @@ export class EditorService extends Disposable implements EditorServiceImpl {
|
||||
private readonly openEditorHandlers: IOpenEditorOverrideHandler[] = [];
|
||||
|
||||
overrideOpenEditor(handler: IOpenEditorOverrideHandler): IDisposable {
|
||||
this.openEditorHandlers.push(handler);
|
||||
const remove = insert(this.openEditorHandlers, handler);
|
||||
|
||||
return toDisposable(() => {
|
||||
const index = this.openEditorHandlers.indexOf(handler);
|
||||
if (index >= 0) {
|
||||
this.openEditorHandlers.splice(index, 1);
|
||||
}
|
||||
});
|
||||
return toDisposable(() => remove());
|
||||
}
|
||||
|
||||
private onGroupWillOpenEditor(group: IEditorGroup, event: IEditorOpeningEvent): void {
|
||||
|
||||
@@ -12,7 +12,6 @@ import { IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows'
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { serializableToMap } from 'vs/base/common/map';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
|
||||
export class BrowserWindowConfiguration implements IWindowConfiguration {
|
||||
@@ -69,6 +68,7 @@ interface IExtensionHostDebugEnvironment {
|
||||
isExtensionDevelopment: boolean;
|
||||
extensionDevelopmentLocationURI?: URI[];
|
||||
extensionTestsLocationURI?: URI;
|
||||
extensionEnabledProposedApi?: string[];
|
||||
}
|
||||
|
||||
export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironmentService {
|
||||
@@ -156,6 +156,14 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
||||
return this._extensionHostDebugEnvironment.extensionTestsLocationURI;
|
||||
}
|
||||
|
||||
get extensionEnabledProposedApi(): string[] | undefined {
|
||||
if (!this._extensionHostDebugEnvironment) {
|
||||
this._extensionHostDebugEnvironment = this.resolveExtensionHostDebugEnvironment();
|
||||
}
|
||||
|
||||
return this._extensionHostDebugEnvironment.extensionEnabledProposedApi;
|
||||
}
|
||||
|
||||
@memoize
|
||||
get webviewExternalEndpoint(): string {
|
||||
// TODO: get fallback from product.json
|
||||
@@ -184,7 +192,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
||||
|
||||
constructor(readonly options: IBrowserWorkbenchEnvironmentConstructionOptions) {
|
||||
if (options.workspaceProvider && Array.isArray(options.workspaceProvider.payload)) {
|
||||
this.payload = serializableToMap(options.workspaceProvider.payload);
|
||||
this.payload = new Map(options.workspaceProvider.payload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +224,9 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
||||
extensionHostDebugEnvironment.params.port = parseInt(value);
|
||||
extensionHostDebugEnvironment.params.break = true;
|
||||
break;
|
||||
case 'enableProposedApi':
|
||||
extensionHostDebugEnvironment.extensionEnabledProposedApi = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,12 +457,12 @@ class ProposedApiController {
|
||||
@IProductService productService: IProductService
|
||||
) {
|
||||
// Make enabled proposed API be lowercase for case insensitive comparison
|
||||
this.enableProposedApiFor = (environmentService.args['enable-proposed-api'] || []).map(id => id.toLowerCase());
|
||||
this.enableProposedApiFor = (environmentService.extensionEnabledProposedApi || []).map(id => id.toLowerCase());
|
||||
|
||||
this.enableProposedApiForAll =
|
||||
!environmentService.isBuilt || // always allow proposed API when running out of sources
|
||||
(!!environmentService.extensionDevelopmentLocationURI && productService.quality !== 'stable') || // do not allow proposed API against stable builds when developing an extension
|
||||
(this.enableProposedApiFor.length === 0 && 'enable-proposed-api' in environmentService.args); // always allow proposed API if --enable-proposed-api is provided without extension ID
|
||||
(this.enableProposedApiFor.length === 0 && Array.isArray(environmentService.extensionEnabledProposedApi)); // always allow proposed API if --enable-proposed-api is provided without extension ID
|
||||
|
||||
this.productAllowProposedApi = new Set<string>();
|
||||
if (isNonEmptyArray(productService.extensionAllowedProposedApi)) {
|
||||
|
||||
@@ -20,7 +20,6 @@ export interface IRPCProtocol {
|
||||
assertRegistered(identifiers: ProxyIdentifier<any>[]): void;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export class ProxyIdentifier<T> {
|
||||
public static count = 0;
|
||||
_proxyIdentifierBrand: void;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as nativeWatchdog from 'native-watchdog';
|
||||
import * as net from 'net';
|
||||
import * as minimist from 'vscode-minimist';
|
||||
import * as minimist from 'minimist';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
|
||||
@@ -17,7 +17,6 @@ import { trackFocus } from 'vs/base/browser/dom';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { mapToSerializable } from 'vs/base/common/map';
|
||||
|
||||
/**
|
||||
* A workspace to open in the workbench can either be:
|
||||
@@ -142,7 +141,7 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
const environment = new Map<string, string>();
|
||||
environment.set('openFile', openable.fileUri.toString());
|
||||
|
||||
this.workspaceProvider.open(undefined, { payload: mapToSerializable(environment) });
|
||||
this.workspaceProvider.open(undefined, { payload: Array.from(environment.entries()) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { isEqual, basenameOrAuthority, basename, joinPath, dirname } from 'vs/base/common/resources';
|
||||
import { tildify, getPathLabel } from 'vs/base/common/labels';
|
||||
import { ltrim, endsWith } from 'vs/base/common/strings';
|
||||
import { ltrim } from 'vs/base/common/strings';
|
||||
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, WORKSPACE_EXTENSION, toWorkspaceIdentifier, isWorkspaceIdentifier, isUntitledWorkspace } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { ILabelService, ResourceLabelFormatter, ResourceLabelFormatting, IFormatterChangeEvent } from 'vs/platform/label/common/label';
|
||||
import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
@@ -200,7 +200,7 @@ export class LabelService extends Disposable implements ILabelService {
|
||||
|
||||
// Workspace: Saved
|
||||
let filename = basename(workspace.configPath);
|
||||
if (endsWith(filename, WORKSPACE_EXTENSION)) {
|
||||
if (filename.endsWith(WORKSPACE_EXTENSION)) {
|
||||
filename = filename.substr(0, filename.length - WORKSPACE_EXTENSION.length - 1);
|
||||
}
|
||||
let label;
|
||||
@@ -275,7 +275,7 @@ export class LabelService extends Disposable implements ILabelService {
|
||||
|
||||
private appendSeparatorIfMissing(label: string, formatting: ResourceLabelFormatting): string {
|
||||
let appendedLabel = label;
|
||||
if (!endsWith(label, formatting.separator)) {
|
||||
if (!label.endsWith(formatting.separator)) {
|
||||
appendedLabel += formatting.separator;
|
||||
}
|
||||
return appendedLabel;
|
||||
|
||||
@@ -11,7 +11,6 @@ import { Event } from 'vs/base/common/event';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
|
||||
export class NotificationService extends Disposable implements INotificationService {
|
||||
|
||||
@@ -21,8 +20,7 @@ export class NotificationService extends Disposable implements INotificationServ
|
||||
get model(): INotificationsModel { return this._model; }
|
||||
|
||||
constructor(
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IStorageKeysSyncRegistryService private readonly storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
|
||||
@IStorageService private readonly storageService: IStorageService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -70,11 +68,6 @@ export class NotificationService extends Disposable implements INotificationServ
|
||||
const scope = notification.neverShowAgain.scope === NeverShowAgainScope.WORKSPACE ? StorageScope.WORKSPACE : StorageScope.GLOBAL;
|
||||
const id = notification.neverShowAgain.id;
|
||||
|
||||
// opt-in to syncing if global
|
||||
if (scope === StorageScope.GLOBAL) {
|
||||
this.storageKeysSyncRegistryService.registerStorageKey({ key: id, version: 1 });
|
||||
}
|
||||
|
||||
// If the user already picked to not show the notification
|
||||
// again, we return with a no-op notification here
|
||||
if (this.storageService.getBoolean(id, scope)) {
|
||||
@@ -126,11 +119,6 @@ export class NotificationService extends Disposable implements INotificationServ
|
||||
const scope = options.neverShowAgain.scope === NeverShowAgainScope.WORKSPACE ? StorageScope.WORKSPACE : StorageScope.GLOBAL;
|
||||
const id = options.neverShowAgain.id;
|
||||
|
||||
// opt-in to syncing if global
|
||||
if (scope === StorageScope.GLOBAL) {
|
||||
this.storageKeysSyncRegistryService.registerStorageKey({ key: id, version: 1 });
|
||||
}
|
||||
|
||||
// If the user already picked to not show the notification
|
||||
// again, we return with a no-op notification here
|
||||
if (this.storageService.getBoolean(id, scope)) {
|
||||
|
||||
@@ -77,7 +77,7 @@ export class FileWalker {
|
||||
this.errors = [];
|
||||
|
||||
if (this.filePattern) {
|
||||
this.normalizedFilePatternLowercase = prepareQuery(this.filePattern).valueLowercase;
|
||||
this.normalizedFilePatternLowercase = prepareQuery(this.filePattern).normalizedLowercase;
|
||||
}
|
||||
|
||||
this.globalExcludePattern = config.excludePattern && glob.parse(config.excludePattern);
|
||||
|
||||
@@ -312,7 +312,7 @@ export class SearchService implements IRawSearchService {
|
||||
|
||||
// Pattern match on results
|
||||
const results: IRawFileMatch[] = [];
|
||||
const normalizedSearchValueLowercase = prepareQuery(searchValue).valueLowercase;
|
||||
const normalizedSearchValueLowercase = prepareQuery(searchValue).normalizedLowercase;
|
||||
for (const entry of cachedEntries) {
|
||||
|
||||
// Check if this entry is a match for the search value
|
||||
|
||||
@@ -11,6 +11,7 @@ import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/
|
||||
import { ITextFileSaveParticipant, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { SaveReason } from 'vs/workbench/common/editor';
|
||||
import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { insert } from 'vs/base/common/arrays';
|
||||
|
||||
export class TextFileSaveParticipant extends Disposable {
|
||||
|
||||
@@ -24,9 +25,9 @@ export class TextFileSaveParticipant extends Disposable {
|
||||
}
|
||||
|
||||
addSaveParticipant(participant: ITextFileSaveParticipant): IDisposable {
|
||||
this.saveParticipants.push(participant);
|
||||
const remove = insert(this.saveParticipants, participant);
|
||||
|
||||
return toDisposable(() => this.saveParticipants.splice(this.saveParticipants.indexOf(participant), 1));
|
||||
return toDisposable(() => remove());
|
||||
}
|
||||
|
||||
participate(model: ITextFileEditorModel, context: { reason: SaveReason; }, token: CancellationToken): Promise<void> {
|
||||
|
||||
@@ -40,6 +40,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
|
||||
import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService';
|
||||
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||
import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class NativeTextFileService extends AbstractTextFileService {
|
||||
|
||||
@@ -58,7 +59,8 @@ export class NativeTextFileService extends AbstractTextFileService {
|
||||
@ITextModelService textModelService: ITextModelService,
|
||||
@ICodeEditorService codeEditorService: ICodeEditorService,
|
||||
@IRemotePathService remotePathService: IRemotePathService,
|
||||
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService
|
||||
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
super(fileService, untitledTextEditorService, lifecycleService, instantiationService, modelService, environmentService, dialogService, fileDialogService, textResourceConfigurationService, filesConfigurationService, textModelService, codeEditorService, remotePathService, workingCopyFileService);
|
||||
}
|
||||
@@ -298,8 +300,16 @@ export class NativeTextFileService extends AbstractTextFileService {
|
||||
sudoCommand.push('--file-write', `"${source}"`, `"${target}"`);
|
||||
|
||||
sudoPrompt.exec(sudoCommand.join(' '), promptOptions, (error: string, stdout: string, stderr: string) => {
|
||||
if (error || stderr) {
|
||||
reject(error || stderr);
|
||||
if (stdout) {
|
||||
this.logService.trace(`[sudo-prompt] received stdout: ${stdout}`);
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
this.logService.trace(`[sudo-prompt] received stderr: ${stderr}`);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(undefined);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ export class ProductIconThemeData implements IWorkbenchProductIconTheme {
|
||||
static get defaultTheme(): ProductIconThemeData {
|
||||
let themeData = ProductIconThemeData._defaultProductIconTheme;
|
||||
if (!themeData) {
|
||||
themeData = ProductIconThemeData._defaultProductIconTheme = new ProductIconThemeData(DEFAULT_PRODUCT_ICON_THEME_ID, nls.localize('defaultTheme', 'Default theme'), DEFAULT_PRODUCT_ICON_THEME_SETTING_VALUE);
|
||||
themeData = ProductIconThemeData._defaultProductIconTheme = new ProductIconThemeData(DEFAULT_PRODUCT_ICON_THEME_ID, nls.localize('defaultTheme', 'Default'), DEFAULT_PRODUCT_ICON_THEME_SETTING_VALUE);
|
||||
themeData.isLoaded = true;
|
||||
themeData.extensionData = undefined;
|
||||
themeData.watch = false;
|
||||
|
||||
@@ -115,7 +115,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
|
||||
this.currentFileIconTheme = FileIconThemeData.createUnloadedTheme('');
|
||||
|
||||
this.productIconThemeWatcher = new ThemeFileWatcher(fileService, environmentService, this.reloadCurrentProductIconTheme.bind(this));
|
||||
this.productIconThemeRegistry = new ThemeRegistry(extensionService, productIconThemesExtPoint, ProductIconThemeData.fromExtensionTheme, true, ProductIconThemeData.defaultTheme);
|
||||
this.productIconThemeRegistry = new ThemeRegistry(extensionService, productIconThemesExtPoint, ProductIconThemeData.fromExtensionTheme, true, ProductIconThemeData.defaultTheme, true);
|
||||
this.onProductIconThemeChange = new Emitter<IWorkbenchProductIconTheme>();
|
||||
this.currentProductIconTheme = ProductIconThemeData.createUnloadedTheme('');
|
||||
|
||||
@@ -265,7 +265,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
|
||||
if (e.affectsConfiguration(ThemeSettings.PREFERRED_HC_THEME) && this.getPreferredColorScheme() === HIGH_CONTRAST) {
|
||||
this.applyPreferredColorTheme(HIGH_CONTRAST);
|
||||
}
|
||||
if (e.affectsConfiguration(ThemeSettings.ICON_THEME)) {
|
||||
if (e.affectsConfiguration(ThemeSettings.FILE_ICON_THEME)) {
|
||||
this.restoreFileIconTheme();
|
||||
}
|
||||
if (e.affectsConfiguration(ThemeSettings.PRODUCT_ICON_THEME)) {
|
||||
|
||||
@@ -170,25 +170,6 @@ export class ColorThemeData implements IWorkbenchColorTheme {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const rule of tokenClassificationRegistry.getTokenStylingDefaultRules()) {
|
||||
const matchScore = rule.selector.match(type, modifiers, language);
|
||||
if (matchScore >= 0) {
|
||||
let style: TokenStyle | undefined;
|
||||
if (rule.defaults.scopesToProbe) {
|
||||
style = this.resolveScopes(rule.defaults.scopesToProbe);
|
||||
if (style) {
|
||||
_processStyle(matchScore, style, rule.defaults.scopesToProbe);
|
||||
}
|
||||
}
|
||||
if (!style && useDefault !== false) {
|
||||
const tokenStyleValue = rule.defaults[this.type];
|
||||
style = this.resolveTokenStyleValue(tokenStyleValue);
|
||||
if (style) {
|
||||
_processStyle(matchScore, style, tokenStyleValue!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const rule of this.tokenStylingRules) {
|
||||
const matchScore = rule.selector.match(type, modifiers, language);
|
||||
if (matchScore >= 0) {
|
||||
@@ -201,6 +182,36 @@ export class ColorThemeData implements IWorkbenchColorTheme {
|
||||
_processStyle(matchScore, rule.style, rule);
|
||||
}
|
||||
}
|
||||
let hasUndefinedStyleProperty = false;
|
||||
for (let k in score) {
|
||||
const key = k as keyof TokenStyle;
|
||||
if (score[key] === -1) {
|
||||
hasUndefinedStyleProperty = true;
|
||||
} else {
|
||||
score[key] = Number.MAX_VALUE; // set it to the max, so it won't be replaced by a default
|
||||
}
|
||||
}
|
||||
if (hasUndefinedStyleProperty) {
|
||||
for (const rule of tokenClassificationRegistry.getTokenStylingDefaultRules()) {
|
||||
const matchScore = rule.selector.match(type, modifiers, language);
|
||||
if (matchScore >= 0) {
|
||||
let style: TokenStyle | undefined;
|
||||
if (rule.defaults.scopesToProbe) {
|
||||
style = this.resolveScopes(rule.defaults.scopesToProbe);
|
||||
if (style) {
|
||||
_processStyle(matchScore, style, rule.defaults.scopesToProbe);
|
||||
}
|
||||
}
|
||||
if (!style && useDefault !== false) {
|
||||
const tokenStyleValue = rule.defaults[this.type];
|
||||
style = this.resolveTokenStyleValue(tokenStyleValue);
|
||||
if (style) {
|
||||
_processStyle(matchScore, style, tokenStyleValue!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TokenStyle.fromData(result);
|
||||
|
||||
}
|
||||
@@ -212,8 +223,8 @@ export class ColorThemeData implements IWorkbenchColorTheme {
|
||||
if (tokenStyleValue === undefined) {
|
||||
return undefined;
|
||||
} else if (typeof tokenStyleValue === 'string') {
|
||||
const { type, modifiers, language } = parseClassifierString(tokenStyleValue);
|
||||
return this.getTokenStyle(type, modifiers, language || '');
|
||||
const { type, modifiers, language } = parseClassifierString(tokenStyleValue, '');
|
||||
return this.getTokenStyle(type, modifiers, language);
|
||||
} else if (typeof tokenStyleValue === 'object') {
|
||||
return tokenStyleValue;
|
||||
}
|
||||
@@ -248,8 +259,8 @@ export class ColorThemeData implements IWorkbenchColorTheme {
|
||||
}
|
||||
|
||||
public getTokenStyleMetadata(typeWithLanguage: string, modifiers: string[], defaultLanguage: string, useDefault = true, definitions: TokenStyleDefinitions = {}): ITokenStyle | undefined {
|
||||
const { type, language } = parseClassifierString(typeWithLanguage);
|
||||
let style = this.getTokenStyle(type, modifiers, language || defaultLanguage, useDefault, definitions);
|
||||
const { type, language } = parseClassifierString(typeWithLanguage, defaultLanguage);
|
||||
let style = this.getTokenStyle(type, modifiers, language, useDefault, definitions);
|
||||
if (!style) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -78,11 +78,10 @@ const colorCustomizationsSchema: IConfigurationPropertySchema = {
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
const fileIconThemeSettingSchema: IConfigurationPropertySchema = {
|
||||
type: ['string', 'null'],
|
||||
default: DEFAULT_FILE_ICON_THEME_SETTING_VALUE,
|
||||
description: nls.localize('iconTheme', "Specifies the icon theme used in the workbench or 'null' to not show any file icons."),
|
||||
description: nls.localize('iconTheme', "Specifies the file icon theme used in the workbench or 'null' to not show any file icons."),
|
||||
enum: [null],
|
||||
enumDescriptions: [nls.localize('noIconThemeDesc', 'No file icons')],
|
||||
errorMessage: nls.localize('iconThemeError', "File icon theme is unknown or not installed.")
|
||||
@@ -106,7 +105,7 @@ const themeSettingsConfiguration: IConfigurationNode = {
|
||||
[ThemeSettings.PREFERRED_LIGHT_THEME]: preferredLightThemeSettingSchema,
|
||||
[ThemeSettings.PREFERRED_HC_THEME]: preferredHCThemeSettingSchema,
|
||||
[ThemeSettings.DETECT_COLOR_SCHEME]: detectColorSchemeSettingSchema,
|
||||
[ThemeSettings.ICON_THEME]: fileIconThemeSettingSchema,
|
||||
[ThemeSettings.FILE_ICON_THEME]: fileIconThemeSettingSchema,
|
||||
[ThemeSettings.COLOR_CUSTOMIZATIONS]: colorCustomizationsSchema,
|
||||
[ThemeSettings.PRODUCT_ICON_THEME]: productIconThemeSettingSchema
|
||||
}
|
||||
@@ -212,7 +211,7 @@ export class ThemeConfiguration {
|
||||
}
|
||||
|
||||
public get fileIconTheme(): string | null {
|
||||
return this.configurationService.getValue<string | null>(ThemeSettings.ICON_THEME);
|
||||
return this.configurationService.getValue<string | null>(ThemeSettings.FILE_ICON_THEME);
|
||||
}
|
||||
|
||||
public get productIconTheme(): string {
|
||||
@@ -237,7 +236,7 @@ export class ThemeConfiguration {
|
||||
}
|
||||
|
||||
public async setFileIconTheme(theme: IWorkbenchFileIconTheme, settingsTarget: ConfigurationTarget | undefined | 'auto'): Promise<IWorkbenchFileIconTheme> {
|
||||
await this.writeConfiguration(ThemeSettings.ICON_THEME, theme.settingsId, settingsTarget);
|
||||
await this.writeConfiguration(ThemeSettings.FILE_ICON_THEME, theme.settingsId, settingsTarget);
|
||||
return theme;
|
||||
}
|
||||
|
||||
@@ -257,6 +256,8 @@ export class ThemeConfiguration {
|
||||
settingsTarget = ConfigurationTarget.WORKSPACE_FOLDER;
|
||||
} else if (!types.isUndefined(settings.workspaceValue)) {
|
||||
settingsTarget = ConfigurationTarget.WORKSPACE;
|
||||
} else if (!types.isUndefined(settings.userRemote)) {
|
||||
settingsTarget = ConfigurationTarget.USER_REMOTE;
|
||||
} else {
|
||||
settingsTarget = ConfigurationTarget.USER;
|
||||
}
|
||||
@@ -271,12 +272,11 @@ export class ThemeConfiguration {
|
||||
}
|
||||
value = undefined; // remove configuration from user settings
|
||||
}
|
||||
} else if (settingsTarget === ConfigurationTarget.WORKSPACE || settingsTarget === ConfigurationTarget.WORKSPACE_FOLDER) {
|
||||
} else if (settingsTarget === ConfigurationTarget.WORKSPACE || settingsTarget === ConfigurationTarget.WORKSPACE_FOLDER || settingsTarget === ConfigurationTarget.USER_REMOTE) {
|
||||
if (value === settings.value) {
|
||||
return Promise.resolve(undefined); // nothing to do
|
||||
}
|
||||
}
|
||||
return this.configurationService.updateValue(key, value, settingsTarget);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import * as resources from 'vs/base/common/resources';
|
||||
import { ExtensionMessageCollector, IExtensionPoint, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { ExtensionData, IThemeExtensionPoint, VS_LIGHT_THEME, VS_DARK_THEME, VS_HC_THEME } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionService, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
@@ -128,7 +128,8 @@ export class ThemeRegistry<T extends IThemeData> {
|
||||
private readonly themesExtPoint: IExtensionPoint<IThemeExtensionPoint[]>,
|
||||
private create: (theme: IThemeExtensionPoint, themeLocation: URI, extensionData: ExtensionData) => T,
|
||||
private idRequired = false,
|
||||
private builtInTheme: T | undefined = undefined
|
||||
private builtInTheme: T | undefined = undefined,
|
||||
private isProposedApi = false
|
||||
) {
|
||||
this.extensionThemes = [];
|
||||
this.initialize();
|
||||
@@ -144,6 +145,10 @@ export class ThemeRegistry<T extends IThemeData> {
|
||||
}
|
||||
this.extensionThemes.length = 0;
|
||||
for (let ext of extensions) {
|
||||
if (this.isProposedApi) {
|
||||
checkProposedApiEnabled(ext.description);
|
||||
return;
|
||||
}
|
||||
let extensionData: ExtensionData = {
|
||||
extensionId: ext.description.identifier.value,
|
||||
extensionPublisher: ext.description.publisher,
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { getTokenClassificationRegistry, ITokenClassificationRegistry, typeAndModifierIdPattern, TokenStyleDefaults, TokenStyle, fontStylePattern, selectorPattern } from 'vs/platform/theme/common/tokenClassificationRegistry';
|
||||
import { textmateColorSettingsSchemaId } from 'vs/workbench/services/themes/common/colorThemeSchema';
|
||||
import { getTokenClassificationRegistry, ITokenClassificationRegistry, typeAndModifierIdPattern } from 'vs/platform/theme/common/tokenClassificationRegistry';
|
||||
|
||||
interface ITokenTypeExtensionPoint {
|
||||
id: string;
|
||||
@@ -20,24 +19,10 @@ interface ITokenModifierExtensionPoint {
|
||||
}
|
||||
|
||||
interface ITokenStyleDefaultExtensionPoint {
|
||||
selector: string;
|
||||
scope?: string[];
|
||||
light?: {
|
||||
foreground?: string;
|
||||
fontStyle?: string;
|
||||
};
|
||||
dark?: {
|
||||
foreground?: string;
|
||||
fontStyle?: string;
|
||||
};
|
||||
highContrast?: {
|
||||
foreground?: string;
|
||||
fontStyle?: string;
|
||||
};
|
||||
language?: string;
|
||||
scopes: { [selector: string]: string[] };
|
||||
}
|
||||
|
||||
const colorPattern = '^#([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$';
|
||||
|
||||
const tokenClassificationRegistry: ITokenClassificationRegistry = getTokenClassificationRegistry();
|
||||
|
||||
const tokenTypeExtPoint = ExtensionsRegistry.registerExtensionPoint<ITokenTypeExtensionPoint[]>({
|
||||
@@ -54,6 +39,12 @@ const tokenTypeExtPoint = ExtensionsRegistry.registerExtensionPoint<ITokenTypeEx
|
||||
pattern: typeAndModifierIdPattern,
|
||||
patternErrorMessage: nls.localize('contributes.semanticTokenTypes.id.format', 'Identifiers should be in the form letterOrDigit[_-letterOrDigit]*'),
|
||||
},
|
||||
superType: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.semanticTokenTypes.superType', 'The super type of the semantic token type'),
|
||||
pattern: typeAndModifierIdPattern,
|
||||
patternErrorMessage: nls.localize('contributes.semanticTokenTypes.superType.format', 'Super types should be in the form letterOrDigit[_-letterOrDigit]*'),
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.color.description', 'The description of the semantic token type'),
|
||||
@@ -86,37 +77,26 @@ const tokenModifierExtPoint = ExtensionsRegistry.registerExtensionPoint<ITokenMo
|
||||
});
|
||||
|
||||
const tokenStyleDefaultsExtPoint = ExtensionsRegistry.registerExtensionPoint<ITokenStyleDefaultExtensionPoint[]>({
|
||||
extensionPoint: 'semanticTokenStyleDefaults',
|
||||
extensionPoint: 'semanticTokenScopes',
|
||||
jsonSchema: {
|
||||
description: nls.localize('contributes.semanticTokenStyleDefaults', 'Contributes semantic token style defaults.'),
|
||||
description: nls.localize('contributes.semanticTokenScopes', 'Contributes semantic token scope maps.'),
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
selector: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.semanticTokenStyleDefaults.selector', 'The selector matching token types and modifiers.'),
|
||||
pattern: selectorPattern,
|
||||
patternErrorMessage: nls.localize('contributes.semanticTokenStyleDefaults.selector.format', 'Selectors should be in the form (type|*)(.modifier)*(:language)?'),
|
||||
language: {
|
||||
description: nls.localize('contributes.semanticTokenScopes.languages', 'Lists the languge for which the defaults are.'),
|
||||
type: 'string'
|
||||
},
|
||||
scope: {
|
||||
type: 'array',
|
||||
description: nls.localize('contributes.semanticTokenStyleDefaults.scope', 'A TextMate scope against the current color theme is matched to find the style for the given selector'),
|
||||
items: {
|
||||
type: 'string'
|
||||
scopes: {
|
||||
description: nls.localize('contributes.semanticTokenScopes.scopes', 'Maps a semantic token (described by semantic token selector) to one or more textMate scopes used to represent that token.'),
|
||||
type: 'object',
|
||||
additionalProperties: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
},
|
||||
light: {
|
||||
description: nls.localize('contributes.semanticTokenStyleDefaults.light', 'The default style used for light themes'),
|
||||
$ref: textmateColorSettingsSchemaId
|
||||
},
|
||||
dark: {
|
||||
description: nls.localize('contributes.semanticTokenStyleDefaults.dark', 'The default style used for dark themes'),
|
||||
$ref: textmateColorSettingsSchemaId
|
||||
},
|
||||
highContrast: {
|
||||
description: nls.localize('contributes.semanticTokenStyleDefaults.hc', 'The default style used for high contrast themes'),
|
||||
$ref: textmateColorSettingsSchemaId
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,24 +127,6 @@ export class TokenClassificationExtensionPoints {
|
||||
}
|
||||
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 one or a combination 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) {
|
||||
@@ -216,49 +178,45 @@ export class TokenClassificationExtensionPoints {
|
||||
const collector = extension.collector;
|
||||
|
||||
if (!extensionValue || !Array.isArray(extensionValue)) {
|
||||
collector.error(nls.localize('invalid.semanticTokenStyleDefaultConfiguration', "'configuration.semanticTokenStyleDefaults' must be an array"));
|
||||
collector.error(nls.localize('invalid.semanticTokenScopes.configuration', "'configuration.semanticTokenScopes' must be an array"));
|
||||
return;
|
||||
}
|
||||
for (const contribution of extensionValue) {
|
||||
if (typeof contribution.selector !== 'string' || contribution.selector.length === 0) {
|
||||
collector.error(nls.localize('invalid.selector', "'configuration.semanticTokenStyleDefaults.selector' must be defined and can not be empty"));
|
||||
if (contribution.language && typeof contribution.language !== 'string') {
|
||||
collector.error(nls.localize('invalid.semanticTokenScopes.language', "'configuration.semanticTokenScopes.language' must be a string"));
|
||||
continue;
|
||||
}
|
||||
if (!contribution.selector.match(selectorPattern)) {
|
||||
collector.error(nls.localize('invalid.selector.format', "'configuration.semanticTokenStyleDefaults.selector' must be in the form (type|*)(.modifier)*(:language)?"));
|
||||
if (!contribution.scopes || typeof contribution.scopes !== 'object') {
|
||||
collector.error(nls.localize('invalid.semanticTokenScopes.scopes', "'configuration.semanticTokenScopes.scopes' must be defined as an object"));
|
||||
continue;
|
||||
}
|
||||
|
||||
const tokenStyleDefault: TokenStyleDefaults = {};
|
||||
|
||||
if (contribution.scope) {
|
||||
if ((!Array.isArray(contribution.scope) || contribution.scope.some(s => typeof s !== 'string'))) {
|
||||
collector.error(nls.localize('invalid.scope', "If defined, 'configuration.semanticTokenStyleDefaults.scope' must be an array of strings"));
|
||||
for (let selectorString in contribution.scopes) {
|
||||
const tmScopes = contribution.scopes[selectorString];
|
||||
if (!Array.isArray(tmScopes) || tmScopes.some(l => typeof l !== 'string')) {
|
||||
collector.error(nls.localize('invalid.semanticTokenScopes.scopes.value', "'configuration.semanticTokenScopes.scopes' values must be an array of strings"));
|
||||
continue;
|
||||
}
|
||||
tokenStyleDefault.scopesToProbe = [contribution.scope];
|
||||
}
|
||||
tokenStyleDefault.light = validateStyle(contribution.light, 'semanticTokenStyleDefaults.light', collector);
|
||||
tokenStyleDefault.dark = validateStyle(contribution.dark, 'semanticTokenStyleDefaults.dark', collector);
|
||||
tokenStyleDefault.hc = validateStyle(contribution.highContrast, 'semanticTokenStyleDefaults.highContrast', collector);
|
||||
|
||||
try {
|
||||
const selector = tokenClassificationRegistry.parseTokenSelector(contribution.selector);
|
||||
tokenClassificationRegistry.registerTokenStyleDefault(selector, tokenStyleDefault);
|
||||
} catch (e) {
|
||||
collector.error(nls.localize('invalid.selector.parsing', "configuration.semanticTokenStyleDefaults.selector': Problems parsing {0}.", contribution.selector));
|
||||
// invalid selector, ignore
|
||||
try {
|
||||
const selector = tokenClassificationRegistry.parseTokenSelector(selectorString, contribution.language);
|
||||
tokenClassificationRegistry.registerTokenStyleDefault(selector, { scopesToProbe: tmScopes.map(s => s.split(' ')) });
|
||||
} catch (e) {
|
||||
collector.error(nls.localize('invalid.semanticTokenScopes.scopes.selector', "configuration.semanticTokenScopes.scopes': Problems parsing selector {0}.", selectorString));
|
||||
// invalid selector, ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const extension of delta.removed) {
|
||||
const extensionValue = <ITokenStyleDefaultExtensionPoint[]>extension.value;
|
||||
for (const contribution of extensionValue) {
|
||||
try {
|
||||
const selector = tokenClassificationRegistry.parseTokenSelector(contribution.selector);
|
||||
tokenClassificationRegistry.deregisterTokenStyleDefault(selector);
|
||||
} catch (e) {
|
||||
// invalid selector, ignore
|
||||
for (let selectorString in contribution.scopes) {
|
||||
const tmScopes = contribution.scopes[selectorString];
|
||||
try {
|
||||
const selector = tokenClassificationRegistry.parseTokenSelector(selectorString, contribution.language);
|
||||
tokenClassificationRegistry.registerTokenStyleDefault(selector, { scopesToProbe: tmScopes.map(s => s.split(' ')) });
|
||||
} catch (e) {
|
||||
// invalid selector, ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@ export const HC_THEME_ID = 'Default High Contrast';
|
||||
|
||||
export enum ThemeSettings {
|
||||
COLOR_THEME = 'workbench.colorTheme',
|
||||
ICON_THEME = 'workbench.iconTheme',
|
||||
FILE_ICON_THEME = 'workbench.iconTheme',
|
||||
PRODUCT_ICON_THEME = 'workbench.productIconTheme',
|
||||
COLOR_CUSTOMIZATIONS = 'workbench.colorCustomizations',
|
||||
TOKEN_COLOR_CUSTOMIZATIONS = 'editor.tokenColorCustomizations',
|
||||
TOKEN_COLOR_CUSTOMIZATIONS_EXPERIMENTAL = 'editor.tokenColorCustomizationsExperimental',
|
||||
@@ -29,18 +30,19 @@ export enum ThemeSettings {
|
||||
PREFERRED_LIGHT_THEME = 'workbench.preferredLightColorTheme',
|
||||
PREFERRED_HC_THEME = 'workbench.preferredHighContrastColorTheme',
|
||||
DETECT_COLOR_SCHEME = 'window.autoDetectColorScheme',
|
||||
DETECT_HC = 'window.autoDetectHighContrast',
|
||||
|
||||
PRODUCT_ICON_THEME = 'workbench.productIconTheme'
|
||||
DETECT_HC = 'window.autoDetectHighContrast'
|
||||
}
|
||||
|
||||
export interface IWorkbenchColorTheme extends IColorTheme {
|
||||
export interface IWorkbenchTheme {
|
||||
readonly id: string;
|
||||
readonly label: string;
|
||||
readonly settingsId: string;
|
||||
readonly extensionData?: ExtensionData;
|
||||
readonly description?: string;
|
||||
readonly isLoaded: boolean;
|
||||
readonly settingsId: string | null;
|
||||
}
|
||||
|
||||
export interface IWorkbenchColorTheme extends IWorkbenchTheme, IColorTheme {
|
||||
readonly settingsId: string;
|
||||
readonly tokenColors: ITextMateThemingRule[];
|
||||
}
|
||||
|
||||
@@ -48,44 +50,28 @@ export interface IColorMap {
|
||||
[id: string]: Color;
|
||||
}
|
||||
|
||||
export interface IWorkbenchFileIconTheme extends IFileIconTheme {
|
||||
readonly id: string;
|
||||
readonly label: string;
|
||||
readonly settingsId: string | null;
|
||||
readonly description?: string;
|
||||
readonly extensionData?: ExtensionData;
|
||||
|
||||
readonly isLoaded: boolean;
|
||||
readonly hasFileIcons: boolean;
|
||||
readonly hasFolderIcons: boolean;
|
||||
readonly hidesExplorerArrows: boolean;
|
||||
export interface IWorkbenchFileIconTheme extends IWorkbenchTheme, IFileIconTheme {
|
||||
}
|
||||
|
||||
export interface IWorkbenchProductIconTheme {
|
||||
readonly id: string;
|
||||
readonly label: string;
|
||||
export interface IWorkbenchProductIconTheme extends IWorkbenchTheme {
|
||||
readonly settingsId: string;
|
||||
readonly description?: string;
|
||||
readonly extensionData?: ExtensionData;
|
||||
|
||||
readonly isLoaded: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface IWorkbenchThemeService extends IThemeService {
|
||||
_serviceBrand: undefined;
|
||||
setColorTheme(themeId: string | undefined, settingsTarget: ConfigurationTarget | undefined): Promise<IWorkbenchColorTheme | null>;
|
||||
setColorTheme(themeId: string | undefined, settingsTarget: ConfigurationTarget | undefined | 'auto'): Promise<IWorkbenchColorTheme | null>;
|
||||
getColorTheme(): IWorkbenchColorTheme;
|
||||
getColorThemes(): Promise<IWorkbenchColorTheme[]>;
|
||||
onDidColorThemeChange: Event<IWorkbenchColorTheme>;
|
||||
restoreColorTheme(): void;
|
||||
|
||||
setFileIconTheme(iconThemeId: string | undefined, settingsTarget: ConfigurationTarget | undefined): Promise<IWorkbenchFileIconTheme>;
|
||||
setFileIconTheme(iconThemeId: string | undefined, settingsTarget: ConfigurationTarget | undefined | 'auto'): Promise<IWorkbenchFileIconTheme>;
|
||||
getFileIconTheme(): IWorkbenchFileIconTheme;
|
||||
getFileIconThemes(): Promise<IWorkbenchFileIconTheme[]>;
|
||||
onDidFileIconThemeChange: Event<IWorkbenchFileIconTheme>;
|
||||
|
||||
setProductIconTheme(iconThemeId: string | undefined, settingsTarget: ConfigurationTarget | undefined): Promise<IWorkbenchProductIconTheme>;
|
||||
setProductIconTheme(iconThemeId: string | undefined, settingsTarget: ConfigurationTarget | undefined | 'auto'): Promise<IWorkbenchProductIconTheme>;
|
||||
getProductIconTheme(): IWorkbenchProductIconTheme;
|
||||
getProductIconThemes(): Promise<IWorkbenchProductIconTheme[]>;
|
||||
onDidProductIconThemeChange: Event<IWorkbenchProductIconTheme>;
|
||||
|
||||
@@ -398,8 +398,11 @@ suite('Themes - TokenStyleResolving', () => {
|
||||
|
||||
test('language - scope resolving', async () => {
|
||||
const registry = getTokenClassificationRegistry();
|
||||
registry.registerTokenStyleDefault(registry.parseTokenSelector('type:typescript'), { scopesToProbe: [['entity.name.type.ts']] });
|
||||
|
||||
const numberOfDefaultRules = registry.getTokenStylingDefaultRules().length;
|
||||
|
||||
registry.registerTokenStyleDefault(registry.parseTokenSelector('type', 'typescript1'), { scopesToProbe: [['entity.name.type.ts1']] });
|
||||
registry.registerTokenStyleDefault(registry.parseTokenSelector('type:javascript1'), { scopesToProbe: [['entity.name.type.js1']] });
|
||||
|
||||
try {
|
||||
const themeData = ColorThemeData.createLoadedEmptyTheme('test', 'test');
|
||||
@@ -411,17 +414,20 @@ suite('Themes - TokenStyleResolving', () => {
|
||||
settings: { foreground: '#aa0000' }
|
||||
},
|
||||
{
|
||||
scope: 'entity.name.type.ts',
|
||||
scope: 'entity.name.type.ts1',
|
||||
settings: { foreground: '#bb0000' }
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
assertTokenStyles(themeData, { 'type': ts('#aa0000', undefined) }, 'javascript');
|
||||
assertTokenStyles(themeData, { 'type': ts('#bb0000', undefined) }, 'typescript');
|
||||
assertTokenStyles(themeData, { 'type': ts('#aa0000', undefined) }, 'javascript1');
|
||||
assertTokenStyles(themeData, { 'type': ts('#bb0000', undefined) }, 'typescript1');
|
||||
|
||||
} finally {
|
||||
registry.deregisterTokenType('type/typescript');
|
||||
registry.deregisterTokenStyleDefault(registry.parseTokenSelector('type', 'typescript1'));
|
||||
registry.deregisterTokenStyleDefault(registry.parseTokenSelector('type:javascript1'));
|
||||
|
||||
assert.equal(registry.getTokenStylingDefaultRules().length, numberOfDefaultRules);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { firstIndex } from 'vs/base/common/arrays';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
class CounterSet<T> implements IReadableSet<T> {
|
||||
|
||||
@@ -219,7 +220,8 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -452,6 +454,43 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor
|
||||
|
||||
if (!skipCacheUpdate) {
|
||||
this.saveViewPositionsToCache();
|
||||
|
||||
const containerToString = (container: ViewContainer): string => {
|
||||
if (container.id.startsWith(ViewDescriptorService.COMMON_CONTAINER_ID_PREFIX)) {
|
||||
return 'custom';
|
||||
}
|
||||
|
||||
if (!container.extensionId) {
|
||||
return container.id;
|
||||
}
|
||||
|
||||
return 'extension';
|
||||
};
|
||||
|
||||
// Log on cache update to avoid duplicate events in other windows
|
||||
const viewCount = views.length;
|
||||
const fromContainer = containerToString(from);
|
||||
const toContainer = containerToString(to);
|
||||
const fromLocation = oldLocation === ViewContainerLocation.Panel ? 'panel' : 'sidebar';
|
||||
const toLocation = newLocation === ViewContainerLocation.Panel ? 'panel' : 'sidebar';
|
||||
|
||||
interface ViewDescriptorServiceMoveViewsEvent {
|
||||
viewCount: number;
|
||||
fromContainer: string;
|
||||
toContainer: string;
|
||||
fromLocation: string;
|
||||
toLocation: string;
|
||||
}
|
||||
|
||||
type ViewDescriptorServiceMoveViewsClassification = {
|
||||
viewCount: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
fromContainer: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
toContainer: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
fromLocation: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
toLocation: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
|
||||
this.telemetryService.publicLog2<ViewDescriptorServiceMoveViewsEvent, ViewDescriptorServiceMoveViewsClassification>('viewDescriptorService.moveViews', { viewCount, fromContainer, toContainer, fromLocation, toLocation });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { IWorkingCopyFileOperationParticipant } from 'vs/workbench/services/work
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { FileOperation } from 'vs/platform/files/common/files';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { insert } from 'vs/base/common/arrays';
|
||||
|
||||
export class WorkingCopyFileOperationParticipant extends Disposable {
|
||||
|
||||
@@ -27,9 +28,9 @@ export class WorkingCopyFileOperationParticipant extends Disposable {
|
||||
}
|
||||
|
||||
addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable {
|
||||
this.participants.push(participant);
|
||||
const remove = insert(this.participants, participant);
|
||||
|
||||
return toDisposable(() => this.participants.splice(this.participants.indexOf(participant), 1));
|
||||
return toDisposable(() => remove());
|
||||
}
|
||||
|
||||
async participate(target: URI, source: URI | undefined, operation: FileOperation): Promise<void> {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Disposable, IDisposable, toDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
import { values, ResourceMap } from 'vs/base/common/map';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor';
|
||||
import { ITextSnapshot } from 'vs/editor/common/model';
|
||||
import { Schemas } from 'vs/base/common/network'; // {{SQL CARBON EDIT}} @chlafreniere need to block working copies of notebook editors from being tracked
|
||||
@@ -185,7 +185,7 @@ export class WorkingCopyService extends Disposable implements IWorkingCopyServic
|
||||
|
||||
//#region Registry
|
||||
|
||||
get workingCopies(): IWorkingCopy[] { return values(this._workingCopies); }
|
||||
get workingCopies(): IWorkingCopy[] { return Array.from(this._workingCopies.values()); }
|
||||
private _workingCopies = new Set<IWorkingCopy>();
|
||||
|
||||
private readonly mapResourceToWorkingCopy = new ResourceMap<IWorkingCopy>();
|
||||
|
||||
@@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IJSONEditingService, JSONEditingError, JSONEditingErrorCode } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesService, rewriteWorkspaceFileForNewLocation, WORKSPACE_FILTER, IEnterWorkspaceResult, hasWorkspaceFileExtension, WORKSPACE_EXTENSION } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, IWorkspacesService, rewriteWorkspaceFileForNewLocation, WORKSPACE_FILTER, IEnterWorkspaceResult, hasWorkspaceFileExtension, WORKSPACE_EXTENSION, isUntitledWorkspace } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { WorkspaceService } from 'vs/workbench/services/configuration/browser/configurationService';
|
||||
import { ConfigurationScope, IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
@@ -234,9 +234,11 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi
|
||||
return;
|
||||
}
|
||||
|
||||
const isFromUntitledWorkspace = isUntitledWorkspace(configPathURI, this.environmentService);
|
||||
|
||||
// Read the contents of the workspace file, update it to new location and save it.
|
||||
const raw = await this.fileService.readFile(configPathURI);
|
||||
const newRawWorkspaceContents = rewriteWorkspaceFileForNewLocation(raw.value.toString(), configPathURI, targetConfigPathURI);
|
||||
const newRawWorkspaceContents = rewriteWorkspaceFileForNewLocation(raw.value.toString(), configPathURI, isFromUntitledWorkspace, targetConfigPathURI);
|
||||
await this.textFileService.create(targetConfigPathURI, newRawWorkspaceContents, { overwrite: true });
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS
|
||||
const storedWorkspaceFolder: IStoredWorkspaceFolder[] = [];
|
||||
if (folders) {
|
||||
for (const folder of folders) {
|
||||
storedWorkspaceFolder.push(getStoredWorkspaceFolder(folder.uri, folder.name, this.environmentService.untitledWorkspacesHome));
|
||||
storedWorkspaceFolder.push(getStoredWorkspaceFolder(folder.uri, true, folder.name, this.environmentService.untitledWorkspacesHome));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +165,15 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
|
||||
//#region Dirty Workspaces
|
||||
|
||||
async getDirtyWorkspaces(): Promise<Array<IWorkspaceIdentifier | URI>> {
|
||||
return []; // Currently not supported in web
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
registerSingleton(IWorkspacesService, BrowserWorkspacesService, true);
|
||||
|
||||
@@ -140,8 +140,6 @@ export class NativeWorkspaceEditingService extends AbstractWorkspaceEditingServi
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async isValidTargetWorkspacePath(path: URI): Promise<boolean> {
|
||||
|
||||
Reference in New Issue
Block a user