提交 1311b224 编写于 作者: B Benjamin Pasero

text files - 💄 names

上级 1233630e
...@@ -7,7 +7,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; ...@@ -7,7 +7,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { IEditorViewState } from 'vs/editor/common/editorCommon'; import { IEditorViewState } from 'vs/editor/common/editorCommon';
import { toResource, SideBySideEditorInput, IWorkbenchEditorConfiguration, SideBySideEditor as SideBySideEditorChoice } from 'vs/workbench/common/editor'; import { toResource, SideBySideEditorInput, IWorkbenchEditorConfiguration, SideBySideEditor as SideBySideEditorChoice } from 'vs/workbench/common/editor';
import { ITextFileService, ModelState } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, TextFileEditorModelState } from 'vs/workbench/services/textfile/common/textfiles';
import { FileOperationEvent, FileOperation, IFileService, FileChangeType, FileChangesEvent, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { FileOperationEvent, FileOperation, IFileService, FileChangeType, FileChangesEvent, FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput'; import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
...@@ -285,7 +285,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut ...@@ -285,7 +285,7 @@ export class FileEditorTracker extends Disposable implements IWorkbenchContribut
} }
const model = this.textFileService.files.get(resource); const model = this.textFileService.files.get(resource);
if (model?.hasState(ModelState.PENDING_SAVE)) { if (model?.hasState(TextFileEditorModelState.PENDING_SAVE)) {
return false; // resource must not be pending to save return false; // resource must not be pending to save
} }
......
...@@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri'; ...@@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
import { EncodingMode, IFileEditorInput, Verbosity, TextResourceEditorInput } from 'vs/workbench/common/editor'; import { EncodingMode, IFileEditorInput, Verbosity, TextResourceEditorInput } from 'vs/workbench/common/editor';
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
import { ITextFileService, ModelState, LoadReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, TextFileEditorModelState, TextFileLoadReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IReference, dispose, DisposableStore } from 'vs/base/common/lifecycle'; import { IReference, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ITextModelService } from 'vs/editor/common/services/resolverService';
...@@ -174,7 +174,7 @@ export class FileEditorInput extends TextResourceEditorInput implements IFileEdi ...@@ -174,7 +174,7 @@ export class FileEditorInput extends TextResourceEditorInput implements IFileEdi
} }
private decorateLabel(label: string): string { private decorateLabel(label: string): string {
const orphaned = this.model?.hasState(ModelState.ORPHAN); const orphaned = this.model?.hasState(TextFileEditorModelState.ORPHAN);
const readonly = this.isReadonly(); const readonly = this.isReadonly();
if (orphaned && readonly) { if (orphaned && readonly) {
...@@ -205,7 +205,7 @@ export class FileEditorInput extends TextResourceEditorInput implements IFileEdi ...@@ -205,7 +205,7 @@ export class FileEditorInput extends TextResourceEditorInput implements IFileEdi
} }
isSaving(): boolean { isSaving(): boolean {
if (this.model?.hasState(ModelState.SAVED) || this.model?.hasState(ModelState.CONFLICT) || this.model?.hasState(ModelState.ERROR)) { if (this.model?.hasState(TextFileEditorModelState.SAVED) || this.model?.hasState(TextFileEditorModelState.CONFLICT) || this.model?.hasState(TextFileEditorModelState.ERROR)) {
return false; // require the model to be dirty and not in conflict or error state return false; // require the model to be dirty and not in conflict or error state
} }
...@@ -241,7 +241,7 @@ export class FileEditorInput extends TextResourceEditorInput implements IFileEdi ...@@ -241,7 +241,7 @@ export class FileEditorInput extends TextResourceEditorInput implements IFileEdi
encoding: this.preferredEncoding, encoding: this.preferredEncoding,
reload: { async: true }, // trigger a reload of the model if it exists already but do not wait to show the model reload: { async: true }, // trigger a reload of the model if it exists already but do not wait to show the model
allowBinary: this.forceOpenAs === ForceOpenAs.Text, allowBinary: this.forceOpenAs === ForceOpenAs.Text,
reason: LoadReason.EDITOR reason: TextFileLoadReason.EDITOR
}); });
// This is a bit ugly, because we first resolve the model and then resolve a model reference. the reason being that binary // This is a bit ugly, because we first resolve the model and then resolve a model reference. the reason being that binary
......
...@@ -19,7 +19,7 @@ import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; ...@@ -19,7 +19,7 @@ import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
import { configurationTelemetry } from 'vs/platform/telemetry/common/telemetryUtils'; import { configurationTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ITextFileService, ITextFileModelSaveEvent, ITextFileModelLoadEvent } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, ITextFileSaveEvent, ITextFileLoadEvent } from 'vs/workbench/services/textfile/common/textfiles';
import { extname, basename, isEqual, isEqualOrParent, joinPath } from 'vs/base/common/resources'; import { extname, basename, isEqual, isEqualOrParent, joinPath } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
...@@ -131,7 +131,7 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr ...@@ -131,7 +131,7 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr
this._register(lifecycleService.onShutdown(() => this.dispose())); this._register(lifecycleService.onShutdown(() => this.dispose()));
} }
private onTextFileModelLoaded(e: ITextFileModelLoadEvent): void { private onTextFileModelLoaded(e: ITextFileLoadEvent): void {
const settingsType = this.getTypeIfSettings(e.model.resource); const settingsType = this.getTypeIfSettings(e.model.resource);
if (settingsType) { if (settingsType) {
type SettingsReadClassification = { type SettingsReadClassification = {
...@@ -146,7 +146,7 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr ...@@ -146,7 +146,7 @@ export class TelemetryContribution extends Disposable implements IWorkbenchContr
} }
} }
private onTextFileModelSaved(e: ITextFileModelSaveEvent): void { private onTextFileModelSaved(e: ITextFileSaveEvent): void {
const settingsType = this.getTypeIfSettings(e.model.resource); const settingsType = this.getTypeIfSettings(e.model.resource);
if (settingsType) { if (settingsType) {
type SettingsWrittenClassification = { type SettingsWrittenClassification = {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { AbstractTextFileService } from 'vs/workbench/services/textfile/browser/textFileService'; import { AbstractTextFileService } from 'vs/workbench/services/textfile/browser/textFileService';
import { ITextFileService, IResourceEncodings, IResourceEncoding, ModelState } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, IResourceEncodings, IResourceEncoding, TextFileEditorModelState } from 'vs/workbench/services/textfile/common/textfiles';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle'; import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
...@@ -24,7 +24,7 @@ export class BrowserTextFileService extends AbstractTextFileService { ...@@ -24,7 +24,7 @@ export class BrowserTextFileService extends AbstractTextFileService {
} }
protected onBeforeShutdown(reason: ShutdownReason): boolean { protected onBeforeShutdown(reason: ShutdownReason): boolean {
if (this.files.models.some(model => model.hasState(ModelState.PENDING_SAVE))) { if (this.files.models.some(model => model.hasState(TextFileEditorModelState.PENDING_SAVE))) {
console.warn('Unload prevented: pending file saves'); console.warn('Unload prevented: pending file saves');
return true; // files are pending to be saved: veto return true; // files are pending to be saved: veto
......
...@@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; ...@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types';
import { ITextFileService, ModelState, ITextFileEditorModel, ITextFileStreamContent, ILoadOptions, IResolvedTextFileEditorModel, ITextFileSaveOptions, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, TextFileEditorModelState, ITextFileEditorModel, ITextFileStreamContent, ITextFileLoadOptions, IResolvedTextFileEditorModel, ITextFileSaveOptions, TextFileLoadReason } from 'vs/workbench/services/textfile/common/textfiles';
import { EncodingMode, IRevertOptions, SaveReason } from 'vs/workbench/common/editor'; import { EncodingMode, IRevertOptions, SaveReason } from 'vs/workbench/common/editor';
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
import { IBackupFileService, IResolvedBackup } from 'vs/workbench/services/backup/common/backup'; import { IBackupFileService, IResolvedBackup } from 'vs/workbench/services/backup/common/backup';
...@@ -43,7 +43,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -43,7 +43,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
private readonly _onDidChangeContent = this._register(new Emitter<void>()); private readonly _onDidChangeContent = this._register(new Emitter<void>());
readonly onDidChangeContent = this._onDidChangeContent.event; readonly onDidChangeContent = this._onDidChangeContent.event;
private readonly _onDidLoad = this._register(new Emitter<LoadReason>()); private readonly _onDidLoad = this._register(new Emitter<TextFileLoadReason>());
readonly onDidLoad = this._onDidLoad.event; readonly onDidLoad = this._onDidLoad.event;
private readonly _onDidChangeDirty = this._register(new Emitter<void>()); private readonly _onDidChangeDirty = this._register(new Emitter<void>());
...@@ -248,7 +248,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -248,7 +248,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
//#region Load //#region Load
async load(options?: ILoadOptions): Promise<ITextFileEditorModel> { async load(options?: ITextFileLoadOptions): Promise<TextFileEditorModel> {
this.logService.trace('[text file model] load() - enter', this.resource.toString()); this.logService.trace('[text file model] load() - enter', this.resource.toString());
// It is very important to not reload the model when the model is dirty. // It is very important to not reload the model when the model is dirty.
...@@ -281,7 +281,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -281,7 +281,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
return this.loadFromFile(options); return this.loadFromFile(options);
} }
private async loadFromBackup(backup: IResolvedBackup<IBackupMetaData>, options?: ILoadOptions): Promise<TextFileEditorModel> { private async loadFromBackup(backup: IResolvedBackup<IBackupMetaData>, options?: ITextFileLoadOptions): Promise<TextFileEditorModel> {
// Load with backup // Load with backup
this.loadFromContent({ this.loadFromContent({
...@@ -303,7 +303,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -303,7 +303,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
return this; return this;
} }
private async loadFromFile(options?: ILoadOptions): Promise<TextFileEditorModel> { private async loadFromFile(options?: ITextFileLoadOptions): Promise<TextFileEditorModel> {
const forceReadFromDisk = options?.forceReadFromDisk; const forceReadFromDisk = options?.forceReadFromDisk;
const allowBinary = this.isResolved() /* always allow if we resolved previously */ || options?.allowBinary; const allowBinary = this.isResolved() /* always allow if we resolved previously */ || options?.allowBinary;
...@@ -358,7 +358,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -358,7 +358,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
} }
} }
private loadFromContent(content: ITextFileStreamContent, options?: ILoadOptions, fromBackup?: boolean): TextFileEditorModel { private loadFromContent(content: ITextFileStreamContent, options?: ITextFileLoadOptions, fromBackup?: boolean): TextFileEditorModel {
this.logService.trace('[text file model] load() - resolved content', this.resource.toString()); this.logService.trace('[text file model] load() - resolved content', this.resource.toString());
// Update our resolved disk stat model // Update our resolved disk stat model
...@@ -396,7 +396,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -396,7 +396,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
} }
// Emit as event // Emit as event
this._onDidLoad.fire(options?.reason ?? LoadReason.OTHER); this._onDidLoad.fire(options?.reason ?? TextFileLoadReason.OTHER);
return this; return this;
} }
...@@ -544,7 +544,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -544,7 +544,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
} }
if ( if (
(this.hasState(ModelState.CONFLICT) || this.hasState(ModelState.ERROR)) && (this.hasState(TextFileEditorModelState.CONFLICT) || this.hasState(TextFileEditorModelState.ERROR)) &&
(options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE) (options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)
) { ) {
this.logService.trace('[text file model] save() - ignoring auto save request for model that is in conflict or error', this.resource.toString()); this.logService.trace('[text file model] save() - ignoring auto save request for model that is in conflict or error', this.resource.toString());
...@@ -794,19 +794,19 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -794,19 +794,19 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
//#endregion //#endregion
hasState(state: ModelState): boolean { hasState(state: TextFileEditorModelState): boolean {
switch (state) { switch (state) {
case ModelState.CONFLICT: case TextFileEditorModelState.CONFLICT:
return this.inConflictMode; return this.inConflictMode;
case ModelState.DIRTY: case TextFileEditorModelState.DIRTY:
return this.dirty; return this.dirty;
case ModelState.ERROR: case TextFileEditorModelState.ERROR:
return this.inErrorMode; return this.inErrorMode;
case ModelState.ORPHAN: case TextFileEditorModelState.ORPHAN:
return this.inOrphanMode; return this.inOrphanMode;
case ModelState.PENDING_SAVE: case TextFileEditorModelState.PENDING_SAVE:
return this.saveSequentializer.hasPending(); return this.saveSequentializer.hasPending();
case ModelState.SAVED: case TextFileEditorModelState.SAVED:
return !this.dirty; return !this.dirty;
} }
} }
......
...@@ -9,7 +9,7 @@ import { Emitter } from 'vs/base/common/event'; ...@@ -9,7 +9,7 @@ import { Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { dispose, IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { dispose, IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { ITextFileEditorModel, ITextFileEditorModelManager, IModelLoadOrCreateOptions, ITextFileModelLoadEvent, ITextFileModelSaveEvent, ITextFileSaveParticipant, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileEditorModel, ITextFileEditorModelManager, ITextFileEditorModelLoadOrCreateOptions, ITextFileLoadEvent, ITextFileSaveEvent, ITextFileSaveParticipant, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ResourceMap } from 'vs/base/common/map'; import { ResourceMap } from 'vs/base/common/map';
...@@ -29,31 +29,31 @@ import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; ...@@ -29,31 +29,31 @@ import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
export class TextFileEditorModelManager extends Disposable implements ITextFileEditorModelManager { export class TextFileEditorModelManager extends Disposable implements ITextFileEditorModelManager {
private readonly _onDidCreate = this._register(new Emitter<ITextFileEditorModel>()); private readonly _onDidCreate = this._register(new Emitter<TextFileEditorModel>());
readonly onDidCreate = this._onDidCreate.event; readonly onDidCreate = this._onDidCreate.event;
private readonly _onDidLoad = this._register(new Emitter<ITextFileModelLoadEvent>()); private readonly _onDidLoad = this._register(new Emitter<ITextFileLoadEvent>());
readonly onDidLoad = this._onDidLoad.event; readonly onDidLoad = this._onDidLoad.event;
private readonly _onDidChangeDirty = this._register(new Emitter<ITextFileEditorModel>()); private readonly _onDidChangeDirty = this._register(new Emitter<TextFileEditorModel>());
readonly onDidChangeDirty = this._onDidChangeDirty.event; readonly onDidChangeDirty = this._onDidChangeDirty.event;
private readonly _onDidSaveError = this._register(new Emitter<ITextFileEditorModel>()); private readonly _onDidSaveError = this._register(new Emitter<TextFileEditorModel>());
readonly onDidSaveError = this._onDidSaveError.event; readonly onDidSaveError = this._onDidSaveError.event;
private readonly _onDidSave = this._register(new Emitter<ITextFileModelSaveEvent>()); private readonly _onDidSave = this._register(new Emitter<ITextFileSaveEvent>());
readonly onDidSave = this._onDidSave.event; readonly onDidSave = this._onDidSave.event;
private readonly _onDidRevert = this._register(new Emitter<ITextFileEditorModel>()); private readonly _onDidRevert = this._register(new Emitter<TextFileEditorModel>());
readonly onDidRevert = this._onDidRevert.event; readonly onDidRevert = this._onDidRevert.event;
private readonly _onDidChangeEncoding = this._register(new Emitter<ITextFileEditorModel>()); private readonly _onDidChangeEncoding = this._register(new Emitter<TextFileEditorModel>());
readonly onDidChangeEncoding = this._onDidChangeEncoding.event; readonly onDidChangeEncoding = this._onDidChangeEncoding.event;
private readonly mapResourceToModel = new ResourceMap<ITextFileEditorModel>(); private readonly mapResourceToModel = new ResourceMap<TextFileEditorModel>();
private readonly mapResourceToModelListeners = new ResourceMap<IDisposable>(); private readonly mapResourceToModelListeners = new ResourceMap<IDisposable>();
private readonly mapResourceToDisposeListener = new ResourceMap<IDisposable>(); private readonly mapResourceToDisposeListener = new ResourceMap<IDisposable>();
private readonly mapResourceToPendingModelLoaders = new ResourceMap<Promise<ITextFileEditorModel>>(); private readonly mapResourceToPendingModelLoaders = new ResourceMap<Promise<TextFileEditorModel>>();
private readonly modelLoadQueue = this._register(new ResourceQueue()); private readonly modelLoadQueue = this._register(new ResourceQueue());
...@@ -67,7 +67,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE ...@@ -67,7 +67,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
}; };
})(); })();
get models(): ITextFileEditorModel[] { get models(): TextFileEditorModel[] {
return this.mapResourceToModel.values(); return this.mapResourceToModel.values();
} }
...@@ -111,7 +111,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE ...@@ -111,7 +111,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
).forEach(model => this.queueModelLoad(model)); ).forEach(model => this.queueModelLoad(model));
} }
private queueModelLoad(model: ITextFileEditorModel): void { private queueModelLoad(model: TextFileEditorModel): void {
// Load model to update (use a queue to prevent accumulation of loads // Load model to update (use a queue to prevent accumulation of loads
// when the load actually takes long. At most we only want the queue // when the load actually takes long. At most we only want the queue
...@@ -137,8 +137,8 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE ...@@ -137,8 +137,8 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
if (source && (e.operation === FileOperation.COPY || e.operation === FileOperation.MOVE)) { if (source && (e.operation === FileOperation.COPY || e.operation === FileOperation.MOVE)) {
// find all models that related to either source or target (can be many if resource is a folder) // find all models that related to either source or target (can be many if resource is a folder)
const sourceModels: ITextFileEditorModel[] = []; const sourceModels: TextFileEditorModel[] = [];
const targetModels: ITextFileEditorModel[] = []; const targetModels: TextFileEditorModel[] = [];
for (const model of this.models) { for (const model of this.models) {
const resource = model.resource; const resource = model.resource;
...@@ -238,11 +238,11 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE ...@@ -238,11 +238,11 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
} }
} }
get(resource: URI): ITextFileEditorModel | undefined { get(resource: URI): TextFileEditorModel | undefined {
return this.mapResourceToModel.get(resource); return this.mapResourceToModel.get(resource);
} }
async resolve(resource: URI, options?: IModelLoadOrCreateOptions): Promise<ITextFileEditorModel> { async resolve(resource: URI, options?: ITextFileEditorModelLoadOrCreateOptions): Promise<TextFileEditorModel> {
// Return early if model is currently being loaded // Return early if model is currently being loaded
const pendingLoad = this.mapResourceToPendingModelLoaders.get(resource); const pendingLoad = this.mapResourceToPendingModelLoaders.get(resource);
...@@ -250,7 +250,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE ...@@ -250,7 +250,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
return pendingLoad; return pendingLoad;
} }
let modelPromise: Promise<ITextFileEditorModel>; let modelPromise: Promise<TextFileEditorModel>;
let model = this.get(resource); let model = this.get(resource);
let didCreateModel = false; let didCreateModel = false;
...@@ -281,15 +281,15 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE ...@@ -281,15 +281,15 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
modelPromise = model.load(options); modelPromise = model.load(options);
// Install model listeners // Install model listeners
const listeners = new DisposableStore(); const modelListeners = new DisposableStore();
listeners.add(model.onDidLoad(reason => this._onDidLoad.fire({ model: newModel, reason }))); modelListeners.add(model.onDidLoad(reason => this._onDidLoad.fire({ model: newModel, reason })));
listeners.add(model.onDidChangeDirty(() => this._onDidChangeDirty.fire(newModel))); modelListeners.add(model.onDidChangeDirty(() => this._onDidChangeDirty.fire(newModel)));
listeners.add(model.onDidSaveError(() => this._onDidSaveError.fire(newModel))); modelListeners.add(model.onDidSaveError(() => this._onDidSaveError.fire(newModel)));
listeners.add(model.onDidSave(reason => this._onDidSave.fire({ model: newModel, reason }))); modelListeners.add(model.onDidSave(reason => this._onDidSave.fire({ model: newModel, reason })));
listeners.add(model.onDidRevert(() => this._onDidRevert.fire(newModel))); modelListeners.add(model.onDidRevert(() => this._onDidRevert.fire(newModel)));
listeners.add(model.onDidChangeEncoding(() => this._onDidChangeEncoding.fire(newModel))); modelListeners.add(model.onDidChangeEncoding(() => this._onDidChangeEncoding.fire(newModel)));
this.mapResourceToModelListeners.set(resource, listeners); this.mapResourceToModelListeners.set(resource, modelListeners);
} }
// Store pending loads to avoid race conditions // Store pending loads to avoid race conditions
...@@ -335,7 +335,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE ...@@ -335,7 +335,7 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
} }
} }
add(resource: URI, model: ITextFileEditorModel): void { add(resource: URI, model: TextFileEditorModel): void {
const knownModel = this.mapResourceToModel.get(resource); const knownModel = this.mapResourceToModel.get(resource);
if (knownModel === model) { if (knownModel === model) {
return; // already cached return; // already cached
......
...@@ -161,13 +161,18 @@ export const enum TextFileOperationResult { ...@@ -161,13 +161,18 @@ export const enum TextFileOperationResult {
} }
export class TextFileOperationError extends FileOperationError { export class TextFileOperationError extends FileOperationError {
constructor(message: string, public textFileOperationResult: TextFileOperationResult, public options?: IReadTextFileOptions & IWriteTextFileOptions) {
super(message, FileOperationResult.FILE_OTHER_ERROR);
}
static isTextFileOperationError(obj: unknown): obj is TextFileOperationError { static isTextFileOperationError(obj: unknown): obj is TextFileOperationError {
return obj instanceof Error && !isUndefinedOrNull((obj as TextFileOperationError).textFileOperationResult); return obj instanceof Error && !isUndefinedOrNull((obj as TextFileOperationError).textFileOperationResult);
} }
constructor(
message: string,
public textFileOperationResult: TextFileOperationResult,
public options?: IReadTextFileOptions & IWriteTextFileOptions
) {
super(message, FileOperationResult.FILE_OTHER_ERROR);
}
} }
export interface IResourceEncodings { export interface IResourceEncodings {
...@@ -193,7 +198,7 @@ export interface ISaveErrorHandler { ...@@ -193,7 +198,7 @@ export interface ISaveErrorHandler {
/** /**
* States the text file editor model can be in. * States the text file editor model can be in.
*/ */
export const enum ModelState { export const enum TextFileEditorModelState {
/** /**
* A model is saved. * A model is saved.
...@@ -228,17 +233,7 @@ export const enum ModelState { ...@@ -228,17 +233,7 @@ export const enum ModelState {
ERROR ERROR
} }
export interface ITextFileOperationResult { export const enum TextFileLoadReason {
results: IResult[];
}
export interface IResult {
source: URI;
target?: URI;
error?: boolean;
}
export const enum LoadReason {
EDITOR = 1, EDITOR = 1,
REFERENCE = 2, REFERENCE = 2,
OTHER = 3 OTHER = 3
...@@ -268,12 +263,12 @@ export interface ITextFileStreamContent extends IBaseTextFileContent { ...@@ -268,12 +263,12 @@ export interface ITextFileStreamContent extends IBaseTextFileContent {
value: ITextBufferFactory; value: ITextBufferFactory;
} }
export interface IModelLoadOrCreateOptions { export interface ITextFileEditorModelLoadOrCreateOptions {
/** /**
* Context why the model is being loaded or created. * Context why the model is being loaded or created.
*/ */
reason?: LoadReason; reason?: TextFileLoadReason;
/** /**
* The language mode to use for the model text content. * The language mode to use for the model text content.
...@@ -303,14 +298,14 @@ export interface IModelLoadOrCreateOptions { ...@@ -303,14 +298,14 @@ export interface IModelLoadOrCreateOptions {
allowBinary?: boolean; allowBinary?: boolean;
} }
export interface ITextFileModelSaveEvent { export interface ITextFileSaveEvent {
model: ITextFileEditorModel; model: ITextFileEditorModel;
reason: SaveReason; reason: SaveReason;
} }
export interface ITextFileModelLoadEvent { export interface ITextFileLoadEvent {
model: ITextFileEditorModel; model: ITextFileEditorModel;
reason: LoadReason; reason: TextFileLoadReason;
} }
export interface ITextFileSaveParticipant { export interface ITextFileSaveParticipant {
...@@ -330,36 +325,69 @@ export interface ITextFileSaveParticipant { ...@@ -330,36 +325,69 @@ export interface ITextFileSaveParticipant {
export interface ITextFileEditorModelManager { export interface ITextFileEditorModelManager {
readonly onDidCreate: Event<ITextFileEditorModel>; readonly onDidCreate: Event<ITextFileEditorModel>;
readonly onDidLoad: Event<ITextFileModelLoadEvent>; readonly onDidLoad: Event<ITextFileLoadEvent>;
readonly onDidChangeDirty: Event<ITextFileEditorModel>; readonly onDidChangeDirty: Event<ITextFileEditorModel>;
readonly onDidChangeEncoding: Event<ITextFileEditorModel>;
readonly onDidSaveError: Event<ITextFileEditorModel>; readonly onDidSaveError: Event<ITextFileEditorModel>;
readonly onDidSave: Event<ITextFileModelSaveEvent>; readonly onDidSave: Event<ITextFileSaveEvent>;
readonly onDidRevert: Event<ITextFileEditorModel>; readonly onDidRevert: Event<ITextFileEditorModel>;
readonly onDidChangeEncoding: Event<ITextFileEditorModel>;
readonly models: ITextFileEditorModel[]; readonly models: ITextFileEditorModel[];
saveErrorHandler: ISaveErrorHandler; saveErrorHandler: ISaveErrorHandler;
/**
* Returns the text file editor model for the provided resource
* or undefined if none.
*/
get(resource: URI): ITextFileEditorModel | undefined; get(resource: URI): ITextFileEditorModel | undefined;
resolve(resource: URI, options?: IModelLoadOrCreateOptions): Promise<ITextFileEditorModel>; /**
* Allows to load a text file model from disk.
*/
resolve(resource: URI, options?: ITextFileEditorModelLoadOrCreateOptions): Promise<ITextFileEditorModel>;
/**
* Adds a participant for saving text file models.
*/
addSaveParticipant(participant: ITextFileSaveParticipant): IDisposable; addSaveParticipant(participant: ITextFileSaveParticipant): IDisposable;
runSaveParticipants(model: IResolvedTextFileEditorModel, context: { reason: SaveReason; }, token: CancellationToken): Promise<void> runSaveParticipants(model: IResolvedTextFileEditorModel, context: { reason: SaveReason; }, token: CancellationToken): Promise<void>
disposeModel(model: ITextFileEditorModel): void; disposeModel(model: ITextFileEditorModel): void;
} }
export interface ITextFileSaveOptions extends ISaveOptions { export interface ITextFileSaveOptions extends ISaveOptions {
/**
* Makes the file writable if it is readonly.
*/
overwriteReadonly?: boolean; overwriteReadonly?: boolean;
/**
* Overwrite the encoding of the file on disk as configured.
*/
overwriteEncoding?: boolean; overwriteEncoding?: boolean;
/**
* Save the file with elevated privileges.
*
* Note: This may not be supported in all environments.
*/
writeElevated?: boolean; writeElevated?: boolean;
/**
* Allows to write to a file even if it has been modified on disk.
*/
ignoreModifiedSince?: boolean; ignoreModifiedSince?: boolean;
/**
* If set, will bubble up the error to the caller instead of handling it.
*/
ignoreErrorHandler?: boolean; ignoreErrorHandler?: boolean;
} }
export interface ILoadOptions { export interface ITextFileLoadOptions {
/** /**
* Go to disk bypassing any cache of the model if any. * Go to disk bypassing any cache of the model if any.
...@@ -374,39 +402,29 @@ export interface ILoadOptions { ...@@ -374,39 +402,29 @@ export interface ILoadOptions {
/** /**
* Context why the model is being loaded. * Context why the model is being loaded.
*/ */
reason?: LoadReason; reason?: TextFileLoadReason;
} }
export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport, IModeSupport, IWorkingCopy { export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport, IModeSupport, IWorkingCopy {
readonly onDidChangeContent: Event<void>; readonly onDidChangeContent: Event<void>;
readonly onDidLoad: Event<LoadReason>;
readonly onDidSaveError: Event<void>; readonly onDidSaveError: Event<void>;
readonly onDidSave: Event<SaveReason>;
readonly onDidRevert: Event<void>;
readonly onDidChangeEncoding: Event<void>;
readonly onDidChangeOrphaned: Event<void>; readonly onDidChangeOrphaned: Event<void>;
hasState(state: ModelState): boolean; hasState(state: TextFileEditorModelState): boolean;
updatePreferredEncoding(encoding: string | undefined): void; updatePreferredEncoding(encoding: string | undefined): void;
updateTextEditorModel(newValue?: ITextBufferFactory, preferredMode?: string): void;
save(options?: ITextFileSaveOptions): Promise<boolean>; save(options?: ITextFileSaveOptions): Promise<boolean>;
load(options?: ILoadOptions): Promise<ITextFileEditorModel>;
revert(options?: IRevertOptions): Promise<boolean>; revert(options?: IRevertOptions): Promise<boolean>;
isDirty(): this is IResolvedTextFileEditorModel; load(options?: ITextFileLoadOptions): Promise<ITextFileEditorModel>;
setDirty(dirty: boolean): void; isDirty(): this is IResolvedTextFileEditorModel;
getMode(): string | undefined; getMode(): string | undefined;
isResolved(): this is IResolvedTextFileEditorModel; isResolved(): this is IResolvedTextFileEditorModel;
isDisposed(): boolean; isDisposed(): boolean;
} }
......
...@@ -7,7 +7,7 @@ import * as assert from 'assert'; ...@@ -7,7 +7,7 @@ import * as assert from 'assert';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { EncodingMode } from 'vs/workbench/common/editor'; import { EncodingMode } from 'vs/workbench/common/editor';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { ITextFileService, ModelState, snapshotToString } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, TextFileEditorModelState, snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
import { createFileInput, TestFileService, TestTextFileService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices'; import { createFileInput, TestFileService, TestTextFileService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { toResource } from 'vs/base/test/common/utils'; import { toResource } from 'vs/base/test/common/utils';
import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager';
...@@ -100,7 +100,7 @@ suite('Files - TextFileEditorModel', () => { ...@@ -100,7 +100,7 @@ suite('Files - TextFileEditorModel', () => {
model.textEditorModel!.setValue('bar'); model.textEditorModel!.setValue('bar');
assert.ok(getLastModifiedTime(model) <= Date.now()); assert.ok(getLastModifiedTime(model) <= Date.now());
assert.ok(model.hasState(ModelState.DIRTY)); assert.ok(model.hasState(TextFileEditorModelState.DIRTY));
assert.equal(accessor.workingCopyService.dirtyCount, 1); assert.equal(accessor.workingCopyService.dirtyCount, 1);
assert.equal(accessor.workingCopyService.isDirty(model.resource), true); assert.equal(accessor.workingCopyService.isDirty(model.resource), true);
...@@ -116,11 +116,11 @@ suite('Files - TextFileEditorModel', () => { ...@@ -116,11 +116,11 @@ suite('Files - TextFileEditorModel', () => {
}); });
const pendingSave = model.save(); const pendingSave = model.save();
assert.ok(model.hasState(ModelState.PENDING_SAVE)); assert.ok(model.hasState(TextFileEditorModelState.PENDING_SAVE));
await pendingSave; await pendingSave;
assert.ok(model.hasState(ModelState.SAVED)); assert.ok(model.hasState(TextFileEditorModelState.SAVED));
assert.ok(!model.isDirty()); assert.ok(!model.isDirty());
assert.ok(savedEvent); assert.ok(savedEvent);
assert.ok(workingCopyEvent); assert.ok(workingCopyEvent);
...@@ -169,11 +169,11 @@ suite('Files - TextFileEditorModel', () => { ...@@ -169,11 +169,11 @@ suite('Files - TextFileEditorModel', () => {
accessor.fileService.writeShouldThrowError = new Error('failed to write'); accessor.fileService.writeShouldThrowError = new Error('failed to write');
try { try {
const pendingSave = model.save(); const pendingSave = model.save();
assert.ok(model.hasState(ModelState.PENDING_SAVE)); assert.ok(model.hasState(TextFileEditorModelState.PENDING_SAVE));
await pendingSave; await pendingSave;
assert.ok(model.hasState(ModelState.ERROR)); assert.ok(model.hasState(TextFileEditorModelState.ERROR));
assert.ok(model.isDirty()); assert.ok(model.isDirty());
assert.ok(saveErrorEvent); assert.ok(saveErrorEvent);
...@@ -199,11 +199,11 @@ suite('Files - TextFileEditorModel', () => { ...@@ -199,11 +199,11 @@ suite('Files - TextFileEditorModel', () => {
accessor.fileService.writeShouldThrowError = new FileOperationError('save conflict', FileOperationResult.FILE_MODIFIED_SINCE); accessor.fileService.writeShouldThrowError = new FileOperationError('save conflict', FileOperationResult.FILE_MODIFIED_SINCE);
try { try {
const pendingSave = model.save(); const pendingSave = model.save();
assert.ok(model.hasState(ModelState.PENDING_SAVE)); assert.ok(model.hasState(TextFileEditorModelState.PENDING_SAVE));
await pendingSave; await pendingSave;
assert.ok(model.hasState(ModelState.CONFLICT)); assert.ok(model.hasState(TextFileEditorModelState.CONFLICT));
assert.ok(model.isDirty()); assert.ok(model.isDirty());
assert.ok(saveErrorEvent); assert.ok(saveErrorEvent);
...@@ -273,7 +273,7 @@ suite('Files - TextFileEditorModel', () => { ...@@ -273,7 +273,7 @@ suite('Files - TextFileEditorModel', () => {
test('Load does not trigger save', async function () { test('Load does not trigger save', async function () {
const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index.txt'), 'utf8', undefined); const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index.txt'), 'utf8', undefined);
assert.ok(model.hasState(ModelState.SAVED)); assert.ok(model.hasState(TextFileEditorModelState.SAVED));
model.onDidSave(e => assert.fail()); model.onDidSave(e => assert.fail());
model.onDidChangeDirty(e => assert.fail()); model.onDidChangeDirty(e => assert.fail());
...@@ -290,7 +290,7 @@ suite('Files - TextFileEditorModel', () => { ...@@ -290,7 +290,7 @@ suite('Files - TextFileEditorModel', () => {
await model.load(); await model.load();
model.textEditorModel!.setValue('foo'); model.textEditorModel!.setValue('foo');
assert.ok(model.isDirty()); assert.ok(model.isDirty());
assert.ok(model.hasState(ModelState.DIRTY)); assert.ok(model.hasState(TextFileEditorModelState.DIRTY));
await model.load(); await model.load();
assert.ok(model.isDirty()); assert.ok(model.isDirty());
......
...@@ -10,7 +10,7 @@ import { ITextModel } from 'vs/editor/common/model'; ...@@ -10,7 +10,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { IDisposable, toDisposable, IReference, ReferenceCollection, ImmortalReference } from 'vs/base/common/lifecycle'; import { IDisposable, toDisposable, IReference, ReferenceCollection, ImmortalReference } from 'vs/base/common/lifecycle';
import { IModelService } from 'vs/editor/common/services/modelService'; import { IModelService } from 'vs/editor/common/services/modelService';
import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel'; import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel';
import { ITextFileService, LoadReason } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, TextFileLoadReason } from 'vs/workbench/services/textfile/common/textfiles';
import * as network from 'vs/base/common/network'; import * as network from 'vs/base/common/network';
import { ITextModelService, ITextModelContentProvider, ITextEditorModel, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { ITextModelService, ITextModelContentProvider, ITextEditorModel, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService'; import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
...@@ -38,7 +38,7 @@ class ResourceModelCollection extends ReferenceCollection<Promise<ITextEditorMod ...@@ -38,7 +38,7 @@ class ResourceModelCollection extends ReferenceCollection<Promise<ITextEditorMod
// File or remote file provider already known // File or remote file provider already known
if (this.fileService.canHandleResource(resource)) { if (this.fileService.canHandleResource(resource)) {
return this.textFileService.files.resolve(resource, { reason: LoadReason.REFERENCE }); return this.textFileService.files.resolve(resource, { reason: TextFileLoadReason.REFERENCE });
} }
// Virtual documents // Virtual documents
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册