Revert "Merge from vscode 81d7885dc2e9dc617e1522697a2966bc4025a45d (#5949)" (#5983)

This reverts commit d15a3fcc98.
This commit is contained in:
Karl Burtram
2019-06-11 12:35:58 -07:00
committed by GitHub
parent 95a50b7892
commit 5a7562a37b
926 changed files with 11394 additions and 19540 deletions

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IMenu, IMenuActionOptions, IMenuItem, IMenuService, isIMenuItem, ISubmenuItem, MenuId, MenuItemAction, MenuRegistry, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr, IContextKeyService, IContextKeyChangeEvent } from 'vs/platform/contextkey/common/contextkey';
@@ -30,7 +30,7 @@ type MenuItemGroup = [string, Array<IMenuItem | ISubmenuItem>];
class Menu implements IMenu {
private readonly _onDidChange = new Emitter<IMenu | undefined>();
private readonly _dispoables = new DisposableStore();
private readonly _disposables: IDisposable[] = [];
private _menuGroups: MenuItemGroup[];
private _contextKeys: Set<string>;
@@ -44,24 +44,19 @@ class Menu implements IMenu {
// rebuild this menu whenever the menu registry reports an
// event for this MenuId
this._dispoables.add(Event.debounce(
Event.debounce(
Event.filter(MenuRegistry.onDidChangeMenu, menuId => menuId === this._id),
() => { },
50
)(this._build, this));
)(this._build, this, this._disposables);
// when context keys change we need to check if the menu also
// has changed
this._dispoables.add(Event.debounce<IContextKeyChangeEvent, boolean>(
Event.debounce<IContextKeyChangeEvent, boolean>(
this._contextKeyService.onDidChangeContext,
(last, event) => last || event.affectsSome(this._contextKeys),
50
)(e => e && this._onDidChange.fire(undefined), this));
}
dispose(): void {
this._dispoables.dispose();
this._onDidChange.dispose();
)(e => e && this._onDidChange.fire(undefined), this, this._disposables);
}
private _build(): void {
@@ -100,6 +95,11 @@ class Menu implements IMenu {
this._onDidChange.fire(this);
}
dispose() {
dispose(this._disposables);
this._onDidChange.dispose();
}
get onDidChange(): Event<IMenu | undefined> {
return this._onDidChange.event;
}

View File

@@ -244,7 +244,7 @@ export class BackupMainService implements IBackupMainService {
return [];
}
const seenIds: Set<string> = new Set();
const seenIds: { [id: string]: boolean } = Object.create(null);
const result: IWorkspaceBackupInfo[] = [];
// Validate Workspaces
@@ -254,8 +254,8 @@ export class BackupMainService implements IBackupMainService {
return []; // wrong format, skip all entries
}
if (!seenIds.has(workspace.id)) {
seenIds.add(workspace.id);
if (!seenIds[workspace.id]) {
seenIds[workspace.id] = true;
const backupPath = this.getBackupPath(workspace.id);
const hasBackups = await this.hasBackups(backupPath);
@@ -283,11 +283,11 @@ export class BackupMainService implements IBackupMainService {
}
const result: URI[] = [];
const seenIds: Set<string> = new Set();
const seen: { [id: string]: boolean } = Object.create(null);
for (let folderURI of folderWorkspaces) {
const key = getComparisonKey(folderURI);
if (!seenIds.has(key)) {
seenIds.add(key);
if (!seen[key]) {
seen[key] = true;
const backupPath = this.getBackupPath(this.getFolderHash(folderURI));
const hasBackups = await this.hasBackups(backupPath);
@@ -315,7 +315,7 @@ export class BackupMainService implements IBackupMainService {
}
const result: IEmptyWindowBackupInfo[] = [];
const seenIds: Set<string> = new Set();
const seen: { [id: string]: boolean } = Object.create(null);
// Validate Empty Windows
for (let backupInfo of emptyWorkspaces) {
@@ -324,8 +324,8 @@ export class BackupMainService implements IBackupMainService {
return [];
}
if (!seenIds.has(backupFolder)) {
seenIds.add(backupFolder);
if (!seen[backupFolder]) {
seen[backupFolder] = true;
const backupPath = this.getBackupPath(backupFolder);
if (await this.hasBackups(backupPath)) {

View File

@@ -131,13 +131,11 @@ export interface IDefaultConfigurationExtension {
defaults: { [key: string]: {} };
}
type SettingProperties = { [key: string]: any };
export const allSettings: { properties: SettingProperties, patternProperties: SettingProperties } = { properties: {}, patternProperties: {} };
export const applicationSettings: { properties: SettingProperties, patternProperties: SettingProperties } = { properties: {}, patternProperties: {} };
export const machineSettings: { properties: SettingProperties, patternProperties: SettingProperties } = { properties: {}, patternProperties: {} };
export const windowSettings: { properties: SettingProperties, patternProperties: SettingProperties } = { properties: {}, patternProperties: {} };
export const resourceSettings: { properties: SettingProperties, patternProperties: SettingProperties } = { properties: {}, patternProperties: {} };
export const allSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const applicationSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const machineSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const windowSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const resourceSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} };
export const editorConfigurationSchemaId = 'vscode://schemas/settings/editor';
const contributionRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);

View File

@@ -0,0 +1,56 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ConfigurationModelParser, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { ConfigWatcher } from 'vs/base/node/config';
import { Event, Emitter } from 'vs/base/common/event';
export class NodeBasedUserConfiguration extends Disposable {
private userConfigModelWatcher: ConfigWatcher<ConfigurationModelParser>;
private initializePromise: Promise<void>;
private readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>());
readonly onDidChangeConfiguration: Event<ConfigurationModel> = this._onDidChangeConfiguration.event;
constructor(private settingsPath: string) {
super();
}
initialize(): Promise<ConfigurationModel> {
if (!this.initializePromise) {
this.initializePromise = new Promise<void>((c, e) => {
this.userConfigModelWatcher = new ConfigWatcher(this.settingsPath, {
changeBufferDelay: 300, onError: error => onUnexpectedError(error), defaultConfig: new ConfigurationModelParser(this.settingsPath), parse: (content: string, parseErrors: any[]) => {
const userConfigModelParser = new ConfigurationModelParser(this.settingsPath);
userConfigModelParser.parseContent(content);
parseErrors = [...userConfigModelParser.errors];
return userConfigModelParser;
}, initCallback: () => c(undefined)
});
this._register(this.userConfigModelWatcher);
// Listeners
this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this._onDidChangeConfiguration.fire(this.userConfigModelWatcher.getConfig().configurationModel)));
});
}
return this.initializePromise.then(() => this.userConfigModelWatcher.getConfig().configurationModel);
}
initializeSync(): ConfigurationModel {
this.initialize();
return this.userConfigModelWatcher.getConfig().configurationModel;
}
reload(): Promise<ConfigurationModel> {
return this.initialize().then(() => new Promise<ConfigurationModel>(c => this.userConfigModelWatcher.reload(userConfigModelParser => c(userConfigModelParser.configurationModel))));
}
getConfigurationModel(): ConfigurationModel {
return this.userConfigModelWatcher.getConfig().configurationModel;
}
}

View File

@@ -7,49 +7,40 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, compare, isConfigurationOverrides, IConfigurationData } from 'vs/platform/configuration/common/configuration';
import { DefaultConfigurationModel, Configuration, ConfigurationChangeEvent, ConfigurationModel, ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels';
import { DefaultConfigurationModel, Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { Event, Emitter } from 'vs/base/common/event';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ConfigWatcher } from 'vs/base/node/config';
import { onUnexpectedError } from 'vs/base/common/errors';
import { NodeBasedUserConfiguration } from 'vs/platform/configuration/node/configuration';
export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable {
_serviceBrand: any;
private configuration: Configuration;
private userConfigModelWatcher: ConfigWatcher<ConfigurationModelParser> | undefined;
private _configuration: Configuration;
private userConfiguration: NodeBasedUserConfiguration;
private readonly _onDidChangeConfiguration: Emitter<IConfigurationChangeEvent> = this._register(new Emitter<IConfigurationChangeEvent>());
readonly onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event;
constructor(
private readonly configurationPath: string
configurationPath: string
) {
super();
this.configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel());
this.userConfiguration = this._register(new NodeBasedUserConfiguration(configurationPath));
// Initialize
const defaults = new DefaultConfigurationModel();
const user = this.userConfiguration.initializeSync();
this._configuration = new Configuration(defaults, user);
// Listeners
this._register(this.userConfiguration.onDidChangeConfiguration(userConfigurationModel => this.onDidChangeUserConfiguration(userConfigurationModel)));
this._register(Registry.as<IConfigurationRegistry>(Extensions.Configuration).onDidUpdateConfiguration(configurationProperties => this.onDidDefaultConfigurationChange(configurationProperties)));
}
initialize(): Promise<void> {
if (this.userConfigModelWatcher) {
this.userConfigModelWatcher.dispose();
}
return new Promise<void>((c, e) => {
this.userConfigModelWatcher = this._register(new ConfigWatcher(this.configurationPath, {
changeBufferDelay: 300, onError: error => onUnexpectedError(error), defaultConfig: new ConfigurationModelParser(this.configurationPath), parse: (content: string, parseErrors: any[]) => {
const userConfigModelParser = new ConfigurationModelParser(this.configurationPath);
userConfigModelParser.parseContent(content);
parseErrors = [...userConfigModelParser.errors];
return userConfigModelParser;
}, initCallback: () => {
this.configuration = new Configuration(new DefaultConfigurationModel(), this.userConfigModelWatcher!.getConfig().configurationModel);
this._register(this.userConfigModelWatcher!.onDidUpdateConfiguration(() => this.onDidChangeUserConfiguration(this.userConfigModelWatcher!.getConfig().configurationModel)));
c();
}
}));
});
get configuration(): Configuration {
return this._configuration;
}
getConfigurationData(): IConfigurationData {
@@ -94,26 +85,21 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
}
reloadConfiguration(folder?: IWorkspaceFolder): Promise<void> {
if (this.userConfigModelWatcher) {
return new Promise<void>(c => this.userConfigModelWatcher!.reload(userConfigModelParser => {
this.onDidChangeUserConfiguration(userConfigModelParser.configurationModel);
c();
}));
}
return this.initialize();
return folder ? Promise.resolve(undefined) :
this.userConfiguration.reload().then(userConfigurationModel => this.onDidChangeUserConfiguration(userConfigurationModel));
}
private onDidChangeUserConfiguration(userConfigurationModel: ConfigurationModel): void {
const { added, updated, removed } = compare(this.configuration.localUserConfiguration, userConfigurationModel);
const { added, updated, removed } = compare(this._configuration.localUserConfiguration, userConfigurationModel);
const changedKeys = [...added, ...updated, ...removed];
if (changedKeys.length) {
this.configuration.updateLocalUserConfiguration(userConfigurationModel);
this._configuration.updateLocalUserConfiguration(userConfigurationModel);
this.trigger(changedKeys, ConfigurationTarget.USER);
}
}
private onDidDefaultConfigurationChange(keys: string[]): void {
this.configuration.updateDefaultConfiguration(new DefaultConfigurationModel());
this._configuration.updateDefaultConfiguration(new DefaultConfigurationModel());
this.trigger(keys, ConfigurationTarget.DEFAULT);
}
@@ -124,9 +110,9 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
private getTargetConfiguration(target: ConfigurationTarget): any {
switch (target) {
case ConfigurationTarget.DEFAULT:
return this.configuration.defaults.contents;
return this._configuration.defaults.contents;
case ConfigurationTarget.USER:
return this.configuration.localUserConfiguration.contents;
return this._configuration.localUserConfiguration.contents;
}
return {};
}

View File

@@ -32,7 +32,7 @@ suite('Configuration', () => {
assert.deepEqual(target, { 'a': { 'b': 2 } });
});
test('removeFromValueTree: remove a single segmented key', () => {
test('removeFromValueTree: remove a single segemented key', () => {
let target = { 'a': 1 };
removeFromValueTree(target, 'a');
@@ -40,7 +40,7 @@ suite('Configuration', () => {
assert.deepEqual(target, {});
});
test('removeFromValueTree: remove a single segmented key when its value is undefined', () => {
test('removeFromValueTree: remove a single segemented key when its value is undefined', () => {
let target = { 'a': undefined };
removeFromValueTree(target, 'a');
@@ -48,7 +48,7 @@ suite('Configuration', () => {
assert.deepEqual(target, {});
});
test('removeFromValueTree: remove a multi segmented key when its value is undefined', () => {
test('removeFromValueTree: remove a multi segemented key when its value is undefined', () => {
let target = { 'a': { 'b': 1 } };
removeFromValueTree(target, 'a.b');
@@ -56,7 +56,7 @@ suite('Configuration', () => {
assert.deepEqual(target, {});
});
test('removeFromValueTree: remove a multi segmented key when its value is array', () => {
test('removeFromValueTree: remove a multi segemented key when its value is array', () => {
let target = { 'a': { 'b': [1] } };
removeFromValueTree(target, 'a.b');
@@ -64,7 +64,7 @@ suite('Configuration', () => {
assert.deepEqual(target, {});
});
test('removeFromValueTree: remove a multi segmented key first segment value is array', () => {
test('removeFromValueTree: remove a multi segemented key first segment value is array', () => {
let target = { 'a': [1] };
removeFromValueTree(target, 'a.0');
@@ -80,7 +80,7 @@ suite('Configuration', () => {
assert.deepEqual(target, {});
});
test('removeFromValueTree: remove a multi segmented key when the first node has more values', () => {
test('removeFromValueTree: remove a multi segemented key when the first node has more values', () => {
let target = { 'a': { 'b': { 'c': 1 }, 'd': 1 } };
removeFromValueTree(target, 'a.b.c');
@@ -88,7 +88,7 @@ suite('Configuration', () => {
assert.deepEqual(target, { 'a': { 'd': 1 } });
});
test('removeFromValueTree: remove a multi segmented key when in between node has more values', () => {
test('removeFromValueTree: remove a multi segemented key when in between node has more values', () => {
let target = { 'a': { 'b': { 'c': { 'd': 1 }, 'd': 1 } } };
removeFromValueTree(target, 'a.b.c.d');
@@ -96,7 +96,7 @@ suite('Configuration', () => {
assert.deepEqual(target, { 'a': { 'b': { 'd': 1 } } });
});
test('removeFromValueTree: remove a multi segmented key when the last but one node has more values', () => {
test('removeFromValueTree: remove a multi segemented key when the last but one node has more values', () => {
let target = { 'a': { 'b': { 'c': 1, 'd': 1 } } };
removeFromValueTree(target, 'a.b.c');

View File

@@ -82,7 +82,7 @@ suite('ConfigurationModel', () => {
assert.deepEqual(testObject.keys, ['a.b']);
});
test('removeValue: remove a single segmented key', () => {
test('removeValue: remove a single segemented key', () => {
let testObject = new ConfigurationModel({ 'a': 1 }, ['a']);
testObject.removeValue('a');
@@ -91,7 +91,7 @@ suite('ConfigurationModel', () => {
assert.deepEqual(testObject.keys, []);
});
test('removeValue: remove a multi segmented key', () => {
test('removeValue: remove a multi segemented key', () => {
let testObject = new ConfigurationModel({ 'a': { 'b': 1 } }, ['a.b']);
testObject.removeValue('a.b');

View File

@@ -21,7 +21,6 @@ suite('ConfigurationService - Node', () => {
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
const service = new ConfigurationService(res.testFile);
await service.initialize();
const config = service.getValue<{
foo: string;
}>();
@@ -39,7 +38,6 @@ suite('ConfigurationService - Node', () => {
fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }');
const service = new ConfigurationService(res.testFile);
await service.initialize();
const config = service.getValue<{
testworkbench: {
editor: {
@@ -62,7 +60,6 @@ suite('ConfigurationService - Node', () => {
fs.writeFileSync(res.testFile, ',,,,');
const service = new ConfigurationService(res.testFile);
await service.initialize();
const config = service.getValue<{
foo: string;
}>();
@@ -72,14 +69,13 @@ suite('ConfigurationService - Node', () => {
return res.cleanUp();
});
test('missing file does not explode', async () => {
test('missing file does not explode', () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'config', id);
const testFile = path.join(newDir, 'config.json');
const service = new ConfigurationService(testFile);
await service.initialize();
const config = service.getValue<{ foo: string }>();
assert.ok(config);
@@ -91,7 +87,6 @@ suite('ConfigurationService - Node', () => {
const res = await testFile('config', 'config.json');
const service = new ConfigurationService(res.testFile);
await service.initialize();
return new Promise((c, e) => {
service.onDidChangeConfiguration(() => {
assert.equal(service.getValue('foo'), 'bar');
@@ -109,7 +104,6 @@ suite('ConfigurationService - Node', () => {
fs.writeFileSync(res.testFile, '{ "foo": "bar" }');
const service = new ConfigurationService(res.testFile);
await service.initialize();
let config = service.getValue<{
foo: string;
}>();
@@ -136,7 +130,7 @@ suite('ConfigurationService - Node', () => {
return res.cleanUp();
});
test('model defaults', async () => {
test('model defaults', () => {
interface ITestSetting {
configuration: {
service: {
@@ -158,7 +152,6 @@ suite('ConfigurationService - Node', () => {
});
let serviceWithoutFile = new ConfigurationService('__testFile');
await serviceWithoutFile.initialize();
let setting = serviceWithoutFile.getValue<ITestSetting>();
assert.ok(setting);
@@ -201,8 +194,6 @@ suite('ConfigurationService - Node', () => {
const r = await testFile('config', 'config.json');
const service = new ConfigurationService(r.testFile);
service.initialize();
let res = service.inspect('something.missing');
assert.strictEqual(res.value, undefined);
assert.strictEqual(res.default, undefined);
@@ -239,8 +230,6 @@ suite('ConfigurationService - Node', () => {
const r = await testFile('config', 'config.json');
const service = new ConfigurationService(r.testFile);
service.initialize();
let res = service.inspect('lookup.service.testNullSetting');
assert.strictEqual(res.default, null);
assert.strictEqual(res.value, null);

View File

@@ -5,7 +5,7 @@
import 'vs/css!./contextMenuHandler';
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle';
import { ActionRunner, IRunEvent } from 'vs/base/common/actions';
import { Menu } from 'vs/base/browser/ui/menu/menu';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
@@ -104,7 +104,7 @@ export class ContextMenuHandler {
this.contextViewService.hideContextView(true);
}, null, menuDisposables);
return combinedDisposable(...menuDisposables, menu);
return combinedDisposable([...menuDisposables, menu]);
},
focus: () => {

View File

@@ -1,16 +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 { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const ICredentialsService = createDecorator<ICredentialsService>('ICredentialsService');
export interface ICredentialsService {
_serviceBrand: any;
getPassword(service: string, account: string): Promise<string | null>;
setPassword(service: string, account: string, password: string): Promise<void>;
deletePassword(service: string, account: string): Promise<boolean>;
findPassword(service: string): Promise<string | null>;
}

View File

@@ -1,41 +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 { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { IdleValue } from 'vs/base/common/async';
type KeytarModule = {
getPassword(service: string, account: string): Promise<string | null>;
setPassword(service: string, account: string, password: string): Promise<void>;
deletePassword(service: string, account: string): Promise<boolean>;
findPassword(service: string): Promise<string | null>;
};
export class KeytarCredentialsService implements ICredentialsService {
_serviceBrand: any;
private readonly _keytar = new IdleValue<Promise<KeytarModule>>(() => import('keytar'));
async getPassword(service: string, account: string): Promise<string | null> {
const keytar = await this._keytar.getValue();
return keytar.getPassword(service, account);
}
async setPassword(service: string, account: string, password: string): Promise<void> {
const keytar = await this._keytar.getValue();
return keytar.setPassword(service, account, password);
}
async deletePassword(service: string, account: string): Promise<boolean> {
const keytar = await this._keytar.getValue();
return keytar.deletePassword(service, account);
}
async findPassword(service: string): Promise<string | null> {
const keytar = await this._keytar.getValue();
return keytar.findPassword(service);
}
}

View File

@@ -36,7 +36,7 @@ export interface IConfirmationResult {
/**
* This will only be defined if the confirmation was created
* with the checkbox option defined.
* with the checkox option defined.
*/
checkboxChecked?: boolean;
}

View File

@@ -10,7 +10,7 @@ import { IMainProcessService } from 'vs/platform/ipc/electron-browser/mainProces
import { getTopLeftOffset, getClientArea } from 'vs/base/browser/dom';
import * as electron from 'electron';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { Terminal } from 'xterm';
import { Terminal } from 'vscode-xterm';
import { timeout } from 'vs/base/common/async';
import { coalesce } from 'vs/base/common/arrays';

View File

@@ -210,5 +210,5 @@ export async function serve(
const channel = new DriverChannel(driver);
server.registerChannel('driver', channel);
return combinedDisposable(server, windowServer);
return combinedDisposable([server, windowServer]);
}

View File

@@ -95,17 +95,15 @@ export interface IEditorOptions {
readonly forceReload?: boolean;
/**
* Will reveal the editor if it is already opened and visible in any of the opened editor groups.
*
* Note that this option is just a hint that might be ignored if the user wants to open an editor explicitly
* Will reveal the editor if it is already opened and visible in any of the opened editor groups. Note
* that this option is just a hint that might be ignored if the user wants to open an editor explicitly
* to the side of another one or into a specific editor group.
*/
readonly revealIfVisible?: boolean;
/**
* Will reveal the editor if it is already opened (even when not visible) in any of the opened editor groups.
*
* Note that this option is just a hint that might be ignored if the user wants to open an editor explicitly
* Will reveal the editor if it is already opened (even when not visible) in any of the opened editor groups. Note
* that this option is just a hint that might be ignored if the user wants to open an editor explicitly
* to the side of another one or into a specific editor group.
*/
readonly revealIfOpened?: boolean;

View File

@@ -27,6 +27,7 @@ export interface ParsedArgs {
'prof-startup'?: string;
'prof-startup-prefix'?: string;
'prof-append-timers'?: string;
'prof-modules'?: string;
verbose?: boolean;
trace?: boolean;
'trace-category-filter'?: string;
@@ -68,7 +69,6 @@ export interface ParsedArgs {
'driver'?: string;
'driver-verbose'?: boolean;
remote?: string;
'disable-user-env-probe'?: boolean;
// {{SQL CARBON EDIT}}
aad?: boolean;
database?: string;
@@ -105,7 +105,7 @@ export interface IEnvironmentService {
appNameLong: string;
appQuality?: string;
appSettingsHome: string;
settingsResource: URI;
appSettingsPath: string;
appKeybindingsPath: string;
machineSettingsHome: string;

View File

@@ -8,7 +8,7 @@ import * as os from 'os';
import { localize } from 'vs/nls';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { join } from 'vs/base/common/path';
import { writeFileSync } from 'vs/base/node/pfs';
import { writeFileSync } from 'fs';
/**
* This code is also used by standalone cli's. Avoid adding any other dependencies.
@@ -54,6 +54,7 @@ export const options: Option[] = [
{ id: 'verbose', type: 'boolean', cat: 't', description: localize('verbose', "Print verbose output (implies --wait).") },
{ id: 'log', type: 'string', cat: 't', args: 'level', description: localize('log', "Log level to use. Default is 'info'. Allowed values are 'critical', 'error', 'warn', 'info', 'debug', 'trace', 'off'.") },
{ id: 'status', type: 'boolean', alias: 's', cat: 't', description: localize('status', "Print process usage and diagnostics information.") },
{ id: 'prof-modules', type: 'boolean', alias: 'p', cat: 't', description: localize('prof-modules', "Capture performance markers while loading JS modules and print them with 'F1 > Developer: Startup Performance") },
{ id: 'prof-startup', type: 'boolean', cat: 't', description: localize('prof-startup', "Run CPU profiler during startup") },
{ id: 'disable-extensions', type: 'boolean', deprecates: 'disableExtensions', cat: 't', description: localize('disableExtensions', "Disable all installed extensions.") },
{ id: 'disable-extension', type: 'string', cat: 't', args: 'extension-id', description: localize('disableExtension', "Disable an extension.") },

View File

@@ -21,9 +21,7 @@ import { URI } from 'vs/base/common/uri';
const xdgRuntimeDir = process.env['XDG_RUNTIME_DIR'];
function getNixIPCHandle(userDataPath: string, type: string): string {
const vscodePortable = process.env['VSCODE_PORTABLE'];
if (xdgRuntimeDir && !vscodePortable) {
if (xdgRuntimeDir) {
const scope = crypto.createHash('md5').update(userDataPath).digest('hex').substr(0, 8);
return path.join(xdgRuntimeDir, `vscode-${scope}-${pkg.version}-${type}.sock`);
}
@@ -95,7 +93,6 @@ export class EnvironmentService implements IEnvironmentService {
@memoize
get userDataPath(): string {
const vscodePortable = process.env['VSCODE_PORTABLE'];
if (vscodePortable) {
return path.join(vscodePortable, 'user-data');
}
@@ -111,7 +108,7 @@ export class EnvironmentService implements IEnvironmentService {
get appSettingsHome(): string { return path.join(this.userDataPath, 'User'); }
@memoize
get settingsResource(): URI { return URI.file(path.join(this.appSettingsHome, 'settings.json')); }
get appSettingsPath(): string { return path.join(this.appSettingsHome, 'settings.json'); }
@memoize
get machineSettingsHome(): string { return path.join(this.userDataPath, 'Machine'); }
@@ -173,7 +170,6 @@ export class EnvironmentService implements IEnvironmentService {
}
const vscodePortable = process.env['VSCODE_PORTABLE'];
if (vscodePortable) {
return path.join(vscodePortable, 'extensions');
}
@@ -293,7 +289,6 @@ export function parseDebugPort(debugArg: string | undefined, debugBrkArg: string
const portStr = debugBrkArg || debugArg;
const port = Number(portStr) || (!isBuild ? defaultBuildPort : null);
const brk = port ? Boolean(!!debugBrkArg) : false;
return { port, break: brk, debugId };
}
@@ -308,9 +303,9 @@ function parsePathArg(arg: string | undefined, process: NodeJS.Process): string
if (path.normalize(arg) === resolved) {
return resolved;
} else {
return path.resolve(process.env['VSCODE_CWD'] || process.cwd(), arg);
}
return path.resolve(process.env['VSCODE_CWD'] || process.cwd(), arg);
}
export function parseUserDataDir(args: ParsedArgs, process: NodeJS.Process): string {

View File

@@ -5,7 +5,6 @@
import { ILocalExtension, IGalleryExtension, IExtensionIdentifier, IReportedExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { compareIgnoreCase } from 'vs/base/common/strings';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifier): boolean {
if (a.uuid && b.uuid) {
@@ -17,24 +16,6 @@ export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifi
return compareIgnoreCase(a.id, b.id) === 0;
}
export class ExtensionIdentifierWithVersion {
constructor(
readonly identifier: IExtensionIdentifier,
readonly version: string
) { }
key(): string {
return `${this.identifier.id}-${this.version}`;
}
equals(o: any): boolean {
if (!(o instanceof ExtensionIdentifierWithVersion)) {
return false;
}
return areSameExtensions(this.identifier, o.identifier) && this.version === o.version;
}
}
export function adoptToGalleryExtensionId(id: string): string {
return id.toLocaleLowerCase();
}
@@ -108,7 +89,7 @@ export function getGalleryExtensionTelemetryData(extension: IGalleryExtension):
};
}
export const BetterMergeId = new ExtensionIdentifier('pprice.better-merge');
export const BetterMergeId = 'pprice.better-merge';
export function getMaliciousExtensionsSet(report: IReportedExtension[]): Set<string> {
const result = new Set<string>();

View File

@@ -828,7 +828,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
/* __GDPR__
"galleryService:requestError" : {
"url" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"cdn": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"cdn": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"message": { "classification": "CallstackOrException", "purpose": "FeatureInsight" }
}
*/

View File

@@ -21,7 +21,7 @@ import {
INSTALL_ERROR_MALICIOUS,
INSTALL_ERROR_INCOMPATIBLE
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, ExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { localizeManifest } from '../common/extensionNls';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Limiter, createCancelablePromise, CancelablePromise, Queue } from 'vs/base/common/async';
@@ -44,7 +44,7 @@ import { Schemas } from 'vs/base/common/network';
import { CancellationToken } from 'vs/base/common/cancellation';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions';
import { IExtensionManifest, ExtensionType, ExtensionIdentifierWithVersion } from 'vs/platform/extensions/common/extensions';
// {{SQL CARBON EDIT}
import product from 'vs/platform/product/node/product';
@@ -117,16 +117,16 @@ export class ExtensionManagementService extends Disposable implements IExtension
private readonly manifestCache: ExtensionsManifestCache;
private readonly extensionLifecycle: ExtensionsLifecycle;
private readonly _onInstallExtension = this._register(new Emitter<InstallExtensionEvent>());
private readonly _onInstallExtension = new Emitter<InstallExtensionEvent>();
readonly onInstallExtension: Event<InstallExtensionEvent> = this._onInstallExtension.event;
private readonly _onDidInstallExtension = this._register(new Emitter<DidInstallExtensionEvent>());
private readonly _onDidInstallExtension = new Emitter<DidInstallExtensionEvent>();
readonly onDidInstallExtension: Event<DidInstallExtensionEvent> = this._onDidInstallExtension.event;
private readonly _onUninstallExtension = this._register(new Emitter<IExtensionIdentifier>());
private readonly _onUninstallExtension = new Emitter<IExtensionIdentifier>();
readonly onUninstallExtension: Event<IExtensionIdentifier> = this._onUninstallExtension.event;
private _onDidUninstallExtension = this._register(new Emitter<DidUninstallExtensionEvent>());
private _onDidUninstallExtension = new Emitter<DidUninstallExtensionEvent>();
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
constructor(
@@ -287,6 +287,9 @@ export class ExtensionManagementService extends Disposable implements IExtension
async installFromGallery(extension: IGalleryExtension): Promise<void> {
const startTime = new Date().getTime();
this.logService.info('Installing extension:', extension.identifier.id);
this._onInstallExtension.fire({ identifier: extension.identifier, gallery: extension });
const onDidInstallExtensionSuccess = (extension: IGalleryExtension, operation: InstallOperation, local: ILocalExtension) => {
this.logService.info(`Extensions installed successfully:`, extension.identifier.id);
this._onDidInstallExtension.fire({ identifier: extension.identifier, gallery: extension, local, operation });
@@ -314,9 +317,6 @@ export class ExtensionManagementService extends Disposable implements IExtension
let cancellablePromise = this.installingExtensions.get(key);
if (!cancellablePromise) {
this.logService.info('Installing extension:', extension.identifier.id);
this._onInstallExtension.fire({ identifier: extension.identifier, gallery: extension });
let operation: InstallOperation = InstallOperation.Install;
let cancellationToken: CancellationToken, successCallback: (a?: any) => void, errorCallback: (e?: any) => any | null;
cancellablePromise = createCancelablePromise(token => { cancellationToken = token; return new Promise((c, e) => { successCallback = c; errorCallback = e; }); });
@@ -367,7 +367,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
const compatibleExtension = await this.galleryService.getCompatibleExtension(extension);
if (!compatibleExtension) {
return Promise.reject(new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Unable to install '{0}' extension because it is not compatible with the current version of VS Code (version {1}).", extension.identifier.id, pkg.version), INSTALL_ERROR_INCOMPATIBLE));
return Promise.reject(new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Unable to install because, the extension '{0}' compatible with current version '{1}' of VS Code is not found.", extension.identifier.id, pkg.version), INSTALL_ERROR_INCOMPATIBLE));
}
return compatibleExtension;
@@ -500,12 +500,12 @@ export class ExtensionManagementService extends Disposable implements IExtension
e => Promise.reject(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_DELETING)));
}
private rename(identifier: IExtensionIdentifier, extractPath: string, renamePath: string, retryUntil: number): Promise<void> {
private rename(identfier: IExtensionIdentifier, extractPath: string, renamePath: string, retryUntil: number): Promise<void> {
return pfs.rename(extractPath, renamePath)
.then(undefined, error => {
if (isWindows && error && error.code === 'EPERM' && Date.now() < retryUntil) {
this.logService.info(`Failed renaming ${extractPath} to ${renamePath} with 'EPERM' error. Trying again...`, identifier.id);
return this.rename(identifier, extractPath, renamePath, retryUntil);
this.logService.info(`Failed renaming ${extractPath} to ${renamePath} with 'EPERM' error. Trying again...`, identfier.id);
return this.rename(identfier, extractPath, renamePath, retryUntil);
}
return Promise.reject(new ExtensionManagementError(error.message || nls.localize('renameError', "Unknown error while renaming {0} to {1}", extractPath, renamePath), error.code || INSTALL_ERROR_RENAMING));
});
@@ -743,7 +743,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
this.logService.trace('Started scanning system extensions');
const systemExtensionsPromise = this.scanExtensions(this.systemExtensionsPath, ExtensionType.System)
.then(result => {
this.logService.trace('Scanned system extensions:', result.length);
this.logService.info('Scanned system extensions:', result.length);
return result;
});
if (this.environmentService.isBuilt) {
@@ -756,7 +756,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
if (devSystemExtensionsList.length) {
return this.scanExtensions(this.devSystemExtensionsPath, ExtensionType.System)
.then(result => {
this.logService.trace('Scanned dev system extensions:', result.length);
this.logService.info('Scanned dev system extensions:', result.length);
return result.filter(r => devSystemExtensionsList.some(id => areSameExtensions(r.identifier, { id })));
});
} else {
@@ -776,7 +776,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
const byExtension: ILocalExtension[][] = groupByExtension(extensions, e => e.identifier);
extensions = byExtension.map(p => p.sort((a, b) => semver.rcompare(a.manifest.version, b.manifest.version))[0]);
}
this.logService.trace('Scanned user extensions:', extensions.length);
this.logService.info('Scanned user extensions:', extensions.length);
return extensions;
});
}
@@ -806,29 +806,19 @@ export class ExtensionManagementService extends Disposable implements IExtension
.then(undefined, () => null);
}
async removeDeprecatedExtensions(): Promise<void> {
await this.removeUninstalledExtensions();
await this.removeOutdatedExtensions();
removeDeprecatedExtensions(): Promise<any> {
return this.removeUninstalledExtensions()
.then(() => this.removeOutdatedExtensions());
}
private async removeUninstalledExtensions(): Promise<void> {
const uninstalled = await this.getUninstalledExtensions();
const extensions = await this.scanExtensions(this.extensionsPath, ExtensionType.User); // All user extensions
const installed: Set<string> = new Set<string>();
for (const e of extensions) {
if (!uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]) {
installed.add(e.identifier.id.toLowerCase());
}
}
const byExtension: ILocalExtension[][] = groupByExtension(extensions, e => e.identifier);
await Promise.all(byExtension.map(async e => {
const latest = e.sort((a, b) => semver.rcompare(a.manifest.version, b.manifest.version))[0];
if (!installed.has(latest.identifier.id.toLowerCase())) {
await this.extensionLifecycle.postUninstall(latest);
}
}));
const toRemove: ILocalExtension[] = extensions.filter(e => uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]);
await Promise.all(toRemove.map(e => this.removeUninstalledExtension(e)));
private removeUninstalledExtensions(): Promise<void> {
return this.getUninstalledExtensions()
.then(uninstalled => this.scanExtensions(this.extensionsPath, ExtensionType.User) // All user extensions
.then(extensions => {
const toRemove: ILocalExtension[] = extensions.filter(e => uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]);
return Promise.all(toRemove.map(e => this.extensionLifecycle.postUninstall(e).then(() => this.removeUninstalledExtension(e))));
})
).then(() => undefined);
}
private removeOutdatedExtensions(): Promise<void> {
@@ -855,8 +845,8 @@ export class ExtensionManagementService extends Disposable implements IExtension
return pfs.rimraf(extension.location.fsPath).then(() => this.logService.info('Deleted from disk', extension.identifier.id, extension.location.fsPath));
}
private isUninstalled(identifier: ExtensionIdentifierWithVersion): Promise<boolean> {
return this.filterUninstalled(identifier).then(uninstalled => uninstalled.length === 1);
private isUninstalled(identfier: ExtensionIdentifierWithVersion): Promise<boolean> {
return this.filterUninstalled(identfier).then(uninstalled => uninstalled.length === 1);
}
private filterUninstalled(...identifiers: ExtensionIdentifierWithVersion[]): Promise<string[]> {

View File

@@ -16,11 +16,11 @@ export class ExtensionsManifestCache extends Disposable {
constructor(
private readonly environmentService: IEnvironmentService,
extensionsManagementService: IExtensionManagementService
extensionsManagementServuce: IExtensionManagementService
) {
super();
this._register(extensionsManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e)));
this._register(extensionsManagementService.onDidUninstallExtension(e => this.onDidUnInstallExtension(e)));
this._register(extensionsManagementServuce.onDidInstallExtension(e => this.onDidInstallExtension(e)));
this._register(extensionsManagementServuce.onDidUninstallExtension(e => this.onDidUnInstallExtension(e)));
}
private onDidInstallExtension(e: DidInstallExtensionEvent): void {

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import * as strings from 'vs/base/common/strings';
import { ILocalization } from 'vs/platform/localizations/common/localizations';
import { URI } from 'vs/base/common/uri';
@@ -108,6 +109,24 @@ export interface IExtensionContributions {
export type ExtensionKind = 'ui' | 'workspace';
export class ExtensionIdentifierWithVersion {
constructor(
readonly identifier: IExtensionIdentifier,
readonly version: string
) { }
key(): string {
return `${this.identifier.id}-${this.version}`;
}
equals(o: any): boolean {
if (!(o instanceof ExtensionIdentifierWithVersion)) {
return false;
}
return areSameExtensions(this.identifier, o.identifier) && this.version === o.version;
}
}
export function isIExtensionIdentifier(thing: any): thing is IExtensionIdentifier {
return thing
&& typeof thing === 'object'

View File

@@ -517,7 +517,7 @@ interface IBaseStat {
resource: URI;
/**
* The name which is the last segment
* The name which is the last segement
* of the {{path}}.
*/
name: string;
@@ -531,7 +531,7 @@ interface IBaseStat {
size?: number;
/**
* The last modification date represented
* The last modifictaion date represented
* as millis from unix epoch.
*
* The value may or may not be resolved as

View File

@@ -22,8 +22,6 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { getSimpleWorkspaceLabel } from 'vs/platform/label/common/label';
import { toStoreData, restoreRecentlyOpened, RecentlyOpenedStorageData } from 'vs/platform/history/electron-main/historyStorage';
import { exists } from 'vs/base/node/pfs';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { ILifecycleService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
export class HistoryMainService implements IHistoryMainService {
@@ -39,10 +37,10 @@ export class HistoryMainService implements IHistoryMainService {
private static readonly recentlyOpenedStorageKey = 'openedPathsList';
_serviceBrand: ServiceIdentifier<IHistoryMainService>;
_serviceBrand: any;
private _onRecentlyOpenedChange = new Emitter<void>();
readonly onRecentlyOpenedChange: CommonEvent<void> = this._onRecentlyOpenedChange.event;
onRecentlyOpenedChange: CommonEvent<void> = this._onRecentlyOpenedChange.event;
private macOSRecentDocumentsUpdater: ThrottledDelayer<void>;
@@ -50,21 +48,9 @@ export class HistoryMainService implements IHistoryMainService {
@IStateService private readonly stateService: IStateService,
@ILogService private readonly logService: ILogService,
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@ILifecycleService lifecycleService: ILifecycleService
@IEnvironmentService private readonly environmentService: IEnvironmentService
) {
this.macOSRecentDocumentsUpdater = new ThrottledDelayer<void>(800);
lifecycleService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.handleWindowsJumpList());
}
private handleWindowsJumpList(): void {
if (!isWindows) {
return; // only on windows
}
this.updateWindowsJumpList();
this.onRecentlyOpenedChange(() => this.updateWindowsJumpList());
}
addRecentlyOpened(newlyAdded: IRecent[]): void {

View File

@@ -15,6 +15,7 @@ import { IKeybindingEvent, IKeybindingService, IKeyboardEvent } from 'vs/platfor
import { IResolveResult, KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
interface CurrentChord {
@@ -25,32 +26,45 @@ interface CurrentChord {
export abstract class AbstractKeybindingService extends Disposable implements IKeybindingService {
public _serviceBrand: any;
protected readonly _onDidUpdateKeybindings: Emitter<IKeybindingEvent> = this._register(new Emitter<IKeybindingEvent>());
get onDidUpdateKeybindings(): Event<IKeybindingEvent> {
return this._onDidUpdateKeybindings ? this._onDidUpdateKeybindings.event : Event.None; // Sinon stubbing walks properties on prototype
}
private _currentChord: CurrentChord | null;
private _currentChordChecker: IntervalTimer;
private _currentChordStatusMessage: IDisposable | null;
protected _onDidUpdateKeybindings: Emitter<IKeybindingEvent>;
private _contextKeyService: IContextKeyService;
private _statusService: IStatusbarService | undefined;
private _notificationService: INotificationService;
protected _commandService: ICommandService;
protected _telemetryService: ITelemetryService;
constructor(
private _contextKeyService: IContextKeyService,
protected _commandService: ICommandService,
protected _telemetryService: ITelemetryService,
private _notificationService: INotificationService,
contextKeyService: IContextKeyService,
commandService: ICommandService,
telemetryService: ITelemetryService,
notificationService: INotificationService,
statusService?: IStatusbarService
) {
super();
this._contextKeyService = contextKeyService;
this._commandService = commandService;
this._telemetryService = telemetryService;
this._statusService = statusService;
this._notificationService = notificationService;
this._currentChord = null;
this._currentChordChecker = new IntervalTimer();
this._currentChordStatusMessage = null;
this._onDidUpdateKeybindings = this._register(new Emitter<IKeybindingEvent>());
}
public dispose(): void {
super.dispose();
}
get onDidUpdateKeybindings(): Event<IKeybindingEvent> {
return this._onDidUpdateKeybindings ? this._onDidUpdateKeybindings.event : Event.None; // Sinon stubbing walks properties on prototype
}
protected abstract _getResolver(): KeybindingResolver;
protected abstract _documentHasFocus(): boolean;
public abstract resolveKeybinding(keybinding: Keybinding): ResolvedKeybinding[];
@@ -114,7 +128,9 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
keypress: firstPart,
label: keypressLabel
};
this._currentChordStatusMessage = this._notificationService.status(nls.localize('first.chord', "({0}) was pressed. Waiting for second key of chord...", keypressLabel));
if (this._statusService) {
this._currentChordStatusMessage = this._statusService.setStatusMessage(nls.localize('first.chord', "({0}) was pressed. Waiting for second key of chord...", keypressLabel));
}
const chordEnterTime = Date.now();
this._currentChordChecker.cancelAndSet(() => {
@@ -176,9 +192,9 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
return shouldPreventDefault;
}
if (this._currentChord) {
if (this._statusService && this._currentChord) {
if (!resolveResult || !resolveResult.commandId) {
this._notificationService.status(nls.localize('missing.chord', "The key combination ({0}, {1}) is not a command.", this._currentChord.label, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });
this._statusService.setStatusMessage(nls.localize('missing.chord', "The key combination ({0}, {1}) is not a command.", this._currentChord.label, keypressLabel), 10 * 1000 /* 10s */);
shouldPreventDefault = true;
}
}

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { KeyChord, KeyCode, KeyMod, Keybinding, ResolvedKeybinding, SimpleKeybinding, createKeybinding, createSimpleKeybinding } from 'vs/base/common/keyCodes';
import { IDisposable } from 'vs/base/common/lifecycle';
import { OS } from 'vs/base/common/platform';
import Severity from 'vs/base/common/severity';
import { ICommandService } from 'vs/platform/commands/common/commands';
@@ -13,9 +14,9 @@ import { IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
import { INotification, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
import { INotification, INotificationService, IPromptChoice, IPromptOptions, NoOpNotification } from 'vs/platform/notification/common/notification';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
function createContext(ctx: any) {
return {
@@ -34,9 +35,10 @@ suite('AbstractKeybindingService', () => {
resolver: KeybindingResolver,
contextKeyService: IContextKeyService,
commandService: ICommandService,
notificationService: INotificationService
notificationService: INotificationService,
statusService?: IStatusbarService
) {
super(contextKeyService, commandService, NullTelemetryService, notificationService);
super(contextKeyService, commandService, NullTelemetryService, notificationService, statusService);
this._resolver = resolver;
}
@@ -127,7 +129,7 @@ suite('AbstractKeybindingService', () => {
};
let notificationService: INotificationService = {
_serviceBrand: {} as ServiceIdentifier<INotificationService>,
_serviceBrand: undefined,
notify: (notification: INotification) => {
showMessageCalls.push({ sev: notification.severity, message: notification.message });
return new NoOpNotification();
@@ -146,8 +148,13 @@ suite('AbstractKeybindingService', () => {
},
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) {
throw new Error('not implemented');
},
status(message: string, options?: IStatusMessageOptions) {
}
};
let statusbarService: IStatusbarService = {
_serviceBrand: undefined,
addEntry: undefined!,
setStatusMessage: (message: string, autoDisposeAfter?: number, delayBy?: number): IDisposable => {
statusMessageCalls!.push(message);
return {
dispose: () => {
@@ -159,7 +166,7 @@ suite('AbstractKeybindingService', () => {
let resolver = new KeybindingResolver(items, []);
return new TestKeybindingService(resolver, contextKeyService, commandService, notificationService);
return new TestKeybindingService(resolver, contextKeyService, commandService, notificationService, statusbarService);
};
});

View File

@@ -8,7 +8,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IURLService } from 'vs/platform/url/common/url';
import { IProcessEnvironment, isMacintosh } from 'vs/base/common/platform';
import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { OpenContext, IWindowSettings } from 'vs/platform/windows/common/windows';
import { IWindowsMainService, ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { whenDeleted } from 'vs/base/node/pfs';
@@ -107,7 +107,7 @@ export class LaunchChannel implements IServerChannel {
export class LaunchChannelClient implements ILaunchService {
_serviceBrand: ServiceIdentifier<ILaunchService>;
_serviceBrand: any;
constructor(private channel: IChannel) { }
@@ -134,7 +134,7 @@ export class LaunchChannelClient implements ILaunchService {
export class LaunchService implements ILaunchService {
_serviceBrand: ServiceIdentifier<ILaunchService>;
_serviceBrand: any;
constructor(
@ILogService private readonly logService: ILogService,

View File

@@ -29,7 +29,7 @@ export interface BeforeShutdownEvent {
/**
* The reason why the application will be shutting down.
*/
readonly reason: ShutdownReason;
reason: ShutdownReason;
}
/**
@@ -51,7 +51,7 @@ export interface WillShutdownEvent {
/**
* The reason why the application is shutting down.
*/
readonly reason: ShutdownReason;
reason: ShutdownReason;
}
export const enum ShutdownReason {

View File

@@ -7,12 +7,11 @@ import { ipcMain as ipc, app } from 'electron';
import { ILogService } from 'vs/platform/log/common/log';
import { IStateService } from 'vs/platform/state/common/state';
import { Event, Emitter } from 'vs/base/common/event';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICodeWindow } from 'vs/platform/windows/electron-main/windows';
import { handleVetos } from 'vs/platform/lifecycle/common/lifecycle';
import { isMacintosh, isWindows } from 'vs/base/common/platform';
import { Disposable } from 'vs/base/common/lifecycle';
import { Barrier } from 'vs/base/common/async';
export const ILifecycleService = createDecorator<ILifecycleService>('lifecycleService');
@@ -39,48 +38,42 @@ export interface ShutdownEvent {
}
export interface ILifecycleService {
_serviceBrand: ServiceIdentifier<ILifecycleService>;
_serviceBrand: any;
/**
* Will be true if the program was restarted (e.g. due to explicit request or update).
*/
readonly wasRestarted: boolean;
wasRestarted: boolean;
/**
* Will be true if the program was requested to quit.
*/
readonly quitRequested: boolean;
/**
* A flag indicating in what phase of the lifecycle we currently are.
*/
phase: LifecycleMainPhase;
quitRequested: boolean;
/**
* An event that fires when the application is about to shutdown before any window is closed.
* The shutdown can still be prevented by any window that vetos this event.
*/
readonly onBeforeShutdown: Event<void>;
onBeforeShutdown: Event<void>;
/**
* An event that fires after the onBeforeShutdown event has been fired and after no window has
* vetoed the shutdown sequence. At this point listeners are ensured that the application will
* quit without veto.
*/
readonly onWillShutdown: Event<ShutdownEvent>;
onWillShutdown: Event<ShutdownEvent>;
/**
* An event that fires before a window closes. This event is fired after any veto has been dealt
* with so that listeners know for sure that the window will close without veto.
*/
readonly onBeforeWindowClose: Event<ICodeWindow>;
onBeforeWindowClose: Event<ICodeWindow>;
/**
* An event that fires before a window is about to unload. Listeners can veto this event to prevent
* the window from unloading.
*/
readonly onBeforeWindowUnload: Event<IWindowUnloadEvent>;
onBeforeWindowUnload: Event<IWindowUnloadEvent>;
/**
* Unload a window for the provided reason. All lifecycle event handlers are triggered.
@@ -101,32 +94,6 @@ export interface ILifecycleService {
* Forcefully shutdown the application. No livecycle event handlers are triggered.
*/
kill(code?: number): void;
/**
* Returns a promise that resolves when a certain lifecycle phase
* has started.
*/
when(phase: LifecycleMainPhase): Promise<void>;
}
export const enum LifecycleMainPhase {
/**
* The first phase signals that we are about to startup.
*/
Starting = 1,
/**
* Services are ready and first window is about to open.
*/
Ready = 2,
/**
* This phase signals a point in time after the window has opened
* and is typically the best place to do work that is not required
* for the window to open.
*/
AfterWindowOpen = 3
}
export class LifecycleService extends Disposable implements ILifecycleService {
@@ -135,7 +102,7 @@ export class LifecycleService extends Disposable implements ILifecycleService {
private static readonly QUIT_FROM_RESTART_MARKER = 'quit.from.restart'; // use a marker to find out if the session was restarted
private windowToCloseRequest: Set<number> = new Set();
private windowToCloseRequest: { [windowId: string]: boolean } = Object.create(null);
private oneTimeListenerTokenGenerator = 0;
private windowCounter = 0;
@@ -162,11 +129,6 @@ export class LifecycleService extends Disposable implements ILifecycleService {
private readonly _onBeforeWindowUnload = this._register(new Emitter<IWindowUnloadEvent>());
readonly onBeforeWindowUnload: Event<IWindowUnloadEvent> = this._onBeforeWindowUnload.event;
private _phase: LifecycleMainPhase = LifecycleMainPhase.Starting;
get phase(): LifecycleMainPhase { return this._phase; }
private phaseWhen = new Map<LifecycleMainPhase, Barrier>();
constructor(
@ILogService private readonly logService: ILogService,
@IStateService private readonly stateService: IStateService
@@ -174,7 +136,6 @@ export class LifecycleService extends Disposable implements ILifecycleService {
super();
this.handleRestarted();
this.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
}
private handleRestarted(): void {
@@ -185,6 +146,10 @@ export class LifecycleService extends Disposable implements ILifecycleService {
}
}
ready(): void {
this.registerListeners();
}
private registerListeners(): void {
// before-quit: an event that is fired if application quit was
@@ -273,40 +238,6 @@ export class LifecycleService extends Disposable implements ILifecycleService {
return this.pendingWillShutdownPromise;
}
set phase(value: LifecycleMainPhase) {
if (value < this.phase) {
throw new Error('Lifecycle cannot go backwards');
}
if (this._phase === value) {
return;
}
this.logService.trace(`lifecycle (main): phase changed (value: ${value})`);
this._phase = value;
const barrier = this.phaseWhen.get(this._phase);
if (barrier) {
barrier.open();
this.phaseWhen.delete(this._phase);
}
}
async when(phase: LifecycleMainPhase): Promise<void> {
if (phase <= this._phase) {
return;
}
let barrier = this.phaseWhen.get(phase);
if (!barrier) {
barrier = new Barrier();
this.phaseWhen.set(phase, barrier);
}
await barrier.wait();
}
registerWindow(window: ICodeWindow): void {
// track window count
@@ -317,8 +248,8 @@ export class LifecycleService extends Disposable implements ILifecycleService {
// The window already acknowledged to be closed
const windowId = window.id;
if (this.windowToCloseRequest.has(windowId)) {
this.windowToCloseRequest.delete(windowId);
if (this.windowToCloseRequest[windowId]) {
delete this.windowToCloseRequest[windowId];
return;
}
@@ -329,11 +260,11 @@ export class LifecycleService extends Disposable implements ILifecycleService {
e.preventDefault();
this.unload(window, UnloadReason.CLOSE).then(veto => {
if (veto) {
this.windowToCloseRequest.delete(windowId);
delete this.windowToCloseRequest[windowId];
return;
}
this.windowToCloseRequest.add(windowId);
this.windowToCloseRequest[windowId] = true;
// Fire onBeforeWindowClose before actually closing
this.logService.trace(`Lifecycle#onBeforeWindowClose.fire() - window ID ${windowId}`);
@@ -459,6 +390,10 @@ export class LifecycleService extends Disposable implements ILifecycleService {
});
}
/**
* A promise that completes to indicate if the quit request has been veto'd
* by the user or not.
*/
quit(fromUpdate?: boolean): Promise<boolean /* veto */> {
if (this.pendingQuitPromise) {
return this.pendingQuitPromise;

View File

@@ -8,7 +8,7 @@ import { IListMouseEvent, IListTouchEvent, IListRenderer, IListVirtualDelegate }
import { IPagedRenderer, PagedList } from 'vs/base/browser/ui/list/listPaging';
import { DefaultStyleController, IListOptions, IMultipleSelectionController, IOpenController, isSelectionRangeChangeEvent, isSelectionSingleChangeEvent, List } from 'vs/base/browser/ui/list/listWidget';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, dispose, IDisposable, toDisposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle';
import { combinedDisposable, Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { ITree, ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree';
@@ -78,7 +78,7 @@ export class ListService implements IListService {
this._lastFocusedWidget = widget;
}
return combinedDisposable(
const result = combinedDisposable([
widget.onDidFocus(() => this._lastFocusedWidget = widget),
toDisposable(() => this.lists.splice(this.lists.indexOf(registeredList), 1)),
widget.onDidDispose(() => {
@@ -87,7 +87,9 @@ export class ListService implements IListService {
this._lastFocusedWidget = undefined;
}
})
);
]);
return result;
}
}
@@ -198,18 +200,18 @@ class WorkbenchOpenController extends Disposable implements IOpenController {
}
function toWorkbenchListOptions<T>(options: IListOptions<T>, configurationService: IConfigurationService, keybindingService: IKeybindingService): [IListOptions<T>, IDisposable] {
const disposables = new DisposableStore();
const disposables: IDisposable[] = [];
const result = { ...options };
if (options.multipleSelectionSupport !== false && !options.multipleSelectionController) {
const multipleSelectionController = new MultipleSelectionController(configurationService);
result.multipleSelectionController = multipleSelectionController;
disposables.add(multipleSelectionController);
disposables.push(multipleSelectionController);
}
const openController = new WorkbenchOpenController(configurationService, options.openController);
result.openController = openController;
disposables.add(openController);
disposables.push(openController);
if (options.keyboardNavigationLabelProvider) {
const tlp = options.keyboardNavigationLabelProvider;
@@ -220,7 +222,7 @@ function toWorkbenchListOptions<T>(options: IListOptions<T>, configurationServic
};
}
return [result, disposables];
return [result, combinedDisposable(disposables)];
}
let sharedListStyleSheet: HTMLStyleElement;
@@ -281,7 +283,7 @@ export class WorkbenchList<T> extends List<T> {
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
this.disposables.push(
this.disposables.push(combinedDisposable([
this.contextKeyService,
(listService as ListService).register(this),
attachListStyler(this, themeService),
@@ -299,7 +301,7 @@ export class WorkbenchList<T> extends List<T> {
this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
})
);
]));
this.registerListeners();
}
@@ -322,7 +324,7 @@ export class WorkbenchPagedList<T> extends PagedList<T> {
readonly contextKeyService: IContextKeyService;
private readonly configurationService: IConfigurationService;
private readonly disposables: DisposableStore;
private disposables: IDisposable[];
private _useAltAsMultipleSelectionModifier: boolean;
@@ -349,8 +351,7 @@ export class WorkbenchPagedList<T> extends PagedList<T> {
}
);
this.disposables = new DisposableStore();
this.disposables.add(workbenchListOptionsDisposable);
this.disposables = [workbenchListOptionsDisposable];
this.contextKeyService = createScopedContextKeyService(contextKeyService, this);
this.configurationService = configurationService;
@@ -360,15 +361,17 @@ export class WorkbenchPagedList<T> extends PagedList<T> {
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
this.disposables.add(this.contextKeyService);
this.disposables.add((listService as ListService).register(this));
this.disposables.add(attachListStyler(this, themeService));
this.disposables.push(combinedDisposable([
this.contextKeyService,
(listService as ListService).register(this),
attachListStyler(this, themeService)
]));
this.registerListeners();
}
private registerListeners(): void {
this.disposables.add(this.configurationService.onDidChangeConfiguration(e => {
this.disposables.push(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(multiSelectModifierSettingKey)) {
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(this.configurationService);
}
@@ -382,7 +385,7 @@ export class WorkbenchPagedList<T> extends PagedList<T> {
dispose(): void {
super.dispose();
this.disposables.dispose();
this.disposables = dispose(this.disposables);
}
}
@@ -530,7 +533,7 @@ function massageControllerOptions(options: IControllerOptions): IControllerOptio
*/
export class WorkbenchTreeController extends DefaultController {
protected readonly disposables = new DisposableStore();
protected disposables: IDisposable[] = [];
constructor(
options: IControllerOptions,
@@ -546,7 +549,7 @@ export class WorkbenchTreeController extends DefaultController {
}
private registerListeners(): void {
this.disposables.add(this.configurationService.onDidChangeConfiguration(e => {
this.disposables.push(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(openModeSettingKey)) {
this.setOpenMode(this.getOpenModeSetting());
}
@@ -558,7 +561,7 @@ export class WorkbenchTreeController extends DefaultController {
}
dispose(): void {
this.disposables.dispose();
this.disposables = dispose(this.disposables);
}
}

View File

@@ -186,7 +186,7 @@ export class ConsoleLogService extends AbstractLogService implements ILogService
export class MultiplexLogService extends AbstractLogService implements ILogService {
_serviceBrand: any;
constructor(private readonly logServices: ReadonlyArray<ILogService>) {
constructor(private logServices: ILogService[]) {
super();
if (logServices.length) {
this.setLevel(logServices[0].getLevel());

View File

@@ -4,20 +4,24 @@
*--------------------------------------------------------------------------------------------*/
import * as path from 'vs/base/common/path';
import { ILogService, LogLevel, AbstractLogService } from 'vs/platform/log/common/log';
import { ILogService, LogLevel, NullLogService, AbstractLogService } from 'vs/platform/log/common/log';
import * as spdlog from 'spdlog';
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
async function createSpdLogLogger(processName: string, logsFolder: string): Promise<spdlog.RotatingLogger | null> {
export async function createSpdLogService(processName: string, logLevel: LogLevel, logsFolder: string): Promise<ILogService> {
// Do not crash if spdlog cannot be loaded
try {
const _spdlog = await import('spdlog');
const _spdlog: typeof spdlog = require.__$__nodeRequire('spdlog');
_spdlog.setAsyncMode(8192, 500);
const logfilePath = path.join(logsFolder, `${processName}.log`);
return _spdlog.createRotatingLoggerAsync(processName, logfilePath, 1024 * 1024 * 5, 6);
const logger = await _spdlog.createRotatingLoggerAsync(processName, logfilePath, 1024 * 1024 * 5, 6);
logger.setLevel(0);
return new SpdLogService(logger, logLevel);
} catch (e) {
console.error(e);
}
return null;
return new NullLogService();
}
export function createRotatingLogger(name: string, filename: string, filesize: number, filecount: number): spdlog.RotatingLogger {
@@ -25,88 +29,45 @@ export function createRotatingLogger(name: string, filename: string, filesize: n
return _spdlog.createRotatingLogger(name, filename, filesize, filecount);
}
interface ILog {
level: LogLevel;
message: string;
export function createBufferSpdLogService(processName: string, logLevel: LogLevel, logsFolder: string): ILogService {
const bufferLogService = new BufferLogService();
createSpdLogService(processName, logLevel, logsFolder).then(logger => bufferLogService.logger = logger);
return bufferLogService;
}
function log(logger: spdlog.RotatingLogger, level: LogLevel, message: string): void {
switch (level) {
case LogLevel.Trace: return logger.trace(message);
case LogLevel.Debug: return logger.debug(message);
case LogLevel.Info: return logger.info(message);
case LogLevel.Warning: return logger.warn(message);
case LogLevel.Error: return logger.error(message);
case LogLevel.Critical: return logger.critical(message);
default: throw new Error('Invalid log level');
}
}
export class SpdLogService extends AbstractLogService implements ILogService {
class SpdLogService extends AbstractLogService implements ILogService {
_serviceBrand: any;
private buffer: ILog[] = [];
private _loggerCreationPromise: Promise<void> | undefined = undefined;
private _logger: spdlog.RotatingLogger | undefined;
constructor(private readonly name: string, private readonly logsFolder: string, level: LogLevel) {
constructor(
private readonly logger: spdlog.RotatingLogger,
level: LogLevel = LogLevel.Error
) {
super();
this.setLevel(level);
this._createSpdLogLogger();
this._register(this.onDidChangeLogLevel(level => {
if (this._logger) {
this._logger.setLevel(level);
}
}));
}
private _createSpdLogLogger(): Promise<void> {
if (!this._loggerCreationPromise) {
this._loggerCreationPromise = createSpdLogLogger(this.name, this.logsFolder)
.then(logger => {
if (logger) {
this._logger = logger;
this._logger.setLevel(this.getLevel());
for (const { level, message } of this.buffer) {
log(this._logger, level, message);
}
this.buffer = [];
}
});
}
return this._loggerCreationPromise;
}
private _log(level: LogLevel, message: string): void {
if (this._logger) {
log(this._logger, level, message);
} else if (this.getLevel() <= level) {
this.buffer.push({ level, message });
}
}
trace(): void {
if (this.getLevel() <= LogLevel.Trace) {
this._log(LogLevel.Trace, this.format(arguments));
this.logger.trace(this.format(arguments));
}
}
debug(): void {
if (this.getLevel() <= LogLevel.Debug) {
this._log(LogLevel.Debug, this.format(arguments));
this.logger.debug(this.format(arguments));
}
}
info(): void {
if (this.getLevel() <= LogLevel.Info) {
this._log(LogLevel.Info, this.format(arguments));
this.logger.info(this.format(arguments));
}
}
warn(): void {
if (this.getLevel() <= LogLevel.Warning) {
this._log(LogLevel.Warning, this.format(arguments));
this.logger.warn(this.format(arguments));
}
}
@@ -117,33 +78,21 @@ export class SpdLogService extends AbstractLogService implements ILogService {
if (arg instanceof Error) {
const array = Array.prototype.slice.call(arguments) as any[];
array[0] = arg.stack;
this._log(LogLevel.Error, this.format(array));
this.logger.error(this.format(array));
} else {
this._log(LogLevel.Error, this.format(arguments));
this.logger.error(this.format(arguments));
}
}
}
critical(): void {
if (this.getLevel() <= LogLevel.Critical) {
this._log(LogLevel.Critical, this.format(arguments));
this.logger.critical(this.format(arguments));
}
}
dispose(): void {
if (this._logger) {
this.disposeLogger();
} else if (this._loggerCreationPromise) {
this._loggerCreationPromise.then(() => this.disposeLogger());
}
this._loggerCreationPromise = undefined;
}
private disposeLogger(): void {
if (this._logger) {
this._logger.drop();
this._logger = undefined;
}
this.logger.drop();
}
private format(args: any): string {

View File

@@ -71,15 +71,6 @@ export namespace MarkerSeverity {
case Severity.Ignore: return MarkerSeverity.Hint;
}
}
export function toSeverity(severity: MarkerSeverity): Severity {
switch (severity) {
case MarkerSeverity.Error: return Severity.Error;
case MarkerSeverity.Warning: return Severity.Warning;
case MarkerSeverity.Info: return Severity.Info;
case MarkerSeverity.Hint: return Severity.Ignore;
}
}
}
/**

View File

@@ -4,10 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import BaseSeverity from 'vs/base/common/severity';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IAction } from 'vs/base/common/actions';
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
export import Severity = BaseSeverity;
@@ -70,14 +69,14 @@ export interface INotificationActions {
* Primary actions show up as buttons as part of the message and will close
* the notification once clicked.
*/
primary?: ReadonlyArray<IAction>;
primary?: IAction[];
/**
* Secondary actions are meant to provide additional configuration or context
* for the notification and will show up less prominent. A notification does not
* close automatically when invoking a secondary action.
*/
secondary?: ReadonlyArray<IAction>;
secondary?: IAction[];
}
export interface INotificationProgress {
@@ -173,21 +172,6 @@ export interface IPromptOptions extends INotificationProperties {
onCancel?: () => void;
}
export interface IStatusMessageOptions {
/**
* An optional timeout after which the status message should show. By default
* the status message will show immediately.
*/
showAfter?: number;
/**
* An optional timeout after which the status message is to be hidden. By default
* the status message will not hide until another status message is displayed.
*/
hideAfter?: number;
}
/**
* A service to bring up notifications and non-modal prompts.
*
@@ -195,7 +179,7 @@ export interface IStatusMessageOptions {
*/
export interface INotificationService {
_serviceBrand: ServiceIdentifier<INotificationService>;
_serviceBrand: any;
/**
* Show the provided notification to the user. The returned `INotificationHandle`
@@ -237,24 +221,16 @@ export interface INotificationService {
* @returns a handle on the notification to e.g. hide it or update message, buttons, etc.
*/
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle;
/**
* Shows a status message in the status area with the provied text.
*
* @param message the message to show as status
* @param options provides some optional configuration options
*
* @returns a disposable to hide the status message
*/
status(message: NotificationMessage, options?: IStatusMessageOptions): IDisposable;
}
export class NoOpNotification implements INotificationHandle {
readonly progress = new NoOpProgress();
private readonly _onDidClose: Emitter<void> = new Emitter();
get onDidClose(): Event<void> { return this._onDidClose.event; }
get onDidClose(): Event<void> {
return this._onDidClose.event;
}
updateSeverity(severity: Severity): void { }
updateMessage(message: NotificationMessage): void { }

View File

@@ -3,36 +3,31 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions, IStatusMessageOptions } from 'vs/platform/notification/common/notification';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { INotificationService, INotificationHandle, NoOpNotification, Severity, INotification, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification';
export class TestNotificationService implements INotificationService {
_serviceBrand: any;
public _serviceBrand: any;
private static readonly NO_OP: INotificationHandle = new NoOpNotification();
info(message: string): INotificationHandle {
public info(message: string): INotificationHandle {
return this.notify({ severity: Severity.Info, message });
}
warn(message: string): INotificationHandle {
public warn(message: string): INotificationHandle {
return this.notify({ severity: Severity.Warning, message });
}
error(error: string | Error): INotificationHandle {
public error(error: string | Error): INotificationHandle {
return this.notify({ severity: Severity.Error, message: error });
}
notify(notification: INotification): INotificationHandle {
public notify(notification: INotification): INotificationHandle {
return TestNotificationService.NO_OP;
}
prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions): INotificationHandle {
return TestNotificationService.NO_OP;
}
status(message: string | Error, options?: IStatusMessageOptions): IDisposable {
return Disposable.None;
}
}

View File

@@ -10,13 +10,8 @@ export const IProductService = createDecorator<IProductService>('productService'
export interface IProductService {
_serviceBrand: any;
version: string;
version?: string;
commit?: string;
nameLong: string;
urlProtocol: string;
extensionAllowedProposedApi: string[];
uiExtensions?: string[];
enableTelemetry: boolean;
}

View File

@@ -81,6 +81,7 @@ export interface IProductConfiguration {
hockeyApp: {
'win32-ia32': string;
'win32-x64': string;
'linux-ia32': string;
'linux-x64': string;
'darwin': string;
};

View File

@@ -11,17 +11,9 @@ export class ProductService implements IProductService {
_serviceBrand: any;
get version(): string { return pkg.version; }
get version(): string | undefined { return pkg.version; }
get commit(): string | undefined { return product.commit; }
get nameLong(): string { return product.nameLong; }
get urlProtocol(): string { return product.urlProtocol; }
get extensionAllowedProposedApi(): string[] { return product.extensionAllowedProposedApi; }
get uiExtensions(): string[] | undefined { return product.uiExtensions; }
get enableTelemetry(): boolean { return product.enableTelemetry; }
}

View File

@@ -3,32 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { IAction } from 'vs/base/common/actions';
export const IProgressService = createDecorator<IProgressService>('progressService');
/**
* A progress service that can be used to report progress to various locations of the UI.
*/
export interface IProgressService {
_serviceBrand: ServiceIdentifier<IProgressService>;
withProgress<R = any>(options: IProgressOptions | IProgressNotificationOptions | IProgressCompositeOptions, task: (progress: IProgress<IProgressStep>) => Promise<R>, onDidCancel?: () => void): Promise<R>;
}
export const ILocalProgressService = createDecorator<ILocalProgressService>('localProgressService');
/**
* A progress service that will report progress local to the UI piece triggered from. E.g.
* if used from an action of a viewlet, the progress will be reported in that viewlet.
*/
export interface ILocalProgressService {
_serviceBrand: ServiceIdentifier<ILocalProgressService>;
_serviceBrand: any;
/**
* Show progress customized with the provided flags.
@@ -61,14 +44,9 @@ export interface IProgressOptions {
}
export interface IProgressNotificationOptions extends IProgressOptions {
readonly location: ProgressLocation.Notification;
readonly primaryActions?: ReadonlyArray<IAction>;
readonly secondaryActions?: ReadonlyArray<IAction>;
}
export interface IProgressCompositeOptions extends IProgressOptions {
location: ProgressLocation.Explorer | ProgressLocation.Extensions | ProgressLocation.Scm | string;
delay?: number;
location: ProgressLocation.Notification;
primaryActions?: IAction[];
secondaryActions?: IAction[];
}
export interface IProgressStep {
@@ -76,6 +54,15 @@ export interface IProgressStep {
increment?: number;
}
export const IProgressService2 = createDecorator<IProgressService2>('progressService2');
export interface IProgressService2 {
_serviceBrand: any;
withProgress<R = any>(options: IProgressOptions, task: (progress: IProgress<IProgressStep>) => Promise<R>, onDidCancel?: () => void): Promise<R>;
}
export interface IProgressRunner {
total(value: number): void;
worked(value: number): void;
@@ -131,7 +118,7 @@ export class LongRunningOperation {
private currentProgressTimeout: any;
constructor(
private localProgressService: ILocalProgressService
private progressService: IProgressService
) { }
start(progressDelay: number): IOperation {
@@ -144,7 +131,7 @@ export class LongRunningOperation {
const newOperationToken = new CancellationTokenSource();
this.currentProgressTimeout = setTimeout(() => {
if (newOperationId === this.currentOperationId) {
this.currentProgressRunner = this.localProgressService.show(true);
this.currentProgressRunner = this.progressService.show(true);
}
}, progressDelay);

View File

@@ -31,22 +31,26 @@ export interface IRegistry {
class RegistryImpl implements IRegistry {
private readonly data = new Map<string, any>();
private data: { [id: string]: any; };
constructor() {
this.data = {};
}
public add(id: string, data: any): void {
Assert.ok(Types.isString(id));
Assert.ok(Types.isObject(data));
Assert.ok(!this.data.has(id), 'There is already an extension with this id');
Assert.ok(!this.data.hasOwnProperty(id), 'There is already an extension with this id');
this.data.set(id, data);
this.data[id] = data;
}
public knows(id: string): boolean {
return this.data.has(id);
return this.data.hasOwnProperty(id);
}
public as(id: string): any {
return this.data.get(id) || null;
return this.data[id] || null;
}
}

View File

@@ -21,11 +21,14 @@ export class RemoteAuthorityResolverService implements IRemoteAuthorityResolverS
}
clearResolvedAuthority(authority: string): void {
throw new Error(`Not implemented`);
}
setResolvedAuthority(resolvedAuthority: ResolvedAuthority) {
throw new Error(`Not implemented`);
}
setResolvedAuthorityError(authority: string, err: any): void {
throw new Error(`Not implemented`);
}
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import { IDisposable } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { IRequestOptions, IRequestContext, IRequestFunction, request } from 'vs/base/node/request';
import { getProxyAgent } from 'vs/base/node/proxy';
@@ -16,21 +16,21 @@ import { CancellationToken } from 'vs/base/common/cancellation';
* This service exposes the `request` API, while using the global
* or configured proxy settings.
*/
export class RequestService extends Disposable implements IRequestService {
export class RequestService implements IRequestService {
_serviceBrand: any;
private proxyUrl?: string;
private strictSSL: boolean;
private authorization?: string;
private disposables: IDisposable[] = [];
constructor(
@IConfigurationService configurationService: IConfigurationService,
@ILogService private readonly logService: ILogService
) {
super();
this.configure(configurationService.getValue<IHTTPConfiguration>());
this._register(configurationService.onDidChangeConfiguration(() => this.configure(configurationService.getValue()), this));
configurationService.onDidChangeConfiguration(() => this.configure(configurationService.getValue()), this, this.disposables);
}
private configure(config: IHTTPConfiguration) {

View File

@@ -1,73 +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 Severity from 'vs/base/common/severity';
import { registerThemingParticipant, ITheme, LIGHT } from 'vs/platform/theme/common/themeService';
import { Color } from 'vs/base/common/color';
const errorStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8" cy="8" r="6" fill="#F6F6F6"/><path d="M8 3C5.238 3 3 5.238 3 8s2.238 5 5 5 5-2.238 5-5-2.238-5-5-5zm3 7l-1 1-2-2-2 2-1-1 2-2.027L5 6l1-1 2 2 2-2 1 1-2 1.973L11 10z" fill="`);
const errorEnd = encodeURIComponent(`"/><path fill="#fff" d="M11 6l-1-1-2 2-2-2-1 1 2 1.973L5 10l1 1 2-2 2 2 1-1-2-2.027z"/></svg>`);
const errorDarkStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="16" width="16"><circle cx="8" cy="8" r="6" fill="#1E1E1E"/><path d="M8 3C5.238 3 3 5.238 3 8s2.238 5 5 5 5-2.238 5-5-2.238-5-5-5zm3 7l-1 1-2-2-2 2-1-1 2-2.027L5 6l1-1 2 2 2-2 1 1-2 1.973L11 10z" fill="`);
const errorDarkEnd = encodeURIComponent(`"/><path fill="#252526" d="M11 6l-1-1-2 2-2-2-1 1 2 1.973L5 10l1 1 2-2 2 2 1-1-2-2.027z"/></svg>`);
const warningStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M7.5 2L2 12l2 2h9l2-2L9.5 2z"/><path d="M9 3H8l-4.5 9 1 1h8l1-1L9 3zm0 9H8v-1h1v1zm0-2H8V6h1v4z" fill="`);
const warningEnd = encodeURIComponent(`"/><path d="M9 10H8V6h1v4zm0 1H8v1h1v-1z"/></svg>`);
const warningDarkStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="16" width="16"><path fill="#1E1E1E" d="M7.5 2L2 12l2 2h9l2-2L9.5 2z"/><path d="M9 3H8l-4.5 9 1 1h8l1-1L9 3zm0 9H8v-1h1v1zm0-2H8V6h1v4z" fill="`);
const warningDarkEnd = encodeURIComponent(`"/><path d="M9 10H8V6h1v4zm0 1H8v1h1v-1z"/></svg>`);
const infoStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8.5" cy="7.5" r="5.5" fill="#F6F6F6"/><path d="M8.5 3C6.015 3 4 5.015 4 7.5S6.015 12 8.5 12 13 9.985 13 7.5 10.985 3 8.5 3zm.5 8H8V6h1v5zm0-6H8V4h1v1z" fill="`);
const infoEnd = encodeURIComponent(`"/><path d="M8 6h1v5H8V6zm0-2v1h1V4H8z" fill="#fff"/></svg>`);
const infoDarkStart = encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8.5" cy="7.5" r="5.5" fill="#1E1E1E"/><path d="M8.5 3C6.015 3 4 5.015 4 7.5S6.015 12 8.5 12 13 9.985 13 7.5 10.985 3 8.5 3zm.5 8H8V6h1v5zm0-6H8V4h1v1z" fill="`);
const infoDarkEnd = encodeURIComponent(`"/><path d="M8 6h1v5H8V6zm0-2v1h1V4H8z" fill="#252526"/></svg>`);
export namespace SeverityIcon {
export function getSVGData(severity: Severity, theme: ITheme): string {
switch (severity) {
case Severity.Ignore:
const ignoreColor = theme.type === LIGHT ? Color.fromHex('#1BA1E2') : Color.fromHex('#1BA1E2');
return theme.type === LIGHT ? infoStart + encodeURIComponent(ignoreColor.toString()) + infoEnd
: infoDarkStart + encodeURIComponent(ignoreColor.toString()) + infoDarkEnd;
case Severity.Info:
const infoColor = theme.type === LIGHT ? Color.fromHex('#1BA1E2') : Color.fromHex('#1BA1E2');
return theme.type === LIGHT ? infoStart + encodeURIComponent(infoColor.toString()) + infoEnd
: infoDarkStart + encodeURIComponent(infoColor.toString()) + infoDarkEnd;
case Severity.Warning:
const warningColor = theme.type === LIGHT ? Color.fromHex('#fc0') : Color.fromHex('#fc0');
return theme.type === LIGHT ? warningStart + encodeURIComponent(warningColor.toString()) + warningEnd
: warningDarkStart + encodeURIComponent(warningColor.toString()) + warningDarkEnd;
case Severity.Error:
const errorColor = theme.type === LIGHT ? Color.fromHex('#E51400') : Color.fromHex('#F48771');
return theme.type === LIGHT ? errorStart + encodeURIComponent(errorColor.toString()) + errorEnd
: errorDarkStart + encodeURIComponent(errorColor.toString()) + errorDarkEnd;
}
return '';
}
export function className(severity: Severity): string {
switch (severity) {
case Severity.Ignore:
return 'severity-icon severity-ignore';
case Severity.Info:
return 'severity-icon severity-info';
case Severity.Warning:
return 'severity-icon severity-warning';
case Severity.Error:
return 'severity-icon severity-error';
}
return '';
}
}
function getCSSRule(severity: Severity, theme: ITheme): string {
return `.${SeverityIcon.className(severity).split(' ').join('.')} { background: url("data:image/svg+xml,${SeverityIcon.getSVGData(severity, theme)}") center center no-repeat; height: 16px; width: 16px; }`;
}
registerThemingParticipant((theme, collector) => {
collector.addRule(getCSSRule(Severity.Error, theme));
collector.addRule(getCSSRule(Severity.Warning, theme));
collector.addRule(getCSSRule(Severity.Info, theme));
collector.addRule(getCSSRule(Severity.Ignore, theme));
});

View File

@@ -27,36 +27,27 @@ export class FileStorage {
}
async init(): Promise<void> {
if (this._database) {
return; // return if database was already loaded
}
const database = await this.loadAsync();
if (this._database) {
return; // return if database was already loaded
}
this._database = database;
}
private loadSync(): object {
try {
this.lastFlushedSerializedDatabase = fs.readFileSync(this.dbPath).toString();
const contents = await readFile(this.dbPath);
return JSON.parse(this.lastFlushedSerializedDatabase);
try {
this.lastFlushedSerializedDatabase = contents.toString();
this._database = JSON.parse(this.lastFlushedSerializedDatabase);
} catch (error) {
this._database = {};
}
} catch (error) {
if (error.code !== 'ENOENT') {
this.onError(error);
}
return {};
this._database = {};
}
}
private async loadAsync(): Promise<object> {
private loadSync(): object {
try {
this.lastFlushedSerializedDatabase = (await readFile(this.dbPath)).toString();
this.lastFlushedSerializedDatabase = fs.readFileSync(this.dbPath).toString();
return JSON.parse(this.lastFlushedSerializedDatabase);
} catch (error) {

View File

@@ -3,15 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export const IStatusbarService = createDecorator<IStatusbarService>('statusbarService');
export const enum StatusbarAlignment {
LEFT,
RIGHT
LEFT, RIGHT
}
/**
@@ -51,6 +51,11 @@ export interface IStatusbarEntry {
*/
readonly arguments?: any[];
/**
* An optional extension ID if this entry is provided from an extension.
*/
readonly extensionId?: ExtensionIdentifier;
/**
* Wether to show a beak above the status bar entry.
*/
@@ -59,24 +64,18 @@ export interface IStatusbarEntry {
export interface IStatusbarService {
_serviceBrand: ServiceIdentifier<IStatusbarService>;
_serviceBrand: any;
/**
* Adds an entry to the statusbar with the given alignment and priority. Use the returned accessor
* to update or remove the statusbar entry.
*
* @param id identifier of the entry is needed to allow users to hide entries via settings
* @param name human readable name the entry is about
* @param alignment either LEFT or RIGHT
* @param priority items get arranged from highest priority to lowest priority from left to right
* in their respective alignment slot
*/
addEntry(entry: IStatusbarEntry, id: string, name: string, alignment: StatusbarAlignment, priority?: number): IStatusbarEntryAccessor;
addEntry(entry: IStatusbarEntry, alignment: StatusbarAlignment, priority?: number): IStatusbarEntryAccessor;
/**
* Allows to update an entry's visibilty with the provided ID.
* Prints something to the status bar area with optional auto dispose and delay.
*/
updateEntryVisibility(id: string, visible: boolean): void;
setStatusMessage(message: string, autoDisposeAfter?: number, delayBy?: number): IDisposable;
}
export interface IStatusbarEntryAccessor extends IDisposable {

View File

@@ -14,7 +14,7 @@ export const lastSessionDateStorageKey = 'telemetry.lastSessionDate';
// {{ SQL CARBON EDIT }}
import product from 'vs/platform/product/node/product';
export async function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string | undefined, version: string | undefined, machineId: string, installSourcePath: string, remoteAuthority?: string): Promise<{ [name: string]: string | undefined }> {
export async function resolveWorkbenchCommonProperties(storageService: IStorageService, commit: string | undefined, version: string | undefined, machineId: string, installSourcePath: string): Promise<{ [name: string]: string | undefined }> {
const result = await resolveCommonProperties(commit, version, machineId, installSourcePath);
const instanceId = storageService.get(instanceStorageKey, StorageScope.GLOBAL)!;
const firstSessionDate = storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL)!;
@@ -32,9 +32,11 @@ export async function resolveWorkbenchCommonProperties(storageService: IStorageS
// result['common.isNewSession'] = !lastSessionDate ? '1' : '0';
// __GDPR__COMMON__ "common.instanceId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
// result['common.instanceId'] = instanceId;
// __GDPR__COMMON__ "common.remoteAuthority" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
// result['common.remoteAuthority'] = cleanRemoteAuthority(remoteAuthority);
// __GDPR__COMMON__ "common.version.shell" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
result['common.version.shell'] = process.versions && process.versions['electron'];
// __GDPR__COMMON__ "common.version.renderer" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
result['common.version.renderer'] = process.versions && process.versions['chrome'];
// {{SQL CARBON EDIT}}
result['common.application.name'] = product.nameLong;
// {{SQL CARBON EDIT}}
@@ -60,20 +62,5 @@ function setUsageDates(storageService: IStorageService): void {
// monthly last usage date
const monthlyLastUseDate = storageService.get('telemetry.monthlyLastUseDate', StorageScope.GLOBAL, appStartDate.toUTCString());
storageService.store('telemetry.monthlyLastUseDate', monthlyLastUseDate, StorageScope.GLOBAL);
}
function cleanRemoteAuthority(remoteAuthority?: string): string {
if (!remoteAuthority) {
return 'none';
}
let ret = 'other';
// Whitelisted remote authorities
['ssh-remote', 'dev-container', 'wsl'].forEach((res: string) => {
if (remoteAuthority!.indexOf(`${res}+`) === 0) {
ret = res;
}
});
return ret;
}

View File

@@ -266,18 +266,6 @@ export const menuSelectionBackground = registerColor('menu.selectionBackground',
export const menuSelectionBorder = registerColor('menu.selectionBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('menuSelectionBorder', "Border color of the selected menu item in menus."));
export const menuSeparatorBackground = registerColor('menu.separatorBackground', { dark: '#BBBBBB', light: '#888888', hc: contrastBorder }, nls.localize('menuSeparatorBackground', "Color of a separator menu item in menus."));
export const editorErrorForeground = registerColor('editorError.foreground', { dark: '#F48771', light: '#E51400', hc: null }, nls.localize('editorError.foreground', 'Foreground color of error squigglies in the editor.'));
export const editorErrorBorder = registerColor('editorError.border', { dark: null, light: null, hc: Color.fromHex('#E47777').transparent(0.8) }, nls.localize('errorBorder', 'Border color of error boxes in the editor.'));
export const editorWarningForeground = registerColor('editorWarning.foreground', { dark: '#FFCC00', light: '#E9A700', hc: null }, nls.localize('editorWarning.foreground', 'Foreground color of warning squigglies in the editor.'));
export const editorWarningBorder = registerColor('editorWarning.border', { dark: null, light: null, hc: Color.fromHex('#FFCC00').transparent(0.8) }, nls.localize('warningBorder', 'Border color of warning boxes in the editor.'));
export const editorInfoForeground = registerColor('editorInfo.foreground', { dark: '#008000', light: '#008000', hc: null }, nls.localize('editorInfo.foreground', 'Foreground color of info squigglies in the editor.'));
export const editorInfoBorder = registerColor('editorInfo.border', { dark: null, light: null, hc: Color.fromHex('#71B771').transparent(0.8) }, nls.localize('infoBorder', 'Border color of info boxes in the editor.'));
export const editorHintForeground = registerColor('editorHint.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hc: null }, nls.localize('editorHint.foreground', 'Foreground color of hint squigglies in the editor.'));
export const editorHintBorder = registerColor('editorHint.border', { dark: null, light: null, hc: Color.fromHex('#eeeeee').transparent(0.8) }, nls.localize('hintBorder', 'Border color of hint boxes in the editor.'));
/**
* Editor background color.
* Because of bug https://monacotools.visualstudio.com/DefaultCollection/Monaco/_workitems/edit/13254

View File

@@ -351,4 +351,4 @@ export const defaultDialogStyles = <IDialogStyleOverrides>{
export function attachDialogStyler(widget: IThemable, themeService: IThemeService, style?: IDialogStyleOverrides): IDisposable {
return attachStyler(themeService, { ...defaultDialogStyles, ...style }, widget);
}
}

View File

@@ -1,67 +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 { isWindows, isMacintosh } from 'vs/base/common/platform';
import { systemPreferences, ipcMain as ipc } from 'electron';
import { IStateService } from 'vs/platform/state/common/state';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
const DEFAULT_BG_LIGHT = '#FFFFFF';
const DEFAULT_BG_DARK = '#1E1E1E';
const DEFAULT_BG_HC_BLACK = '#000000';
const THEME_STORAGE_KEY = 'theme';
const THEME_BG_STORAGE_KEY = 'themeBackground';
export const IThemeMainService = createDecorator<IThemeMainService>('themeMainService');
export interface IThemeMainService {
_serviceBrand: any;
getBackgroundColor(): string;
}
export class ThemeMainService implements IThemeMainService {
_serviceBrand: any;
constructor(@IStateService private stateService: IStateService) {
ipc.on('vscode:changeColorTheme', (e: Event, windowId: number, broadcast: string) => {
// Theme changes
if (typeof broadcast === 'string') {
this.storeBackgroundColor(JSON.parse(broadcast));
}
});
}
private storeBackgroundColor(data: { baseTheme: string, background: string }): void {
this.stateService.setItem(THEME_STORAGE_KEY, data.baseTheme);
this.stateService.setItem(THEME_BG_STORAGE_KEY, data.background);
}
public getBackgroundColor(): string {
if (isWindows && systemPreferences.isInvertedColorScheme()) {
return DEFAULT_BG_HC_BLACK;
}
let background = this.stateService.getItem<string | null>(THEME_BG_STORAGE_KEY, null);
if (!background) {
let baseTheme: string;
if (isWindows && systemPreferences.isInvertedColorScheme()) {
baseTheme = 'hc-black';
} else {
baseTheme = this.stateService.getItem<string>(THEME_STORAGE_KEY, 'vs-dark').split(' ')[0];
}
background = (baseTheme === 'hc-black') ? DEFAULT_BG_HC_BLACK : (baseTheme === 'vs' ? DEFAULT_BG_LIGHT : DEFAULT_BG_DARK);
}
if (isMacintosh && background.toUpperCase() === DEFAULT_BG_DARK) {
background = '#171717'; // https://github.com/electron/electron/issues/5150
}
return background;
}
}

View File

@@ -239,10 +239,10 @@ export class Win32UpdateService extends AbstractUpdateService {
});
const readyMutexName = `${product.win32MutexName}-ready`;
const mutex = await import('windows-mutex');
const isActive = (require.__$__nodeRequire('windows-mutex') as any).isActive;
// poll for mutex-ready
pollUntil(() => mutex.isActive(readyMutexName))
pollUntil(() => isActive(readyMutexName))
.then(() => this.setState(State.Ready(update)));
}

View File

@@ -6,7 +6,7 @@
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IProcessEnvironment, isMacintosh, isLinux, isWeb } from 'vs/base/common/platform';
import { IProcessEnvironment, isMacintosh, isLinux } from 'vs/base/common/platform';
import { ParsedArgs, IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened, IRecent } from 'vs/platform/history/common/history';
@@ -282,10 +282,6 @@ export interface IWindowSettings {
}
export function getTitleBarStyle(configurationService: IConfigurationService, environment: IEnvironmentService, isExtensionDevelopment = environment.isExtensionDevelopment): 'native' | 'custom' {
if (isWeb) {
return 'custom';
}
const configuration = configurationService.getValue<IWindowSettings>('window');
const isDev = !environment.isBuilt || isExtensionDevelopment;

View File

@@ -92,6 +92,7 @@ export interface IWindowsMainService {
readonly onWindowClose: Event<number>;
// methods
ready(initialUserEnv: IProcessEnvironment): void;
reload(win: ICodeWindow, cli?: ParsedArgs): void;
enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined>;
closeWorkspace(win: ICodeWindow): void;

View File

@@ -403,20 +403,19 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
buttons = [ok, copy];
}
const result = await this.windowsMainService.showMessageBox({
this.windowsMainService.showMessageBox({
title: product.nameLong,
type: 'info',
message: product.nameLong,
detail: `\n${detail}`,
buttons,
noLink: true,
defaultId: buttons.indexOf(ok),
cancelId: buttons.indexOf(ok)
}, this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow());
if (buttons[result.button] === copy) {
clipboard.writeText(detail);
}
defaultId: buttons.indexOf(ok)
}, this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow()).then(result => {
if (buttons[result.button] === copy) {
clipboard.writeText(detail);
}
});
}
async handleURL(uri: URI): Promise<boolean> {

View File

@@ -228,7 +228,7 @@ export function toWorkspaceFolder(resource: URI): WorkspaceFolder {
export function toWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[], workspaceConfigFile: URI): WorkspaceFolder[] {
let result: WorkspaceFolder[] = [];
let seen: Set<string> = new Set();
let seen: { [uri: string]: boolean } = Object.create(null);
const relativeTo = resources.dirname(workspaceConfigFile);
for (let configuredFolder of configuredFolders) {
@@ -252,8 +252,8 @@ export function toWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[],
if (uri) {
// remove duplicates
let comparisonKey = resources.getComparisonKey(uri);
if (!seen.has(comparisonKey)) {
seen.add(comparisonKey);
if (!seen[comparisonKey]) {
seen[comparisonKey] = true;
const name = configuredFolder.name || resources.basenameOrAuthority(uri);
result.push(new WorkspaceFolder({ uri, name, index: result.length }, configuredFolder));