Browse Source

Closes #116 - adds full commit msg to annotations

Switches to use HoverProvider for hovers in file blames
main
Eric Amodio 7 years ago
parent
commit
2809991096
11 changed files with 139 additions and 210 deletions
  1. +5
    -1
      CHANGELOG.md
  2. +0
    -1
      README.md
  3. +0
    -5
      package.json
  4. +2
    -2
      src/annotations/annotationController.ts
  5. +5
    -4
      src/annotations/annotations.ts
  6. +42
    -5
      src/annotations/blameAnnotationProvider.ts
  7. +27
    -54
      src/annotations/gutterBlameAnnotationProvider.ts
  8. +34
    -54
      src/annotations/hoverBlameAnnotationProvider.ts
  9. +1
    -6
      src/annotations/recentChangesAnnotationProvider.ts
  10. +0
    -1
      src/configuration.ts
  11. +23
    -77
      src/currentLineController.ts

+ 5
- 1
CHANGELOG.md View File

@ -6,12 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [5.0.1] - 2017-09-14 ## [5.0.1] - 2017-09-14
### Added ### 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 ### Changed
- Optimizes performance of the providing blame annotations, especially for large files (saw a ~61% improvement on some files) - 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 - 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 ### Fixed
## [5.0.0] - 2017-09-12 ## [5.0.0] - 2017-09-12

+ 0
- 1
README.md View File

