Browse Source

Fixes #667 - Updates tracked lines on content changes

main
Eric Amodio 5 years ago
parent
commit
2d81082d0c
3 changed files with 84 additions and 25 deletions
  1. +20
    -1
      src/trackers/documentTracker.ts
  2. +32
    -19
      src/trackers/gitLineTracker.ts
  3. +32
    -5
      src/trackers/lineTracker.ts

+ 20
- 1
src/trackers/documentTracker.ts View File

@ -9,6 +9,7 @@ import {
Range,
TextDocument,
TextDocumentChangeEvent,
TextDocumentContentChangeEvent,
TextEditor,
TextLine,
Uri,
@ -23,6 +24,12 @@ import { DocumentBlameStateChangeEvent, TrackedDocument } from './trackedDocumen
export * from './trackedDocument';
export interface DocumentContentChangeEvent<T> {
readonly editor: TextEditor;
readonly document: TrackedDocument<T>;
readonly contentChanges: ReadonlyArray<TextDocumentContentChangeEvent>;
}
export interface DocumentDirtyStateChangeEvent<T> {
readonly editor: TextEditor;
readonly document: TrackedDocument<T>;
@ -40,6 +47,11 @@ export class DocumentTracker implements Disposable {
return this._onDidChangeBlameState.event;
}
private _onDidChangeContent = new EventEmitter<DocumentContentChangeEvent<T>>();
get onDidChangeContent(): Event<DocumentContentChangeEvent<T>> {
return this._onDidChangeContent.event;
}
private _onDidChangeDirtyState = new EventEmitter<DocumentDirtyStateChangeEvent<T>>();
get onDidChangeDirtyState(): Event<DocumentDirtyStateChangeEvent<T>> {
return this._onDidChangeDirtyState.event;
@ -127,7 +139,9 @@ export class DocumentTracker implements Disposable {
private onTextDocumentChanged(e: TextDocumentChangeEvent) {
const { scheme } = e.document.uri;
if (scheme !== DocumentSchemes.File && scheme !== DocumentSchemes.Vsls) return;
if (scheme !== DocumentSchemes.File && scheme !== DocumentSchemes.Git && scheme !== DocumentSchemes.Vsls) {
return;
}
let doc = this._documentMap.get(e.document);
if (doc === undefined) {
@ -148,6 +162,11 @@ export class DocumentTracker implements Disposable {
}
}
// Only fire change events for the active document
if (editor !== undefined && editor.document === e.document) {
this._onDidChangeContent.fire({ editor: editor, document: doc, contentChanges: e.contentChanges });
}
if (!doc.forceDirtyStateChangeOnNextDocumentChange && doc.dirty === dirty) return;
doc.resetForceDirtyStateChangeOnNextDocumentChange();

+ 32
- 19
src/trackers/gitLineTracker.ts View File

@ -4,6 +4,7 @@ import { Container } from '../container';
import { GitBlameCommit, GitLogCommit } from '../git/gitService';
import {
DocumentBlameStateChangeEvent,
DocumentContentChangeEvent,
DocumentDirtyIdleTriggerEvent,
DocumentDirtyStateChangeEvent,
GitDocumentState
@ -22,21 +23,39 @@ export class GitLineTracker extends LineTracker {
this.reset();
let updated = false;
if (!this._suspended && !e.pending && e.lines !== undefined && e.editor !== undefined) {
if (!this.suspended && !e.pending && e.lines !== undefined && e.editor !== undefined) {
updated = await this.updateState(e.lines, e.editor);
}
return super.fireLinesChanged(updated ? e : { ...e, lines: undefined });
}
private _subscriptionOnlyWhenActive: Disposable | undefined;
protected onStart(): Disposable | undefined {
this.onResume();
return Disposable.from(
{ dispose: () => this.onSuspend() },
Container.tracker.onDidChangeBlameState(this.onBlameStateChanged, this),
Container.tracker.onDidChangeDirtyState(this.onDirtyStateChanged, this),
Container.tracker.onDidTriggerDirtyIdle(this.onDirtyIdleTriggered, this)
);
}
protected onResume(): void {
if (this._subscriptionOnlyWhenActive === undefined) {
this._subscriptionOnlyWhenActive = Container.tracker.onDidChangeContent(this.onContentChanged, this);
}
}
protected onSuspend(): void {
if (this._subscriptionOnlyWhenActive === undefined) return;
this._subscriptionOnlyWhenActive.dispose();
this._subscriptionOnlyWhenActive = undefined;
}
@debug({
args: {
0: (e: DocumentBlameStateChangeEvent<GitDocumentState>) =>
@ -51,6 +70,18 @@ export class GitLineTracker extends LineTracker {
@debug({
args: {
0: (e: DocumentContentChangeEvent<GitDocumentState>) =>
`editor=${e.editor.document.uri.toString(true)}, doc=${e.document.uri.toString(true)}`
}
})
private onContentChanged(e: DocumentContentChangeEvent<GitDocumentState>) {
if (e.contentChanges.some(cc => this.lines?.some(l => cc.range.start.line <= l && cc.range.end.line >= l))) {
this.trigger('editor');
}
}
@debug({
args: {
0: (e: DocumentDirtyIdleTriggerEvent<GitDocumentState>) =>
`editor=${e.editor.document.uri.toString(true)}, doc=${e.document.uri.toString(true)}`
}
@ -76,24 +107,6 @@ export class GitLineTracker extends LineTracker {
}
}
private _suspended = false;
@debug()
private resume(options: { force?: boolean } = {}) {
if (!options.force && !this._suspended) return;
this._suspended = false;
this.trigger('editor');
}
@debug()
private suspend(options: { force?: boolean } = {}) {
if (!options.force && this._suspended) return;
this._suspended = true;
this.trigger('editor');
}
private async updateState(lines: number[], editor: TextEditor): Promise<boolean> {
const trackedDocument = await Container.tracker.getOrAdd(editor.document);
if (!trackedDocument.isBlameable || !this.includesAll(lines)) return false;

+ 32
- 5
src/trackers/lineTracker.ts View File

@ -1,7 +1,7 @@
'use strict';
import { Disposable, Event, EventEmitter, TextEditor, TextEditorSelectionChangeEvent, window } from 'vscode';
import { isTextEditor } from '../constants';
import { Deferrable, Functions } from '../system';
import { debug, Deferrable, Functions } from '../system';
export interface LinesChangeEvent {
readonly editor: TextEditor | undefined;
@ -88,10 +88,9 @@ export class LineTracker implements Disposable {
return this._subscriptions.has(subscriber);
}
protected onStart(): Disposable | undefined {
return undefined;
}
protected onStart?(): Disposable | undefined;
@debug({ args: false })
start(subscriber: any, subscription: Disposable): Disposable {
const disposable = {
dispose: () => this.stop(subscriber)
@ -111,7 +110,7 @@ export class LineTracker implements Disposable {
this._disposable = Disposable.from(
window.onDidChangeActiveTextEditor(Functions.debounce(this.onActiveTextEditorChanged, 0), this),
window.onDidChangeTextEditorSelection(this.onTextEditorSelectionChanged, this),
this.onStart() ?? { dispose: () => {} }
this.onStart?.() ?? { dispose: () => {} }
);
setImmediate(() => this.onActiveTextEditorChanged(window.activeTextEditor));
@ -120,6 +119,7 @@ export class LineTracker implements Disposable {
return disposable;
}
@debug({ args: false })
stop(subscriber: any) {
const subs = this._subscriptions.get(subscriber);
if (subs === undefined) return;
@ -141,6 +141,33 @@ export class LineTracker implements Disposable {
}
}
private _suspended = false;
get suspended() {
return this._suspended;
}
protected onResume?(): void;
@debug()
resume(options: { force?: boolean } = {}) {
if (!options.force && !this._suspended) return;
this._suspended = false;
void this.onResume?.();
this.trigger('editor');
}
protected onSuspend?(): void;
@debug()
suspend(options: { force?: boolean } = {}) {
if (!options.force && this._suspended) return;
this._suspended = true;
void this.onSuspend?.();
this.trigger('editor');
}
protected fireLinesChanged(e: LinesChangeEvent) {
this._onDidChangeActiveLines.fire(e);
}

Loading…
Cancel
Save