diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 21d511c7bef..b4ecea4cee0 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -129,9 +129,31 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil private onFileChanges(e: FileChangesEvent): void { // Track ADD and DELETES for updates of this model to orphan-mode - const newInOrphanMode = e.contains(this.resource, FileChangeType.DELETED) && !e.contains(this.resource, FileChangeType.ADDED); - if (this.inOrphanMode !== newInOrphanMode) { - this.setOrphaned(newInOrphanMode); + const newInOrphanModeGuess = e.contains(this.resource, FileChangeType.DELETED) && !e.contains(this.resource, FileChangeType.ADDED); + if (this.inOrphanMode !== newInOrphanModeGuess) { + let checkOrphanedPromise: TPromise; + 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 (TODO@Ben revisit when we + // have a more stable file watcher in place for this scenario). + 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); + } + }); } } diff --git a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts index 246abedf701..694e123be2c 100644 --- a/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts @@ -385,10 +385,12 @@ suite('Files - TextFileEditorModel', () => { }); accessor.fileService.fireFileChanges(new FileChangesEvent([{ resource: model.getResource(), type: FileChangeType.DELETED }])); - assert.ok(model.hasState(ModelState.ORPHAN)); + return TPromise.timeout(110).then(() => { + assert.ok(model.hasState(ModelState.ORPHAN)); - accessor.fileService.fireFileChanges(new FileChangesEvent([{ resource: model.getResource(), type: FileChangeType.ADDED }])); - assert.ok(!model.hasState(ModelState.ORPHAN)); + accessor.fileService.fireFileChanges(new FileChangesEvent([{ resource: model.getResource(), type: FileChangeType.ADDED }])); + assert.ok(!model.hasState(ModelState.ORPHAN)); + }); }); test('SaveSequentializer - pending basics', function (done) {