@ -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<br />`gutter` - adds a gutter glyph<br />`line` - adds a full-line highlight background color<br />`overviewRuler` - adds a decoration to the overviewRuler (scroll bar) |`gitlens.recentChanges.file.lineHighlight.locations`|Specifies where the highlights of the recently changed lines will be shown<br />`gutter` - adds a gutter glyph<br />`line` - adds a full-line highlight background color<br />`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.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.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 ### Code Lens Settings

+ 0
- 5
package.json View File

@ -132,11 +132,6 @@
"default": true, "default": true,
"description": "Specifies whether or not to provide a changes (diff) hover annotation" "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": { "gitlens.annotations.line.hover.details": {
"type": "boolean", "type": "boolean",
"default": true, "default": true,

+ 2
- 2
src/annotations/annotationController.ts View File

@ -222,7 +222,7 @@ export class AnnotationController extends Disposable {
} }
getProvider(editor: TextEditor | undefined): AnnotationProviderBase | undefined { 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); 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; if (!editor || !editor.document || !this.git.isEditorBlameable(editor)) return false;
const currentProvider = this._annotationProviders.get(editor.viewColumn || -1); 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); await currentProvider.selection(shaOrLine);
return true; return true;
} }

+ 5
- 4
src/annotations/annotations.ts View File

@ -187,11 +187,12 @@ export class Annotations {
} as IRenderOptions; } 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; } as DecorationOptions;
this.applyHeatmap(decoration, commit.date, now);
return decoration;
} }
static hoverRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig): IRenderOptions { static hoverRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig): IRenderOptions {

+ 42
- 5
src/annotations/blameAnnotationProvider.ts View File

@ -1,13 +1,15 @@
'use strict'; 'use strict';
import { Iterables } from '../system'; 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 { 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'; import { WhitespaceController } from './whitespaceController';
export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase {
export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase implements HoverProvider {
protected _blame: Promise<GitBlame | undefined>; protected _blame: Promise<GitBlame | undefined>;
protected _hoverProviderDisposable: Disposable;
constructor(context: ExtensionContext, editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, whitespaceController: WhitespaceController | undefined, protected git: GitService, protected uri: GitUri) { 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); super(context, editor, decoration, highlightDecoration, whitespaceController);
@ -15,6 +17,11 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
this._blame = this.git.getBlameForFile(this.uri); this._blame = this.git.getBlameForFile(this.uri);
} }
async clear() {
this._hoverProviderDisposable && this._hoverProviderDisposable.dispose();
super.clear();
}
async selection(shaOrLine?: string | number, blame?: GitBlame) { async selection(shaOrLine?: string | number, blame?: GitBlame) {
if (!this.highlightDecoration) return; if (!this.highlightDecoration) return;
@ -56,6 +63,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase
const blame = await this._blame; const blame = await this._blame;
return blame !== undefined && blame.lines.length !== 0; return blame !== undefined && blame.lines.length !== 0;
} }
protected async getBlame(requiresWhitespaceHack: boolean): Promise<GitBlame | undefined> { protected async getBlame(requiresWhitespaceHack: boolean): Promise<GitBlame | undefined> {
let whitespacePromise: Promise<void> | undefined; let whitespacePromise: Promise<void> | undefined;
// HACK: Until https://github.com/Microsoft/vscode/issues/11485 is fixed -- override whitespace (turn off) // 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; let blame: GitBlame | undefined;
if (whitespacePromise) {
if (whitespacePromise !== undefined) {
[blame] = await Promise.all([this._blame, whitespacePromise]); [blame] = await Promise.all([this._blame, whitespacePromise]);
} }
else { else {
blame = await this._blame; blame = await this._blame;
} }
if (blame === undefined || !blame.lines.length) {
if (blame === undefined || blame.lines.length === 0) {
this.whitespaceController && await this.whitespaceController.restore(); this.whitespaceController && await this.whitespaceController.restore();
return undefined; return undefined;
} }
return blame; return blame;
} }
registerHoverProvider() {
this._hoverProviderDisposable = languages.registerHoverProvider({ pattern: this.uri.fsPath }, this);
}
async provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise<Hover | undefined> {
// 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)));
}
} }

+ 27
- 54
src/annotations/gutterBlameAnnotationProvider.ts View File

@ -2,7 +2,7 @@
import { Strings } from '../system'; import { Strings } from '../system';
import { DecorationOptions, Range } from 'vscode'; import { DecorationOptions, Range } from 'vscode';
import { FileAnnotationType } from './annotationController'; import { FileAnnotationType } from './annotationController';
import { Annotations, endOfLineIndex } from './annotations';
import { Annotations } from './annotations';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { GlyphChars } from '../constants'; import { GlyphChars } from '../constants';
import { GitBlameCommit, ICommitFormatOptions } from '../gitService'; import { GitBlameCommit, ICommitFormatOptions } from '../gitService';
@ -35,18 +35,14 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
const now = Date.now(); const now = Date.now();
const offset = this.uri.offset; const offset = this.uri.offset;
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap); const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap);
const dateFormat = this._config.defaultDateFormat;
const separateLines = this._config.theme.annotations.file.gutter.separateLines; const separateLines = this._config.theme.annotations.file.gutter.separateLines;
const decorations: DecorationOptions[] = []; 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 commit: GitBlameCommit | undefined;
let compacted = false; let compacted = false;
let details: DecorationOptions | undefined;
let gutter: DecorationOptions | undefined; let gutter: DecorationOptions | undefined;
let hasRemotes: boolean | undefined;
let previousSha: string | undefined; let previousSha: string | undefined;
for (const l of blame.lines) { for (const l of blame.lines) {
@ -55,38 +51,35 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
if (previousSha === l.sha) { if (previousSha === l.sha) {
// Use a shallow copy of the previous decoration options // Use a shallow copy of the previous decoration options
gutter = { ...gutter } as DecorationOptions; gutter = { ...gutter } as DecorationOptions;
if (cfg.compact && !compacted) { if (cfg.compact && !compacted) {
// Since we are wiping out the contextText make sure to copy the objects // 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) { 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; 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); 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; continue;
} }
@ -94,24 +87,14 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
previousSha = l.sha; previousSha = l.sha;
gutter = decorationsMap[l.sha]; gutter = decorationsMap[l.sha];
if (gutter !== undefined) { 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); 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; continue;
} }
@ -124,24 +107,10 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
Annotations.applyHeatmap(gutter, commit.date, now); 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); decorations.push(gutter);
decorationsMap[l.sha] = 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) { if (decorations.length) {
@ -151,6 +120,10 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
const duration = process.hrtime(start); const duration = process.hrtime(start);
Logger.log(`${(duration[0] * 1000) + Math.floor(duration[1] / 1000000)} ms to compute gutter blame annotations`); 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); this.selection(shaOrLine, blame);
return true; return true;
} }

+ 34
- 54
src/annotations/hoverBlameAnnotationProvider.ts View File

@ -1,7 +1,7 @@
'use strict'; 'use strict';
import { DecorationOptions, Range } from 'vscode'; import { DecorationOptions, Range } from 'vscode';
import { FileAnnotationType } from './annotationController'; import { FileAnnotationType } from './annotationController';
import { Annotations, endOfLineIndex } from './annotations';
import { Annotations } from './annotations';
import { BlameAnnotationProviderBase } from './blameAnnotationProvider'; import { BlameAnnotationProviderBase } from './blameAnnotationProvider';
import { GitBlameCommit } from '../gitService'; import { GitBlameCommit } from '../gitService';
import { Logger } from '../logger'; import { Logger } from '../logger';
@ -11,80 +11,60 @@ export class HoverBlameAnnotationProvider extends BlameAnnotationProviderBase {
async provideAnnotation(shaOrLine?: string | number): Promise<boolean> { async provideAnnotation(shaOrLine?: string | number): Promise<boolean> {
this.annotationType = FileAnnotationType.Hover; 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; 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); this.selection(shaOrLine, blame);
return true; return true;
} }

+ 1
- 6
src/annotations/recentChangesAnnotationProvider.ts View File

@ -37,12 +37,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase {
if (line.state === 'unchanged') continue; 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) { if (cfg.hover.details) {
decorators.push({ decorators.push({

+ 0
- 1
src/configuration.ts View File

@ -251,7 +251,6 @@ export interface IConfig {
hover: { hover: {
details: boolean; details: boolean;
changes: boolean; changes: boolean;
wholeLine: boolean;
}; };
}; };
}; };

+ 23
- 77
src/currentLineController.ts View File

@ -295,12 +295,10 @@ export class CurrentLineController extends Disposable {
const decorationOptions: DecorationOptions[] = []; const decorationOptions: DecorationOptions[] = [];
let showChanges = false; let showChanges = false;
let showChangesStartIndex = 0;
let showChangesInStartingWhitespace = false;
let showDetails = false; let showDetails = false;
let showDetailsStartIndex = 0;
let showDetailsInStartingWhitespace = false;
let showAtStart = false;
let showStartIndex = 0;
switch (state.annotationType) { switch (state.annotationType) {
case LineAnnotationType.Trailing: { case LineAnnotationType.Trailing: {
@ -308,21 +306,7 @@ export class CurrentLineController extends Disposable {
showChanges = cfgAnnotations.hover.changes; showChanges = cfgAnnotations.hover.changes;
showDetails = cfgAnnotations.hover.details; 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); 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)); 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; const cfgAnnotations = this._config.annotations.line.hover;
showChanges = cfgAnnotations.changes; showChanges = cfgAnnotations.changes;
showChangesStartIndex = 0;
showChangesInStartingWhitespace = false;
showDetails = cfgAnnotations.details; showDetails = cfgAnnotations.details;
showDetailsStartIndex = 0;
showDetailsInStartingWhitespace = false;
showStartIndex = 0;
break; break;
} }
@ -348,25 +328,15 @@ export class CurrentLineController extends Disposable {
if (showDetails || showChanges) { if (showDetails || showChanges) {
const annotationType = this.annotationController.getAnnotationType(editor); const annotationType = this.annotationController.getAnnotationType(editor);
const firstNonWhitespace = editor.document.lineAt(line).firstNonWhitespaceCharacterIndex;
switch (annotationType) { switch (annotationType) {
case FileAnnotationType.Gutter: { case FileAnnotationType.Gutter: {
const cfgHover = this._config.annotations.file.gutter.hover; const cfgHover = this._config.annotations.file.gutter.hover;
if (cfgHover.details) { if (cfgHover.details) {
showDetailsInStartingWhitespace = false;
if (cfgHover.wholeLine) { 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: { case FileAnnotationType.Hover: {
const cfgHover = this._config.annotations.file.hover; const cfgHover = this._config.annotations.file.hover;
showDetailsInStartingWhitespace = false;
if (cfgHover.wholeLine) { 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; break;
@ -395,29 +356,21 @@ export class CurrentLineController extends Disposable {
case FileAnnotationType.RecentChanges: { case FileAnnotationType.RecentChanges: {
const cfgChanges = this._config.annotations.file.recentChanges.hover; const cfgChanges = this._config.annotations.file.recentChanges.hover;
if (cfgChanges.details) { 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.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; break;
} }
} }
const range = editor.document.validateRange(new Range(line, showStartIndex, line, endOfLineIndex));
if (showDetails) { if (showDetails) {
// Get the full commit message -- since blame only returns the summary // Get the full commit message -- since blame only returns the summary
let logCommit: GitCommit | undefined = undefined; 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); 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)); 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); 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) { if (showChanges) {
const decoration = await Annotations.changesHover(commit, line, this._uri, this.git); 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); 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));
} }
} }
} }

Loading…
Cancel
Save