mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-11 10:38:31 -05:00
This reverts commit d15a3fcc98.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
56
src/vs/platform/configuration/node/configuration.ts
Normal file
56
src/vs/platform/configuration/node/configuration.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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 {};
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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: () => {
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.") },
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -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[]> {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ export interface IProductConfiguration {
|
||||
hockeyApp: {
|
||||
'win32-ia32': string;
|
||||
'win32-x64': string;
|
||||
'linux-ia32': string;
|
||||
'linux-x64': string;
|
||||
'darwin': string;
|
||||
};
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -351,4 +351,4 @@ export const defaultDialogStyles = <IDialogStyleOverrides>{
|
||||
|
||||
export function attachDialogStyler(widget: IThemable, themeService: IThemeService, style?: IDialogStyleOverrides): IDisposable {
|
||||
return attachStyler(themeService, { ...defaultDialogStyles, ...style }, widget);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user