Merge from vscode 5b9869eb02fa4c96205a74d05cad9164dfd06d60 (#5607)

This commit is contained in:
Anthony Dresser
2019-05-24 12:20:30 -07:00
committed by GitHub
parent 361ada4963
commit bcc449b524
126 changed files with 3096 additions and 2255 deletions

View File

@@ -82,46 +82,40 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
}
private createCommandHandler(descriptor: SyncActionDescriptor): ICommandHandler {
return (accessor, args) => {
return async (accessor, args) => {
const notificationService = accessor.get(INotificationService);
const instantiationService = accessor.get(IInstantiationService);
const lifecycleService = accessor.get(ILifecycleService);
Promise.resolve(this.triggerAndDisposeAction(instantiationService, lifecycleService, descriptor, args)).then(undefined, err => {
notificationService.error(err);
});
try {
await this.triggerAndDisposeAction(instantiationService, lifecycleService, descriptor, args);
} catch (error) {
notificationService.error(error);
}
};
}
private triggerAndDisposeAction(instantiationService: IInstantiationService, lifecycleService: ILifecycleService, descriptor: SyncActionDescriptor, args: any): Promise<void> {
private async triggerAndDisposeAction(instantiationService: IInstantiationService, lifecycleService: ILifecycleService, descriptor: SyncActionDescriptor, args: any): Promise<void> {
// run action when workbench is created
return lifecycleService.when(LifecyclePhase.Ready).then(() => {
const actionInstance = instantiationService.createInstance(descriptor.syncDescriptor);
try {
actionInstance.label = descriptor.label || actionInstance.label;
await lifecycleService.when(LifecyclePhase.Ready);
// don't run the action when not enabled
if (!actionInstance.enabled) {
actionInstance.dispose();
const actionInstance = instantiationService.createInstance(descriptor.syncDescriptor);
actionInstance.label = descriptor.label || actionInstance.label;
return undefined;
}
// don't run the action when not enabled
if (!actionInstance.enabled) {
actionInstance.dispose();
const from = args && args.from || 'keybinding';
return;
}
return Promise.resolve(actionInstance.run(undefined, { from })).then(() => {
actionInstance.dispose();
}, err => {
actionInstance.dispose();
return Promise.reject(err);
});
} catch (err) {
actionInstance.dispose();
return Promise.reject(err);
}
});
// otherwise run and dispose
try {
const from = args && args.from || 'keybinding';
await actionInstance.run(undefined, { from });
} finally {
actionInstance.dispose();
}
}
});

View File

@@ -80,9 +80,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
// Otherwise wait for phase to be reached
else {
lifecycleService.when(phase).then(() => {
this.doInstantiateByPhase(instantiationService, phase);
});
lifecycleService.when(phase).then(() => this.doInstantiateByPhase(instantiationService, phase));
}
}

View File

@@ -72,20 +72,17 @@ export class BinaryEditorModel extends EditorModel {
return this.etag;
}
load(): Promise<BinaryEditorModel> {
async load(): Promise<BinaryEditorModel> {
// Make sure to resolve up to date stat for file resources
if (this.fileService.canHandleResource(this.resource)) {
return this.fileService.resolve(this.resource, { resolveMetadata: true }).then(stat => {
this.etag = stat.etag;
if (typeof stat.size === 'number') {
this.size = stat.size;
}
return this;
});
const stat = await this.fileService.resolve(this.resource, { resolveMetadata: true });
this.etag = stat.etag;
if (typeof stat.size === 'number') {
this.size = stat.size;
}
}
return Promise.resolve(this);
return this;
}
}

View File

