Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a (#7436)

* Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a

* fix strict null checks
This commit is contained in:
Anthony Dresser
2019-09-30 23:35:45 -07:00
committed by GitHub
parent 6ab03053a0
commit 084524cd2d
196 changed files with 2927 additions and 2547 deletions

View File

@@ -19,15 +19,17 @@ export interface IOpenedWindow {
filename?: string;
}
export interface IOpenInWindowOptions {
forceNewWindow?: boolean;
export interface IBaseOpenWindowsOptions {
forceReuseWindow?: boolean;
}
export interface IOpenWindowOptions extends IBaseOpenWindowsOptions {
forceNewWindow?: boolean;
noRecentEntry?: boolean;
}
export interface IOpenEmptyWindowOptions {
reuse?: boolean;
export interface IOpenEmptyWindowOptions extends IBaseOpenWindowsOptions {
remoteAuthority?: string;
}

View File

@@ -9,10 +9,10 @@ import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { IWorkspaceIdentifier, IEnterWorkspaceResult } from 'vs/platform/workspaces/common/workspaces';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { URI } from 'vs/base/common/uri';
import { MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue, Rectangle, BrowserWindow, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions } from 'electron';
import { Rectangle, BrowserWindow } from 'electron';
export interface IWindowState {
width?: number;
@@ -86,38 +86,34 @@ export interface IWindowsCountChangedEvent {
}
export interface IWindowsMainService {
_serviceBrand: undefined;
// events
readonly onWindowReady: Event<ICodeWindow>;
readonly onWindowsCountChanged: Event<IWindowsCountChangedEvent>;
readonly onWindowClose: Event<number>;
// methods
reload(win: ICodeWindow, cli?: ParsedArgs): void;
enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined>;
closeWorkspace(win: ICodeWindow): void;
open(openConfig: IOpenConfiguration): ICodeWindow[];
openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): void;
openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[];
openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[];
pickFileFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
pickFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
pickFileAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
pickWorkspaceAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void>;
showMessageBox(options: MessageBoxOptions, win?: ICodeWindow): Promise<MessageBoxReturnValue>;
showSaveDialog(options: SaveDialogOptions, win?: ICodeWindow): Promise<SaveDialogReturnValue>;
showOpenDialog(options: OpenDialogOptions, win?: ICodeWindow): Promise<OpenDialogReturnValue>;
focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow;
getLastActiveWindow(): ICodeWindow | undefined;
waitForWindowCloseOrLoad(windowId: number): Promise<void>;
openEmptyWindow(context: OpenContext, options?: IOpenEmptyWindowOptions): ICodeWindow[];
openNewTabbedWindow(context: OpenContext): ICodeWindow[];
openExternal(url: string): Promise<boolean>;
sendToFocused(channel: string, ...args: any[]): void;
sendToAll(channel: string, payload: any, windowIdsToIgnore?: number[]): void;
getFocusedWindow(): ICodeWindow | undefined;
getLastActiveWindow(): ICodeWindow | undefined;
getWindowById(windowId: number): ICodeWindow | undefined;
getWindows(): ICodeWindow[];
getWindowCount(): number;
waitForWindowCloseOrLoad(windowId: number): Promise<void>;
reload(win: ICodeWindow, cli?: ParsedArgs): void;
closeWorkspace(win: ICodeWindow): void;
quit(): void;
}
@@ -139,8 +135,3 @@ export interface IOpenConfiguration {
readonly initialStartup?: boolean;
readonly noRecentEntry?: boolean;
}
export interface ISharedProcess {
whenReady(): Promise<void>;
toggle(): void;
}

View File

@@ -3,12 +3,136 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IOpenInWindowOptions } from 'vs/platform/windows/common/windows';
import { OpenContext, IOpenWindowOptions } from 'vs/platform/windows/common/windows';
import { URI } from 'vs/base/common/uri';
import * as platform from 'vs/base/common/platform';
import * as extpath from 'vs/base/common/extpath';
import { IWorkspaceIdentifier, IResolvedWorkspace, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { isEqual, isEqualOrParent } from 'vs/base/common/resources';
export interface INativeOpenInWindowOptions extends IOpenInWindowOptions {
export interface INativeOpenWindowOptions extends IOpenWindowOptions {
diffMode?: boolean;
addMode?: boolean;
gotoLineMode?: boolean;
waitMarkerFileURI?: URI;
}
export interface IWindowContext {
openedWorkspace?: IWorkspaceIdentifier;
openedFolderUri?: URI;
extensionDevelopmentPath?: string[];
lastFocusTime: number;
}
export interface IBestWindowOrFolderOptions<W extends IWindowContext> {
windows: W[];
newWindow: boolean;
context: OpenContext;
fileUri?: URI;
userHome?: string;
codeSettingsFolder?: string;
localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null;
}
export function findBestWindowOrFolderForFile<W extends IWindowContext>({ windows, newWindow, context, fileUri, localWorkspaceResolver: workspaceResolver }: IBestWindowOrFolderOptions<W>): W | undefined {
if (!newWindow && fileUri && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK)) {
const windowOnFilePath = findWindowOnFilePath(windows, fileUri, workspaceResolver);
if (windowOnFilePath) {
return windowOnFilePath;
}
}
return !newWindow ? getLastActiveWindow(windows) : undefined;
}
function findWindowOnFilePath<W extends IWindowContext>(windows: W[], fileUri: URI, localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null): W | null {
// First check for windows with workspaces that have a parent folder of the provided path opened
for (const window of windows) {
const workspace = window.openedWorkspace;
if (workspace) {
const resolvedWorkspace = localWorkspaceResolver(workspace);
if (resolvedWorkspace) {
// workspace could be resolved: It's in the local file system
if (resolvedWorkspace.folders.some(folder => isEqualOrParent(fileUri, folder.uri))) {
return window;
}
} else {
// use the config path instead
if (isEqualOrParent(fileUri, workspace.configPath)) {
return window;
}
}
}
}
// Then go with single folder windows that are parent of the provided file path
const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && isEqualOrParent(fileUri, window.openedFolderUri));
if (singleFolderWindowsOnFilePath.length) {
return singleFolderWindowsOnFilePath.sort((a, b) => -(a.openedFolderUri!.path.length - b.openedFolderUri!.path.length))[0];
}
return null;
}
export function getLastActiveWindow<W extends IWindowContext>(windows: W[]): W | undefined {
const lastFocusedDate = Math.max.apply(Math, windows.map(window => window.lastFocusTime));
return windows.filter(window => window.lastFocusTime === lastFocusedDate)[0];
}
export function findWindowOnWorkspace<W extends IWindowContext>(windows: W[], workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier)): W | null {
if (isSingleFolderWorkspaceIdentifier(workspace)) {
for (const window of windows) {
// match on folder
if (isSingleFolderWorkspaceIdentifier(workspace)) {
if (window.openedFolderUri && isEqual(window.openedFolderUri, workspace)) {
return window;
}
}
}
} else if (isWorkspaceIdentifier(workspace)) {
for (const window of windows) {
// match on workspace
if (window.openedWorkspace && window.openedWorkspace.id === workspace.id) {
return window;
}
}
}
return null;
}
export function findWindowOnExtensionDevelopmentPath<W extends IWindowContext>(windows: W[], extensionDevelopmentPaths: string[]): W | null {
const matches = (uriString: string): boolean => {
return extensionDevelopmentPaths.some(p => extpath.isEqual(p, uriString, !platform.isLinux /* ignorecase */));
};
for (const window of windows) {
// match on extension development path. The path can be one or more paths or uri strings, using paths.isEqual is not 100% correct but good enough
const currPaths = window.extensionDevelopmentPath;
if (currPaths && currPaths.some(p => matches(p))) {
return window;
}
}
return null;
}
export function findWindowOnWorkspaceOrFolderUri<W extends IWindowContext>(windows: W[], uri: URI | undefined): W | null {
if (!uri) {
return null;
}
for (const window of windows) {
// check for workspace config path
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, uri)) {
return window;
}
// check for folder path
if (window.openedFolderUri && isEqual(window.openedFolderUri, uri)) {
return window;
}
}
return null;
}

