Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -15,7 +15,7 @@ import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window';
import { hasArgs, asArray } from 'vs/platform/environment/node/argv';
import { ipcMain as ipc, screen, BrowserWindow, dialog, systemPreferences, FileFilter } from 'electron';
import { parseLineAndColumnAware } from 'vs/code/node/paths';
import { ILifecycleService, UnloadReason, LifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { ILifecycleService, UnloadReason, LifecycleService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, INativeOpenDialogOptions, IPathsToWaitFor, IEnterWorkspaceResult, IMessageBoxResult, INewWindowOptions, IURIToOpen, isFileToOpen, isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows';
@@ -38,6 +38,8 @@ import { getComparisonKey, isEqual, normalizePath, basename as resourcesBasename
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage';
import { getWorkspaceIdentifier } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { once } from 'vs/base/common/functional';
import { Disposable } from 'vs/base/common/lifecycle';
const enum WindowError {
UNRESPONSIVE = 1,
@@ -153,15 +155,13 @@ interface IWorkspacePathToOpen {
label?: string;
}
export class WindowsManager implements IWindowsMainService {
export class WindowsManager extends Disposable implements IWindowsMainService {
_serviceBrand: any;
private static readonly windowsStateStorageKey = 'windowsState';
private static WINDOWS: ICodeWindow[] = [];
private initialUserEnv: IProcessEnvironment;
private static readonly WINDOWS: ICodeWindow[] = [];
private readonly windowsState: IWindowsState;
private lastClosedWindowState?: IWindowState;
@@ -169,20 +169,21 @@ export class WindowsManager implements IWindowsMainService {
private readonly dialogs: Dialogs;
private readonly workspacesManager: WorkspacesManager;
private _onWindowReady = new Emitter<ICodeWindow>();
onWindowReady: CommonEvent<ICodeWindow> = this._onWindowReady.event;
private readonly _onWindowReady = this._register(new Emitter<ICodeWindow>());
readonly onWindowReady: CommonEvent<ICodeWindow> = this._onWindowReady.event;
private _onWindowClose = new Emitter<number>();
onWindowClose: CommonEvent<number> = this._onWindowClose.event;
private readonly _onWindowClose = this._register(new Emitter<number>());
readonly onWindowClose: CommonEvent<number> = this._onWindowClose.event;
private _onWindowLoad = new Emitter<number>();
onWindowLoad: CommonEvent<number> = this._onWindowLoad.event;
private readonly _onWindowLoad = this._register(new Emitter<number>());
readonly onWindowLoad: CommonEvent<number> = this._onWindowLoad.event;
private _onWindowsCountChanged = new Emitter<IWindowsCountChangedEvent>();
onWindowsCountChanged: CommonEvent<IWindowsCountChangedEvent> = this._onWindowsCountChanged.event;
private readonly _onWindowsCountChanged = this._register(new Emitter<IWindowsCountChangedEvent>());
readonly onWindowsCountChanged: CommonEvent<IWindowsCountChangedEvent> = this._onWindowsCountChanged.event;
constructor(
private readonly machineId: string,
private readonly initialUserEnv: IProcessEnvironment,
@ILogService private readonly logService: ILogService,
@IStateService private readonly stateService: IStateService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@@ -194,6 +195,7 @@ export class WindowsManager implements IWindowsMainService {
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super();
const windowsStateStoreData = this.stateService.getItem<WindowsStateStorageData>(WindowsManager.windowsStateStorageKey);
this.windowsState = restoreWindowsState(windowsStateStoreData);
@@ -203,12 +205,21 @@ export class WindowsManager implements IWindowsMainService {
this.dialogs = new Dialogs(stateService, this);
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, this);
this.lifecycleService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
this.lifecycleService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.installWindowsMutex());
}
ready(initialUserEnv: IProcessEnvironment): void {
this.initialUserEnv = initialUserEnv;
this.registerListeners();
private installWindowsMutex(): void {
if (isWindows) {
try {
const WindowsMutex = (require.__$__nodeRequire('windows-mutex') as typeof import('windows-mutex')).Mutex;
const mutex = new WindowsMutex(product.win32MutexName);
once(this.lifecycleService.onWillShutdown)(() => mutex.release());
} catch (e) {
this.logService.error(e);
}
}
}
private registerListeners(): void {
@@ -543,6 +554,7 @@ export class WindowsManager implements IWindowsMainService {
// Find suitable window or folder path to open files in
const fileToCheck = fileInputs.filesToOpenOrCreate[0] || fileInputs.filesToDiff[0];
// only look at the windows with correct authority
const windows = WindowsManager.WINDOWS.filter(w => w.remoteAuthority === fileInputs!.remoteAuthority);
@@ -639,7 +651,6 @@ export class WindowsManager implements IWindowsMainService {
// Handle folders to open (instructed and to restore)
const allFoldersToOpen = arrays.distinct(foldersToOpen, folder => getComparisonKey(folder.folderUri)); // prevent duplicates
if (allFoldersToOpen.length > 0) {
// Check for existing instances
@@ -713,7 +724,9 @@ export class WindowsManager implements IWindowsMainService {
if (fileInputs && !emptyToOpen) {
emptyToOpen++;
}
const remoteAuthority = fileInputs ? fileInputs.remoteAuthority : (openConfig.cli && openConfig.cli.remote || undefined);
for (let i = 0; i < emptyToOpen; i++) {
usedWindows.push(this.openInBrowserWindow({
userEnv: openConfig.userEnv,
@@ -1289,7 +1302,7 @@ export class WindowsManager implements IWindowsMainService {
// 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.environmentService.backupHome.fsPath, options.emptyWindowBackupInfo.backupFolder);
}
let window: ICodeWindow | undefined;
@@ -1536,14 +1549,13 @@ export class WindowsManager implements IWindowsMainService {
return state;
}
reload(win: ICodeWindow, cli?: ParsedArgs): void {
async reload(win: ICodeWindow, cli?: ParsedArgs): Promise<void> {
// Only reload when the window has not vetoed this
this.lifecycleService.unload(win, UnloadReason.RELOAD).then(veto => {
if (!veto) {
win.reload(undefined, cli);
}
});
const veto = await this.lifecycleService.unload(win, UnloadReason.RELOAD);
if (!veto) {
win.reload(undefined, cli);
}
}
closeWorkspace(win: ICodeWindow): void {
@@ -1554,8 +1566,10 @@ export class WindowsManager implements IWindowsMainService {
});
}
enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined> {
return this.workspacesManager.enterWorkspace(win, path).then(result => result ? this.doEnterWorkspace(win, result) : undefined);
async enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined> {
const result = await this.workspacesManager.enterWorkspace(win, path);
return result ? this.doEnterWorkspace(win, result) : undefined;
}
private doEnterWorkspace(win: ICodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult {
@@ -1666,14 +1680,13 @@ export class WindowsManager implements IWindowsMainService {
private onWindowError(window: ICodeWindow, error: WindowError): void {
this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive');
/* __GDPR__
"windowerror" : {
"type" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }
}
*/
this.telemetryService.publicLog('windowerror', { type: error });
type WindowErrorClassification = {
type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
};
type WindowErrorEvent = {
type: WindowError;
};
this.telemetryService.publicLog2<WindowErrorEvent, WindowErrorClassification>('windowerror', { type: error });
// Unresponsive
if (error === WindowError.UNRESPONSIVE) {
if (window.isExtensionDevelopmentHost || window.isExtensionTestHost || (window.win && window.win.webContents && window.win.webContents.isDevToolsOpened())) {
@@ -1751,8 +1764,10 @@ export class WindowsManager implements IWindowsMainService {
const paths = await this.dialogs.pick({ ...options, pickFolders: true, pickFiles: true, title });
if (paths) {
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData);
const urisToOpen = await Promise.all(paths.map(path => {
return dirExists(path).then(isDir => isDir ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) });
const urisToOpen = await Promise.all(paths.map(async path => {
const isDir = await dirExists(path);
return isDir ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) };
}));
this.open({
context: OpenContext.DIALOG,
@@ -1880,7 +1895,7 @@ class Dialogs {
this.noWindowDialogQueue = new Queue<void>();
}
pick(options: IInternalNativeOpenDialogOptions): Promise<string[] | undefined> {
async pick(options: IInternalNativeOpenDialogOptions): Promise<string[] | undefined> {
// Ensure dialog options
const dialogOptions: Electron.OpenDialogOptions = {
@@ -1913,16 +1928,16 @@ class Dialogs {
// Show Dialog
const focusedWindow = (typeof options.windowId === 'number' ? this.windowsMainService.getWindowById(options.windowId) : undefined) || this.windowsMainService.getFocusedWindow();
return this.showOpenDialog(dialogOptions, focusedWindow).then(paths => {
if (paths && paths.length > 0) {
const paths = await this.showOpenDialog(dialogOptions, focusedWindow);
if (paths && paths.length > 0) {
// Remember path in storage for next time
this.stateService.setItem(Dialogs.workingDirPickerStorageKey, dirname(paths[0]));
return paths;
}
// Remember path in storage for next time
this.stateService.setItem(Dialogs.workingDirPickerStorageKey, dirname(paths[0]));
return undefined;
});
return paths;
}
return undefined; // {{SQL CARBON EDIT}} @anthonydresser strict-null-check
}
private getDialogQueue(window?: ICodeWindow): Queue<any> {
@@ -2028,28 +2043,26 @@ class WorkspacesManager {
private readonly windowsMainService: IWindowsMainService,
) { }
enterWorkspace(window: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | null> {
async enterWorkspace(window: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | null> {
if (!window || !window.win || !window.isReady) {
return Promise.resolve(null); // return early if the window is not ready or disposed
return null; // return early if the window is not ready or disposed
}
return this.isValidTargetWorkspacePath(window, path).then(isValid => {
if (!isValid) {
return null; // return early if the workspace is not valid
}
const workspaceIdentifier = getWorkspaceIdentifier(path);
return this.doOpenWorkspace(window, workspaceIdentifier);
});
const isValid = await this.isValidTargetWorkspacePath(window, path);
if (!isValid) {
return null; // return early if the workspace is not valid
}
return this.doOpenWorkspace(window, getWorkspaceIdentifier(path));
}
private isValidTargetWorkspacePath(window: ICodeWindow, path?: URI): Promise<boolean> {
private async isValidTargetWorkspacePath(window: ICodeWindow, path?: URI): Promise<boolean> {
if (!path) {
return Promise.resolve(true);
return true;
}
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, path)) {
return Promise.resolve(false); // window is already opened on a workspace with that path
return false; // window is already opened on a workspace with that path
}
// Prevent overwriting a workspace that is currently opened in another window
@@ -2063,10 +2076,12 @@ class WorkspacesManager {
noLink: true
};
return this.windowsMainService.showMessageBox(options, this.windowsMainService.getFocusedWindow()).then(() => false);
await this.windowsMainService.showMessageBox(options, this.windowsMainService.getFocusedWindow());
return false;
}
return Promise.resolve(true); // OK
return true; // OK
}
private doOpenWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): IEnterWorkspaceResult {
@@ -2090,14 +2105,16 @@ class WorkspacesManager {
return { workspace, backupPath };
}
}
function resourceFromURIToOpen(u: IURIToOpen) {
function resourceFromURIToOpen(u: IURIToOpen): URI {
if (isWorkspaceToOpen(u)) {
return u.workspaceUri;
} else if (isFolderToOpen(u)) {
}
if (isFolderToOpen(u)) {
return u.folderUri;
}
return u.fileUri;
}