From e10d7eb648bbb4a0d9318a1fa77c0c9884c88e4d Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Fri, 28 Jul 2017 17:09:34 -0400 Subject: [PATCH] Increases performance of blame annotations especially for larger file --- src/annotations/annotations.ts | 7 +-- .../gutterBlameAnnotationProvider.ts | 63 +++++++++++++++---- .../hoverBlameAnnotationProvider.ts | 14 ++++- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/annotations/annotations.ts b/src/annotations/annotations.ts index b188787..47161c0 100644 --- a/src/annotations/annotations.ts +++ b/src/annotations/annotations.ts @@ -99,11 +99,8 @@ export class Annotations { } as DecorationOptions; } - static gutter(commit: GitCommit, format: string, dateFormatOrFormatOptions: string | null | ICommitFormatOptions, renderOptions: IRenderOptions, compact: boolean): DecorationOptions { - let content = Strings.pad(CommitFormatter.fromTemplate(format, commit, dateFormatOrFormatOptions), 1, 1); - if (compact) { - content = GlyphChars.Space.repeat(content.length); - } + static gutter(commit: GitCommit, format: string, dateFormatOrFormatOptions: string | null | ICommitFormatOptions, renderOptions: IRenderOptions): DecorationOptions { + const content = Strings.pad(CommitFormatter.fromTemplate(format, commit, dateFormatOrFormatOptions), 1, 1); return { renderOptions: { diff --git a/src/annotations/gutterBlameAnnotationProvider.ts b/src/annotations/gutterBlameAnnotationProvider.ts index dc2e2a3..c311f09 100644 --- a/src/annotations/gutterBlameAnnotationProvider.ts +++ b/src/annotations/gutterBlameAnnotationProvider.ts @@ -2,9 +2,10 @@ import { Strings } from '../system'; import { DecorationOptions, Range } from 'vscode'; import { FileAnnotationType } from './annotationController'; -import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; import { Annotations, endOfLineIndex } from './annotations'; -import { ICommitFormatOptions } from '../gitService'; +import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; +import { GlyphChars } from '../constants'; +import { GitBlameCommit, ICommitFormatOptions } from '../gitService'; import * as moment from 'moment'; export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { @@ -15,6 +16,8 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { const blame = await this.getBlame(true); if (blame === undefined) return false; + // console.time('Computing blame annotations...'); + const cfg = this._config.annotations.file.gutter; // Precalculate the formatting options so we don't need to do it on each iteration @@ -31,37 +34,73 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { const now = moment(); const offset = this.uri.offset; - let previousLine: string | undefined = undefined; const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap); const dateFormat = this._config.defaultDateFormat; const decorations: DecorationOptions[] = []; + const document = this.document; + + let commit: GitBlameCommit | undefined; + let compacted = false; + let details: DecorationOptions | undefined; + let gutter: DecorationOptions | undefined; + let previousSha: string | undefined; for (const l of blame.lines) { - const commit = blame.commits.get(l.sha); + commit = blame.commits.get(l.sha); if (commit === undefined) continue; const line = l.line + offset; - const gutter = Annotations.gutter(commit, cfg.format, options, renderOptions, cfg.compact && previousLine === l.sha); + if (previousSha === l.sha) { + // Use a shallow copy of the previous decoration options + gutter = { ...gutter } as DecorationOptions; + if (cfg.compact && !compacted) { + // Since we are wiping out the contextText make sure to copy the objects + gutter.renderOptions = { ...gutter.renderOptions }; + gutter.renderOptions.before = { ...gutter.renderOptions.before, ...{ contentText: GlyphChars.Space.repeat(gutter.renderOptions!.before!.contentText!.length) } }; // !.before!.contentText = GlyphChars.Space.repeat(gutter.renderOptions!.before!.contentText!.length); + compacted = true; + } + // const firstNonWhitespace = document.lineAt(line).firstNonWhitespaceCharacterIndex; + gutter.range = new Range(line, 0, line, 0); // document.validateRange(new Range(line, 0, line, firstNonWhitespace)); + decorations.push(gutter); + + if (details !== undefined) { + details = { ...details } as DecorationOptions; + details.range = cfg.hover.wholeLine + ? document.validateRange(new Range(line, 0, line, endOfLineIndex)) + : gutter.range; + decorations.push(details); + } + + continue; + } + + compacted = false; + gutter = Annotations.gutter(commit, cfg.format, options, renderOptions); + + // TODO: Remove this "if" once vscode 1.15 ships - since empty lines won't be "missing" anymore -- Woo! if (cfg.compact) { - const isEmptyOrWhitespace = this.document.lineAt(line).isEmptyOrWhitespace; - previousLine = isEmptyOrWhitespace ? undefined : l.sha; + const isEmptyOrWhitespace = document.lineAt(line).isEmptyOrWhitespace; + previousSha = isEmptyOrWhitespace ? undefined : l.sha; + } + else { + previousSha = l.sha; } if (cfg.heatmap.enabled) { Annotations.applyHeatmap(gutter, commit.date, now); } - const firstNonWhitespace = this.editor.document.lineAt(line).firstNonWhitespaceCharacterIndex; - gutter.range = this.editor.document.validateRange(new Range(line, 0, line, firstNonWhitespace)); + // const firstNonWhitespace = document.lineAt(line).firstNonWhitespaceCharacterIndex; + gutter.range = new Range(line, 0, line, 0); // document.validateRange(new Range(line, 0, line, firstNonWhitespace)); decorations.push(gutter); if (cfg.hover.details) { - const details = Annotations.detailsHover(commit, dateFormat); + details = Annotations.detailsHover(commit, dateFormat); details.range = cfg.hover.wholeLine - ? this.editor.document.validateRange(new Range(line, 0, line, endOfLineIndex)) + ? document.validateRange(new Range(line, 0, line, endOfLineIndex)) : gutter.range; decorations.push(details); } @@ -71,6 +110,8 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { this.editor.setDecorations(this.decoration!, decorations); } + // console.timeEnd('Computing blame annotations...'); + this.selection(shaOrLine, blame); return true; } diff --git a/src/annotations/hoverBlameAnnotationProvider.ts b/src/annotations/hoverBlameAnnotationProvider.ts index d879961..ace42fc 100644 --- a/src/annotations/hoverBlameAnnotationProvider.ts +++ b/src/annotations/hoverBlameAnnotationProvider.ts @@ -1,8 +1,9 @@ 'use strict'; import { DecorationOptions, Range } from 'vscode'; import { FileAnnotationType } from './annotationController'; -import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; import { Annotations, endOfLineIndex } from './annotations'; +import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; +import { GitBlameCommit } from '../gitService'; import * as moment from 'moment'; export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase { @@ -13,6 +14,8 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase { const blame = await this.getBlame(this._config.annotations.file.hover.heatmap.enabled); if (blame === undefined) return false; + // console.time('Computing blame annotations...'); + const cfg = this._config.annotations.file.hover; const now = moment(); @@ -22,13 +25,16 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase { const decorations: DecorationOptions[] = []; + let commit: GitBlameCommit | undefined; + let hover: DecorationOptions | undefined; + for (const l of blame.lines) { - const commit = blame.commits.get(l.sha); + commit = blame.commits.get(l.sha); if (commit === undefined) continue; const line = l.line + offset; - const hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled, dateFormat); + hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled, dateFormat); const endIndex = cfg.wholeLine ? endOfLineIndex : this.editor.document.lineAt(line).firstNonWhitespaceCharacterIndex; hover.range = this.editor.document.validateRange(new Range(line, 0, line, endIndex)); @@ -44,6 +50,8 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase { this.editor.setDecorations(this.decoration!, decorations); } + // console.timeEnd('Computing blame annotations...'); + this.selection(shaOrLine, blame); return true; }