@@ -34,45 +34,44 @@ export class DiffEditorInput extends SideBySideEditorInput {
return this.master;
}
resolve(): Promise<EditorModel> {
async resolve(): Promise<EditorModel> {
// Create Model - we never reuse our cached model if refresh is true because we cannot
// decide for the inputs within if the cached model can be reused or not. There may be
// inputs that need to be loaded again and thus we always recreate the model and dispose
// the previous one - if any.
return this.createModel().then(resolvedModel => {
if (this.cachedModel) {
this.cachedModel.dispose();
}
const resolvedModel = await this.createModel();
if (this.cachedModel) {
this.cachedModel.dispose();
}
this.cachedModel = resolvedModel;
this.cachedModel = resolvedModel;
return this.cachedModel;
});
return this.cachedModel;
}
getPreferredEditorId(candidates: string[]): string {
return this.forceOpenAsBinary ? BINARY_DIFF_EDITOR_ID : TEXT_DIFF_EDITOR_ID;
}
private createModel(): Promise<DiffEditorModel> {
private async createModel(): Promise<DiffEditorModel> {
// Join resolve call over two inputs and build diff editor model
return Promise.all([
const models = await Promise.all([
this.originalInput.resolve(),
this.modifiedInput.resolve()
]).then(models => {
const originalEditorModel = models[0];
const modifiedEditorModel = models[1];
]);
// If both are text models, return textdiffeditor model
if (modifiedEditorModel instanceof BaseTextEditorModel && originalEditorModel instanceof BaseTextEditorModel) {
return new TextDiffEditorModel(originalEditorModel, modifiedEditorModel);
}
const originalEditorModel = models[0];
const modifiedEditorModel = models[1];
// Otherwise return normal diff model
return new DiffEditorModel(originalEditorModel, modifiedEditorModel);
});
// If both are text models, return textdiffeditor model
if (modifiedEditorModel instanceof BaseTextEditorModel && originalEditorModel instanceof BaseTextEditorModel) {
return new TextDiffEditorModel(originalEditorModel, modifiedEditorModel);
}
// Otherwise return normal diff model
return new DiffEditorModel(originalEditorModel, modifiedEditorModel);
}
dispose(): void {

View File

@@ -37,11 +37,13 @@ export class DiffEditorModel extends EditorModel {
return this._modifiedModel;
}
load(): Promise<EditorModel> {
return Promise.all([
async load(): Promise<EditorModel> {
await Promise.all([
this._originalModel ? this._originalModel.load() : Promise.resolve(undefined),
this._modifiedModel ? this._modifiedModel.load() : Promise.resolve(undefined),
]).then(() => this);
]);
return this;
}
isResolved(): boolean {

View File

@@ -76,31 +76,31 @@ export class ResourceEditorInput extends EditorInput implements IModeSupport {
this.preferredMode = mode;
}
resolve(): Promise<ITextEditorModel> {
async resolve(): Promise<ITextEditorModel> {
if (!this.modelReference) {
this.modelReference = this.textModelResolverService.createModelReference(this.resource);
}
return this.modelReference.then(ref => {
const model = ref.object;
const ref = await this.modelReference;
// Ensure the resolved model is of expected type
if (!(model instanceof ResourceEditorModel)) {
ref.dispose();
this.modelReference = null;
const model = ref.object;
return Promise.reject(new Error(`Unexpected model for ResourceInput: ${this.resource}`));
}
// Ensure the resolved model is of expected type
if (!(model instanceof ResourceEditorModel)) {
ref.dispose();
this.modelReference = null;
this.cachedModel = model;
return Promise.reject(new Error(`Unexpected model for ResourceInput: ${this.resource}`));
}
// Set mode if we have a preferred mode configured
if (this.preferredMode) {
model.setMode(this.preferredMode);
}
this.cachedModel = model;
return model;
});
// Set mode if we have a preferred mode configured
if (this.preferredMode) {
model.setMode(this.preferredMode);
}
return model;
}
matches(otherInput: unknown): boolean {

View File

@@ -26,6 +26,7 @@ export class ResourceEditorModel extends BaseTextEditorModel {
}
dispose(): void {
// TODO@Joao: force this class to dispose the underlying model
if (this.textEditorModelHandle) {
this.modelService.destroyModel(this.textEditorModelHandle);

View File

@@ -33,12 +33,12 @@ export class TextDiffEditorModel extends DiffEditorModel {
return this._modifiedModel;
}
load(): Promise<EditorModel> {
return super.load().then(() => {
this.updateTextDiffEditorModel();
async load(): Promise<EditorModel> {
await super.load();
return this;
});
this.updateTextDiffEditorModel();
return this;
}
private updateTextDiffEditorModel(): void {

View File

@@ -11,7 +11,7 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { Event, Emitter } from 'vs/base/common/event';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IBackupFileService, IResolvedBackup } from 'vs/workbench/services/backup/common/backup';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { ITextBufferFactory } from 'vs/editor/common/model';
import { createTextBufferFactory } from 'vs/editor/common/model/textModel';
@@ -135,52 +135,48 @@ export class UntitledEditorModel extends BaseTextEditorModel implements IEncodin
return Promise.resolve();
}
load(): Promise<UntitledEditorModel & IResolvedTextEditorModel> {
async load(): Promise<UntitledEditorModel & IResolvedTextEditorModel> {
// Check for backups first
return this.backupFileService.loadBackupResource(this.resource).then(backupResource => {
if (backupResource) {
return this.backupFileService.resolveBackupContent(backupResource);
}
let backup: IResolvedBackup<object> | undefined = undefined;
const backupResource = await this.backupFileService.loadBackupResource(this.resource);
if (backupResource) {
backup = await this.backupFileService.resolveBackupContent(backupResource);
}
return Promise.resolve(undefined);
}).then(backup => {
const hasBackup = !!backup;
// untitled associated to file path are dirty right away as well as untitled with content
this.setDirty(this._hasAssociatedFilePath || !!backup || !!this.initialValue);
// untitled associated to file path are dirty right away as well as untitled with content
this.setDirty(this._hasAssociatedFilePath || hasBackup || !!this.initialValue);
let untitledContents: ITextBufferFactory;
if (backup) {
untitledContents = backup.value;
} else {
untitledContents = createTextBufferFactory(this.initialValue || '');
}
let untitledContents: ITextBufferFactory;
if (backup) {
untitledContents = backup.value;
} else {
untitledContents = createTextBufferFactory(this.initialValue || '');
}
// Create text editor model if not yet done
if (!this.textEditorModel) {
this.createTextEditorModel(untitledContents, this.resource, this.preferredMode);
}
// Create text editor model if not yet done
if (!this.textEditorModel) {
this.createTextEditorModel(untitledContents, this.resource, this.preferredMode);
}
// Otherwise update
else {
this.updateTextEditorModel(untitledContents, this.preferredMode);
}
// Otherwise update
else {
this.updateTextEditorModel(untitledContents, this.preferredMode);
}
// Encoding
this.configuredEncoding = this.configurationService.getValue<string>(this.resource, 'files.encoding');
// Encoding
this.configuredEncoding = this.configurationService.getValue<string>(this.resource, 'files.encoding');
// We know for a fact there is a text editor model here
const textEditorModel = this.textEditorModel!;
// We know for a fact there is a text editor model here
const textEditorModel = this.textEditorModel!;
// Listen to content changes
this._register(textEditorModel.onDidChangeContent(() => this.onModelContentChanged()));
// Listen to content changes
this._register(textEditorModel.onDidChangeContent(() => this.onModelContentChanged()));
// Listen to mode changes
this._register(textEditorModel.onDidChangeLanguage(() => this.onConfigurationChange())); // mode change can have impact on config
// Listen to mode changes
this._register(textEditorModel.onDidChangeLanguage(() => this.onConfigurationChange())); // mode change can have impact on config
return this as UntitledEditorModel & IResolvedTextEditorModel;
});
return this as UntitledEditorModel & IResolvedTextEditorModel;
}
private onModelContentChanged(): void {