mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 19:48:37 -05:00
Merge VS Code 1.23.1 (#1520)
This commit is contained in:
@@ -5,21 +5,20 @@
|
||||
'use strict';
|
||||
|
||||
import * as path from 'vs/base/common/paths';
|
||||
import nls = require('vs/nls');
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { TPromise, TValueCallback, ErrorCallback } from 'vs/base/common/winjs.base';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { guessMimeTypes } from 'vs/base/common/mime';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import paths = require('vs/base/common/paths');
|
||||
import diagnostics = require('vs/base/common/diagnostics');
|
||||
import types = require('vs/base/common/types');
|
||||
import * as diagnostics from 'vs/base/common/diagnostics';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { IMode } from 'vs/editor/common/modes';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ITextFileService, IAutoSaveConfiguration, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, IRawTextContent, ILoadOptions } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { EncodingMode } from 'vs/workbench/common/editor';
|
||||
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
|
||||
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
||||
@@ -63,8 +62,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
private disposed: boolean;
|
||||
private lastSaveAttemptTime: number;
|
||||
private createTextEditorModelPromise: TPromise<TextFileEditorModel>;
|
||||
private _onDidContentChange: Emitter<StateChange>;
|
||||
private _onDidStateChange: Emitter<StateChange>;
|
||||
private readonly _onDidContentChange: Emitter<StateChange>;
|
||||
private readonly _onDidStateChange: Emitter<StateChange>;
|
||||
|
||||
private inConflictMode: boolean;
|
||||
private inOrphanMode: boolean;
|
||||
@@ -129,38 +128,51 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
}
|
||||
|
||||
private onFileChanges(e: FileChangesEvent): void {
|
||||
let fileEventImpactsModel = false;
|
||||
let newInOrphanModeGuess: boolean;
|
||||
|
||||
// Track ADD and DELETES for updates of this model to orphan-mode
|
||||
const modelFileDeleted = e.contains(this.resource, FileChangeType.DELETED);
|
||||
const modelFileAdded = e.contains(this.resource, FileChangeType.ADDED);
|
||||
|
||||
if (modelFileDeleted || modelFileAdded) {
|
||||
const newInOrphanModeGuess = modelFileDeleted && !modelFileAdded;
|
||||
if (this.inOrphanMode !== newInOrphanModeGuess) {
|
||||
let checkOrphanedPromise: TPromise<boolean>;
|
||||
if (newInOrphanModeGuess) {
|
||||
// We have received reports of users seeing delete events even though the file still
|
||||
// exists (network shares issue: https://github.com/Microsoft/vscode/issues/13665).
|
||||
// Since we do not want to mark the model as orphaned, we have to check if the
|
||||
// file is really gone and not just a faulty file event.
|
||||
checkOrphanedPromise = TPromise.timeout(100).then(() => {
|
||||
if (this.disposed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.fileService.existsFile(this.resource).then(exists => !exists);
|
||||
});
|
||||
} else {
|
||||
checkOrphanedPromise = TPromise.as(false);
|
||||
}
|
||||
|
||||
checkOrphanedPromise.done(newInOrphanModeValidated => {
|
||||
if (this.inOrphanMode !== newInOrphanModeValidated && !this.disposed) {
|
||||
this.setOrphaned(newInOrphanModeValidated);
|
||||
}
|
||||
});
|
||||
// If we are currently orphaned, we check if the model file was added back
|
||||
if (this.inOrphanMode) {
|
||||
const modelFileAdded = e.contains(this.resource, FileChangeType.ADDED);
|
||||
if (modelFileAdded) {
|
||||
newInOrphanModeGuess = false;
|
||||
fileEventImpactsModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise we check if the model file was deleted
|
||||
else {
|
||||
const modelFileDeleted = e.contains(this.resource, FileChangeType.DELETED);
|
||||
if (modelFileDeleted) {
|
||||
newInOrphanModeGuess = true;
|
||||
fileEventImpactsModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileEventImpactsModel && this.inOrphanMode !== newInOrphanModeGuess) {
|
||||
let checkOrphanedPromise: TPromise<boolean>;
|
||||
if (newInOrphanModeGuess) {
|
||||
// We have received reports of users seeing delete events even though the file still
|
||||
// exists (network shares issue: https://github.com/Microsoft/vscode/issues/13665).
|
||||
// Since we do not want to mark the model as orphaned, we have to check if the
|
||||
// file is really gone and not just a faulty file event.
|
||||
checkOrphanedPromise = TPromise.timeout(100).then(() => {
|
||||
if (this.disposed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.fileService.existsFile(this.resource).then(exists => !exists);
|
||||
});
|
||||
} else {
|
||||
checkOrphanedPromise = TPromise.as(false);
|
||||
}
|
||||
|
||||
checkOrphanedPromise.done(newInOrphanModeValidated => {
|
||||
if (this.inOrphanMode !== newInOrphanModeValidated && !this.disposed) {
|
||||
this.setOrphaned(newInOrphanModeValidated);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private setOrphaned(orphaned: boolean): void {
|
||||
@@ -244,7 +256,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
if (soft) {
|
||||
loadPromise = TPromise.as(this);
|
||||
} else {
|
||||
loadPromise = this.load(true /* force */);
|
||||
loadPromise = this.load({ forceReadFromDisk: true });
|
||||
}
|
||||
|
||||
return loadPromise.then(() => {
|
||||
@@ -260,28 +272,28 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
});
|
||||
}
|
||||
|
||||
public load(force?: boolean /* bypass any caches and really go to disk */): TPromise<TextFileEditorModel> {
|
||||
public load(options?: ILoadOptions): TPromise<TextFileEditorModel> {
|
||||
diag('load() - enter', this.resource, new Date());
|
||||
|
||||
// It is very important to not reload the model when the model is dirty. We only want to reload the model from the disk
|
||||
// if no save is pending to avoid data loss. This might cause a save conflict in case the file has been modified on the disk
|
||||
// meanwhile, but this is a very low risk.
|
||||
if (this.dirty) {
|
||||
diag('load() - exit - without loading because model is dirty', this.resource, new Date());
|
||||
if (this.dirty || this.saveSequentializer.hasPendingSave()) {
|
||||
diag('load() - exit - without loading because model is dirty or being saved', this.resource, new Date());
|
||||
|
||||
return TPromise.as(this);
|
||||
}
|
||||
|
||||
// Only for new models we support to load from backup
|
||||
if (!this.textEditorModel && !this.createTextEditorModelPromise) {
|
||||
return this.loadWithBackup(force);
|
||||
return this.loadWithBackup(options);
|
||||
}
|
||||
|
||||
// Otherwise load from file resource
|
||||
return this.loadFromFile(force);
|
||||
return this.loadFromFile(options);
|
||||
}
|
||||
|
||||
private loadWithBackup(force: boolean): TPromise<TextFileEditorModel> {
|
||||
private loadWithBackup(options?: ILoadOptions): TPromise<TextFileEditorModel> {
|
||||
return this.backupFileService.loadBackupResource(this.resource).then(backup => {
|
||||
|
||||
// Make sure meanwhile someone else did not suceed or start loading
|
||||
@@ -293,34 +305,36 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
if (!!backup) {
|
||||
const content: IRawTextContent = {
|
||||
resource: this.resource,
|
||||
name: paths.basename(this.resource.fsPath),
|
||||
name: path.basename(this.resource.fsPath),
|
||||
mtime: Date.now(),
|
||||
etag: void 0,
|
||||
value: createTextBufferFactory(''), /* will be filled later from backup */
|
||||
encoding: this.fileService.getEncoding(this.resource, this.preferredEncoding)
|
||||
encoding: this.fileService.encoding.getWriteEncoding(this.resource, this.preferredEncoding)
|
||||
};
|
||||
|
||||
return this.loadWithContent(content, backup);
|
||||
}
|
||||
|
||||
// Otherwise load from file
|
||||
return this.loadFromFile(force);
|
||||
return this.loadFromFile(options);
|
||||
});
|
||||
}
|
||||
|
||||
private loadFromFile(force: boolean): TPromise<TextFileEditorModel> {
|
||||
private loadFromFile(options?: ILoadOptions): TPromise<TextFileEditorModel> {
|
||||
const forceReadFromDisk = options && options.forceReadFromDisk;
|
||||
const allowBinary = this.isResolved() /* always allow if we resolved previously */ || (options && options.allowBinary);
|
||||
|
||||
// Decide on etag
|
||||
let etag: string;
|
||||
if (force) {
|
||||
etag = void 0; // bypass cache if force loading is true
|
||||
if (forceReadFromDisk) {
|
||||
etag = void 0; // reset ETag if we enforce to read from disk
|
||||
} else if (this.lastResolvedDiskStat) {
|
||||
etag = this.lastResolvedDiskStat.etag; // otherwise respect etag to support caching
|
||||
}
|
||||
|
||||
// Resolve Content
|
||||
return this.textFileService
|
||||
.resolveTextContent(this.resource, { acceptTextOnly: true, etag, encoding: this.preferredEncoding })
|
||||
.resolveTextContent(this.resource, { acceptTextOnly: !allowBinary, etag, encoding: this.preferredEncoding })
|
||||
.then(content => this.handleLoadSuccess(content), error => this.handleLoadError(error));
|
||||
}
|
||||
|
||||
@@ -370,10 +384,10 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
"fileGet" : {
|
||||
"mimeType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"path": { "classification": "CustomerContent", "purpose": "FeatureInsight" }
|
||||
"path": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.resource.fsPath), path: this.hashService.createSHA1(this.resource.fsPath) });
|
||||
this.telemetryService.publicLog('fileGet', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: path.extname(this.resource.fsPath), path: this.hashService.createSHA1(this.resource.fsPath) });
|
||||
}
|
||||
|
||||
return model;
|
||||
@@ -678,16 +692,15 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
// mark the save participant as current pending save operation
|
||||
return this.saveSequentializer.setPending(versionId, saveParticipantPromise.then(newVersionId => {
|
||||
|
||||
// Under certain conditions a save to the model will not cause the contents to the flushed on
|
||||
// disk because we can assume that the contents are already on disk. Instead, we just touch the
|
||||
// file to still trigger external file watchers for example.
|
||||
// Under certain conditions we do a short-cut of flushing contents to disk when we can assume that
|
||||
// the file has not changed and as such was not dirty before.
|
||||
// The conditions are all of:
|
||||
// - a forced, explicit save (Ctrl+S)
|
||||
// - the model is not dirty (otherwise we know there are changed which needs to go to the file)
|
||||
// - the model is not in orphan mode (because in that case we know the file does not exist on disk)
|
||||
// - the model version did not change due to save participants running
|
||||
if (options.force && !this.dirty && !this.inOrphanMode && options.reason === SaveReason.EXPLICIT && versionId === newVersionId) {
|
||||
return this.doTouch();
|
||||
return this.doTouch(newVersionId);
|
||||
}
|
||||
|
||||
// update versionId with its new value (if pre-save changes happened)
|
||||
@@ -725,7 +738,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
"ext": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
this.telemetryService.publicLog('filePUT', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: paths.extname(this.lastResolvedDiskStat.resource.fsPath) });
|
||||
this.telemetryService.publicLog('filePUT', { mimeType: guessMimeTypes(this.resource.fsPath).join(', '), ext: path.extname(this.lastResolvedDiskStat.resource.fsPath) });
|
||||
}
|
||||
|
||||
// Update dirty state unless model has changed meanwhile
|
||||
@@ -774,16 +787,20 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
// Check for workspace settings file
|
||||
return this.contextService.getWorkspace().folders.some(folder => {
|
||||
// {{SQL CARBON EDIT}}
|
||||
return paths.isEqualOrParent(this.resource.fsPath, path.join(folder.uri.fsPath, '.sqlops'));
|
||||
return path.isEqualOrParent(this.resource.fsPath, path.join(folder.uri.fsPath, '.sqlops'));
|
||||
});
|
||||
}
|
||||
|
||||
private doTouch(): TPromise<void> {
|
||||
return this.fileService.touchFile(this.resource).then(stat => {
|
||||
private doTouch(versionId: number): TPromise<void> {
|
||||
return this.saveSequentializer.setPending(versionId, this.fileService.updateContent(this.lastResolvedDiskStat.resource, this.createSnapshot(), {
|
||||
mtime: this.lastResolvedDiskStat.mtime,
|
||||
encoding: this.getEncoding(),
|
||||
etag: this.lastResolvedDiskStat.etag
|
||||
}).then(stat => {
|
||||
|
||||
// Updated resolved stat with updated stat since touching it might have changed mtime
|
||||
this.updateLastResolvedDiskStat(stat);
|
||||
}, () => void 0 /* gracefully ignore errors if just touching */);
|
||||
}, () => void 0 /* gracefully ignore errors if just touching */));
|
||||
}
|
||||
|
||||
private setDirty(dirty: boolean): () => void {
|
||||
@@ -829,8 +846,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
}
|
||||
|
||||
// Subsequent resolve - make sure that we only assign it if the mtime is equal or has advanced.
|
||||
// This is essential a If-Modified-Since check on the client ot prevent race conditions from loading
|
||||
// and saving. If a save comes in late after a revert was called, the mtime could be out of sync.
|
||||
// This prevents race conditions from loading and saving. If a save comes in late after a revert
|
||||
// was called, the mtime could be out of sync.
|
||||
else if (this.lastResolvedDiskStat.mtime <= newVersionOnDiskStat.mtime) {
|
||||
this.lastResolvedDiskStat = newVersionOnDiskStat;
|
||||
}
|
||||
@@ -923,7 +940,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
|
||||
this.updatePreferredEncoding(encoding);
|
||||
|
||||
// Load
|
||||
this.load(true /* force because encoding has changed */).done(null, onUnexpectedError);
|
||||
this.load({
|
||||
forceReadFromDisk: true // because encoding has changed
|
||||
}).done(null, onUnexpectedError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1083,10 +1102,10 @@ export class SaveSequentializer {
|
||||
|
||||
class DefaultSaveErrorHandler implements ISaveErrorHandler {
|
||||
|
||||
constructor( @INotificationService private notificationService: INotificationService) { }
|
||||
constructor(@INotificationService private notificationService: INotificationService) { }
|
||||
|
||||
public onSaveError(error: any, model: TextFileEditorModel): void {
|
||||
this.notificationService.error(nls.localize('genericSaveError', "Failed to save '{0}': {1}", paths.basename(model.getResource().fsPath), toErrorMessage(error, false)));
|
||||
this.notificationService.error(nls.localize('genericSaveError', "Failed to save '{0}': {1}", path.basename(model.getResource().fsPath), toErrorMessage(error, false)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter, debounceEvent } from 'vs/base/common/event';
|
||||
import { Event, Emitter, debounceEvent } from 'vs/base/common/event';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ITextFileEditorModel, ITextFileEditorModelManager, TextFileModelChangeEvent, StateChange, IModelLoadOrCreateOptions } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ITextFileEditorModel, ITextFileEditorModelManager, TextFileModelChangeEvent, StateChange, IModelLoadOrCreateOptions, ILoadOptions } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
@@ -17,14 +17,14 @@ import { ResourceMap } from 'vs/base/common/map';
|
||||
export class TextFileEditorModelManager implements ITextFileEditorModelManager {
|
||||
private toUnbind: IDisposable[];
|
||||
|
||||
private _onModelDisposed: Emitter<URI>;
|
||||
private _onModelContentChanged: Emitter<TextFileModelChangeEvent>;
|
||||
private _onModelDirty: Emitter<TextFileModelChangeEvent>;
|
||||
private _onModelSaveError: Emitter<TextFileModelChangeEvent>;
|
||||
private _onModelSaved: Emitter<TextFileModelChangeEvent>;
|
||||
private _onModelReverted: Emitter<TextFileModelChangeEvent>;
|
||||
private _onModelEncodingChanged: Emitter<TextFileModelChangeEvent>;
|
||||
private _onModelOrphanedChanged: Emitter<TextFileModelChangeEvent>;
|
||||
private readonly _onModelDisposed: Emitter<URI>;
|
||||
private readonly _onModelContentChanged: Emitter<TextFileModelChangeEvent>;
|
||||
private readonly _onModelDirty: Emitter<TextFileModelChangeEvent>;
|
||||
private readonly _onModelSaveError: Emitter<TextFileModelChangeEvent>;
|
||||
private readonly _onModelSaved: Emitter<TextFileModelChangeEvent>;
|
||||
private readonly _onModelReverted: Emitter<TextFileModelChangeEvent>;
|
||||
private readonly _onModelEncodingChanged: Emitter<TextFileModelChangeEvent>;
|
||||
private readonly _onModelOrphanedChanged: Emitter<TextFileModelChangeEvent>;
|
||||
|
||||
private _onModelsDirtyEvent: Event<TextFileModelChangeEvent[]>;
|
||||
private _onModelsSaveError: Event<TextFileModelChangeEvent[]>;
|
||||
@@ -167,22 +167,27 @@ export class TextFileEditorModelManager implements ITextFileEditorModelManager {
|
||||
return pendingLoad;
|
||||
}
|
||||
|
||||
let modelLoadOptions: ILoadOptions;
|
||||
if (options && options.allowBinary) {
|
||||
modelLoadOptions = { allowBinary: true };
|
||||
}
|
||||
|
||||
let modelPromise: TPromise<ITextFileEditorModel>;
|
||||
|
||||
// Model exists
|
||||
let model = this.get(resource);
|
||||
if (model) {
|
||||
if (!options || !options.reload) {
|
||||
modelPromise = TPromise.as(model);
|
||||
if (options && options.reload) {
|
||||
modelPromise = model.load(modelLoadOptions);
|
||||
} else {
|
||||
modelPromise = model.load();
|
||||
modelPromise = TPromise.as(model);
|
||||
}
|
||||
}
|
||||
|
||||
// Model does not exist
|
||||
else {
|
||||
model = this.instantiationService.createInstance(TextFileEditorModel, resource, options ? options.encoding : void 0);
|
||||
modelPromise = model.load();
|
||||
modelPromise = model.load(modelLoadOptions);
|
||||
|
||||
// Install state change listener
|
||||
this.mapResourceToStateChangeListener.set(resource, model.onDidStateChange(state => {
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
import * as nls from 'vs/nls';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import paths = require('vs/base/common/paths');
|
||||
import errors = require('vs/base/common/errors');
|
||||
import objects = require('vs/base/common/objects');
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import platform = require('vs/base/common/platform');
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { IWindowsService } from 'vs/platform/windows/common/windows';
|
||||
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
||||
import { IResult, ITextFileOperationResult, ITextFileService, IRawTextContent, IAutoSaveConfiguration, AutoSaveMode, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions, AutoSaveContext } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
@@ -51,10 +51,10 @@ export abstract class TextFileService implements ITextFileService {
|
||||
private toUnbind: IDisposable[];
|
||||
private _models: TextFileEditorModelManager;
|
||||
|
||||
private _onFilesAssociationChange: Emitter<void>;
|
||||
private readonly _onFilesAssociationChange: Emitter<void>;
|
||||
private currentFilesAssociationConfig: { [key: string]: string; };
|
||||
|
||||
private _onAutoSaveConfigurationChange: Emitter<IAutoSaveConfiguration>;
|
||||
private readonly _onAutoSaveConfigurationChange: Emitter<IAutoSaveConfiguration>;
|
||||
private configuredAutoSaveDelay: number;
|
||||
private configuredAutoSaveOnFocusChange: boolean;
|
||||
private configuredAutoSaveOnWindowChange: boolean;
|
||||
@@ -484,8 +484,8 @@ export abstract class TextFileService implements ITextFileService {
|
||||
private doSaveAllFiles(resources?: URI[], options: ISaveOptions = Object.create(null)): TPromise<ITextFileOperationResult> {
|
||||
const dirtyFileModels = this.getDirtyFileModels(Array.isArray(resources) ? resources : void 0 /* Save All */)
|
||||
.filter(model => {
|
||||
if (model.hasState(ModelState.CONFLICT) && (options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)) {
|
||||
return false; // if model is in save conflict, do not save unless save reason is explicit or not provided at all
|
||||
if ((model.hasState(ModelState.CONFLICT) || model.hasState(ModelState.ERROR)) && (options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)) {
|
||||
return false; // if model is in save conflict or error, do not save unless save reason is explicit or not provided at all
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IEncodingSupport, ConfirmResult } from 'vs/workbench/common/editor';
|
||||
import { IBaseStat, IResolveContentOptions, ITextSnapshot } from 'vs/platform/files/common/files';
|
||||
@@ -140,8 +140,22 @@ export interface IRawTextContent extends IBaseStat {
|
||||
}
|
||||
|
||||
export interface IModelLoadOrCreateOptions {
|
||||
|
||||
|
||||
/**
|
||||
* The encoding to use when resolving the model text content.
|
||||
*/
|
||||
encoding?: string;
|
||||
|
||||
/**
|
||||
* Wether to reload the model if it already exists.
|
||||
*/
|
||||
reload?: boolean;
|
||||
|
||||
/**
|
||||
* Allow to load a model even if we think it is a binary file.
|
||||
*/
|
||||
allowBinary?: boolean;
|
||||
}
|
||||
|
||||
export interface ITextFileEditorModelManager {
|
||||
@@ -179,6 +193,19 @@ export interface ISaveOptions {
|
||||
writeElevated?: boolean;
|
||||
}
|
||||
|
||||
export interface ILoadOptions {
|
||||
|
||||
/**
|
||||
* Go to disk bypassing any cache of the model if any.
|
||||
*/
|
||||
forceReadFromDisk?: boolean;
|
||||
|
||||
/**
|
||||
* Allow to load a model even if we think it is a binary file.
|
||||
*/
|
||||
allowBinary?: boolean;
|
||||
}
|
||||
|
||||
export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport {
|
||||
|
||||
onDidContentChange: Event<StateChange>;
|
||||
@@ -196,7 +223,7 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport
|
||||
|
||||
save(options?: ISaveOptions): TPromise<void>;
|
||||
|
||||
load(): TPromise<ITextFileEditorModel>;
|
||||
load(options?: ILoadOptions): TPromise<ITextFileEditorModel>;
|
||||
|
||||
revert(soft?: boolean): TPromise<void>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user