diff --git a/CHANGELOG.md b/CHANGELOG.md index ae4df5e..4bf1a44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [5.0.1] - 2017-09-14 ### Added -- Adds an external link icon to the `details` hover annotation to run the `Open Commit in Remote` command (`gitlens.openCommitInRemote`) +- Adds an external link icon to the `details` hover annotations to run the `Open Commit in Remote` command (`gitlens.openCommitInRemote`) +- Adds full (multi-line) commit message to the `details` hover annotations ### Changed - Optimizes performance of the providing blame annotations, especially for large files (saw a ~61% improvement on some files) - Optimizes date handling (parsing and formatting) for better performance and reduced memory consumption +### Removed +- Removes `gitlens.annotations.file.recentChanges.hover.wholeLine` setting as it didn't really make sense + ### Fixed ## [5.0.0] - 2017-09-12 diff --git a/README.md b/README.md index d727828..6cf0e98 100644 --- a/README.md +++ b/README.md @@ -332,7 +332,6 @@ GitLens is highly customizable and provides many configuration settings to allow |`gitlens.recentChanges.file.lineHighlight.locations`|Specifies where the highlights of the recently changed lines will be shown
`gutter` - adds a gutter glyph
`line` - adds a full-line highlight background color
`overviewRuler` - adds a decoration to the overviewRuler (scroll bar) |`gitlens.annotations.file.recentChanges.hover.details`|Specifies whether or not to provide a commit details hover annotation |`gitlens.annotations.file.recentChanges.hover.changes`|Specifies whether or not to provide a changes (diff) hover annotation -|`gitlens.annotations.file.recentChanges.hover.wholeLine`|Specifies whether or not to trigger hover annotations over the whole line ### Code Lens Settings diff --git a/package.json b/package.json index 2fc0d7a..eb74757 100644 --- a/package.json +++ b/package.json @@ -132,11 +132,6 @@ "default": true, "description": "Specifies whether or not to provide a changes (diff) hover annotation" }, - "gitlens.annotations.file.recentChanges.hover.wholeLine": { - "type": "boolean", - "default": true, - "description": "Specifies whether or not to trigger hover annotations over the whole line" - }, "gitlens.annotations.line.hover.details": { "type": "boolean", "default": true, diff --git a/src/annotations/annotationController.ts b/src/annotations/annotationController.ts index 885a94d..4050f87 100644 --- a/src/annotations/annotationController.ts +++ b/src/annotations/annotationController.ts @@ -222,7 +222,7 @@ export class AnnotationController extends Disposable { } getProvider(editor: TextEditor | undefined): AnnotationProviderBase | undefined { - if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return undefined; + if (editor === undefined || editor.document === undefined || !this.git.isEditorBlameable(editor)) return undefined; return this._annotationProviders.get(editor.viewColumn || -1); } @@ -233,7 +233,7 @@ export class AnnotationController extends Disposable { if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false; const currentProvider = this._annotationProviders.get(editor.viewColumn || -1); - if (currentProvider && TextEditorComparer.equals(currentProvider.editor, editor)) { + if (currentProvider !== undefined && TextEditorComparer.equals(currentProvider.editor, editor)) { await currentProvider.selection(shaOrLine); return true; } diff --git a/src/annotations/annotations.ts b/src/annotations/annotations.ts index 68a59ac..455080f 100644 --- a/src/annotations/annotations.ts +++ b/src/annotations/annotations.ts @@ -187,11 +187,12 @@ export class Annotations { } as IRenderOptions; } - static hover(commit: GitCommit, renderOptions: IRenderOptions, heatmap: boolean, dateFormat: string | null, hasRemotes: boolean): DecorationOptions { - return { - hoverMessage: this.getHoverMessage(commit, dateFormat, hasRemotes), - renderOptions: heatmap ? { before: { ...renderOptions.before } } : undefined + static hover(commit: GitCommit, renderOptions: IRenderOptions, now: number): DecorationOptions { + const decoration = { + renderOptions: { before: { ...renderOptions.before } } } as DecorationOptions; + this.applyHeatmap(decoration, commit.date, now); + return decoration; } static hoverRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig): IRenderOptions { diff --git a/src/annotations/blameAnnotationProvider.ts b/src/annotations/blameAnnotationProvider.ts index 49116bc..434f743 100644 --- a/src/annotations/blameAnnotationProvider.ts +++ b/src/annotations/blameAnnotationProvider.ts @@ -1,13 +1,15 @@ 'use strict'; import { Iterables } from '../system'; -import { ExtensionContext, Range, TextEditor, TextEditorDecorationType } from 'vscode'; +import { CancellationToken, Disposable, ExtensionContext, Hover, HoverProvider, languages, Position, Range, TextDocument, TextEditor, TextEditorDecorationType } from 'vscode'; import { AnnotationProviderBase } from './annotationProvider'; -import { GitBlame, GitService, GitUri } from '../gitService'; +import { Annotations, endOfLineIndex } from './annotations'; +import { GitBlame, GitCommit, GitService, GitUri } from '../gitService'; import { WhitespaceController } from './whitespaceController'; -export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase { +export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase implements HoverProvider { protected _blame: Promise; + protected _hoverProviderDisposable: Disposable; constructor(context: ExtensionContext, editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, whitespaceController: WhitespaceController | undefined, protected git: GitService, protected uri: GitUri) { super(context, editor, decoration, highlightDecoration, whitespaceController); @@ -15,6 +17,11 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase this._blame = this.git.getBlameForFile(this.uri); } + async clear() { + this._hoverProviderDisposable && this._hoverProviderDisposable.dispose(); + super.clear(); + } + async selection(shaOrLine?: string | number, blame?: GitBlame) { if (!this.highlightDecoration) return; @@ -56,6 +63,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase const blame = await this._blame; return blame !== undefined && blame.lines.length !== 0; } + protected async getBlame(requiresWhitespaceHack: boolean): Promise { let whitespacePromise: Promise | undefined; // HACK: Until https://github.com/Microsoft/vscode/issues/11485 is fixed -- override whitespace (turn off) @@ -64,18 +72,47 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase } let blame: GitBlame | undefined; - if (whitespacePromise) { + if (whitespacePromise !== undefined) { [blame] = await Promise.all([this._blame, whitespacePromise]); } else { blame = await this._blame; } - if (blame === undefined || !blame.lines.length) { + if (blame === undefined || blame.lines.length === 0) { this.whitespaceController && await this.whitespaceController.restore(); return undefined; } return blame; } + + registerHoverProvider() { + this._hoverProviderDisposable = languages.registerHoverProvider({ pattern: this.uri.fsPath }, this); + } + + async provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise { + // Avoid double annotations if we are showing the whole-file hover blame annotations + if (this._config.blame.line.enabled && this.editor.selection.start.line === position.line) return undefined; + + const cfg = this._config.annotations.file.gutter; + if (!cfg.hover.wholeLine && position.character !== 0) return undefined; + + const blame = await this.getBlame(true); + if (blame === undefined) return undefined; + + const line = blame.lines[position.line - this.uri.offset]; + + const commit = blame.commits.get(line.sha); + if (commit === undefined) return undefined; + + // Get the full commit message -- since blame only returns the summary + let logCommit: GitCommit | undefined = undefined; + if (!commit.isUncommitted) { + logCommit = await this.git.getLogCommit(commit.repoPath, commit.uri.fsPath, commit.sha); + } + + const message = Annotations.getHoverMessage(logCommit || commit, this._config.defaultDateFormat, this.git.hasRemotes(commit.repoPath)); + return new Hover(message, document.validateRange(new Range(position.line, 0, position.line, endOfLineIndex))); + } } \ No newline at end of file diff --git a/src/annotations/gutterBlameAnnotationProvider.ts b/src/annotations/gutterBlameAnnotationProvider.ts index f0b9e7a..0625548 100644 --- a/src/annotations/gutterBlameAnnotationProvider.ts +++ b/src/annotations/gutterBlameAnnotationProvider.ts @@ -2,7 +2,7 @@ import { Strings } from '../system'; import { DecorationOptions, Range } from 'vscode'; import { FileAnnotationType } from './annotationController'; -import { Annotations, endOfLineIndex } from './annotations'; +import { Annotations } from './annotations'; import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; import { GlyphChars } from '../constants'; import { GitBlameCommit, ICommitFormatOptions } from '../gitService'; @@ -35,18 +35,14 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { const now = Date.now(); const offset = this.uri.offset; const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap); - const dateFormat = this._config.defaultDateFormat; const separateLines = this._config.theme.annotations.file.gutter.separateLines; const decorations: DecorationOptions[] = []; - const decorationsMap: { [sha: string]: DecorationOptions } = Object.create(null); - const document = this.document; + const decorationsMap: { [sha: string]: DecorationOptions | undefined } = Object.create(null); let commit: GitBlameCommit | undefined; let compacted = false; - let details: DecorationOptions | undefined; let gutter: DecorationOptions | undefined; - let hasRemotes: boolean | undefined; let previousSha: string | undefined; for (const l of blame.lines) { @@ -55,38 +51,35 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { 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(Strings.getWidth(gutter.renderOptions!.before!.contentText!)) } + gutter.renderOptions = { + ...gutter.renderOptions, + before: { + ...gutter.renderOptions!.before, + contentText: GlyphChars.Space.repeat(Strings.getWidth(gutter.renderOptions!.before!.contentText!)) + } }; if (separateLines) { - gutter.renderOptions.dark = { ...gutter.renderOptions.dark }; - gutter.renderOptions.dark.before = { ...gutter.renderOptions.dark.before, ...{ textDecoration: 'none' } }; - gutter.renderOptions.light = { ...gutter.renderOptions.light }; - gutter.renderOptions.light.before = { ...gutter.renderOptions.light.before, ...{ textDecoration: 'none' } }; + gutter.renderOptions.dark = { + ...gutter.renderOptions.dark, + before: { ...gutter.renderOptions.dark!.before, textDecoration: 'none' } + }; + gutter.renderOptions.light = { + ...gutter.renderOptions.light, + before: { ...gutter.renderOptions.light!.before, textDecoration: 'none' } + }; } compacted = true; } - const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex; - gutter.range = new Range(line, 0, line, endIndex); + gutter.range = new Range(line, 0, line, 0); 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; } @@ -94,24 +87,14 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { previousSha = l.sha; gutter = decorationsMap[l.sha]; - if (gutter !== undefined) { - gutter = { ...gutter } as DecorationOptions; - - const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex; - gutter.range = new Range(line, 0, line, endIndex); + gutter = { + ...gutter, + range: new Range(line, 0, line, 0) + } as DecorationOptions; 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; } @@ -124,24 +107,10 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { Annotations.applyHeatmap(gutter, commit.date, now); } - const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex; - gutter.range = new Range(line, 0, line, endIndex); + gutter.range = new Range(line, 0, line, 0); decorations.push(gutter); decorationsMap[l.sha] = gutter; - - if (cfg.hover.details) { - if (hasRemotes === undefined) { - hasRemotes = this.git.hasRemotes(commit.repoPath); - } - - details = Annotations.detailsHover(commit, dateFormat, hasRemotes); - details.range = cfg.hover.wholeLine - ? document.validateRange(new Range(line, 0, line, endOfLineIndex)) - : gutter.range; - - decorations.push(details); - } } if (decorations.length) { @@ -151,6 +120,10 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase { const duration = process.hrtime(start); Logger.log(`${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms to compute gutter blame annotations`); + if (cfg.hover.details) { + this.registerHoverProvider(); + } + this.selection(shaOrLine, blame); return true; } diff --git a/src/annotations/hoverBlameAnnotationProvider.ts b/src/annotations/hoverBlameAnnotationProvider.ts index 3befb97..0714c77 100644 --- a/src/annotations/hoverBlameAnnotationProvider.ts +++ b/src/annotations/hoverBlameAnnotationProvider.ts @@ -1,7 +1,7 @@ 'use strict'; import { DecorationOptions, Range } from 'vscode'; import { FileAnnotationType } from './annotationController'; -import { Annotations, endOfLineIndex } from './annotations'; +import { Annotations } from './annotations'; import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; import { GitBlameCommit } from '../gitService'; import { Logger } from '../logger'; @@ -11,80 +11,60 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase { async provideAnnotation(shaOrLine?: string | number): Promise { this.annotationType = FileAnnotationType.Hover; - const blame = await this.getBlame(this._config.annotations.file.hover.heatmap.enabled); + const cfg = this._config.annotations.file.hover; + + const blame = await this.getBlame(cfg.heatmap.enabled); if (blame === undefined) return false; - const start = process.hrtime(); + if (cfg.heatmap.enabled) { + const start = process.hrtime(); - const cfg = this._config.annotations.file.hover; + const now = Date.now(); + const offset = this.uri.offset; + const renderOptions = Annotations.hoverRenderOptions(this._config.theme, cfg.heatmap); - const now = Date.now(); - const offset = this.uri.offset; - const renderOptions = Annotations.hoverRenderOptions(this._config.theme, cfg.heatmap); - const dateFormat = this._config.defaultDateFormat; + const decorations: DecorationOptions[] = []; + const decorationsMap: { [sha: string]: DecorationOptions } = Object.create(null); - const decorations: DecorationOptions[] = []; - const decorationsMap: { [sha: string]: DecorationOptions } = Object.create(null); - const document = this.document; + let commit: GitBlameCommit | undefined; + let hover: DecorationOptions | undefined; - let commit: GitBlameCommit | undefined; - let hasRemotes: boolean | undefined; - let hover: DecorationOptions | undefined; + for (const l of blame.lines) { + const line = l.line + offset; - for (const l of blame.lines) { - const line = l.line + offset; + hover = decorationsMap[l.sha]; - hover = decorationsMap[l.sha]; + if (hover !== undefined) { + hover = { + ...hover, + range: new Range(line, 0, line, 0) + } as DecorationOptions; - if (hover !== undefined) { - hover = { ...hover } as DecorationOptions; + decorations.push(hover); - if (cfg.wholeLine) { - hover.range = document.validateRange(new Range(line, 0, line, endOfLineIndex)); - } - else { - const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex; - hover.range = new Range(line, 0, line, endIndex); + continue; } - decorations.push(hover); - - continue; - } + commit = blame.commits.get(l.sha); + if (commit === undefined) continue; - commit = blame.commits.get(l.sha); - if (commit === undefined) continue; + hover = Annotations.hover(commit, renderOptions, now); + hover.range = new Range(line, 0, line, 0); - if (hasRemotes === undefined) { - hasRemotes = this.git.hasRemotes(commit.repoPath); - } - - hover = Annotations.hover(commit, renderOptions, cfg.heatmap.enabled, dateFormat, hasRemotes); + decorations.push(hover); + decorationsMap[l.sha] = hover; - if (cfg.wholeLine) { - hover.range = document.validateRange(new Range(line, 0, line, endOfLineIndex)); - } - else { - const endIndex = document.lineAt(line).firstNonWhitespaceCharacterIndex; - hover.range = new Range(line, 0, line, endIndex); } - if (cfg.heatmap.enabled) { - Annotations.applyHeatmap(hover, commit.date, now); + if (decorations.length) { + this.editor.setDecorations(this.decoration!, decorations); } - decorations.push(hover); - decorationsMap[l.sha] = hover; - + const duration = process.hrtime(start); + Logger.log(`${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms to compute hover blame annotations`); } - if (decorations.length) { - this.editor.setDecorations(this.decoration!, decorations); - } - - const duration = process.hrtime(start); - Logger.log(`${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms to compute hover blame annotations`); - + this.registerHoverProvider(); this.selection(shaOrLine, blame); return true; } diff --git a/src/annotations/recentChangesAnnotationProvider.ts b/src/annotations/recentChangesAnnotationProvider.ts index e73cd4c..92b50fb 100644 --- a/src/annotations/recentChangesAnnotationProvider.ts +++ b/src/annotations/recentChangesAnnotationProvider.ts @@ -37,12 +37,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase { if (line.state === 'unchanged') continue; - let endingIndex = 0; - if (cfg.hover.details || cfg.hover.changes) { - endingIndex = cfg.hover.wholeLine ? endOfLineIndex : this.editor.document.lineAt(count).firstNonWhitespaceCharacterIndex; - } - - const range = this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, endingIndex))); + const range = this.editor.document.validateRange(new Range(new Position(count, 0), new Position(count, endOfLineIndex))); if (cfg.hover.details) { decorators.push({ diff --git a/src/configuration.ts b/src/configuration.ts index 830ab51..b435cff 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -251,7 +251,6 @@ export interface IConfig { hover: { details: boolean; changes: boolean; - wholeLine: boolean; }; }; }; diff --git a/src/currentLineController.ts b/src/currentLineController.ts index 9b5db7a..8c21ecc 100644 --- a/src/currentLineController.ts +++ b/src/currentLineController.ts @@ -295,12 +295,10 @@ export class CurrentLineController extends Disposable { const decorationOptions: DecorationOptions[] = []; let showChanges = false; - let showChangesStartIndex = 0; - let showChangesInStartingWhitespace = false; - let showDetails = false; - let showDetailsStartIndex = 0; - let showDetailsInStartingWhitespace = false; + + let showAtStart = false; + let showStartIndex = 0; switch (state.annotationType) { case LineAnnotationType.Trailing: { @@ -308,21 +306,7 @@ export class CurrentLineController extends Disposable { showChanges = cfgAnnotations.hover.changes; showDetails = cfgAnnotations.hover.details; - - if (cfgAnnotations.hover.wholeLine) { - showChangesStartIndex = 0; - showChangesInStartingWhitespace = false; - - showDetailsStartIndex = 0; - showDetailsInStartingWhitespace = false; - } - else { - showChangesStartIndex = endOfLineIndex; - showChangesInStartingWhitespace = true; - - showDetailsStartIndex = endOfLineIndex; - showDetailsInStartingWhitespace = true; - } + showStartIndex = cfgAnnotations.hover.wholeLine ? 0 : endOfLineIndex; const decoration = Annotations.trailing(commit, cfgAnnotations.format, cfgAnnotations.dateFormat === null ? this._config.defaultDateFormat : cfgAnnotations.dateFormat, this._config.theme); decoration.range = editor.document.validateRange(new Range(line, endOfLineIndex, line, endOfLineIndex)); @@ -334,12 +318,8 @@ export class CurrentLineController extends Disposable { const cfgAnnotations = this._config.annotations.line.hover; showChanges = cfgAnnotations.changes; - showChangesStartIndex = 0; - showChangesInStartingWhitespace = false; - showDetails = cfgAnnotations.details; - showDetailsStartIndex = 0; - showDetailsInStartingWhitespace = false; + showStartIndex = 0; break; } @@ -348,25 +328,15 @@ export class CurrentLineController extends Disposable { if (showDetails || showChanges) { const annotationType = this.annotationController.getAnnotationType(editor); - const firstNonWhitespace = editor.document.lineAt(line).firstNonWhitespaceCharacterIndex; - switch (annotationType) { case FileAnnotationType.Gutter: { const cfgHover = this._config.annotations.file.gutter.hover; if (cfgHover.details) { - showDetailsInStartingWhitespace = false; if (cfgHover.wholeLine) { - // Avoid double annotations if we are showing the whole-file hover blame annotations - showDetails = false; + showStartIndex = 0; } - else { - if (showDetailsStartIndex === 0) { - showDetailsStartIndex = firstNonWhitespace === 0 ? 1 : firstNonWhitespace; - } - if (showChangesStartIndex === 0) { - showChangesInStartingWhitespace = true; - showChangesStartIndex = firstNonWhitespace === 0 ? 1 : firstNonWhitespace; - } + else if (showStartIndex !== 0) { + showAtStart = true; } } @@ -374,20 +344,11 @@ export class CurrentLineController extends Disposable { } case FileAnnotationType.Hover: { const cfgHover = this._config.annotations.file.hover; - showDetailsInStartingWhitespace = false; if (cfgHover.wholeLine) { - // Avoid double annotations if we are showing the whole-file hover blame annotations - showDetails = false; - showChangesStartIndex = 0; + showStartIndex = 0; } - else { - if (showDetailsStartIndex === 0) { - showDetailsStartIndex = firstNonWhitespace === 0 ? 1 : firstNonWhitespace; - } - if (showChangesStartIndex === 0) { - showChangesInStartingWhitespace = true; - showChangesStartIndex = firstNonWhitespace === 0 ? 1 : firstNonWhitespace; - } + else if (showStartIndex !== 0) { + showAtStart = true; } break; @@ -395,29 +356,21 @@ export class CurrentLineController extends Disposable { case FileAnnotationType.RecentChanges: { const cfgChanges = this._config.annotations.file.recentChanges.hover; if (cfgChanges.details) { - if (cfgChanges.wholeLine) { - // Avoid double annotations if we are showing the whole-file hover blame annotations - showDetails = false; - } - else { - showDetailsInStartingWhitespace = false; - } + // Avoid double annotations if we are showing the whole-file hover blame annotations + showDetails = false; } if (cfgChanges.changes) { - if (cfgChanges.wholeLine) { - // Avoid double annotations if we are showing the whole-file hover blame annotations - showChanges = false; - } - else { - showChangesInStartingWhitespace = false; - } + // Avoid double annotations if we are showing the whole-file hover blame annotations + showChanges = false; } break; } } + const range = editor.document.validateRange(new Range(line, showStartIndex, line, endOfLineIndex)); + if (showDetails) { // Get the full commit message -- since blame only returns the summary let logCommit: GitCommit | undefined = undefined; @@ -425,29 +378,22 @@ export class CurrentLineController extends Disposable { logCommit = await this.git.getLogCommit(this._uri.repoPath, this._uri.fsPath, commit.sha); } - // I have no idea why I need this protection -- but it happens - if (editor.document === undefined) return; - const decoration = Annotations.detailsHover(logCommit || commit, this._config.defaultDateFormat, this.git.hasRemotes((logCommit || commit).repoPath)); - decoration.range = editor.document.validateRange(new Range(line, showDetailsStartIndex, line, endOfLineIndex)); + decoration.range = range; decorationOptions.push(decoration); - if (showDetailsInStartingWhitespace && showDetailsStartIndex !== 0 && decoration.range.end.character !== 0) { - decorationOptions.push(Annotations.withRange(decoration, 0, firstNonWhitespace)); + if (showAtStart) { + decorationOptions.push(Annotations.withRange(decoration, 0, 0)); } } if (showChanges) { const decoration = await Annotations.changesHover(commit, line, this._uri, this.git); - - // I have no idea why I need this protection -- but it happens - if (editor.document === undefined) return; - - decoration.range = editor.document.validateRange(new Range(line, showChangesStartIndex, line, endOfLineIndex)); + decoration.range = range; decorationOptions.push(decoration); - if (showChangesInStartingWhitespace && showChangesStartIndex !== 0 && decoration.range.end.character !== 0) { - decorationOptions.push(Annotations.withRange(decoration, 0, firstNonWhitespace)); + if (showAtStart) { + decorationOptions.push(Annotations.withRange(decoration, 0, 0)); } } }