Merge from vscode 966b87dd4013be1a9c06e2b8334522ec61905cc2 (#4696)

This commit is contained in:
Anthony Dresser
2019-03-26 11:43:38 -07:00
committed by GitHub
parent b1393ae615
commit 0d8ef9583b
268 changed files with 5947 additions and 3422 deletions

View File

@@ -90,10 +90,10 @@ export function fillInActionBarActions(menu: IMenu, options: IMenuActionOptions
}
// {{SQL CARBON EDIT}} add export modifier
export function fillInActions(groups: [string, Array<MenuItemAction | SubmenuItemAction>][], target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, getAlternativeActions, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation'): void {
export function fillInActions(groups: [string, Array<MenuItemAction | SubmenuItemAction>][], target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, useAlternativeActions: boolean, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation'): void {
for (let tuple of groups) {
let [group, actions] = tuple;
if (getAlternativeActions) {
if (useAlternativeActions) {
actions = actions.map(a => (a instanceof MenuItemAction) && !!a.alt ? a.alt : a);
}

View File

@@ -65,7 +65,7 @@ export const enum MenuId {
DebugConsoleContext,
DebugVariablesContext,
DebugWatchContext,
DebugToolbar,
DebugToolBar,
EditorContext,
EditorTitle,
EditorTitleContext,

View File

@@ -29,6 +29,8 @@ export interface IConfigurationOverrides {
export const enum ConfigurationTarget {
USER = 1,
USER_LOCAL,
USER_REMOTE,
WORKSPACE,
WORKSPACE_FOLDER,
DEFAULT,
@@ -37,6 +39,8 @@ export const enum ConfigurationTarget {
export function ConfigurationTargetToString(configurationTarget: ConfigurationTarget) {
switch (configurationTarget) {
case ConfigurationTarget.USER: return 'USER';
case ConfigurationTarget.USER_LOCAL: return 'USER_LOCAL';
case ConfigurationTarget.USER_REMOTE: return 'USER_REMOTE';
case ConfigurationTarget.WORKSPACE: return 'WORKSPACE';
case ConfigurationTarget.WORKSPACE_FOLDER: return 'WORKSPACE_FOLDER';
case ConfigurationTarget.DEFAULT: return 'DEFAULT';
@@ -88,6 +92,8 @@ export interface IConfigurationService {
inspect<T>(key: string, overrides?: IConfigurationOverrides): {
default: T,
user: T,
userLocal?: T,
userRemote?: T,
workspace?: T,
workspaceFolder?: T,
memory?: T,

View File

@@ -36,6 +36,10 @@ export class ConfigurationModel implements IConfigurationModel {
return this.checkAndFreeze(this._keys);
}
isEmpty(): boolean {
return this._keys.length === 0 && Object.keys(this._contents).length === 0 && this._overrides.length === 0;
}
getValue<V>(section: string | undefined): V {
return section ? getConfigurationValue<any>(this.contents, section) : this.contents;
}
@@ -284,7 +288,8 @@ export class Configuration {
constructor(
private _defaultConfiguration: ConfigurationModel,
private _userConfiguration: ConfigurationModel,
private _localUserConfiguration: ConfigurationModel,
private _remoteUserConfiguration: ConfigurationModel = new ConfigurationModel(),
private _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(),
private _folderConfigurations: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>(),
private _memoryConfiguration: ConfigurationModel = new ConfigurationModel(),
@@ -323,6 +328,8 @@ export class Configuration {
inspect<C>(key: string, overrides: IConfigurationOverrides, workspace: Workspace | undefined): {
default: C,
user: C,
userLocal?: C,
userRemote?: C,
workspace?: C,
workspaceFolder?: C
memory?: C
@@ -333,7 +340,9 @@ export class Configuration {
const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;
return {
default: overrides.overrideIdentifier ? this._defaultConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._defaultConfiguration.freeze().getValue(key),
user: overrides.overrideIdentifier ? this._userConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._userConfiguration.freeze().getValue(key),
user: overrides.overrideIdentifier ? this.userConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.userConfiguration.freeze().getValue(key),
userLocal: overrides.overrideIdentifier ? this.localUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.localUserConfiguration.freeze().getValue(key),
userRemote: overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.remoteUserConfiguration.freeze().getValue(key),
workspace: workspace ? overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._workspaceConfiguration.freeze().getValue(key) : undefined, //Check on workspace exists or not because _workspaceConfiguration is never null
workspaceFolder: folderConfigurationModel ? overrides.overrideIdentifier ? folderConfigurationModel.freeze().override(overrides.overrideIdentifier).getValue(key) : folderConfigurationModel.freeze().getValue(key) : undefined,
memory: overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).getValue(key) : memoryConfigurationModel.getValue(key),
@@ -350,7 +359,7 @@ export class Configuration {
const folderConfigurationModel = this.getFolderConfigurationModelForResource(undefined, workspace);
return {
default: this._defaultConfiguration.freeze().keys,
user: this._userConfiguration.freeze().keys,
user: this.userConfiguration.freeze().keys,
workspace: this._workspaceConfiguration.freeze().keys,
workspaceFolder: folderConfigurationModel ? folderConfigurationModel.freeze().keys : []
};
@@ -362,8 +371,16 @@ export class Configuration {
this._foldersConsolidatedConfigurations.clear();
}
updateUserConfiguration(userConfiguration: ConfigurationModel): void {
this._userConfiguration = userConfiguration;
updateLocalUserConfiguration(localUserConfiguration: ConfigurationModel): void {
this._localUserConfiguration = localUserConfiguration;
this._userConfiguration = null;
this._workspaceConsolidatedConfiguration = null;
this._foldersConsolidatedConfigurations.clear();
}
updateRemoteUserConfiguration(remoteUserConfiguration: ConfigurationModel): void {
this._remoteUserConfiguration = remoteUserConfiguration;
this._userConfiguration = null;
this._workspaceConsolidatedConfiguration = null;
this._foldersConsolidatedConfigurations.clear();
}
@@ -380,7 +397,7 @@ export class Configuration {
}
deleteFolderConfiguration(resource: URI): void {
this.folders.delete(resource);
this.folderConfigurations.delete(resource);
this._foldersConsolidatedConfigurations.delete(resource);
}
@@ -388,15 +405,30 @@ export class Configuration {
return this._defaultConfiguration;
}
get user(): ConfigurationModel {
private _userConfiguration: ConfigurationModel | null;
get userConfiguration(): ConfigurationModel {
if (!this._userConfiguration) {
this._userConfiguration = this._remoteUserConfiguration.isEmpty() ? this._localUserConfiguration : this._localUserConfiguration.merge(this._remoteUserConfiguration);
if (this._freeze) {
this._userConfiguration.freeze();
}
}
return this._userConfiguration;
}
get workspace(): ConfigurationModel {
get localUserConfiguration(): ConfigurationModel {
return this._localUserConfiguration;
}
get remoteUserConfiguration(): ConfigurationModel {
return this._remoteUserConfiguration;
}
get workspaceConfiguration(): ConfigurationModel {
return this._workspaceConfiguration;
}
protected get folders(): ResourceMap<ConfigurationModel> {
protected get folderConfigurations(): ResourceMap<ConfigurationModel> {
return this._folderConfigurations;
}
@@ -424,7 +456,7 @@ export class Configuration {
private getWorkspaceConsolidatedConfiguration(): ConfigurationModel {
if (!this._workspaceConsolidatedConfiguration) {
this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this._userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
if (this._freeze) {
this._workspaceConfiguration = this._workspaceConfiguration.freeze();
}
@@ -468,9 +500,9 @@ export class Configuration {
keys: this._defaultConfiguration.keys
},
user: {
contents: this._userConfiguration.contents,
overrides: this._userConfiguration.overrides,
keys: this._userConfiguration.keys
contents: this.userConfiguration.contents,
overrides: this.userConfiguration.overrides,
keys: this.userConfiguration.keys
},
workspace: {
contents: this._workspaceConfiguration.contents,
@@ -489,7 +521,7 @@ export class Configuration {
allKeys(workspace: Workspace | undefined): string[] {
let keys = this.keys(workspace);
let all = [...keys.default];
const addKeys = (keys) => {
const addKeys = (keys: string[]) => {
for (const key of keys) {
if (all.indexOf(key) === -1) {
all.push(key);
@@ -498,8 +530,8 @@ export class Configuration {
};
addKeys(keys.user);
addKeys(keys.workspace);
for (const resource of this.folders.keys()) {
addKeys(this.folders.get(resource)!.keys);
for (const resource of this.folderConfigurations.keys()) {
addKeys(this.folderConfigurations.get(resource)!.keys);
}
return all;
}

View File

@@ -3,13 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, toDisposable } 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';
import { RunOnceScheduler } from 'vs/base/common/async';
import { URI } from 'vs/base/common/uri';
import { IFileService, FileChangesEvent } from 'vs/platform/files/common/files';
import * as resources from 'vs/base/common/resources';
export class UserConfiguration extends Disposable {
export class NodeBasedUserConfiguration extends Disposable {
private userConfigModelWatcher: ConfigWatcher<ConfigurationModelParser>;
private initializePromise: Promise<void>;
@@ -50,4 +54,53 @@ export class UserConfiguration extends Disposable {
return this.initialize().then(() => new Promise<ConfigurationModel>(c => this.userConfigModelWatcher.reload(userConfigModelParser => c(userConfigModelParser.configurationModel))));
}
}
export class FileServiceBasedUserConfiguration extends Disposable {
private readonly reloadConfigurationScheduler: RunOnceScheduler;
protected readonly _onDidChangeConfiguration: Emitter<ConfigurationModel> = this._register(new Emitter<ConfigurationModel>());
readonly onDidChangeConfiguration: Event<ConfigurationModel> = this._onDidChangeConfiguration.event;
constructor(
private readonly configurationResource: URI,
private readonly fileService: IFileService
) {
super();
this._register(fileService.onFileChanges(e => this.handleFileEvents(e)));
this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.reload().then(configurationModel => this._onDidChangeConfiguration.fire(configurationModel)), 50));
this.fileService.watchFileChanges(this.configurationResource);
this._register(toDisposable(() => this.fileService.unwatchFileChanges(this.configurationResource)));
}
initialize(): Promise<ConfigurationModel> {
return this.reload();
}
reload(): Promise<ConfigurationModel> {
return this.fileService.resolveContent(this.configurationResource)
.then(content => content.value, () => {
// File not found
return '';
}).then(content => {
const parser = new ConfigurationModelParser(this.configurationResource.toString());
parser.parse(content);
return parser.configurationModel;
});
}
private handleFileEvents(event: FileChangesEvent): void {
const events = event.changes;
let affectedByChanges = false;
// Find changes that affect workspace file
for (let i = 0, len = events.length; i < len && !affectedByChanges; i++) {
affectedByChanges = resources.isEqual(this.configurationResource, events[i].resource);
}
if (affectedByChanges) {
this.reloadConfigurationScheduler.schedule();
}
}
}

View File

@@ -11,14 +11,14 @@ import { DefaultConfigurationModel, Configuration, ConfigurationChangeEvent, Con
import { Event, Emitter } from 'vs/base/common/event';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { UserConfiguration } from 'vs/platform/configuration/node/configuration';
import { NodeBasedUserConfiguration } from 'vs/platform/configuration/node/configuration';
export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable {
_serviceBrand: any;
private _configuration: Configuration;
private userConfiguration: UserConfiguration;
private userConfiguration: NodeBasedUserConfiguration;
private readonly _onDidChangeConfiguration: Emitter<IConfigurationChangeEvent> = this._register(new Emitter<IConfigurationChangeEvent>());
readonly onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event;
@@ -28,7 +28,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
) {
super();
this.userConfiguration = this._register(new UserConfiguration(environmentService.appSettingsPath));
this.userConfiguration = this._register(new NodeBasedUserConfiguration(environmentService.appSettingsPath));
// Initialize
const defaults = new DefaultConfigurationModel();
@@ -91,10 +91,10 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
}
private onDidChangeUserConfiguration(userConfigurationModel: ConfigurationModel): void {
const { added, updated, removed } = compare(this._configuration.user, userConfigurationModel);
const { added, updated, removed } = compare(this._configuration.localUserConfiguration, userConfigurationModel);
const changedKeys = [...added, ...updated, ...removed];
if (changedKeys.length) {
this._configuration.updateUserConfiguration(userConfigurationModel);
this._configuration.updateLocalUserConfiguration(userConfigurationModel);
this.trigger(changedKeys, ConfigurationTarget.USER);
}
}
@@ -113,7 +113,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
case ConfigurationTarget.DEFAULT:
return this._configuration.defaults.contents;
case ConfigurationTarget.USER:
return this._configuration.user.contents;
return this._configuration.localUserConfiguration.contents;
}
return {};
}

View File

@@ -56,6 +56,8 @@ export class TestConfigurationService implements IConfigurationService {
public inspect<T>(key: string, overrides?: IConfigurationOverrides): {
default: T,
user: T,
userLocal?: T,
userRemote?: T,
workspace?: T,
workspaceFolder?: T
value: T,

View File

@@ -26,7 +26,7 @@ export interface IDiagnosticsService {
formatEnvironment(info: IMainProcessInfo): string;
getPerformanceInfo(info: IMainProcessInfo): Promise<PerformanceInfo>;
getSystemInfo(info: IMainProcessInfo): SystemInfo;
printDiagnostics(info: IMainProcessInfo): Promise<any>;
getDiagnostics(info: IMainProcessInfo): Promise<string>;
}
export interface VersionInfo {
@@ -156,28 +156,29 @@ export class DiagnosticsService implements IDiagnosticsService {
return systemInfo;
}
printDiagnostics(info: IMainProcessInfo): Promise<any> {
getDiagnostics(info: IMainProcessInfo): Promise<string> {
const output: string[] = [];
return listProcesses(info.mainPID).then(rootProcess => {
// Environment Info
console.log('');
console.log(this.formatEnvironment(info));
output.push('');
output.push(this.formatEnvironment(info));
// Process List
console.log('');
console.log(this.formatProcessList(info, rootProcess));
output.push('');
output.push(this.formatProcessList(info, rootProcess));
// Workspace Stats
const workspaceStatPromises: Promise<void>[] = [];
if (info.windows.some(window => window.folderURIs && window.folderURIs.length > 0)) {
console.log('');
console.log('Workspace Stats: ');
output.push('');
output.push('Workspace Stats: ');
info.windows.forEach(window => {
if (window.folderURIs.length === 0) {
return;
}
console.log(`| Window (${window.title})`);
output.push(`| Window (${window.title})`);
window.folderURIs.forEach(uriComponents => {
const folderUri = URI.revive(uriComponents);
@@ -188,22 +189,24 @@ export class DiagnosticsService implements IDiagnosticsService {
if (stats.maxFilesReached) {
countMessage = `more than ${countMessage}`;
}
console.log(`| Folder (${basename(folder)}): ${countMessage}`);
console.log(this.formatWorkspaceStats(stats));
output.push(`| Folder (${basename(folder)}): ${countMessage}`);
output.push(this.formatWorkspaceStats(stats));
}).catch(error => {
console.log(`| Error: Unable to collect workspace stats for folder ${folder} (${error.toString()})`);
output.push(`| Error: Unable to collect workspace stats for folder ${folder} (${error.toString()})`);
}));
} else {
console.log(`| Folder (${folderUri.toString()}): Workspace stats not available.`);
output.push(`| Folder (${folderUri.toString()}): Workspace stats not available.`);
}
});
});
}
return Promise.all(workspaceStatPromises).then(() => {
console.log('');
console.log('');
output.push('');
output.push('');
return output.join('\n');
});
});
}
@@ -340,7 +343,7 @@ function asSortedItems(map: Map<string, number>): WorkspaceStatItem[] {
// const errors: ParseError[] = [];
// const json = parse(contents.toString(), errors);
// if (errors.length) {
// console.log(`Unable to parse ${launchConfig}`);
// output.push(`Unable to parse ${launchConfig}`);
// return resolve([]);
// }

View File

@@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { IDialogService, IDialogOptions, IConfirmation, IConfirmationResult, DialogType } from 'vs/platform/dialogs/common/dialogs';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { ILogService } from 'vs/platform/log/common/log';
import Severity from 'vs/base/common/severity';
import { Dialog } from 'vs/base/browser/ui/dialog/dialog';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachDialogStyler } from 'vs/platform/theme/common/styler';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
export class DialogService implements IDialogService {
_serviceBrand: any;
constructor(
@ILogService private readonly logService: ILogService,
@ILayoutService private readonly layoutService: ILayoutService,
@IThemeService private readonly themeService: IThemeService
) { }
async confirm(confirmation: IConfirmation): Promise<IConfirmationResult> {
this.logService.trace('DialogService#confirm', confirmation.message);
const buttons: string[] = [];
if (confirmation.primaryButton) {
buttons.push(confirmation.primaryButton);
} else {
buttons.push(nls.localize({ key: 'yesButton', comment: ['&& denotes a mnemonic'] }, "&&Yes"));
}
if (confirmation.secondaryButton) {
buttons.push(confirmation.secondaryButton);
} else if (typeof confirmation.secondaryButton === 'undefined') {
buttons.push(nls.localize('cancelButton', "Cancel"));
}
const severity = this.getSeverity(confirmation.type || 'none');
const result = await this.show(severity, confirmation.message, buttons, { cancelId: 1, detail: confirmation.detail });
return { confirmed: result === 0 };
}
private getSeverity(type: DialogType): Severity {
switch (type) {
case 'error':
return Severity.Error;
case 'warning':
return Severity.Warning;
case 'question':
case 'info':
return Severity.Info;
case 'none':
default:
return Severity.Ignore;
}
}
private getDialogType(severity: Severity): DialogType {
return (severity === Severity.Info) ? 'question' : (severity === Severity.Error) ? 'error' : (severity === Severity.Warning) ? 'warning' : 'none';
}
async show(severity: Severity, message: string, buttons: string[], options?: IDialogOptions): Promise<number> {
this.logService.trace('DialogService#show', message);
const dialogDisposables: IDisposable[] = [];
const dialog = new Dialog(
this.layoutService.container,
message,
buttons,
{
detail: options ? options.detail : undefined,
cancelId: options ? options.cancelId : undefined,
type: this.getDialogType(severity)
});
dialogDisposables.push(dialog);
dialogDisposables.push(attachDialogStyler(dialog, this.themeService));
const choice = await dialog.show();
dispose(dialogDisposables);
return choice;
}
}
registerSingleton(IDialogService, DialogService, true);

View File

@@ -11,9 +11,11 @@ import { localize } from 'vs/nls';
import { FileFilter } from 'vs/platform/windows/common/windows';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export type DialogType = 'none' | 'info' | 'error' | 'question' | 'warning';
export interface IConfirmation {
title?: string;
type?: 'none' | 'info' | 'error' | 'question' | 'warning';
type?: DialogType;
message: string;
detail?: string;
primaryButton?: string;

View File

@@ -8,7 +8,7 @@ import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { serve as serveNet } from 'vs/base/parts/ipc/node/ipc.net';
import { combinedDisposable, IDisposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IPCServer, StaticRouter } from 'vs/base/parts/ipc/node/ipc';
import { IPCServer, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
import { SimpleKeybinding, KeyCode } from 'vs/base/common/keyCodes';
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
import { OS } from 'vs/base/common/platform';

View File

@@ -3,7 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { connect as connectNet, Client } from 'vs/base/parts/ipc/node/ipc.net';
import { Client } from 'vs/base/parts/ipc/common/ipc.net';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';

View File

@@ -7,6 +7,8 @@ import * as minimist from 'minimist';
import * as os from 'os';
import { localize } from 'vs/nls';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { join } from 'path';
import { writeFileSync } from 'fs';
/**
* This code is also used by standalone cli's. Avoid adding any other dependencies.
@@ -263,3 +265,20 @@ export function addArg(argv: string[], ...args: string[]): string[] {
return argv;
}
export function createWaitMarkerFile(verbose?: boolean): string | undefined {
const randomWaitMarkerPath = join(os.tmpdir(), Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10));
try {
writeFileSync(randomWaitMarkerPath, '');
if (verbose) {
console.log(`Marker file for --wait created: ${randomWaitMarkerPath}`);
}
return randomWaitMarkerPath;
} catch (err) {
if (verbose) {
console.error(`Failed to create marker file for --wait: ${err}`);
}
return undefined;
}
}

View File

@@ -4,14 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { tmpdir } from 'os';
import { firstIndex } from 'vs/base/common/arrays';
import { localize } from 'vs/nls';
import { ParsedArgs } from '../common/environment';
import { MIN_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files';
import { parseArgs } from 'vs/platform/environment/node/argv';
import { join } from 'vs/base/common/path';
import { writeFile } from 'vs/base/node/pfs';
function validate(args: ParsedArgs): ParsedArgs {
if (args.goto) {
@@ -60,21 +57,3 @@ export function parseCLIProcessArgv(processArgv: string[]): ParsedArgs {
return validate(parseArgs(args));
}
export function createWaitMarkerFile(verbose?: boolean): Promise<string> {
const randomWaitMarkerPath = join(tmpdir(), Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10));
return writeFile(randomWaitMarkerPath, '').then(() => {
if (verbose) {
console.log(`Marker file for --wait created: ${randomWaitMarkerPath}`);
}
return randomWaitMarkerPath;
}, error => {
if (verbose) {
console.error(`Failed to create marker file for --wait: ${error}`);
}
return Promise.resolve(undefined);
});
}

View File

@@ -56,6 +56,11 @@ export interface IFileService {
*/
canHandleResource(resource: URI): boolean;
/**
* Checks if the provider for the provided resource has the provided file system capability.
*/
hasCapability(resource: URI, capability: FileSystemProviderCapabilities): Promise<boolean>;
//#endregion
/**
@@ -188,6 +193,7 @@ export interface FileOpenOptions {
export interface FileDeleteOptions {
recursive: boolean;
useTrash: boolean;
}
export enum FileType {
@@ -215,7 +221,9 @@ export const enum FileSystemProviderCapabilities {
FileFolderCopy = 1 << 3,
PathCaseSensitive = 1 << 10,
Readonly = 1 << 11
Readonly = 1 << 11,
Trash = 1 << 12
}
export interface IFileSystemProvider {
@@ -243,6 +251,34 @@ export interface IFileSystemProvider {
write?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number>;
}
export interface IFileSystemProviderWithFileReadWriteCapability extends IFileSystemProvider {
readFile(resource: URI): Promise<Uint8Array>;
writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void>;
}
export function hasReadWriteCapability(provider: IFileSystemProvider): provider is IFileSystemProviderWithFileReadWriteCapability {
return !!(provider.capabilities & FileSystemProviderCapabilities.FileReadWrite);
}
export interface IFileSystemProviderWithFileFolderCopyCapability extends IFileSystemProvider {
copy(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void>;
}
export function hasFileFolderCopyCapability(provider: IFileSystemProvider): provider is IFileSystemProviderWithFileFolderCopyCapability {
return !!(provider.capabilities & FileSystemProviderCapabilities.FileFolderCopy);
}
export interface IFileSystemProviderWithOpenReadWriteCloseCapability extends IFileSystemProvider {
open(resource: URI, opts: FileOpenOptions): Promise<number>;
close(fd: number): Promise<void>;
read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number>;
write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number>;
}
export function hasOpenReadWriteCloseCapability(provider: IFileSystemProvider): provider is IFileSystemProviderWithOpenReadWriteCloseCapability {
return !!(provider.capabilities & FileSystemProviderCapabilities.FileOpenReadWriteClose);
}
export enum FileSystemProviderErrorCode {
FileExists = 'EntryExists',
FileNotFound = 'EntryNotFound',
@@ -1103,8 +1139,6 @@ export interface ILegacyFileService {
createFile(resource: URI, content?: string, options?: ICreateFileOptions): Promise<IFileStat>;
del(resource: URI, options?: { useTrash?: boolean, recursive?: boolean }): Promise<void>;
watchFileChanges(resource: URI): void;
unwatchFileChanges(resource: URI): void;

View File

@@ -4,11 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { Client, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { Client } from 'vs/base/parts/ipc/common/ipc.net';
import { connect } from 'vs/base/parts/ipc/node/ipc.net';
import { IWindowsService, IWindowService } from 'vs/platform/windows/common/windows';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { getDelayedChannel } from 'vs/base/parts/ipc/node/ipc';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { IChannel, IServerChannel, getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
export const ISharedProcessService = createDecorator<ISharedProcessService>('sharedProcessService');

View File

@@ -89,4 +89,5 @@ export interface IIssueService {
_serviceBrand: any;
openReporter(data: IssueReporterData): Promise<void>;
openProcessExplorer(data: ProcessExplorerData): Promise<void>;
getSystemStatus(): Promise<string>;
}

View File

@@ -25,4 +25,8 @@ export class IssueService implements IIssueService {
openProcessExplorer(data: ProcessExplorerData): Promise<void> {
return this.channel.call('openProcessExplorer', data);
}
getSystemStatus(): Promise<string> {
return this.channel.call('getSystemStatus');
}
}

View File

@@ -214,6 +214,12 @@ export class IssueService implements IIssueService {
});
}
public getSystemStatus(): Promise<string> {
return this.launchService.getMainProcessInfo().then(info => {
return this.diagnosticsService.getDiagnostics(info);
});
}
private getWindowPosition(parentWindow: BrowserWindow, defaultWidth: number, defaultHeight: number): IWindowState {
// We want the new window to open on the same display that the parent is in
let displayToUse: Electron.Display | undefined;

View File

@@ -21,6 +21,8 @@ export class IssueChannel implements IServerChannel {
return this.service.openReporter(arg);
case 'openProcessExplorer':
return this.service.openProcessExplorer(arg);
case 'getSystemStatus':
return this.service.getSystemStatus();
}
throw new Error(`Call not found: ${command}`);

View File

@@ -163,9 +163,11 @@ export class LaunchService implements ILaunchService {
const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP;
let usedWindows: ICodeWindow[] = [];
const waitMarkerFileURI = args.wait && args.waitMarkerFilePath ? URI.file(args.waitMarkerFilePath) : undefined;
// Special case extension development
if (!!args.extensionDevelopmentPath) {
this.windowsMainService.openExtensionDevelopmentHostWindow(args.extensionDevelopmentPath, { context, cli: args, userEnv });
this.windowsMainService.openExtensionDevelopmentHostWindow(args.extensionDevelopmentPath, { context, cli: args, userEnv, waitMarkerFileURI });
}
// Start without file/folder arguments
@@ -199,7 +201,14 @@ export class LaunchService implements ILaunchService {
}
if (openNewWindow) {
usedWindows = this.windowsMainService.open({ context, cli: args, userEnv, forceNewWindow: true, forceEmpty: true });
usedWindows = this.windowsMainService.open({
context,
cli: args,
userEnv,
forceNewWindow: true,
forceEmpty: true,
waitMarkerFileURI
});
} else {
usedWindows = [this.windowsMainService.focusLastActive(args, context)];
}
@@ -216,7 +225,8 @@ export class LaunchService implements ILaunchService {
forceReuseWindow: args['reuse-window'],
diffMode: args.diff,
addMode: args.add,
noRecentEntry: !!args['skip-add-to-recently-opened']
noRecentEntry: !!args['skip-add-to-recently-opened'],
waitMarkerFileURI
});
}
@@ -232,10 +242,10 @@ export class LaunchService implements ILaunchService {
// If the other instance is waiting to be killed, we hook up a window listener if one window
// is being used and only then resolve the startup promise which will kill this second instance.
// In addition, we poll for the wait marker file to be deleted to return.
if (args.wait && args.waitMarkerFilePath && usedWindows.length === 1 && usedWindows[0]) {
if (waitMarkerFileURI && usedWindows.length === 1 && usedWindows[0]) {
return Promise.race([
this.windowsMainService.waitForWindowCloseOrLoad(usedWindows[0].id),
whenDeleted(args.waitMarkerFilePath)
whenDeleted(waitMarkerFileURI.fsPath)
]).then(() => undefined, () => undefined);
}

View File

@@ -195,6 +195,8 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {
valueSelection: Readonly<[number, number]> | undefined;
validationMessage: string | undefined;
inputHasFocus(): boolean;
}
export interface IInputBox extends IQuickInput {

View File

@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ResolvedAuthority, IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
export class RemoteAuthorityResolverService implements IRemoteAuthorityResolverService {
_serviceBrand: any;
constructor() {
}
resolveAuthority(authority: string): Promise<ResolvedAuthority> {
if (authority.indexOf(':') >= 0) {
const pieces = authority.split(':');
return Promise.resolve({ authority, host: pieces[0], port: parseInt(pieces[1], 10) });
}
return Promise.resolve({ authority, host: authority, port: 80 });
}
setResolvedAuthority(resolvedAuthority: ResolvedAuthority) {
throw new Error(`Not implemented`);
}
setResolvedAuthorityError(authority: string, err: any): void {
throw new Error(`Not implemented`);
}
}

View File

@@ -0,0 +1,207 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Client, PersistentProtocol, ISocket } from 'vs/base/parts/ipc/common/ipc.net';
import { generateUuid } from 'vs/base/common/uuid';
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
import { Disposable } from 'vs/base/common/lifecycle';
export const enum ConnectionType {
Management = 1,
ExtensionHost = 2,
Tunnel = 3,
}
interface ISimpleConnectionOptions {
isBuilt: boolean;
commit: string | undefined;
host: string;
port: number;
reconnectionToken: string;
reconnectionProtocol: PersistentProtocol | null;
webSocketFactory: IWebSocketFactory;
}
export interface IConnectCallback {
(err: any | undefined, socket: ISocket | undefined): void;
}
export interface IWebSocketFactory {
connect(host: string, port: number, query: string, callback: IConnectCallback): void;
}
async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptions, connectionType: ConnectionType, args: any | undefined): Promise<PersistentProtocol> {
throw new Error(`Not implemented`);
}
interface IManagementConnectionResult {
protocol: PersistentProtocol;
}
async function doConnectRemoteAgentManagement(options: ISimpleConnectionOptions): Promise<IManagementConnectionResult> {
const protocol = await connectToRemoteExtensionHostAgent(options, ConnectionType.Management, undefined);
return new Promise<IManagementConnectionResult>((c, e) => {
const registration = protocol.onControlMessage(raw => {
registration.dispose();
const msg = JSON.parse(raw.toString());
const error = getErrorFromMessage(msg);
if (error) {
return e(error);
}
if (options.reconnectionProtocol) {
options.reconnectionProtocol.endAcceptReconnection();
}
c({ protocol });
});
});
}
export interface IRemoteExtensionHostStartParams {
language: string;
debugId?: string;
break?: boolean;
port?: number | null;
updatePort?: boolean;
}
interface IExtensionHostConnectionResult {
protocol: PersistentProtocol;
debugPort?: number;
}
async function doConnectRemoteAgentExtensionHost(options: ISimpleConnectionOptions, startArguments: IRemoteExtensionHostStartParams): Promise<IExtensionHostConnectionResult> {
const protocol = await connectToRemoteExtensionHostAgent(options, ConnectionType.ExtensionHost, startArguments);
return new Promise<IExtensionHostConnectionResult>((c, e) => {
const registration = protocol.onControlMessage(raw => {
registration.dispose();
const msg = JSON.parse(raw.toString());
const error = getErrorFromMessage(msg);
if (error) {
return e(error);
}
const debugPort = msg && msg.debugPort;
if (options.reconnectionProtocol) {
options.reconnectionProtocol.endAcceptReconnection();
}
c({ protocol, debugPort });
});
});
}
export interface ITunnelConnectionStartParams {
port: number;
}
async function doConnectRemoteAgentTunnel(options: ISimpleConnectionOptions, startParams: ITunnelConnectionStartParams): Promise<PersistentProtocol> {
const protocol = await connectToRemoteExtensionHostAgent(options, ConnectionType.Tunnel, startParams);
return protocol;
}
export interface IConnectionOptions {
isBuilt: boolean;
commit: string | undefined;
webSocketFactory: IWebSocketFactory;
addressProvider: IAddressProvider;
}
async function resolveConnectionOptions(options: IConnectionOptions, reconnectionToken: string, reconnectionProtocol: PersistentProtocol | null): Promise<ISimpleConnectionOptions> {
const { host, port } = await options.addressProvider.getAddress();
return {
isBuilt: options.isBuilt,
commit: options.commit,
host: host,
port: port,
reconnectionToken: reconnectionToken,
reconnectionProtocol: reconnectionProtocol,
webSocketFactory: options.webSocketFactory,
};
}
export interface IAddress {
host: string;
port: number;
}
export interface IAddressProvider {
getAddress(): Promise<IAddress>;
}
export async function connectRemoteAgentManagement(options: IConnectionOptions, remoteAuthority: string, clientId: string): Promise<ManagementPersistentConnection> {
const reconnectionToken = generateUuid();
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
const { protocol } = await doConnectRemoteAgentManagement(simpleOptions);
return new ManagementPersistentConnection(options, remoteAuthority, clientId, reconnectionToken, protocol);
}
export async function connectRemoteAgentExtensionHost(options: IConnectionOptions, startArguments: IRemoteExtensionHostStartParams): Promise<ExtensionHostPersistentConnection> {
const reconnectionToken = generateUuid();
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
const { protocol, debugPort } = await doConnectRemoteAgentExtensionHost(simpleOptions, startArguments);
return new ExtensionHostPersistentConnection(options, startArguments, reconnectionToken, protocol, debugPort);
}
export async function connectRemoteAgentTunnel(options: IConnectionOptions, tunnelRemotePort: number): Promise<PersistentProtocol> {
const simpleOptions = await resolveConnectionOptions(options, generateUuid(), null);
const protocol = await doConnectRemoteAgentTunnel(simpleOptions, { port: tunnelRemotePort });
return protocol;
}
abstract class PersistentConnection extends Disposable {
protected readonly _options: IConnectionOptions;
public readonly reconnectionToken: string;
public readonly protocol: PersistentProtocol;
constructor(options: IConnectionOptions, reconnectionToken: string, protocol: PersistentProtocol) {
super();
this._options = options;
this.reconnectionToken = reconnectionToken;
this.protocol = protocol;
}
protected abstract _reconnect(options: ISimpleConnectionOptions): Promise<void>;
}
export class ManagementPersistentConnection extends PersistentConnection {
public readonly client: Client<RemoteAgentConnectionContext>;
constructor(options: IConnectionOptions, remoteAuthority: string, clientId: string, reconnectionToken: string, protocol: PersistentProtocol) {
super(options, reconnectionToken, protocol);
this.client = this._register(new Client<RemoteAgentConnectionContext>(protocol, {
remoteAuthority: remoteAuthority,
clientId: clientId
}));
}
protected async _reconnect(options: ISimpleConnectionOptions): Promise<void> {
await doConnectRemoteAgentManagement(options);
}
}
export class ExtensionHostPersistentConnection extends PersistentConnection {
private readonly _startArguments: IRemoteExtensionHostStartParams;
public readonly debugPort: number | undefined;
constructor(options: IConnectionOptions, startArguments: IRemoteExtensionHostStartParams, reconnectionToken: string, protocol: PersistentProtocol, debugPort: number | undefined) {
super(options, reconnectionToken, protocol);
this._startArguments = startArguments;
this.debugPort = debugPort;
}
protected async _reconnect(options: ISimpleConnectionOptions): Promise<void> {
await doConnectRemoteAgentExtensionHost(options, this._startArguments);
}
}
function getErrorFromMessage(msg: any): Error | null {
if (msg && msg.type === 'error') {
const error = new Error(`Connection error: ${msg.reason}`);
(<any>error).code = 'VSCODE_CONNECTION_ERROR';
return error;
}
return null;
}

View File

@@ -9,6 +9,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { FileChangeType, FileDeleteOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileType, FileWriteOptions, IFileChange, IFileSystemProvider, IStat, IWatchOptions } from 'vs/platform/files/common/files';
import { VSBuffer } from 'vs/base/common/buffer';
export const REMOTE_FILE_SYSTEM_CHANNEL_NAME = 'remotefilesystem';
@@ -71,20 +72,17 @@ export class RemoteExtensionsFileSystemProvider extends Disposable implements IF
// --- forwarding calls
private static _asBuffer(data: Uint8Array): Buffer {
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
}
stat(resource: URI): Promise<IStat> {
return this._channel.call('stat', [resource]);
}
readFile(resource: URI): Promise<Uint8Array> {
return this._channel.call('readFile', [resource]);
async readFile(resource: URI): Promise<Uint8Array> {
const buff = <VSBuffer>await this._channel.call('readFile', [resource]);
return buff.buffer;
}
writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> {
const contents = RemoteExtensionsFileSystemProvider._asBuffer(content);
const contents = VSBuffer.wrap(content);
return this._channel.call('writeFile', [resource, contents, opts]);
}

View File

@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWebSocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
export const nodeWebSocketFactory = new class implements IWebSocketFactory {
connect(host: string, port: number, query: string, callback: IConnectCallback): void {
throw new Error(`Not implemented`);
}
};

View File

@@ -1,60 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Client, PersistentProtocol } from 'vs/base/parts/ipc/node/ipc.net';
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
import { Disposable } from 'vs/base/common/lifecycle';
export interface IRemoteExtensionHostStartParams {
language: string;
debugId?: string;
break?: boolean;
port?: number | null;
updatePort?: boolean;
}
export async function connectRemoteAgentManagement(remoteAuthority: string, host: string, port: number, clientId: string, isBuilt: boolean): Promise<ManagementPersistentConnection> {
throw new Error(`Not implemented`);
}
export async function connectRemoteAgentExtensionHost(host: string, port: number, startArguments: IRemoteExtensionHostStartParams, isBuilt: boolean): Promise<ExtensionHostPersistentConnection> {
throw new Error(`Not implemented`);
}
abstract class PersistentConnection extends Disposable {
public readonly reconnectionToken: string;
public readonly protocol: PersistentProtocol;
constructor(reconnectionToken: string, protocol: PersistentProtocol) {
super();
this.reconnectionToken = reconnectionToken;
this.protocol = protocol;
}
}
export class ManagementPersistentConnection extends PersistentConnection {
public readonly client: Client<RemoteAgentConnectionContext>;
constructor(remoteAuthority: string, host: string, port: number, clientId: string, isBuilt: boolean, reconnectionToken: string, protocol: PersistentProtocol) {
super(reconnectionToken, protocol);
this.client = this._register(new Client<RemoteAgentConnectionContext>(protocol, {
remoteAuthority: remoteAuthority,
clientId: clientId
}));
}
}
export class ExtensionHostPersistentConnection extends PersistentConnection {
public readonly debugPort: number | undefined;
constructor(host: string, port: number, startArguments: IRemoteExtensionHostStartParams, isBuilt: boolean, reconnectionToken: string, protocol: PersistentProtocol, debugPort: number | undefined) {
super(reconnectionToken, protocol);
this.debugPort = debugPort;
}
}

View File

@@ -259,7 +259,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic
return import('vscode-sqlite3').then(sqlite3 => {
return new Promise<void>((resolve, reject) => {
const handleSuffixKey = (row, key: string, suffix: string) => {
const handleSuffixKey = (row: any, key: string, suffix: string) => {
if (endsWith(key, suffix.toLowerCase())) {
const value: string = row.value.toString('utf16le');
const normalizedKey = key.substring(0, key.length - suffix.length) + suffix;

View File

@@ -61,7 +61,7 @@ export interface IColorRegistry {
/**
* Register a color to the registry.
*/
deregisterColor(id: string);
deregisterColor(id: string): void;
/**
* Get all color contributions

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService';
import { focusBorder, inputBackground, inputForeground, ColorIdentifier, selectForeground, selectBackground, selectListBackground, selectBorder, inputBorder, foreground, editorBackground, contrastBorder, inputActiveOptionBorder, listFocusBackground, listFocusForeground, listActiveSelectionBackground, listActiveSelectionForeground, listInactiveSelectionForeground, listInactiveSelectionBackground, listInactiveFocusBackground, listHoverBackground, listHoverForeground, listDropBackground, pickerGroupBorder, pickerGroupForeground, widgetShadow, inputValidationInfoBorder, inputValidationInfoBackground, inputValidationWarningBorder, inputValidationWarningBackground, inputValidationErrorBorder, inputValidationErrorBackground, activeContrastBorder, buttonForeground, buttonBackground, buttonHoverBackground, ColorFunction, badgeBackground, badgeForeground, progressBarBackground, breadcrumbsForeground, breadcrumbsFocusForeground, breadcrumbsActiveSelectionForeground, breadcrumbsBackground, editorWidgetBorder, inputValidationInfoForeground, inputValidationWarningForeground, inputValidationErrorForeground, menuForeground, menuBackground, menuSelectionForeground, menuSelectionBackground, menuSelectionBorder, menuBorder, menuSeparatorBackground, darken, listFilterWidgetOutline, listFilterWidgetNoMatchesOutline, listFilterWidgetBackground } from 'vs/platform/theme/common/colorRegistry';
import { focusBorder, inputBackground, inputForeground, ColorIdentifier, selectForeground, selectBackground, selectListBackground, selectBorder, inputBorder, foreground, editorBackground, contrastBorder, inputActiveOptionBorder, listFocusBackground, listFocusForeground, listActiveSelectionBackground, listActiveSelectionForeground, listInactiveSelectionForeground, listInactiveSelectionBackground, listInactiveFocusBackground, listHoverBackground, listHoverForeground, listDropBackground, pickerGroupBorder, pickerGroupForeground, widgetShadow, inputValidationInfoBorder, inputValidationInfoBackground, inputValidationWarningBorder, inputValidationWarningBackground, inputValidationErrorBorder, inputValidationErrorBackground, activeContrastBorder, buttonForeground, buttonBackground, buttonHoverBackground, ColorFunction, badgeBackground, badgeForeground, progressBarBackground, breadcrumbsForeground, breadcrumbsFocusForeground, breadcrumbsActiveSelectionForeground, breadcrumbsBackground, editorWidgetBorder, inputValidationInfoForeground, inputValidationWarningForeground, inputValidationErrorForeground, menuForeground, menuBackground, menuSelectionForeground, menuSelectionBackground, menuSelectionBorder, menuBorder, menuSeparatorBackground, darken, listFilterWidgetOutline, listFilterWidgetNoMatchesOutline, listFilterWidgetBackground, editorWidgetBackground } from 'vs/platform/theme/common/colorRegistry';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Color } from 'vs/base/common/color';
import { mixin } from 'vs/base/common/objects';
@@ -329,3 +329,24 @@ export const defaultMenuStyles = <IMenuStyleOverrides>{
export function attachMenuStyler(widget: IThemable, themeService: IThemeService, style?: IMenuStyleOverrides): IDisposable {
return attachStyler(themeService, { ...defaultMenuStyles, ...style }, widget);
}
export interface IDialogStyleOverrides extends IButtonStyleOverrides {
dialogForeground?: ColorIdentifier;
dialogBackground?: ColorIdentifier;
dialogShadow?: ColorIdentifier;
}
export const defaultDialogStyles = <IDialogStyleOverrides>{
dialogBackground: editorWidgetBackground,
dialogForeground: foreground,
dialogShadow: widgetShadow,
buttonForeground: buttonForeground,
buttonBackground: buttonBackground,
buttonHoverBackground: buttonHoverBackground,
buttonBorder: contrastBorder
};
export function attachDialogStyler(widget: IThemable, themeService: IThemeService, style?: IDialogStyleOverrides): IDisposable {
return attachStyler(themeService, { ...defaultDialogStyles, ...style }, widget);
}

View File

@@ -194,7 +194,7 @@ export class Win32UpdateService extends AbstractUpdateService {
}
private async cleanup(exceptVersion: string | null = null): Promise<any> {
const filter = exceptVersion ? one => !(new RegExp(`${product.quality}-${exceptVersion}\\.exe$`).test(one)) : () => true;
const filter = exceptVersion ? (one: string) => !(new RegExp(`${product.quality}-${exceptVersion}\\.exe$`).test(one)) : () => true;
const cachePath = await this.cachePath;
const versions = await pfs.readdir(cachePath);

View File

@@ -84,6 +84,7 @@ export interface SaveDialogOptions {
export interface INewWindowOptions {
remoteAuthority?: string;
reuseWindow?: boolean;
}
export interface IDevToolsOptions {
@@ -149,9 +150,8 @@ export interface IWindowsService {
toggleSharedProcess(): Promise<void>;
// Global methods
openWindow(windowId: number, uris: IURIToOpen[], options?: IOpenSettings): Promise<void>;
openWindow(windowId: number, uris: IURIToOpen[], options: IOpenSettings): Promise<void>;
openNewWindow(options?: INewWindowOptions): Promise<void>;
showWindow(windowId: number): Promise<void>;
getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>;
getWindowCount(): Promise<number>;
log(severity: string, ...messages: string[]): Promise<void>;
@@ -183,6 +183,7 @@ export interface IOpenSettings {
diffMode?: boolean;
addMode?: boolean;
noRecentEntry?: boolean;
waitMarkerFileURI?: URI;
args?: ParsedArgs;
}
@@ -228,7 +229,6 @@ export interface IWindowService {
unmaximizeWindow(): Promise<void>;
minimizeWindow(): Promise<void>;
onWindowTitleDoubleClick(): Promise<void>;
show(): Promise<void>;
showMessageBox(options: MessageBoxOptions): Promise<IMessageBoxResult>;
showSaveDialog(options: SaveDialogOptions): Promise<string>;
showOpenDialog(options: OpenDialogOptions): Promise<string[]>;

View File

@@ -98,7 +98,7 @@ export class WindowService extends Disposable implements IWindowService {
return this.windowsService.enterWorkspace(this.windowId, path);
}
openWindow(uris: IURIToOpen[], options?: IOpenSettings): Promise<void> {
openWindow(uris: IURIToOpen[], options: IOpenSettings = {}): Promise<void> {
if (!!this.configuration.remoteAuthority) {
uris.forEach(u => u.label = u.label || this.getRecentLabel(u, !!(options && options.forceOpenWorkspaceAsFile)));
}
@@ -153,10 +153,6 @@ export class WindowService extends Disposable implements IWindowService {
return this.windowsService.setDocumentEdited(this.windowId, flag);
}
show(): Promise<void> {
return this.windowsService.showWindow(this.windowId);
}
showMessageBox(options: Electron.MessageBoxOptions): Promise<IMessageBoxResult> {
return this.windowsService.showMessageBox(this.windowId, options);
}

View File

@@ -5,7 +5,7 @@
import { Event } from 'vs/base/common/event';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IDevToolsOptions, INewWindowOptions, IURIToOpen } from 'vs/platform/windows/common/windows';
import { IWindowsService, INativeOpenDialogOptions, IEnterWorkspaceResult, CrashReporterStartOptions, IMessageBoxResult, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IDevToolsOptions, INewWindowOptions, IURIToOpen, IOpenSettings } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IRecentlyOpened, IRecent, isRecentWorkspace } from 'vs/platform/history/common/history';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
@@ -186,7 +186,7 @@ export class WindowsService implements IWindowsService {
return this.channel.call('toggleSharedProcess');
}
openWindow(windowId: number, uris: IURIToOpen[], options?: { forceNewWindow?: boolean, forceReuseWindow?: boolean, forceOpenWorkspaceAsFile?: boolean, args?: ParsedArgs }): Promise<void> {
openWindow(windowId: number, uris: IURIToOpen[], options: IOpenSettings): Promise<void> {
return this.channel.call('openWindow', [windowId, uris, options]);
}
@@ -194,10 +194,6 @@ export class WindowsService implements IWindowsService {
return this.channel.call('openNewWindow', options);
}
showWindow(windowId: number): Promise<void> {
return this.channel.call('showWindow', windowId);
}
getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]> {
return this.channel.call<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]>('getWindows').then(result => {
for (const win of result) {

View File

@@ -125,6 +125,7 @@ export interface IOpenConfiguration {
readonly cli: ParsedArgs;
readonly userEnv?: IProcessEnvironment;
readonly urisToOpen?: IURIToOpen[];
readonly waitMarkerFileURI?: URI;
readonly preferNewWindow?: boolean;
readonly forceNewWindow?: boolean;
readonly forceNewTabbedWindow?: boolean;

View File

@@ -218,7 +218,11 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
async focusWindow(windowId: number): Promise<void> {
this.logService.trace('windowsService#focusWindow', windowId);
return this.withWindow(windowId, codeWindow => codeWindow.win.focus());
if (isMacintosh) {
return this.withWindow(windowId, codeWindow => codeWindow.win.show());
} else {
return this.withWindow(windowId, codeWindow => codeWindow.win.focus());
}
}
async closeWindow(windowId: number): Promise<void> {
@@ -273,7 +277,7 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
});
}
async openWindow(windowId: number, urisToOpen: IURIToOpen[], options: IOpenSettings = {}): Promise<void> {
async openWindow(windowId: number, urisToOpen: IURIToOpen[], options: IOpenSettings): Promise<void> {
this.logService.trace('windowsService#openWindow');
if (!urisToOpen || !urisToOpen.length) {
return undefined;
@@ -289,7 +293,8 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
forceOpenWorkspaceAsFile: options.forceOpenWorkspaceAsFile,
diffMode: options.diffMode,
addMode: options.addMode,
noRecentEntry: options.noRecentEntry
noRecentEntry: options.noRecentEntry,
waitMarkerFileURI: options.waitMarkerFileURI
});
}
@@ -299,12 +304,6 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
this.windowsMainService.openNewWindow(OpenContext.API, options);
}
async showWindow(windowId: number): Promise<void> {
this.logService.trace('windowsService#showWindow', windowId);
return this.withWindow(windowId, codeWindow => codeWindow.win.show());
}
async getWindows(): Promise<{ id: number; workspace?: IWorkspaceIdentifier; folderUri?: ISingleFolderWorkspaceIdentifier; title: string; filename?: string; }[]> {
this.logService.trace('windowsService#getWindows');
@@ -466,4 +465,4 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
dispose(): void {
this.disposables = dispose(this.disposables);
}
}
}

View File

@@ -5,7 +5,7 @@
import { Event } from 'vs/base/common/event';
import { IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { IWindowsService, IURIToOpen } from 'vs/platform/windows/common/windows';
import { IWindowsService, IURIToOpen, IOpenSettings } from 'vs/platform/windows/common/windows';
import { reviveWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { IRecent, isRecentFile, isRecentFolder } from 'vs/platform/history/common/history';
@@ -86,9 +86,14 @@ export class WindowsChannel implements IServerChannel {
case 'minimizeWindow': return this.service.minimizeWindow(arg);
case 'onWindowTitleDoubleClick': return this.service.onWindowTitleDoubleClick(arg);
case 'setDocumentEdited': return this.service.setDocumentEdited(arg[0], arg[1]);
case 'openWindow': return this.service.openWindow(arg[0], arg[1] ? (<IURIToOpen[]>arg[1]).map(r => { r.uri = URI.revive(r.uri); return r; }) : arg[1], arg[2]);
case 'openWindow': {
const urisToOpen: IURIToOpen[] = arg[1];
const options: IOpenSettings = arg[2];
urisToOpen.forEach(r => { r.uri = URI.revive(r.uri); return r; });
options.waitMarkerFileURI = options.waitMarkerFileURI && URI.revive(options.waitMarkerFileURI);
return this.service.openWindow(arg[0], urisToOpen, options);
}
case 'openNewWindow': return this.service.openNewWindow(arg);
case 'showWindow': return this.service.showWindow(arg);
case 'getWindows': return this.service.getWindows();
case 'getWindowCount': return this.service.getWindowCount();
case 'relaunch': return this.service.relaunch(arg[0]);