View File

@@ -0,0 +1,128 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as path from 'vs/base/common/path';
import { IBestWindowOrFolderOptions, IWindowContext, findBestWindowOrFolderForFile } from 'vs/platform/windows/node/window';
import { OpenContext } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { toWorkspaceFolders } from 'vs/platform/workspace/common/workspace';
import { URI } from 'vs/base/common/uri';
import { getPathFromAmdModule } from 'vs/base/common/amd';
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);
function options(custom?: Partial<IBestWindowOrFolderOptions<IWindowContext>>): IBestWindowOrFolderOptions<IWindowContext> {
return {
windows: [],
newWindow: false,
context: OpenContext.CLI,
codeSettingsFolder: '_vscode',
localWorkspaceResolver: workspace => { return workspace === testWorkspace ? { id: testWorkspace.id, configPath: workspace.configPath, folders: testWorkspaceFolders } : null; },
...custom
};
}
const vscodeFolderWindow: IWindowContext = { lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder')) };
const lastActiveWindow: IWindowContext = { lastFocusTime: 3, openedFolderUri: undefined };
const noVscodeFolderWindow: IWindowContext = { lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) };
const windows: IWindowContext[] = [
vscodeFolderWindow,
lastActiveWindow,
noVscodeFolderWindow,
];
suite('WindowsFinder', () => {
test('New window without folder when no windows exist', () => {
assert.equal(findBestWindowOrFolderForFile(options()), null);
assert.equal(findBestWindowOrFolderForFile(options({
fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt'))
})), null);
assert.equal(findBestWindowOrFolderForFile(options({
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')),
newWindow: true
})), null);
assert.equal(findBestWindowOrFolderForFile(options({
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')),
})), null);
assert.equal(findBestWindowOrFolderForFile(options({
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')),
context: OpenContext.API
})), null);
assert.equal(findBestWindowOrFolderForFile(options({
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt'))
})), null);
assert.equal(findBestWindowOrFolderForFile(options({
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'new_folder', 'new_file.txt'))
})), null);
});
test('New window without folder when windows exist', () => {
assert.equal(findBestWindowOrFolderForFile(options({
windows,
fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')),
newWindow: true
})), null);
});
test('Last active window', () => {
assert.equal(findBestWindowOrFolderForFile(options({
windows
})), lastActiveWindow);
assert.equal(findBestWindowOrFolderForFile(options({
windows,
fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder2', 'file.txt'))
})), lastActiveWindow);
assert.equal(findBestWindowOrFolderForFile(options({
windows: [lastActiveWindow, noVscodeFolderWindow],
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt')),
})), lastActiveWindow);
assert.equal(findBestWindowOrFolderForFile(options({
windows,
fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt')),
context: OpenContext.API
})), lastActiveWindow);
});
test('Existing window with folder', () => {
assert.equal(findBestWindowOrFolderForFile(options({
windows,
fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'file.txt'))
})), noVscodeFolderWindow);
assert.equal(findBestWindowOrFolderForFile(options({
windows,
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'file.txt'))
})), vscodeFolderWindow);
const window: IWindowContext = { lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder')) };
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window],
fileUri: URI.file(path.join(fixturesFolder, 'vscode_folder', 'nested_folder', 'subfolder', 'file.txt'))
})), window);
});
test('More specific existing window wins', () => {
const window: IWindowContext = { lastFocusTime: 2, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder')) };
const nestedFolderWindow: IWindowContext = { lastFocusTime: 1, openedFolderUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder')) };
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window, nestedFolderWindow],
fileUri: URI.file(path.join(fixturesFolder, 'no_vscode_folder', 'nested_folder', 'subfolder', 'file.txt'))
})), nestedFolderWindow);
});
test('Workspace folder wins', () => {
const window: IWindowContext = { lastFocusTime: 1, openedWorkspace: testWorkspace };
assert.equal(findBestWindowOrFolderForFile(options({
windows: [window],
fileUri: URI.file(path.join(fixturesFolder, 'vscode_workspace_2_folder', 'nested_vscode_folder', 'subfolder', 'file.txt'))
})), window);
});
});