From 021a5b833ad89e11d1c22e453b093fa0a0ca9e57 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 25 May 2017 01:31:24 -0400 Subject: [PATCH] Fixes #71 - blame invalid on external edit --- src/blameAnnotationController.ts | 20 +++++++++++++++++++- src/gitService.ts | 18 +++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/blameAnnotationController.ts b/src/blameAnnotationController.ts index 5e30720..5cc80b8 100644 --- a/src/blameAnnotationController.ts +++ b/src/blameAnnotationController.ts @@ -1,6 +1,6 @@ 'use strict'; import { Functions } from './system'; -import { DecorationRenderOptions, Disposable, Event, EventEmitter, ExtensionContext, OverviewRulerLane, TextDocument, TextEditor, TextEditorDecorationType, TextEditorViewColumnChangeEvent, window, workspace } from 'vscode'; +import { DecorationRenderOptions, Disposable, Event, EventEmitter, ExtensionContext, OverviewRulerLane, TextDocument, TextDocumentChangeEvent, TextEditor, TextEditorDecorationType, TextEditorViewColumnChangeEvent, window, workspace } from 'vscode'; import { BlameAnnotationProvider } from './blameAnnotationProvider'; import { TextDocumentComparer, TextEditorComparer } from './comparers'; import { IBlameConfig } from './configuration'; @@ -176,6 +176,7 @@ export class BlameAnnotationController extends Disposable { subscriptions.push(window.onDidChangeVisibleTextEditors(Functions.debounce(this._onVisibleTextEditorsChanged, 100), this)); subscriptions.push(window.onDidChangeTextEditorViewColumn(this._onTextEditorViewColumnChanged, this)); + subscriptions.push(workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this)); subscriptions.push(workspace.onDidCloseTextDocument(this._onTextDocumentClosed, this)); subscriptions.push(this.gitContextTracker.onDidBlameabilityChange(this._onBlameabilityChanged, this)); @@ -217,6 +218,23 @@ export class BlameAnnotationController extends Disposable { } } + private _onTextDocumentChanged(e: TextDocumentChangeEvent) { + for (const [key, p] of this._annotationProviders) { + if (!TextDocumentComparer.equals(p.document, e.document)) continue; + + // We have to defer because isDirty is not reliable inside this event + setTimeout(() => { + // If the document is dirty all is fine, just kick out since the GitContextTracker will handle it + if (e.document.isDirty) return; + + // If the document isn't dirty, it is very likely this event was triggered by an outside edit of this document + // Which means the document has been reloaded and the blame annotations have been removed, so we need to update (clear) our state tracking + Logger.log('TextDocumentChanged:', `Clear blame annotations for column ${key}`); + this.clear(key); + }, 1); + } + } + private _onTextDocumentClosed(e: TextDocument) { for (const [key, p] of this._annotationProviders) { if (!TextDocumentComparer.equals(p.document, e)) continue; diff --git a/src/gitService.ts b/src/gitService.ts index d025e82..3e0b92c 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -1,6 +1,6 @@ 'use strict'; import { Iterables, Objects } from './system'; -import { Disposable, Event, EventEmitter, ExtensionContext, FileSystemWatcher, languages, Location, Position, Range, TextDocument, TextEditor, Uri, workspace } from 'vscode'; +import { Disposable, Event, EventEmitter, ExtensionContext, FileSystemWatcher, languages, Location, Position, Range, TextDocument, TextDocumentChangeEvent, TextEditor, Uri, workspace } from 'vscode'; import { CommandContext, setCommandContext } from './commands'; import { CodeLensVisibility, IConfig } from './configuration'; import { DocumentSchemes, ExtensionKey } from './constants'; @@ -166,6 +166,7 @@ export class GitService extends Disposable { const disposables: Disposable[] = []; disposables.push(workspace.onDidCloseTextDocument(d => this._removeCachedEntry(d, RemoveCacheReason.DocumentClosed))); + disposables.push(workspace.onDidChangeTextDocument(this._onTextDocumentChanged, this)); disposables.push(workspace.onDidSaveTextDocument(d => this._removeCachedEntry(d, RemoveCacheReason.DocumentSaved))); disposables.push(this._fsWatcher.onDidChange(this._onGitChanged, this)); @@ -208,6 +209,21 @@ export class GitService extends Disposable { this.config = cfg; } + private _onTextDocumentChanged(e: TextDocumentChangeEvent) { + if (!this.UseCaching) return; + if (e.document.uri.scheme !== DocumentSchemes.File) return; + + // We have to defer because isDirty is not reliable inside this event + setTimeout(() => { + // If the document is dirty all is fine, we'll just wait for the save before clearing our cache + if (e.document.isDirty) return; + + // If the document isn't dirty, it is very likely this event was triggered by an outside edit of this document + // Which means the document has been reloaded and we should clear our cache for it + this._removeCachedEntry(e.document, RemoveCacheReason.DocumentSaved); + }, 1); + } + private _onGitChanged() { this._gitCache.clear();