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

@@ -14,7 +14,7 @@ import Event, { Emitter } from 'vs/base/common/event';
import platform = require('vs/base/common/platform');
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IRevertOptions, IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions, AutoSaveContext } from 'vs/workbench/services/textfile/common/textfiles';
import { ConfirmResult } from 'vs/workbench/common/editor';
import { ILifecycleService, ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
@@ -22,14 +22,18 @@ import { IFileService, IResolveContentOptions, IFilesConfiguration, FileOperatio
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IUntitledEditorService, UNTITLED_SCHEMA } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel';
import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IMessageService, Severity } from 'vs/platform/message/common/message';
import { ResourceMap } from 'vs/base/common/map';
import { Schemas } from 'vs/base/common/network';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IRevertOptions } from 'vs/platform/editor/common/editor';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel';
import { IModelService } from 'vs/editor/common/services/modelService';
import { INotificationService } from 'vs/platform/notification/common/notification';
export interface IBackupResult {
didBackup: boolean;
@@ -55,6 +59,8 @@ export abstract class TextFileService implements ITextFileService {
private configuredAutoSaveOnFocusChange: boolean;
private configuredAutoSaveOnWindowChange: boolean;
private autoSaveContext: IContextKey<string>;
private configuredHotExit: string;
constructor(
@@ -64,11 +70,13 @@ export abstract class TextFileService implements ITextFileService {
protected fileService: IFileService,
private untitledEditorService: IUntitledEditorService,
private instantiationService: IInstantiationService,
private messageService: IMessageService,
private notificationService: INotificationService,
protected environmentService: IEnvironmentService,
private backupFileService: IBackupFileService,
private windowsService: IWindowsService,
private historyService: IHistoryService
private historyService: IHistoryService,
contextKeyService: IContextKeyService,
private modelService: IModelService
) {
this.toUnbind = [];
@@ -79,6 +87,7 @@ export abstract class TextFileService implements ITextFileService {
this.toUnbind.push(this._onFilesAssociationChange);
this._models = this.instantiationService.createInstance(TextFileEditorModelManager);
this.autoSaveContext = AutoSaveContext.bindTo(contextKeyService);
const configuration = this.configurationService.getValue<IFilesConfiguration>();
this.currentFilesAssociationConfig = configuration && configuration.files && configuration.files.associations;
@@ -94,9 +103,9 @@ export abstract class TextFileService implements ITextFileService {
abstract resolveTextContent(resource: URI, options?: IResolveContentOptions): TPromise<IRawTextContent>;
abstract promptForPath(defaultPath: string): string;
abstract promptForPath(defaultPath: string): TPromise<string>;
abstract confirmSave(resources?: URI[]): ConfirmResult;
abstract confirmSave(resources?: URI[]): TPromise<ConfirmResult>;
public get onAutoSaveConfigurationChange(): Event<IAutoSaveConfiguration> {
return this._onAutoSaveConfigurationChange.event;
@@ -152,7 +161,7 @@ export abstract class TextFileService implements ITextFileService {
return this.confirmBeforeShutdown();
}, errors => {
const firstError = errors[0];
this.messageService.show(Severity.Error, nls.localize('files.backup.failSave', "Files that are dirty could not be written to the backup location (Error: {0}). Try saving your files first and then exit.", firstError.message));
this.notificationService.error(nls.localize('files.backup.failSave', "Files that are dirty could not be written to the backup location (Error: {0}). Try saving your files first and then exit.", firstError.message));
return true; // veto, the backups failed
});
@@ -222,9 +231,9 @@ export abstract class TextFileService implements ITextFileService {
const filesToBackup: ITextFileEditorModel[] = [];
const untitledToBackup: URI[] = [];
dirtyToBackup.forEach(s => {
if (s.scheme === Schemas.file) {
if (this.fileService.canHandleResource(s)) {
filesToBackup.push(textFileEditorModelManager.get(s));
} else if (s.scheme === UNTITLED_SCHEMA) {
} else if (s.scheme === Schemas.untitled) {
untitledToBackup.push(s);
}
});
@@ -235,7 +244,7 @@ export abstract class TextFileService implements ITextFileService {
private doBackupAll(dirtyFileModels: ITextFileEditorModel[], untitledResources: URI[]): TPromise<void> {
// Handle file resources first
return TPromise.join(dirtyFileModels.map(model => this.backupFileService.backupResource(model.getResource(), model.getValue(), model.getVersionId()))).then(results => {
return TPromise.join(dirtyFileModels.map(model => this.backupFileService.backupResource(model.getResource(), model.createSnapshot(), model.getVersionId()))).then(results => {
// Handle untitled resources
const untitledModelPromises = untitledResources
@@ -244,7 +253,7 @@ export abstract class TextFileService implements ITextFileService {
return TPromise.join(untitledModelPromises).then(untitledModels => {
const untitledBackupPromises = untitledModels.map(model => {
return this.backupFileService.backupResource(model.getResource(), model.getValue(), model.getVersionId());
return this.backupFileService.backupResource(model.getResource(), model.createSnapshot(), model.getVersionId());
});
return TPromise.join(untitledBackupPromises).then(() => void 0);
@@ -253,35 +262,36 @@ export abstract class TextFileService implements ITextFileService {
}
private confirmBeforeShutdown(): boolean | TPromise<boolean> {
const confirm = this.confirmSave();
return this.confirmSave().then(confirm => {
// Save
if (confirm === ConfirmResult.SAVE) {
return this.saveAll(true /* includeUntitled */, { skipSaveParticipants: true }).then(result => {
if (result.results.some(r => !r.success)) {
return true; // veto if some saves failed
}
// Save
if (confirm === ConfirmResult.SAVE) {
return this.saveAll(true /* includeUntitled */, { skipSaveParticipants: true }).then(result => {
if (result.results.some(r => !r.success)) {
return true; // veto if some saves failed
}
return this.noVeto({ cleanUpBackups: true });
});
}
// Don't Save
else if (confirm === ConfirmResult.DONT_SAVE) {
// Make sure to revert untitled so that they do not restore
// see https://github.com/Microsoft/vscode/issues/29572
this.untitledEditorService.revertAll();
return this.noVeto({ cleanUpBackups: true });
});
}
}
// Don't Save
else if (confirm === ConfirmResult.DONT_SAVE) {
// Cancel
else if (confirm === ConfirmResult.CANCEL) {
return true; // veto
}
// Make sure to revert untitled so that they do not restore
// see https://github.com/Microsoft/vscode/issues/29572
this.untitledEditorService.revertAll();
return this.noVeto({ cleanUpBackups: true });
}
// Cancel
else if (confirm === ConfirmResult.CANCEL) {
return true; // veto
}
return void 0;
return void 0;
});
}
private noVeto(options: { cleanUpBackups: boolean }): boolean | TPromise<boolean> {
@@ -304,6 +314,7 @@ export abstract class TextFileService implements ITextFileService {
const wasAutoSaveEnabled = (this.getAutoSaveMode() !== AutoSaveMode.OFF);
const autoSaveMode = (configuration && configuration.files && configuration.files.autoSave) || AutoSaveConfiguration.OFF;
this.autoSaveContext.set(autoSaveMode);
switch (autoSaveMode) {
case AutoSaveConfiguration.AFTER_DELAY:
this.configuredAutoSaveDelay = configuration && configuration.files && configuration.files.autoSaveDelay;
@@ -379,7 +390,7 @@ export abstract class TextFileService implements ITextFileService {
public save(resource: URI, options?: ISaveOptions): TPromise<boolean> {
// Run a forced save if we detect the file is not dirty so that save participants can still run
if (options && options.force && resource.scheme === Schemas.file && !this.isDirty(resource)) {
if (options && options.force && this.fileService.canHandleResource(resource) && !this.isDirty(resource)) {
const model = this._models.get(resource);
if (model) {
model.save({ force: true, reason: SaveReason.EXPLICIT }).then(() => !model.isDirty());
@@ -405,11 +416,7 @@ export abstract class TextFileService implements ITextFileService {
const filesToSave: URI[] = [];
const untitledToSave: URI[] = [];
toSave.forEach(s => {
// TODO@remote
// if (s.scheme === Schemas.file) {
// filesToSave.push(s);
// } else
if ((Array.isArray(arg1) || arg1 === true /* includeUntitled */) && s.scheme === UNTITLED_SCHEMA) {
if ((Array.isArray(arg1) || arg1 === true /* includeUntitled */) && s.scheme === Schemas.untitled) {
untitledToSave.push(s);
} else {
filesToSave.push(s);
@@ -422,7 +429,7 @@ export abstract class TextFileService implements ITextFileService {
private doSaveAll(fileResources: URI[], untitledResources: URI[], options?: ISaveOptions): TPromise<ITextFileOperationResult> {
// Handle files first that can just be saved
return this.doSaveAllFiles(fileResources, options).then(result => {
return this.doSaveAllFiles(fileResources, options).then(async result => {
// Preflight for untitled to handle cancellation from the dialog
const targetsForUntitled: URI[] = [];
@@ -438,7 +445,7 @@ export abstract class TextFileService implements ITextFileService {
// Otherwise ask user
else {
targetPath = this.promptForPath(this.suggestFileName(untitled));
targetPath = await this.promptForPath(this.suggestFileName(untitled));
if (!targetPath) {
return TPromise.as({
results: [...fileResources, ...untitledResources].map(r => {
@@ -525,41 +532,49 @@ export abstract class TextFileService implements ITextFileService {
return this.getFileModels(arg1).filter(model => model.isDirty());
}
public saveAs(resource: URI, target?: URI): TPromise<URI> {
public saveAs(resource: URI, target?: URI, options?: ISaveOptions): TPromise<URI> {
// Get to target resource
if (!target) {
let targetPromise: TPromise<URI>;
if (target) {
targetPromise = TPromise.wrap(target);
} else {
let dialogPath = resource.fsPath;
if (resource.scheme === UNTITLED_SCHEMA) {
if (resource.scheme === Schemas.untitled) {
dialogPath = this.suggestFileName(resource);
}
const pathRaw = this.promptForPath(dialogPath);
if (pathRaw) {
target = URI.file(pathRaw);
targetPromise = this.promptForPath(dialogPath).then(pathRaw => {
if (pathRaw) {
return URI.file(pathRaw);
}
return void 0;
});
}
return targetPromise.then(target => {
if (!target) {
return TPromise.as(null); // user canceled
}
}
if (!target) {
return TPromise.as(null); // user canceled
}
// Just save if target is same as models own resource
if (resource.toString() === target.toString()) {
return this.save(resource, options).then(() => resource);
}
// Just save if target is same as models own resource
if (resource.toString() === target.toString()) {
return this.save(resource).then(() => resource);
}
// Do it
return this.doSaveAs(resource, target);
// Do it
return this.doSaveAs(resource, target, options);
});
}
private doSaveAs(resource: URI, target?: URI): TPromise<URI> {
private doSaveAs(resource: URI, target?: URI, options?: ISaveOptions): TPromise<URI> {
// Retrieve text model from provided resource if any
let modelPromise: TPromise<ITextFileEditorModel | UntitledEditorModel> = TPromise.as(null);
if (resource.scheme === Schemas.file) {
if (this.fileService.canHandleResource(resource)) {
modelPromise = TPromise.as(this._models.get(resource));
} else if (resource.scheme === UNTITLED_SCHEMA && this.untitledEditorService.exists(resource)) {
} else if (resource.scheme === Schemas.untitled && this.untitledEditorService.exists(resource)) {
modelPromise = this.untitledEditorService.loadOrCreate({ resource });
}
@@ -567,7 +582,7 @@ export abstract class TextFileService implements ITextFileService {
// We have a model: Use it (can be null e.g. if this file is binary and not a text file or was never opened before)
if (model) {
return this.doSaveTextFileAs(model, resource, target);
return this.doSaveTextFileAs(model, resource, target, options);
}
// Otherwise we can only copy
@@ -583,7 +598,7 @@ export abstract class TextFileService implements ITextFileService {
});
}
private doSaveTextFileAs(sourceModel: ITextFileEditorModel | UntitledEditorModel, resource: URI, target: URI): TPromise<void> {
private doSaveTextFileAs(sourceModel: ITextFileEditorModel | UntitledEditorModel, resource: URI, target: URI, options?: ISaveOptions): TPromise<void> {
let targetModelResolver: TPromise<ITextFileEditorModel>;
// Prefer an existing model if it is already loaded for the given target resource
@@ -603,15 +618,15 @@ export abstract class TextFileService implements ITextFileService {
// take over encoding and model value from source model
targetModel.updatePreferredEncoding(sourceModel.getEncoding());
targetModel.textEditorModel.setValue(sourceModel.getValue());
this.modelService.updateModel(targetModel.textEditorModel, createTextBufferFactoryFromSnapshot(sourceModel.createSnapshot()));
// save model
return targetModel.save();
return targetModel.save(options);
}, error => {
// binary model: delete the file and run the operation again
if ((<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_IS_BINARY || (<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_TOO_LARGE) {
return this.fileService.del(target).then(() => this.doSaveTextFileAs(sourceModel, resource, target));
return this.fileService.del(target).then(() => this.doSaveTextFileAs(sourceModel, resource, target, options));
}
return TPromise.wrapError(error);