Skip to content

Commit

Permalink
Refreshes line history on selection change
Browse files Browse the repository at this point in the history
Even if the active line didn't change
  • Loading branch information
eamodio committed Aug 17, 2020
1 parent 7d047ea commit fcc55fb
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 89 deletions.
40 changes: 23 additions & 17 deletions src/annotations/lineAnnotationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Container } from '../container';
import { CommitFormatter, GitBlameCommit, PullRequest } from '../git/git';
import { LogCorrelationContext, Logger } from '../logger';
import { debug, Iterables, log, Promises } from '../system';
import { LinesChangeEvent } from '../trackers/gitLineTracker';
import { LinesChangeEvent, LineSelection } from '../trackers/gitLineTracker';

const annotationDecoration: TextEditorDecorationType = window.createTextEditorDecorationType({
after: {
Expand Down Expand Up @@ -94,13 +94,13 @@ export class LineAnnotationController implements Disposable {
@debug({
args: {
0: (e: LinesChangeEvent) =>
`editor=${e.editor?.document.uri.toString(true)}, lines=${e.lines?.join(',')}, pending=${Boolean(
e.pending,
)}, reason=${e.reason}`,
`editor=${e.editor?.document.uri.toString(true)}, selections=${e.selections
?.map(s => `[${s.anchor}-${s.active}]`)
.join(',')}, pending=${Boolean(e.pending)}, reason=${e.reason}`,
},
})
private onActiveLinesChanged(e: LinesChangeEvent) {
if (!e.pending && e.lines !== undefined) {
if (!e.pending && e.selections !== undefined) {
void this.refresh(e.editor);

return;
Expand Down Expand Up @@ -168,21 +168,21 @@ export class LineAnnotationController implements Disposable {
ref => Container.git.getPullRequestForCommit(ref, provider),
timeout,
);
if (prs.size === 0 || Iterables.every(prs.values(), pr => pr === undefined)) return undefined;
if (prs.size === 0 || Iterables.every(prs.values(), pr => pr == null)) return undefined;

return prs;
}

@debug({ args: false })
private async refresh(editor: TextEditor | undefined, options?: { prs?: Map<string, PullRequest | undefined> }) {
if (editor === undefined && this._editor === undefined) return;
if (editor == null && this._editor == null) return;

const cc = Logger.getCorrelationContext();

const lines = Container.lineTracker.lines;
if (editor === undefined || lines === undefined || !isTextEditor(editor)) {
const selections = Container.lineTracker.selections;
if (editor == null || selections == null || !isTextEditor(editor)) {
if (cc) {
cc.exitDetails = ` ${GlyphChars.Dot} Skipped because there is no valid editor or no valid lines`;
cc.exitDetails = ` ${GlyphChars.Dot} Skipped because there is no valid editor or no valid selections`;
}

this.clear(this._editor);
Expand Down Expand Up @@ -221,28 +221,34 @@ export class LineAnnotationController implements Disposable {
}

// Make sure the editor hasn't died since the await above and that we are still on the same line(s)
if (editor.document === undefined || !Container.lineTracker.includesAll(lines)) {
if (editor.document == null || !Container.lineTracker.includes(selections)) {
if (cc) {
cc.exitDetails = ` ${GlyphChars.Dot} Skipped because the ${
editor.document === undefined ? 'editor is gone' : `line(s)=${lines.join()} are no longer current`
editor.document == null
? 'editor is gone'
: `selection(s)=${selections
.map(s => `[${s.anchor}-${s.active}]`)
.join()} are no longer current`
}`;
}
return;
}

if (cc) {
cc.exitDetails = ` ${GlyphChars.Dot} line(s)=${lines.join()}`;
cc.exitDetails = ` ${GlyphChars.Dot} selection(s)=${selections
.map(s => `[${s.anchor}-${s.active}]`)
.join()}`;
}

const commitLines = [
...Iterables.filterMap<number, [number, GitBlameCommit]>(lines, l => {
const state = Container.lineTracker.getState(l);
...Iterables.filterMap<LineSelection, [number, GitBlameCommit]>(selections, selection => {
const state = Container.lineTracker.getState(selection.active);
if (state?.commit == null) {
Logger.debug(cc, `Line ${l} returned no commit`);
Logger.debug(cc, `Line ${selection.active} returned no commit`);
return undefined;
}

return [l, state.commit];
return [selection.active, state.commit];
}),
];

Expand Down
8 changes: 4 additions & 4 deletions src/hovers/lineHoverController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ export class LineHoverController implements Disposable {
@debug({
args: {
0: (e: LinesChangeEvent) =>
`editor=${e.editor?.document.uri.toString(true)}, lines=${e.lines?.join(',')}, pending=${Boolean(
e.pending,
)}, reason=${e.reason}`,
`editor=${e.editor?.document.uri.toString(true)}, selections=${e.selections
?.map(s => `[${s.anchor}-${s.active}]`)
.join(',')}, pending=${Boolean(e.pending)}, reason=${e.reason}`,
},
})
private onActiveLinesChanged(e: LinesChangeEvent) {
if (e.pending) return;

if (e.editor == null || e.lines == null) {
if (e.editor == null || e.selections == null) {
this.unregister();

return;
Expand Down
34 changes: 15 additions & 19 deletions src/statusbar/statusBarController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export class StatusBarController implements Disposable {
this._modeStatusBarItem.text = mode.statusBarItemName;
this._modeStatusBarItem.tooltip = 'Switch GitLens Mode';
this._modeStatusBarItem.show();
} else if (this._modeStatusBarItem !== undefined) {
this._modeStatusBarItem.dispose();
} else {
this._modeStatusBarItem?.dispose();
this._modeStatusBarItem = undefined;
}
}
Expand All @@ -67,8 +67,8 @@ export class StatusBarController implements Disposable {
Container.config.statusBar.alignment !== 'left' ? StatusBarAlignment.Right : StatusBarAlignment.Left;

if (configuration.changed(e, 'statusBar', 'alignment')) {
if (this._blameStatusBarItem !== undefined && this._blameStatusBarItem.alignment !== alignment) {
this._blameStatusBarItem.dispose();
if (this._blameStatusBarItem?.alignment !== alignment) {
this._blameStatusBarItem?.dispose();
this._blameStatusBarItem = undefined;
}
}
Expand All @@ -87,31 +87,29 @@ export class StatusBarController implements Disposable {
} else if (configuration.changed(e, 'statusBar', 'enabled')) {
Container.lineTracker.stop(this);

if (this._blameStatusBarItem !== undefined) {
this._blameStatusBarItem.dispose();
this._blameStatusBarItem = undefined;
}
this._blameStatusBarItem?.dispose();
this._blameStatusBarItem = undefined;
}
}

@debug({
args: {
0: (e: LinesChangeEvent) =>
`editor=${e.editor?.document.uri.toString(true)}, lines=${e.lines?.join(',')}, pending=${Boolean(
e.pending,
)}, reason=${e.reason}`,
`editor=${e.editor?.document.uri.toString(true)}, selections=${e.selections
?.map(s => `[${s.anchor}-${s.active}]`)
.join(',')}, pending=${Boolean(e.pending)}, reason=${e.reason}`,
},
})
private onActiveLinesChanged(e: LinesChangeEvent) {
// If we need to reduceFlicker, don't clear if only the selected lines changed
let clear = !(
Container.config.statusBar.reduceFlicker &&
e.reason === 'selection' &&
(e.pending || e.lines !== undefined)
(e.pending || e.selections != null)
);
if (!e.pending && e.lines !== undefined) {
const state = Container.lineTracker.getState(e.lines[0]);
if (state?.commit !== undefined) {
if (!e.pending && e.selections != null) {
const state = Container.lineTracker.getState(e.selections[0].active);
if (state?.commit != null) {
this.updateBlame(state.commit, e.editor!);

return;
Expand All @@ -126,14 +124,12 @@ export class StatusBarController implements Disposable {
}

clearBlame() {
if (this._blameStatusBarItem !== undefined) {
this._blameStatusBarItem.hide();
}
this._blameStatusBarItem?.hide();
}

private updateBlame(commit: GitCommit, editor: TextEditor) {
const cfg = Container.config.statusBar;
if (!cfg.enabled || this._blameStatusBarItem === undefined || !isTextEditor(editor)) return;
if (!cfg.enabled || this._blameStatusBarItem == null || !isTextEditor(editor)) return;

this._blameStatusBarItem.text = `$(git-commit) ${CommitFormatter.fromTemplate(cfg.format, commit, {
truncateMessageAtNewLine: true,
Expand Down
48 changes: 29 additions & 19 deletions src/trackers/gitLineTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
DocumentDirtyStateChangeEvent,
GitDocumentState,
} from './gitDocumentTracker';
import { LinesChangeEvent, LineTracker } from './lineTracker';
import { LinesChangeEvent, LineSelection, LineTracker } from './lineTracker';
import { Logger } from '../logger';
import { debug } from '../system';

Expand All @@ -25,11 +25,11 @@ export class GitLineTracker extends LineTracker<GitLineState> {
this.reset();

let updated = false;
if (!this.suspended && !e.pending && e.lines !== undefined && e.editor !== undefined) {
updated = await this.updateState(e.lines, e.editor);
if (!this.suspended && !e.pending && e.selections != null && e.editor != null) {
updated = await this.updateState(e.selections, e.editor);
}

return super.fireLinesChanged(updated ? e : { ...e, lines: undefined });
return super.fireLinesChanged(updated ? e : { ...e, selections: undefined });
}

private _subscriptionOnlyWhenActive: Disposable | undefined;
Expand All @@ -46,15 +46,13 @@ export class GitLineTracker extends LineTracker<GitLineState> {
}

protected onResume(): void {
if (this._subscriptionOnlyWhenActive === undefined) {
if (this._subscriptionOnlyWhenActive == null) {
this._subscriptionOnlyWhenActive = Container.tracker.onDidChangeContent(this.onContentChanged, this);
}
}

protected onSuspend(): void {
if (this._subscriptionOnlyWhenActive === undefined) return;

this._subscriptionOnlyWhenActive.dispose();
this._subscriptionOnlyWhenActive?.dispose();
this._subscriptionOnlyWhenActive = undefined;
}

Expand All @@ -77,7 +75,15 @@ export class GitLineTracker extends LineTracker<GitLineState> {
},
})
private onContentChanged(e: DocumentContentChangeEvent<GitDocumentState>) {
if (e.contentChanges.some(cc => this.lines?.some(l => cc.range.start.line <= l && cc.range.end.line >= l))) {
if (
e.contentChanges.some(cc =>
this.selections?.some(
selection =>
(cc.range.end.line >= selection.active && selection.active >= cc.range.start.line) ||
(cc.range.start.line >= selection.active && selection.active >= cc.range.end.line),
),
)
) {
this.trigger('editor');
}
}
Expand Down Expand Up @@ -113,16 +119,16 @@ export class GitLineTracker extends LineTracker<GitLineState> {

@debug({
args: {
0: (lines: number[]) => lines?.join(','),
0: (selections: LineSelection[]) => selections?.map(s => s.active).join(','),
1: (editor: TextEditor) => editor.document.uri.toString(true),
},
exit: updated => `returned ${updated}`,
singleLine: true,
})
private async updateState(lines: number[], editor: TextEditor): Promise<boolean> {
private async updateState(selections: LineSelection[], editor: TextEditor): Promise<boolean> {
const cc = Logger.getCorrelationContext();

if (!this.includesAll(lines)) {
if (!this.includes(selections)) {
if (cc != null) {
cc.exitDetails = ` ${GlyphChars.Dot} lines no longer match`;
}
Expand All @@ -139,10 +145,14 @@ export class GitLineTracker extends LineTracker<GitLineState> {
return false;
}

if (lines.length === 1) {
if (selections.length === 1) {
const blameLine = editor.document.isDirty
? await Container.git.getBlameForLineContents(trackedDocument.uri, lines[0], editor.document.getText())
: await Container.git.getBlameForLine(trackedDocument.uri, lines[0]);
? await Container.git.getBlameForLineContents(
trackedDocument.uri,
selections[0].active,
editor.document.getText(),
)
: await Container.git.getBlameForLine(trackedDocument.uri, selections[0].active);
if (blameLine === undefined) {
if (cc != null) {
cc.exitDetails = ` ${GlyphChars.Dot} blame failed`;
Expand All @@ -164,15 +174,15 @@ export class GitLineTracker extends LineTracker<GitLineState> {
return false;
}

for (const line of lines) {
const commitLine = blame.lines[line];
this.setState(line, new GitLineState(blame.commits.get(commitLine.sha)));
for (const selection of selections) {
const commitLine = blame.lines[selection.active];
this.setState(selection.active, new GitLineState(blame.commits.get(commitLine.sha)));
}
}

// Check again because of the awaits above

if (!this.includesAll(lines)) {
if (!this.includes(selections)) {
if (cc != null) {
cc.exitDetails = ` ${GlyphChars.Dot} lines no longer match`;
}
Expand Down

0 comments on commit fcc55fb

Please sign in to comment.