chore(vscode): update to 1.54.2

This commit is contained in:
Joe Previte
2021-03-11 10:27:10 -07:00
1459 changed files with 53404 additions and 51004 deletions

View File

@@ -81,14 +81,14 @@ export function isFileToOpen(uriToOpen: IWindowOpenable): uriToOpen is IFileToOp
return !!(uriToOpen as IFileToOpen).fileUri;
}
export type MenuBarVisibility = 'default' | 'visible' | 'toggle' | 'hidden' | 'compact';
export type MenuBarVisibility = 'classic' | 'visible' | 'toggle' | 'hidden' | 'compact';
export function getMenuBarVisibility(configurationService: IConfigurationService): MenuBarVisibility {
const titleBarStyle = getTitleBarStyle(configurationService);
const menuBarVisibility = configurationService.getValue<MenuBarVisibility>('window.menuBarVisibility');
const menuBarVisibility = configurationService.getValue<MenuBarVisibility | 'default'>('window.menuBarVisibility');
if (titleBarStyle === 'native' && menuBarVisibility === 'compact') {
return 'default';
if (menuBarVisibility === 'default' || (titleBarStyle === 'native' && menuBarVisibility === 'compact')) {
return 'classic';
} else {
return menuBarVisibility;
}
@@ -114,6 +114,7 @@ export interface IWindowSettings {
readonly enableMenuBarMnemonics: boolean;
readonly closeWhenEmpty: boolean;
readonly clickThroughInactive: boolean;
readonly enableExperimentalMainProcessWorkspaceStorage: boolean;
}
export function getTitleBarStyle(configurationService: IConfigurationService): 'native' | 'custom' {
@@ -169,7 +170,7 @@ export interface IPathData {
readonly openOnlyIfExists?: boolean;
// Specifies an optional id to override the editor used to edit the resource, e.g. custom editor.
readonly overrideId?: string;
readonly editorOverrideId?: string;
}
export interface IPathsToWaitFor extends IPathsToWaitForData {
@@ -253,6 +254,8 @@ export interface INativeWindowConfiguration extends IWindowConfiguration, Native
filesToWait?: IPathsToWaitFor;
os: IOSConfiguration;
enableExperimentalMainProcessWorkspaceStorage: boolean;
}
/**

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,14 @@ export interface IWindowState {
display?: number;
}
export const defaultWindowState = function (mode = WindowMode.Normal): IWindowState {
return {
width: 1024,
height: 768,
mode
};
};
export const enum WindowMode {
Maximized,
Normal,
@@ -52,17 +60,21 @@ export const enum WindowMode {
Fullscreen
}
export interface ILoadEvent {
workspace: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined;
}
export interface ICodeWindow extends IDisposable {
readonly onLoad: Event<void>;
readonly onReady: Event<void>;
readonly onClose: Event<void>;
readonly onDestroy: Event<void>;
readonly onWillLoad: Event<ILoadEvent>;
readonly onDidSignalReady: Event<void>;
readonly onDidClose: Event<void>;
readonly onDidDestroy: Event<void>;
readonly whenClosedOrLoaded: Promise<void>;
readonly id: number;
readonly win: BrowserWindow;
readonly win: BrowserWindow | null; /* `null` after being disposed */
readonly config: INativeWindowConfiguration | undefined;
readonly openedWorkspace?: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier;
@@ -113,6 +125,24 @@ export interface ICodeWindow extends IDisposable {
serializeWindowState(): IWindowState;
}
export const enum WindowError {
/**
* Maps to the `unresponsive` event on a `BrowserWindow`.
*/
UNRESPONSIVE = 1,
/**
* Maps to the `render-proces-gone` event on a `WebContents`.
*/
CRASHED = 2,
/**
* Maps to the `did-fail-load` event on a `WebContents`.
*/
LOAD = 3
}
export const IWindowsMainService = createDecorator<IWindowsMainService>('windowsMainService');
export interface IWindowsCountChangedEvent {
@@ -124,11 +154,11 @@ export interface IWindowsMainService {
readonly _serviceBrand: undefined;
readonly onWindowsCountChanged: Event<IWindowsCountChangedEvent>;
readonly onDidChangeWindowsCount: Event<IWindowsCountChangedEvent>;
readonly onWindowOpened: Event<ICodeWindow>;
readonly onWindowReady: Event<ICodeWindow>;
readonly onWindowDestroyed: Event<ICodeWindow>;
readonly onDidOpenWindow: Event<ICodeWindow>;
readonly onDidSignalReadyWindow: Event<ICodeWindow>;
readonly onDidDestroyWindow: Event<ICodeWindow>;
open(openConfig: IOpenConfiguration): ICodeWindow[];
openEmptyWindow(openConfig: IOpenEmptyConfiguration, options?: IOpenEmptyWindowOptions): ICodeWindow[];

View File

@@ -12,9 +12,9 @@ import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup';
import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { IStateService } from 'vs/platform/state/node/state';
import { CodeWindow } from 'vs/code/electron-main/window';
import { CodeWindow } from 'vs/platform/windows/electron-main/window';
import { BrowserWindow, MessageBoxOptions, WebContents } from 'electron';
import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { ILifecycleMainService, UnloadReason, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, IPath, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest, IPathsToWaitFor, INativeWindowConfiguration, INativeOpenFileRequest } from 'vs/platform/windows/common/windows';
@@ -35,7 +35,7 @@ import { getSingleFolderWorkspaceIdentifier, getWorkspaceIdentifier, IWorkspaces
import { once } from 'vs/base/common/functional';
import { Disposable } from 'vs/base/common/lifecycle';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService';
import { withNullAsUndefined } from 'vs/base/common/types';
import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types';
import { isWindowsDriveLetter, toSlashes, parseLineAndColumnAware, sanitizeFilePath } from 'vs/base/common/extpath';
import { CharCode } from 'vs/base/common/charCode';
import { getPathLabel } from 'vs/base/common/labels';
@@ -118,17 +118,17 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private static readonly WINDOWS: ICodeWindow[] = [];
private readonly _onWindowOpened = this._register(new Emitter<ICodeWindow>());
readonly onWindowOpened = this._onWindowOpened.event;
private readonly _onDidOpenWindow = this._register(new Emitter<ICodeWindow>());
readonly onDidOpenWindow = this._onDidOpenWindow.event;
private readonly _onWindowReady = this._register(new Emitter<ICodeWindow>());
readonly onWindowReady = this._onWindowReady.event;
private readonly _onDidSignalReadyWindow = this._register(new Emitter<ICodeWindow>());
readonly onDidSignalReadyWindow = this._onDidSignalReadyWindow.event;
private readonly _onWindowDestroyed = this._register(new Emitter<ICodeWindow>());
readonly onWindowDestroyed = this._onWindowDestroyed.event;
private readonly _onDidDestroyWindow = this._register(new Emitter<ICodeWindow>());
readonly onDidDestroyWindow = this._onDidDestroyWindow.event;
private readonly _onWindowsCountChanged = this._register(new Emitter<IWindowsCountChangedEvent>());
readonly onWindowsCountChanged = this._onWindowsCountChanged.event;
private readonly _onDidChangeWindowsCount = this._register(new Emitter<IWindowsCountChangedEvent>());
readonly onDidChangeWindowsCount = this._onDidChangeWindowsCount.event;
private readonly windowsStateHandler = this._register(new WindowsStateHandler(this, this.stateService, this.lifecycleMainService, this.logService, this.configurationService));
@@ -137,7 +137,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private readonly initialUserEnv: IProcessEnvironment,
@ILogService private readonly logService: ILogService,
@IStateService private readonly stateService: IStateService,
@IEnvironmentMainService private readonly environmentService: IEnvironmentMainService,
@IEnvironmentMainService private readonly environmentMainService: IEnvironmentMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IBackupMainService private readonly backupMainService: IBackupMainService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@@ -155,11 +155,11 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
private registerListeners(): void {
// Signal a window is ready after having entered a workspace
this._register(this.workspacesManagementMainService.onWorkspaceEntered(event => this._onWindowReady.fire(event.window)));
this._register(this.workspacesManagementMainService.onDidEnterWorkspace(event => this._onDidSignalReadyWindow.fire(event.window)));
}
openEmptyWindow(openConfig: IOpenEmptyConfiguration, options?: IOpenEmptyWindowOptions): ICodeWindow[] {
let cli = this.environmentService.args;
let cli = this.environmentMainService.args;
const remote = options?.remoteAuthority;
if (cli && (cli.remote !== remote)) {
cli = { ...cli, remote };
@@ -670,7 +670,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
buttons: [localize('ok', "OK")],
message: uri.scheme === Schemas.file ? localize('pathNotExistTitle', "Path does not exist") : localize('uriInvalidTitle', "URI can not be opened"),
detail: uri.scheme === Schemas.file ?
localize('pathNotExistDetail', "The path '{0}' does not seem to exist anymore on disk.", getPathLabel(uri.fsPath, this.environmentService)) :
localize('pathNotExistDetail', "The path '{0}' does not seem to exist anymore on disk.", getPathLabel(uri.fsPath, this.environmentMainService)) :
localize('uriInvalidDetail', "The URI '{0}' is not valid and can not be opened.", uri.toString()),
noLink: true
};
@@ -1135,9 +1135,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
// Build `INativeWindowConfiguration` from config and options
const configuration = { ...options.cli } as INativeWindowConfiguration;
configuration.appRoot = this.environmentService.appRoot;
configuration.appRoot = this.environmentMainService.appRoot;
configuration.machineId = this.machineId;
configuration.nodeCachedDataDir = this.environmentService.nodeCachedDataDir;
configuration.nodeCachedDataDir = this.environmentMainService.nodeCachedDataDir;
configuration.mainPid = process.pid;
configuration.execPath = process.execPath;
configuration.userEnv = { ...this.initialUserEnv, ...options.userEnv };
@@ -1157,7 +1157,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
// For all other cases we first call into registerEmptyWindowBackupSync() to set it before
// loading the window.
if (options.emptyWindowBackupInfo) {
configuration.backupPath = join(this.environmentService.backupHome, options.emptyWindowBackupInfo.backupFolder);
configuration.backupPath = join(this.environmentMainService.backupHome, options.emptyWindowBackupInfo.backupFolder);
}
let window: ICodeWindow | undefined;
@@ -1191,20 +1191,22 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
WindowsMainService.WINDOWS.push(createdWindow);
// Indicate new window via event
this._onWindowOpened.fire(createdWindow);
this._onDidOpenWindow.fire(createdWindow);
// Indicate number change via event
this._onWindowsCountChanged.fire({ oldCount: this.getWindowCount() - 1, newCount: this.getWindowCount() });
this._onDidChangeWindowsCount.fire({ oldCount: this.getWindowCount() - 1, newCount: this.getWindowCount() });
// Window Events
once(createdWindow.onReady)(() => this._onWindowReady.fire(createdWindow));
once(createdWindow.onClose)(() => this.onWindowClosed(createdWindow));
once(createdWindow.onDestroy)(() => this._onWindowDestroyed.fire(createdWindow));
createdWindow.win.webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own
createdWindow.win.webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(createdWindow));
once(createdWindow.onDidSignalReady)(() => this._onDidSignalReadyWindow.fire(createdWindow));
once(createdWindow.onDidClose)(() => this.onWindowClosed(createdWindow));
once(createdWindow.onDidDestroy)(() => this._onDidDestroyWindow.fire(createdWindow));
const webContents = assertIsDefined(createdWindow.win?.webContents);
webContents.removeAllListeners('devtools-reload-page'); // remove built in listener so we can handle this on our own
webContents.on('devtools-reload-page', () => this.lifecycleMainService.reload(createdWindow));
// Lifecycle
(this.lifecycleMainService as LifecycleMainService).registerWindow(createdWindow);
this.lifecycleMainService.registerWindow(createdWindow);
}
// Existing window
@@ -1264,7 +1266,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
WindowsMainService.WINDOWS.splice(index, 1);
// Emit
this._onWindowsCountChanged.fire({ oldCount: this.getWindowCount() + 1, newCount: this.getWindowCount() });
this._onDidChangeWindowsCount.fire({ oldCount: this.getWindowCount() + 1, newCount: this.getWindowCount() });
}
getFocusedWindow(): ICodeWindow | undefined {

View File

@@ -8,13 +8,12 @@ import { Disposable } from 'vs/base/common/lifecycle';
import { isMacintosh } from 'vs/base/common/platform';
import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { defaultWindowState } from 'vs/code/electron-main/window';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { ILogService } from 'vs/platform/log/common/log';
import { IStateService } from 'vs/platform/state/node/state';
import { INativeWindowConfiguration, IWindowSettings } from 'vs/platform/windows/common/windows';
import { ICodeWindow, IWindowsMainService, IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { defaultWindowState, ICodeWindow, IWindowsMainService, IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
export interface IWindowState {
@@ -84,9 +83,9 @@ export class WindowsStateHandler extends Disposable {
});
// Handle various lifecycle events around windows
this.lifecycleMainService.onBeforeWindowClose(window => this.onBeforeWindowClose(window));
this.lifecycleMainService.onBeforeCloseWindow(window => this.onBeforeCloseWindow(window));
this.lifecycleMainService.onBeforeShutdown(() => this.onBeforeShutdown());
this.windowsMainService.onWindowsCountChanged(e => {
this.windowsMainService.onDidChangeWindowsCount(e => {
if (e.newCount - e.oldCount > 0) {
// clear last closed window state when a new window opens. this helps on macOS where
// otherwise closing the last window, opening a new window and then quitting would
@@ -96,16 +95,16 @@ export class WindowsStateHandler extends Disposable {
});
// try to save state before destroy because close will not fire
this.windowsMainService.onWindowDestroyed(window => this.onBeforeWindowClose(window));
this.windowsMainService.onDidDestroyWindow(window => this.onBeforeCloseWindow(window));
}
// Note that onBeforeShutdown() and onBeforeWindowClose() are fired in different order depending on the OS:
// Note that onBeforeShutdown() and onBeforeCloseWindow() are fired in different order depending on the OS:
// - macOS: since the app will not quit when closing the last window, you will always first get
// the onBeforeShutdown() event followed by N onBeforeWindowClose() events for each window
// the onBeforeShutdown() event followed by N onBeforeCloseWindow() events for each window
// - other: on other OS, closing the last window will quit the app so the order depends on the
// user interaction: closing the last window will first trigger onBeforeWindowClose()
// user interaction: closing the last window will first trigger onBeforeCloseWindow()
// and then onBeforeShutdown(). Using the quit action however will first issue onBeforeShutdown()
// and then onBeforeWindowClose().
// and then onBeforeCloseWindow().
//
// Here is the behavior on different OS depending on action taken (Electron 1.7.x):
//
@@ -114,27 +113,27 @@ export class WindowsStateHandler extends Disposable {
// - close(1): close one window via the window close button
// - closeAll: close all windows via the taskbar command
// - onBeforeShutdown(N): number of windows reported in this event handler
// - onBeforeWindowClose(N, M): number of windows reported and quitRequested boolean in this event handler
// - onBeforeCloseWindow(N, M): number of windows reported and quitRequested boolean in this event handler
//
// macOS
// - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true)
// - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true)
// - quit(1): onBeforeShutdown(1), onBeforeCloseWindow(1, true)
// - quit(2): onBeforeShutdown(2), onBeforeCloseWindow(2, true), onBeforeCloseWindow(2, true)
// - quit(0): onBeforeShutdown(0)
// - close(1): onBeforeWindowClose(1, false)
// - close(1): onBeforeCloseWindow(1, false)
//
// Windows
// - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true)
// - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true)
// - close(1): onBeforeWindowClose(2, false)[not last window]
// - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window]
// - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0)
// - quit(1): onBeforeShutdown(1), onBeforeCloseWindow(1, true)
// - quit(2): onBeforeShutdown(2), onBeforeCloseWindow(2, true), onBeforeCloseWindow(2, true)
// - close(1): onBeforeCloseWindow(2, false)[not last window]
// - close(1): onBeforeCloseWindow(1, false), onBeforeShutdown(0)[last window]
// - closeAll(2): onBeforeCloseWindow(2, false), onBeforeCloseWindow(2, false), onBeforeShutdown(0)
//
// Linux
// - quit(1): onBeforeShutdown(1), onBeforeWindowClose(1, true)
// - quit(2): onBeforeShutdown(2), onBeforeWindowClose(2, true), onBeforeWindowClose(2, true)
// - close(1): onBeforeWindowClose(2, false)[not last window]
// - close(1): onBeforeWindowClose(1, false), onBeforeShutdown(0)[last window]
// - closeAll(2): onBeforeWindowClose(2, false), onBeforeWindowClose(2, false), onBeforeShutdown(0)
// - quit(1): onBeforeShutdown(1), onBeforeCloseWindow(1, true)
// - quit(2): onBeforeShutdown(2), onBeforeCloseWindow(2, true), onBeforeCloseWindow(2, true)
// - close(1): onBeforeCloseWindow(2, false)[not last window]
// - close(1): onBeforeCloseWindow(1, false), onBeforeShutdown(0)[last window]
// - closeAll(2): onBeforeCloseWindow(2, false), onBeforeCloseWindow(2, false), onBeforeShutdown(0)
//
private onBeforeShutdown(): void {
this.shuttingDown = true;
@@ -186,7 +185,7 @@ export class WindowsStateHandler extends Disposable {
}
// See note on #onBeforeShutdown() for details how these events are flowing
private onBeforeWindowClose(window: ICodeWindow): void {
private onBeforeCloseWindow(window: ICodeWindow): void {
if (this.lifecycleMainService.quitRequested) {
return; // during quit, many windows close in parallel so let it be handled in the before-quit handler
}

View File

@@ -1,109 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as path from 'vs/base/common/path';
import { findWindowOnFile } from 'vs/platform/windows/electron-main/windowsFinder';
import { ICodeWindow, IWindowState } from 'vs/platform/windows/electron-main/windows';
import { IWorkspaceIdentifier, toWorkspaceFolders } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Event } from 'vs/base/common/event';
import { UriDto } from 'vs/base/common/types';
import { ICommandAction } from 'vs/platform/actions/common/actions';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { INativeWindowConfiguration } from 'vs/platform/windows/common/windows';
const fixturesFolder = getPathFromAmdModule(require, './fixtures');
const testWorkspace: IWorkspaceIdentifier = {
id: Date.now().toString(),
configPath: URI.file(path.join(fixturesFolder, 'workspaces.json'))
};
const testWorkspaceFolders = toWorkspaceFolders([{ path: path.join(fixturesFolder, 'vscode_workspace_1_folder') }, { path: path.join(fixturesFolder, 'vscode_workspace_2_folder') }], testWorkspace.configPath, extUriBiasedIgnorePathCase);
const localWorkspaceResolver = (workspace: any) => { return workspace === testWorkspace ? { id: testWorkspace.id, configPath: workspace.configPath, folders: testWorkspaceFolders } : null; };
function createTestCodeWindow(options: { lastFocusTime: number, openedFolderUri?: URI, openedWorkspace?: IWorkspaceIdentifier }): ICodeWindow {
return new class implements ICodeWindow {
onLoad: Event<void> = Event.None;
onReady: Event<void> = Event.None;
onClose: Event<void> = Event.None;
onDestroy: Event<void> = Event.None;
whenClosedOrLoaded: Promise<void> = Promise.resolve();
id: number = -1;
win: Electron.BrowserWindow = undefined!;
config: INativeWindowConfiguration | undefined;
openedWorkspace = options.openedFolderUri ? { id: '', uri: options.openedFolderUri } : options.openedWorkspace;
backupPath?: string | undefined;
remoteAuthority?: string | undefined;
isExtensionDevelopmentHost = false;
isExtensionTestHost = false;
lastFocusTime = options.lastFocusTime;
isFullScreen = false;
isReady = true;
hasHiddenTitleBarStyle = false;
ready(): Promise<ICodeWindow> { throw new Error('Method not implemented.'); }
setReady(): void { throw new Error('Method not implemented.'); }
addTabbedWindow(window: ICodeWindow): void { throw new Error('Method not implemented.'); }
load(config: INativeWindowConfiguration, options: { isReload?: boolean }): void { throw new Error('Method not implemented.'); }
reload(cli?: NativeParsedArgs): void { throw new Error('Method not implemented.'); }
focus(options?: { force: boolean; }): void { throw new Error('Method not implemented.'); }
close(): void { throw new Error('Method not implemented.'); }
getBounds(): Electron.Rectangle { throw new Error('Method not implemented.'); }
send(channel: string, ...args: any[]): void { throw new Error('Method not implemented.'); }
sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void { throw new Error('Method not implemented.'); }
toggleFullScreen(): void { throw new Error('Method not implemented.'); }
isMinimized(): boolean { throw new Error('Method not implemented.'); }
setRepresentedFilename(name: string): void { throw new Error('Method not implemented.'); }
getRepresentedFilename(): string | undefined { throw new Error('Method not implemented.'); }
setDocumentEdited(edited: boolean): void { throw new Error('Method not implemented.'); }
isDocumentEdited(): boolean { throw new Error('Method not implemented.'); }
handleTitleDoubleClick(): void { throw new Error('Method not implemented.'); }
updateTouchBar(items: UriDto<ICommandAction>[][]): void { throw new Error('Method not implemented.'); }
serializeWindowState(): IWindowState { throw new Error('Method not implemented'); }
dispose(): void { }
};
}
const vscodeFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder')) });
const lastActiveWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 3, openedFolderUri: undefined });
const noVscodeFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) });
const windows: ICodeWindow[] = [
vscodeFolderWindow,
lastActiveWindow,
noVscodeFolderWindow,
];
suite('WindowsFinder', () => {
test('New window without folder when no windows exist', () => {
assert.strictEqual(findWindowOnFile([], URI.file('nonexisting'), localWorkspaceResolver), undefined);
assert.strictEqual(findWindowOnFile([], URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')), localWorkspaceResolver), undefined);
});
test('Existing window with folder', () => {
assert.strictEqual(findWindowOnFile(windows, URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')), localWorkspaceResolver), noVscodeFolderWindow);
assert.strictEqual(findWindowOnFile(windows, URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')), localWorkspaceResolver), vscodeFolderWindow);
const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder')) });
assert.strictEqual(findWindowOnFile([window], URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), window);
});
test('More specific existing window wins', () => {
const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) });
const nestedFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder')) });
assert.strictEqual(findWindowOnFile([window, nestedFolderWindow], URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), nestedFolderWindow);
});
test('Workspace folder wins', () => {
const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedWorkspace: testWorkspace });
assert.strictEqual(findWindowOnFile([window], URI.file(path.join(fixturesFolder, 'vscode_workspace_2_folder', 'nested_vscode_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), window);
});
});

View File

@@ -0,0 +1,109 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { join } from 'vs/base/common/path';
import { findWindowOnFile } from 'vs/platform/windows/electron-main/windowsFinder';
import { ICodeWindow, ILoadEvent, IWindowState } from 'vs/platform/windows/electron-main/windows';
import { IWorkspaceIdentifier, toWorkspaceFolders } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { extUriBiasedIgnorePathCase } from 'vs/base/common/resources';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Event } from 'vs/base/common/event';
import { UriDto } from 'vs/base/common/types';
import { ICommandAction } from 'vs/platform/actions/common/actions';
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { INativeWindowConfiguration } from 'vs/platform/windows/common/windows';
suite('WindowsFinder', () => {
const fixturesFolder = getPathFromAmdModule(require, './fixtures');
const testWorkspace: IWorkspaceIdentifier = {
id: Date.now().toString(),
configPath: URI.file(join(fixturesFolder, 'workspaces.json'))
};
const testWorkspaceFolders = toWorkspaceFolders([{ path: join(fixturesFolder, 'vscode_workspace_1_folder') }, { path: join(fixturesFolder, 'vscode_workspace_2_folder') }], testWorkspace.configPath, extUriBiasedIgnorePathCase);
const localWorkspaceResolver = (workspace: any) => { return workspace === testWorkspace ? { id: testWorkspace.id, configPath: workspace.configPath, folders: testWorkspaceFolders } : null; };
function createTestCodeWindow(options: { lastFocusTime: number, openedFolderUri?: URI, openedWorkspace?: IWorkspaceIdentifier }): ICodeWindow {
return new class implements ICodeWindow {
onWillLoad: Event<ILoadEvent> = Event.None;
onDidSignalReady: Event<void> = Event.None;
onDidClose: Event<void> = Event.None;
onDidDestroy: Event<void> = Event.None;
whenClosedOrLoaded: Promise<void> = Promise.resolve();
id: number = -1;
win: Electron.BrowserWindow = null!;
config: INativeWindowConfiguration | undefined;
openedWorkspace = options.openedFolderUri ? { id: '', uri: options.openedFolderUri } : options.openedWorkspace;
backupPath?: string | undefined;
remoteAuthority?: string | undefined;
isExtensionDevelopmentHost = false;
isExtensionTestHost = false;
lastFocusTime = options.lastFocusTime;
isFullScreen = false;
isReady = true;
hasHiddenTitleBarStyle = false;
ready(): Promise<ICodeWindow> { throw new Error('Method not implemented.'); }
setReady(): void { throw new Error('Method not implemented.'); }
addTabbedWindow(window: ICodeWindow): void { throw new Error('Method not implemented.'); }
load(config: INativeWindowConfiguration, options: { isReload?: boolean }): void { throw new Error('Method not implemented.'); }
reload(cli?: NativeParsedArgs): void { throw new Error('Method not implemented.'); }
focus(options?: { force: boolean; }): void { throw new Error('Method not implemented.'); }
close(): void { throw new Error('Method not implemented.'); }
getBounds(): Electron.Rectangle { throw new Error('Method not implemented.'); }
send(channel: string, ...args: any[]): void { throw new Error('Method not implemented.'); }
sendWhenReady(channel: string, token: CancellationToken, ...args: any[]): void { throw new Error('Method not implemented.'); }
toggleFullScreen(): void { throw new Error('Method not implemented.'); }
isMinimized(): boolean { throw new Error('Method not implemented.'); }
setRepresentedFilename(name: string): void { throw new Error('Method not implemented.'); }
getRepresentedFilename(): string | undefined { throw new Error('Method not implemented.'); }
setDocumentEdited(edited: boolean): void { throw new Error('Method not implemented.'); }
isDocumentEdited(): boolean { throw new Error('Method not implemented.'); }
handleTitleDoubleClick(): void { throw new Error('Method not implemented.'); }
updateTouchBar(items: UriDto<ICommandAction>[][]): void { throw new Error('Method not implemented.'); }
serializeWindowState(): IWindowState { throw new Error('Method not implemented'); }
dispose(): void { }
};
}
const vscodeFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(join(fixturesFolder, 'vscode_folder')) });
const lastActiveWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 3, openedFolderUri: undefined });
const noVscodeFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 2, openedFolderUri: URI.file(join(fixturesFolder, 'no_vscode_folder')) });
const windows: ICodeWindow[] = [
vscodeFolderWindow,
lastActiveWindow,
noVscodeFolderWindow,
];
test('New window without folder when no windows exist', () => {
assert.strictEqual(findWindowOnFile([], URI.file('nonexisting'), localWorkspaceResolver), undefined);
assert.strictEqual(findWindowOnFile([], URI.file(join(fixturesFolder, 'no_vscode_folder', 'file.txt')), localWorkspaceResolver), undefined);
});
test('Existing window with folder', () => {
assert.strictEqual(findWindowOnFile(windows, URI.file(join(fixturesFolder, 'no_vscode_folder', 'file.txt')), localWorkspaceResolver), noVscodeFolderWindow);
assert.strictEqual(findWindowOnFile(windows, URI.file(join(fixturesFolder, 'vscode_folder', 'file.txt')), localWorkspaceResolver), vscodeFolderWindow);
const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(join(fixturesFolder, 'vscode_folder', 'nested_folder')) });
assert.strictEqual(findWindowOnFile([window], URI.file(join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), window);
});
test('More specific existing window wins', () => {
const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 2, openedFolderUri: URI.file(join(fixturesFolder, 'no_vscode_folder')) });
const nestedFolderWindow: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedFolderUri: URI.file(join(fixturesFolder, 'no_vscode_folder', 'nested_folder')) });
assert.strictEqual(findWindowOnFile([window, nestedFolderWindow], URI.file(join(fixturesFolder, 'no_vscode_folder', 'nested_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), nestedFolderWindow);
});
test('Workspace folder wins', () => {
const window: ICodeWindow = createTestCodeWindow({ lastFocusTime: 1, openedWorkspace: testWorkspace });
assert.strictEqual(findWindowOnFile([window], URI.file(join(fixturesFolder, 'vscode_workspace_2_folder', 'nested_vscode_folder', 'subfolder', 'file.txt')), localWorkspaceResolver), window);
});
});

View File

@@ -4,78 +4,79 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as os from 'os';
import * as path from 'vs/base/common/path';
import { tmpdir } from 'os';
import { join } from 'vs/base/common/path';
import { restoreWindowsState, getWindowsStateStoreData, IWindowsState, IWindowState } from 'vs/platform/windows/electron-main/windowsStateHandler';
import { IWindowState as IWindowUIState, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
function getUIState(): IWindowUIState {
return {
x: 0,
y: 10,
width: 100,
height: 200,
mode: 0
};
}
function toWorkspace(uri: URI): IWorkspaceIdentifier {
return {
id: '1234',
configPath: uri
};
}
function assertEqualURI(u1: URI | undefined, u2: URI | undefined, message?: string): void {
assert.strictEqual(u1 && u1.toString(), u2 && u2.toString(), message);
}
function assertEqualWorkspace(w1: IWorkspaceIdentifier | undefined, w2: IWorkspaceIdentifier | undefined, message?: string): void {
if (!w1 || !w2) {
assert.strictEqual(w1, w2, message);
return;
}
assert.strictEqual(w1.id, w2.id, message);
assertEqualURI(w1.configPath, w2.configPath, message);
}
function assertEqualWindowState(expected: IWindowState | undefined, actual: IWindowState | undefined, message?: string) {
if (!expected || !actual) {
assert.deepEqual(expected, actual, message);
return;
}
assert.strictEqual(expected.backupPath, actual.backupPath, message);
assertEqualURI(expected.folderUri, actual.folderUri, message);
assert.strictEqual(expected.remoteAuthority, actual.remoteAuthority, message);
assertEqualWorkspace(expected.workspace, actual.workspace, message);
assert.deepEqual(expected.uiState, actual.uiState, message);
}
function assertEqualWindowsState(expected: IWindowsState, actual: IWindowsState, message?: string) {
assertEqualWindowState(expected.lastPluginDevelopmentHostWindow, actual.lastPluginDevelopmentHostWindow, message);
assertEqualWindowState(expected.lastActiveWindow, actual.lastActiveWindow, message);
assert.strictEqual(expected.openedWindows.length, actual.openedWindows.length, message);
for (let i = 0; i < expected.openedWindows.length; i++) {
assertEqualWindowState(expected.openedWindows[i], actual.openedWindows[i], message);
}
}
function assertRestoring(state: IWindowsState, message?: string) {
const stored = getWindowsStateStoreData(state);
const restored = restoreWindowsState(stored);
assertEqualWindowsState(state, restored, message);
}
const testBackupPath1 = path.join(os.tmpdir(), 'windowStateTest', 'backupFolder1');
const testBackupPath2 = path.join(os.tmpdir(), 'windowStateTest', 'backupFolder2');
const testWSPath = URI.file(path.join(os.tmpdir(), 'windowStateTest', 'test.code-workspace'));
const testFolderURI = URI.file(path.join(os.tmpdir(), 'windowStateTest', 'testFolder'));
const testRemoteFolderURI = URI.parse('foo://bar/c/d');
suite('Windows State Storing', () => {
function getUIState(): IWindowUIState {
return {
x: 0,
y: 10,
width: 100,
height: 200,
mode: 0
};
}
function toWorkspace(uri: URI): IWorkspaceIdentifier {
return {
id: '1234',
configPath: uri
};
}
function assertEqualURI(u1: URI | undefined, u2: URI | undefined, message?: string): void {
assert.strictEqual(u1 && u1.toString(), u2 && u2.toString(), message);
}
function assertEqualWorkspace(w1: IWorkspaceIdentifier | undefined, w2: IWorkspaceIdentifier | undefined, message?: string): void {
if (!w1 || !w2) {
assert.strictEqual(w1, w2, message);
return;
}
assert.strictEqual(w1.id, w2.id, message);
assertEqualURI(w1.configPath, w2.configPath, message);
}
function assertEqualWindowState(expected: IWindowState | undefined, actual: IWindowState | undefined, message?: string) {
if (!expected || !actual) {
assert.deepStrictEqual(expected, actual, message);
return;
}
assert.strictEqual(expected.backupPath, actual.backupPath, message);
assertEqualURI(expected.folderUri, actual.folderUri, message);
assert.strictEqual(expected.remoteAuthority, actual.remoteAuthority, message);
assertEqualWorkspace(expected.workspace, actual.workspace, message);
assert.deepStrictEqual(expected.uiState, actual.uiState, message);
}
function assertEqualWindowsState(expected: IWindowsState, actual: IWindowsState, message?: string) {
assertEqualWindowState(expected.lastPluginDevelopmentHostWindow, actual.lastPluginDevelopmentHostWindow, message);
assertEqualWindowState(expected.lastActiveWindow, actual.lastActiveWindow, message);
assert.strictEqual(expected.openedWindows.length, actual.openedWindows.length, message);
for (let i = 0; i < expected.openedWindows.length; i++) {
assertEqualWindowState(expected.openedWindows[i], actual.openedWindows[i], message);
}
}
function assertRestoring(state: IWindowsState, message?: string) {
const stored = getWindowsStateStoreData(state);
const restored = restoreWindowsState(stored);
assertEqualWindowsState(state, restored, message);
}
const testBackupPath1 = join(tmpdir(), 'windowStateTest', 'backupFolder1');
const testBackupPath2 = join(tmpdir(), 'windowStateTest', 'backupFolder2');
const testWSPath = URI.file(join(tmpdir(), 'windowStateTest', 'test.code-workspace'));
const testFolderURI = URI.file(join(tmpdir(), 'windowStateTest', 'testFolder'));
const testRemoteFolderURI = URI.parse('foo://bar/c/d');
test('storing and restoring', () => {
let windowState: IWindowsState;
windowState = {