Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -7,31 +7,110 @@
import URI from 'vs/base/common/uri';
import Event, { Emitter } from 'vs/base/common/event';
import { normalize } from 'vs/base/common/paths';
import { delta } from 'vs/base/common/arrays';
import { delta as arrayDelta } from 'vs/base/common/arrays';
import { relative, dirname } from 'path';
import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext } from './extHost.protocol';
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext, MainThreadMessageServiceShape } from './extHost.protocol';
import * as vscode from 'vscode';
import { compare } from 'vs/base/common/strings';
import { TernarySearchTree } from 'vs/base/common/map';
import { basenameOrAuthority, isEqual } from 'vs/base/common/resources';
import { isLinux } from 'vs/base/common/platform';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { localize } from 'vs/nls';
import { Severity } from 'vs/platform/notification/common/notification';
import { ILogService } from 'vs/platform/log/common/log';
class Workspace2 extends Workspace {
function isFolderEqual(folderA: URI, folderB: URI): boolean {
return isEqual(folderA, folderB, !isLinux);
}
static fromData(data: IWorkspaceData) {
return data ? new Workspace2(data) : null;
function compareWorkspaceFolderByUri(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
return isFolderEqual(a.uri, b.uri) ? 0 : compare(a.uri.toString(), b.uri.toString());
}
function compareWorkspaceFolderByUriAndNameAndIndex(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
if (a.index !== b.index) {
return a.index < b.index ? -1 : 1;
}
return isFolderEqual(a.uri, b.uri) ? compare(a.name, b.name) : compare(a.uri.toString(), b.uri.toString());
}
function delta(oldFolders: vscode.WorkspaceFolder[], newFolders: vscode.WorkspaceFolder[], compare: (a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder) => number): { removed: vscode.WorkspaceFolder[], added: vscode.WorkspaceFolder[] } {
const oldSortedFolders = oldFolders.slice(0).sort(compare);
const newSortedFolders = newFolders.slice(0).sort(compare);
return arrayDelta(oldSortedFolders, newSortedFolders, compare);
}
interface MutableWorkspaceFolder extends vscode.WorkspaceFolder {
name: string;
index: number;
}
class ExtHostWorkspaceImpl extends Workspace {
static toExtHostWorkspace(data: IWorkspaceData, previousConfirmedWorkspace?: ExtHostWorkspaceImpl, previousUnconfirmedWorkspace?: ExtHostWorkspaceImpl): { workspace: ExtHostWorkspaceImpl, added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[] } {
if (!data) {
return { workspace: null, added: [], removed: [] };
}
const { id, name, folders } = data;
const newWorkspaceFolders: vscode.WorkspaceFolder[] = [];
// If we have an existing workspace, we try to find the folders that match our
// data and update their properties. It could be that an extension stored them
// for later use and we want to keep them "live" if they are still present.
const oldWorkspace = previousConfirmedWorkspace;
if (oldWorkspace) {
folders.forEach((folderData, index) => {
const folderUri = URI.revive(folderData.uri);
const existingFolder = ExtHostWorkspaceImpl._findFolder(previousUnconfirmedWorkspace || previousConfirmedWorkspace, folderUri);
if (existingFolder) {
existingFolder.name = folderData.name;
existingFolder.index = folderData.index;
newWorkspaceFolders.push(existingFolder);
} else {
newWorkspaceFolders.push({ uri: folderUri, name: folderData.name, index });
}
});
} else {
newWorkspaceFolders.push(...folders.map(({ uri, name, index }) => ({ uri: URI.revive(uri), name, index })));
}
// make sure to restore sort order based on index
newWorkspaceFolders.sort((f1, f2) => f1.index < f2.index ? -1 : 1);
const workspace = new ExtHostWorkspaceImpl(id, name, newWorkspaceFolders);
const { added, removed } = delta(oldWorkspace ? oldWorkspace.workspaceFolders : [], workspace.workspaceFolders, compareWorkspaceFolderByUri);
return { workspace, added, removed };
}
private static _findFolder(workspace: ExtHostWorkspaceImpl, folderUriToFind: URI): MutableWorkspaceFolder {
for (let i = 0; i < workspace.folders.length; i++) {
const folder = workspace.workspaceFolders[i];
if (isFolderEqual(folder.uri, folderUriToFind)) {
return folder;
}
}
return undefined;
}
private readonly _workspaceFolders: vscode.WorkspaceFolder[] = [];
private readonly _structure = TernarySearchTree.forPaths<vscode.WorkspaceFolder>();
private constructor(data: IWorkspaceData) {
super(data.id, data.name, data.folders.map(folder => new WorkspaceFolder(folder)));
private constructor(id: string, name: string, folders: vscode.WorkspaceFolder[]) {
super(id, name, folders.map(f => new WorkspaceFolder(f)));
// setup the workspace folder data structure
this.folders.forEach(({ name, uri, index }) => {
const workspaceFolder = { name, uri, index };
this._workspaceFolders.push(workspaceFolder);
this._structure.set(workspaceFolder.uri.toString(), workspaceFolder);
folders.forEach(folder => {
this._workspaceFolders.push(folder);
this._structure.set(folder.uri.toString(), folder);
});
}
@@ -54,44 +133,122 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
private readonly _onDidChangeWorkspace = new Emitter<vscode.WorkspaceFoldersChangeEvent>();
private readonly _proxy: MainThreadWorkspaceShape;
private _workspace: Workspace2;
private _confirmedWorkspace: ExtHostWorkspaceImpl;
private _unconfirmedWorkspace: ExtHostWorkspaceImpl;
private _messageService: MainThreadMessageServiceShape;
readonly onDidChangeWorkspace: Event<vscode.WorkspaceFoldersChangeEvent> = this._onDidChangeWorkspace.event;
constructor(mainContext: IMainContext, data: IWorkspaceData) {
this._proxy = mainContext.get(MainContext.MainThreadWorkspace);
this._workspace = Workspace2.fromData(data);
constructor(
mainContext: IMainContext,
data: IWorkspaceData,
private _logService: ILogService
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadWorkspace);
this._messageService = mainContext.getProxy(MainContext.MainThreadMessageService);
this._confirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace(data).workspace;
}
// --- workspace ---
get workspace(): Workspace {
return this._workspace;
return this._actualWorkspace;
}
private get _actualWorkspace(): ExtHostWorkspaceImpl {
return this._unconfirmedWorkspace || this._confirmedWorkspace;
}
getWorkspaceFolders(): vscode.WorkspaceFolder[] {
if (!this._workspace) {
if (!this._actualWorkspace) {
return undefined;
} else {
return this._workspace.workspaceFolders.slice(0);
}
return this._actualWorkspace.workspaceFolders.slice(0);
}
updateWorkspaceFolders(extension: IExtensionDescription, index: number, deleteCount: number, ...workspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[]): boolean {
const validatedDistinctWorkspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[] = [];
if (Array.isArray(workspaceFoldersToAdd)) {
workspaceFoldersToAdd.forEach(folderToAdd => {
if (URI.isUri(folderToAdd.uri) && !validatedDistinctWorkspaceFoldersToAdd.some(f => isFolderEqual(f.uri, folderToAdd.uri))) {
validatedDistinctWorkspaceFoldersToAdd.push({ uri: folderToAdd.uri, name: folderToAdd.name || basenameOrAuthority(folderToAdd.uri) });
}
});
}
if (!!this._unconfirmedWorkspace) {
return false; // prevent accumulated calls without a confirmed workspace
}
if ([index, deleteCount].some(i => typeof i !== 'number' || i < 0)) {
return false; // validate numbers
}
if (deleteCount === 0 && validatedDistinctWorkspaceFoldersToAdd.length === 0) {
return false; // nothing to delete or add
}
const currentWorkspaceFolders: MutableWorkspaceFolder[] = this._actualWorkspace ? this._actualWorkspace.workspaceFolders : [];
if (index + deleteCount > currentWorkspaceFolders.length) {
return false; // cannot delete more than we have
}
// Simulate the updateWorkspaceFolders method on our data to do more validation
const newWorkspaceFolders = currentWorkspaceFolders.slice(0);
newWorkspaceFolders.splice(index, deleteCount, ...validatedDistinctWorkspaceFoldersToAdd.map(f => ({ uri: f.uri, name: f.name || basenameOrAuthority(f.uri), index: undefined })));
for (let i = 0; i < newWorkspaceFolders.length; i++) {
const folder = newWorkspaceFolders[i];
if (newWorkspaceFolders.some((otherFolder, index) => index !== i && isFolderEqual(folder.uri, otherFolder.uri))) {
return false; // cannot add the same folder multiple times
}
}
newWorkspaceFolders.forEach((f, index) => f.index = index); // fix index
const { added, removed } = delta(currentWorkspaceFolders, newWorkspaceFolders, compareWorkspaceFolderByUriAndNameAndIndex);
if (added.length === 0 && removed.length === 0) {
return false; // nothing actually changed
}
// Trigger on main side
if (this._proxy) {
const extName = extension.displayName || extension.name;
this._proxy.$updateWorkspaceFolders(extName, index, deleteCount, validatedDistinctWorkspaceFoldersToAdd).then(null, error => {
// in case of an error, make sure to clear out the unconfirmed workspace
// because we cannot expect the acknowledgement from the main side for this
this._unconfirmedWorkspace = undefined;
// show error to user
this._messageService.$showMessage(Severity.Error, localize('updateerror', "Extension '{0}' failed to update workspace folders: {1}", extName, error.toString()), { extension }, []);
});
}
// Try to accept directly
this.trySetWorkspaceFolders(newWorkspaceFolders);
return true;
}
getWorkspaceFolder(uri: vscode.Uri, resolveParent?: boolean): vscode.WorkspaceFolder {
if (!this._workspace) {
if (!this._actualWorkspace) {
return undefined;
}
return this._workspace.getWorkspaceFolder(uri, resolveParent);
return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent);
}
getPath(): string {
// this is legacy from the days before having
// multi-root and we keep it only alive if there
// is just one workspace folder.
if (!this._workspace) {
if (!this._actualWorkspace) {
return undefined;
}
const { folders } = this._workspace;
const { folders } = this._actualWorkspace;
if (folders.length === 0) {
return undefined;
}
@@ -121,7 +278,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
}
if (typeof includeWorkspace === 'undefined') {
includeWorkspace = this.workspace.folders.length > 1;
includeWorkspace = this._actualWorkspace.folders.length > 1;
}
let result = relative(folder.uri.fsPath, path);
@@ -131,17 +288,30 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
return normalize(result, true);
}
private trySetWorkspaceFolders(folders: vscode.WorkspaceFolder[]): void {
// Update directly here. The workspace is unconfirmed as long as we did not get an
// acknowledgement from the main side (via $acceptWorkspaceData)
if (this._actualWorkspace) {
this._unconfirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace({
id: this._actualWorkspace.id,
name: this._actualWorkspace.name,
configuration: this._actualWorkspace.configuration,
folders
} as IWorkspaceData, this._actualWorkspace).workspace;
}
}
$acceptWorkspaceData(data: IWorkspaceData): void {
// keep old workspace folder, build new workspace, and
// capture new workspace folders. Compute delta between
// them send that as event
const oldRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : [];
const { workspace, added, removed } = ExtHostWorkspaceImpl.toExtHostWorkspace(data, this._confirmedWorkspace, this._unconfirmedWorkspace);
this._workspace = Workspace2.fromData(data);
const newRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : [];
// Update our workspace object. We have a confirmed workspace, so we drop our
// unconfirmed workspace.
this._confirmedWorkspace = workspace;
this._unconfirmedWorkspace = undefined;
const { added, removed } = delta(oldRoots, newRoots, ExtHostWorkspace._compareWorkspaceFolder);
// Events
// {{SQL CARBON EDIT}} - fix build break Argument of type 'Readonly<...
this._onDidChangeWorkspace.fire({
added: added,
@@ -149,13 +319,11 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
});
}
private static _compareWorkspaceFolder(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
return compare(a.uri.toString(), b.uri.toString());
}
// --- search ---
findFiles(include: vscode.GlobPattern, exclude: vscode.GlobPattern, maxResults?: number, token?: vscode.CancellationToken): Thenable<vscode.Uri[]> {
findFiles(include: vscode.GlobPattern, exclude: vscode.GlobPattern, maxResults: number, extensionId: string, token?: vscode.CancellationToken): Thenable<vscode.Uri[]> {
this._logService.trace(`extHostWorkspace#findFiles: fileSearch, extension: ${extensionId}, entryPoint: findFiles`);
const requestId = ExtHostWorkspace._requestIdPool++;
let includePattern: string;
@@ -169,20 +337,22 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
}
}
let excludePattern: string;
if (exclude) {
let excludePatternOrDisregardExcludes: string | false;
if (exclude === null) {
excludePatternOrDisregardExcludes = false;
} else if (exclude) {
if (typeof exclude === 'string') {
excludePattern = exclude;
excludePatternOrDisregardExcludes = exclude;
} else {
excludePattern = exclude.pattern;
excludePatternOrDisregardExcludes = exclude.pattern;
}
}
const result = this._proxy.$startSearch(includePattern, includeFolder, excludePattern, maxResults, requestId);
const result = this._proxy.$startSearch(includePattern, includeFolder, excludePatternOrDisregardExcludes, maxResults, requestId);
if (token) {
token.onCancellationRequested(() => this._proxy.$cancelSearch(requestId));
}
return result;
return result.then(data => data.map(URI.revive));
}
saveAll(includeUntitled?: boolean): Thenable<boolean> {