From e88b960434e6a6dc76c06dd198b482d190e0e69f Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Tue, 26 Nov 2019 00:55:57 -0500 Subject: [PATCH] Splits annotations and hovers --- src/annotations/annotations.ts | 190 +-------------------- src/annotations/blameAnnotationProvider.ts | 13 +- src/annotations/recentChangesAnnotationProvider.ts | 8 +- src/hovers/hovers.ts | 183 ++++++++++++++++++++ src/hovers/lineHoverController.ts | 6 +- src/vsls/vsls.ts | 8 +- 6 files changed, 205 insertions(+), 203 deletions(-) create mode 100644 src/hovers/hovers.ts diff --git a/src/annotations/annotations.ts b/src/annotations/annotations.ts index 997691b..186ad27 100644 --- a/src/annotations/annotations.ts +++ b/src/annotations/annotations.ts @@ -2,26 +2,14 @@ import { DecorationInstanceRenderOptions, DecorationOptions, - MarkdownString, ThemableDecorationAttachmentRenderOptions, ThemableDecorationRenderOptions, ThemeColor } from 'vscode'; -import { DiffWithCommand, ShowQuickCommitDetailsCommand } from '../commands'; -import { configuration, FileAnnotationType } from '../configuration'; +import { configuration } from '../configuration'; import { GlyphChars } from '../constants'; -import { Container } from '../container'; -import { - CommitFormatOptions, - CommitFormatter, - GitBlameCommit, - GitCommit, - GitDiffHunkLine, - GitLogCommit, - GitService, - GitUri -} from '../git/gitService'; -import { debug, Objects, Strings, timeout } from '../system'; +import { CommitFormatOptions, CommitFormatter, GitCommit } from '../git/gitService'; +import { Objects, Strings } from '../system'; import { toRgba } from '../webviews/apps/shared/colors'; export interface ComputedHeatmap { @@ -60,162 +48,6 @@ export class Annotations { decoration.renderOptions!.before!.borderColor = color; } - static async changesHoverMessage( - commit: GitBlameCommit, - uri: GitUri, - editorLine: number - ): Promise; - static async changesHoverMessage( - commit: GitLogCommit, - uri: GitUri, - editorLine: number, - hunkLine: GitDiffHunkLine - ): Promise; - static async changesHoverMessage( - commit: GitBlameCommit | GitLogCommit, - uri: GitUri, - editorLine: number, - hunkLine?: GitDiffHunkLine - ): Promise { - const documentRef = uri.sha; - if (GitBlameCommit.is(commit)) { - // TODO: Figure out how to optimize this - let ref; - if (commit.isUncommitted) { - if (GitService.isUncommittedStaged(documentRef)) { - ref = documentRef; - } - } else { - ref = commit.sha; - } - - const line = editorLine + 1; - const commitLine = commit.lines.find(l => l.line === line) || commit.lines[0]; - - let originalFileName = commit.originalFileName; - if (originalFileName === undefined) { - if (uri.fsPath !== commit.uri.fsPath) { - originalFileName = commit.fileName; - } - } - - editorLine = commitLine.originalLine - 1; - hunkLine = await Container.git.getDiffForLine(uri, editorLine, ref, undefined, originalFileName); - - // If we didn't find a diff & ref is undefined (meaning uncommitted), check for a staged diff - if (hunkLine === undefined && ref === undefined) { - hunkLine = await Container.git.getDiffForLine( - uri, - editorLine, - undefined, - GitService.uncommittedStagedSha, - originalFileName - ); - } - } - - if (hunkLine === undefined || commit.previousSha === undefined) return undefined; - - const diff = this.getDiffFromHunkLine(hunkLine); - - let message; - let previous; - let current; - if (commit.isUncommitted) { - const diffUris = await commit.getPreviousLineDiffUris(uri, editorLine, documentRef); - if (diffUris === undefined || diffUris.previous === undefined) { - return undefined; - } - - message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs({ - lhs: { - sha: diffUris.previous.sha || '', - uri: diffUris.previous.documentUri() - }, - rhs: { - sha: diffUris.current.sha || '', - uri: diffUris.current.documentUri() - }, - repoPath: commit.repoPath, - line: editorLine - })} "Open Changes")`; - - previous = - diffUris.previous.sha === undefined || diffUris.previous.isUncommitted - ? `_${GitService.shortenSha(diffUris.previous.sha, { - strings: { - working: 'Working Tree' - } - })}_` - : `[\`${GitService.shortenSha( - diffUris.previous.sha || '' - )}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( - diffUris.previous.sha || '' - )} "Show Commit Details")`; - - current = - diffUris.current.sha === undefined || diffUris.current.isUncommitted - ? `_${GitService.shortenSha(diffUris.current.sha, { - strings: { - working: 'Working Tree' - } - })}_` - : `[\`${GitService.shortenSha( - diffUris.current.sha || '' - )}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( - diffUris.current.sha || '' - )} "Show Commit Details")`; - } else { - message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit, editorLine)} "Open Changes")`; - - previous = `[\`${commit.previousShortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( - commit.previousSha - )} "Show Commit Details")`; - - current = `[\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( - commit.sha - )} "Show Commit Details")`; - } - - message += `   ${GlyphChars.Dash}   ${previous}  ${GlyphChars.ArrowLeftRightLong}  ${current}\n${diff}`; - - const markdown = new MarkdownString(message); - markdown.isTrusted = true; - return markdown; - } - - static async detailsHoverMessage( - commit: GitCommit, - uri: GitUri, - editorLine: number, - dateFormat: string | null, - annotationType: FileAnnotationType | undefined - ): Promise { - if (dateFormat === null) { - dateFormat = 'MMMM Do, YYYY h:mma'; - } - - const [presence, previousLineDiffUris, remotes] = await Promise.all([ - Annotations.maybeGetPresence(commit.email).catch(reason => undefined), - commit.isUncommitted ? commit.getPreviousLineDiffUris(uri, editorLine, uri.sha) : undefined, - Container.git.getRemotes(commit.repoPath, { sort: true }) - ]); - - const markdown = new MarkdownString( - CommitFormatter.fromTemplate(Container.config.hovers.detailsMarkdownFormat, commit, { - annotationType: annotationType, - dateFormat: dateFormat, - line: editorLine, - markdown: true, - presence: presence, - previousLineDiffUris: previousLineDiffUris, - remotes: remotes - }) - ); - markdown.isTrusted = true; - return markdown; - } - static gutter( commit: GitCommit, format: string, @@ -359,16 +191,6 @@ export class Annotations { }; } - private static getDiffFromHunkLine(hunkLine: GitDiffHunkLine): string { - if (Container.config.hovers.changesDiff === 'hunk') { - return `\`\`\`diff\n${hunkLine.hunk.diff}\n\`\`\``; - } - - return `\`\`\`diff${hunkLine.previous === undefined ? '' : `\n-${hunkLine.previous.line}`}${ - hunkLine.current === undefined ? '' : `\n+${hunkLine.current.line}` - }\n\`\`\``; - } - private static getHeatmapColor(date: Date, heatmap: ComputedHeatmap) { const baseColor = heatmap.cold ? heatmap.colors.cold : heatmap.colors.hot; @@ -390,10 +212,4 @@ export class Annotations { return `rgba(${computedHeatmapColor.rgb}, ${(1 - age / 10).toFixed(2)})`; } - - @debug() - @timeout(250) - private static maybeGetPresence(email: string | undefined) { - return Container.vsls.getContactPresence(email); - } } diff --git a/src/annotations/blameAnnotationProvider.ts b/src/annotations/blameAnnotationProvider.ts index 2582afa..a8b1b50 100644 --- a/src/annotations/blameAnnotationProvider.ts +++ b/src/annotations/blameAnnotationProvider.ts @@ -10,12 +10,13 @@ import { TextEditor, TextEditorDecorationType } from 'vscode'; +import { AnnotationProviderBase } from './annotationProvider'; +import { ComputedHeatmap } from './annotations'; import { Container } from '../container'; import { GitBlame, GitBlameCommit, GitCommit, GitUri } from '../git/gitService'; +import { Hovers } from '../hovers/hovers'; import { Arrays, Iterables, log } from '../system'; import { GitDocumentState, TrackedDocument } from '../trackers/gitDocumentTracker'; -import { AnnotationProviderBase } from './annotationProvider'; -import { Annotations, ComputedHeatmap } from './annotations'; export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase { protected _blame: Promise; @@ -232,7 +233,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase const commitLine = commit.lines.find(l => l.line === line) || commit.lines[0]; editorLine = commitLine.originalLine - 1; - const message = await Annotations.detailsHoverMessage( + const message = await Hovers.detailsMessage( logCommit || commit, await GitUri.fromUri(document.uri), editorLine, @@ -253,11 +254,7 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase const commit = await this.getCommitForHover(position); if (commit === undefined) return undefined; - const message = await Annotations.changesHoverMessage( - commit, - await GitUri.fromUri(document.uri), - position.line - ); + const message = await Hovers.changesMessage(commit, await GitUri.fromUri(document.uri), position.line); if (message === undefined) return undefined; return new Hover( diff --git a/src/annotations/recentChangesAnnotationProvider.ts b/src/annotations/recentChangesAnnotationProvider.ts index 4dab857..8a1c272 100644 --- a/src/annotations/recentChangesAnnotationProvider.ts +++ b/src/annotations/recentChangesAnnotationProvider.ts @@ -8,14 +8,14 @@ import { TextEditorDecorationType, TextEditorRevealType } from 'vscode'; +import { AnnotationProviderBase } from './annotationProvider'; import { FileAnnotationType } from '../configuration'; import { Container } from '../container'; import { GitUri } from '../git/gitService'; +import { Hovers } from '../hovers/hovers'; import { Logger } from '../logger'; import { log, Strings } from '../system'; import { GitDocumentState, TrackedDocument } from '../trackers/gitDocumentTracker'; -import { AnnotationProviderBase } from './annotationProvider'; -import { Annotations } from './annotations'; export class RecentChangesAnnotationProvider extends AnnotationProviderBase { private readonly _uri: GitUri; @@ -90,7 +90,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase { if (cfg.hovers.enabled && cfg.hovers.annotations.enabled) { if (cfg.hovers.annotations.details) { this.decorations.push({ - hoverMessage: await Annotations.detailsHoverMessage( + hoverMessage: await Hovers.detailsMessage( commit, await GitUri.fromUri(this.editor.document.uri), count, @@ -102,7 +102,7 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase { } if (cfg.hovers.annotations.changes) { - message = await Annotations.changesHoverMessage(commit, this._uri, count, hunkLine); + message = await Hovers.changesMessage(commit, this._uri, count, hunkLine); if (message === undefined) continue; } } diff --git a/src/hovers/hovers.ts b/src/hovers/hovers.ts new file mode 100644 index 0000000..e49144f --- /dev/null +++ b/src/hovers/hovers.ts @@ -0,0 +1,183 @@ +'use strict'; +import { MarkdownString } from 'vscode'; +import { DiffWithCommand, ShowQuickCommitDetailsCommand } from '../commands'; +import { FileAnnotationType } from '../configuration'; +import { GlyphChars } from '../constants'; +import { Container } from '../container'; +import { + CommitFormatter, + GitBlameCommit, + GitCommit, + GitDiffHunkLine, + GitLogCommit, + GitService, + GitUri +} from '../git/gitService'; + +export namespace Hovers { + export async function changesMessage( + commit: GitBlameCommit, + uri: GitUri, + editorLine: number + ): Promise; + export async function changesMessage( + commit: GitLogCommit, + uri: GitUri, + editorLine: number, + hunkLine: GitDiffHunkLine + ): Promise; + export async function changesMessage( + commit: GitBlameCommit | GitLogCommit, + uri: GitUri, + editorLine: number, + hunkLine?: GitDiffHunkLine + ): Promise { + const documentRef = uri.sha; + if (GitBlameCommit.is(commit)) { + // TODO: Figure out how to optimize this + let ref; + if (commit.isUncommitted) { + if (GitService.isUncommittedStaged(documentRef)) { + ref = documentRef; + } + } else { + ref = commit.sha; + } + + const line = editorLine + 1; + const commitLine = commit.lines.find(l => l.line === line) || commit.lines[0]; + + let originalFileName = commit.originalFileName; + if (originalFileName === undefined) { + if (uri.fsPath !== commit.uri.fsPath) { + originalFileName = commit.fileName; + } + } + + editorLine = commitLine.originalLine - 1; + hunkLine = await Container.git.getDiffForLine(uri, editorLine, ref, undefined, originalFileName); + + // If we didn't find a diff & ref is undefined (meaning uncommitted), check for a staged diff + if (hunkLine === undefined && ref === undefined) { + hunkLine = await Container.git.getDiffForLine( + uri, + editorLine, + undefined, + GitService.uncommittedStagedSha, + originalFileName + ); + } + } + + if (hunkLine === undefined || commit.previousSha === undefined) return undefined; + + const diff = getDiffFromHunkLine(hunkLine); + + let message; + let previous; + let current; + if (commit.isUncommitted) { + const diffUris = await commit.getPreviousLineDiffUris(uri, editorLine, documentRef); + if (diffUris === undefined || diffUris.previous === undefined) { + return undefined; + } + + message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs({ + lhs: { + sha: diffUris.previous.sha || '', + uri: diffUris.previous.documentUri() + }, + rhs: { + sha: diffUris.current.sha || '', + uri: diffUris.current.documentUri() + }, + repoPath: commit.repoPath, + line: editorLine + })} "Open Changes")`; + + previous = + diffUris.previous.sha === undefined || diffUris.previous.isUncommitted + ? `_${GitService.shortenSha(diffUris.previous.sha, { + strings: { + working: 'Working Tree' + } + })}_` + : `[\`${GitService.shortenSha( + diffUris.previous.sha || '' + )}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( + diffUris.previous.sha || '' + )} "Show Commit Details")`; + + current = + diffUris.current.sha === undefined || diffUris.current.isUncommitted + ? `_${GitService.shortenSha(diffUris.current.sha, { + strings: { + working: 'Working Tree' + } + })}_` + : `[\`${GitService.shortenSha( + diffUris.current.sha || '' + )}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( + diffUris.current.sha || '' + )} "Show Commit Details")`; + } else { + message = `[\`Changes\`](${DiffWithCommand.getMarkdownCommandArgs(commit, editorLine)} "Open Changes")`; + + previous = `[\`${commit.previousShortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( + commit.previousSha + )} "Show Commit Details")`; + + current = `[\`${commit.shortSha}\`](${ShowQuickCommitDetailsCommand.getMarkdownCommandArgs( + commit.sha + )} "Show Commit Details")`; + } + + message += `   ${GlyphChars.Dash}   ${previous}  ${GlyphChars.ArrowLeftRightLong}  ${current}\n${diff}`; + + const markdown = new MarkdownString(message); + markdown.isTrusted = true; + return markdown; + } + + export async function detailsMessage( + commit: GitCommit, + uri: GitUri, + editorLine: number, + dateFormat: string | null, + annotationType: FileAnnotationType | undefined + ): Promise { + if (dateFormat === null) { + dateFormat = 'MMMM Do, YYYY h:mma'; + } + + const [presence, previousLineDiffUris, remotes] = await Promise.all([ + Container.vsls.maybeGetPresence(commit.email).catch(reason => undefined), + commit.isUncommitted ? commit.getPreviousLineDiffUris(uri, editorLine, uri.sha) : undefined, + Container.git.getRemotes(commit.repoPath, { sort: true }) + ]); + + const details = CommitFormatter.fromTemplate(Container.config.hovers.detailsMarkdownFormat, commit, { + annotationType: annotationType, + dateFormat: dateFormat, + line: editorLine, + markdown: true, + presence: presence, + previousLineDiffUris: previousLineDiffUris, + remotes: remotes + }); + + const markdown = new MarkdownString(details); + markdown.isTrusted = true; + return markdown; + } + + function getDiffFromHunkLine(hunkLine: GitDiffHunkLine): string { + if (Container.config.hovers.changesDiff === 'hunk') { + return `\`\`\`diff\n${hunkLine.hunk.diff}\n\`\`\``; + } + + return `\`\`\`diff${hunkLine.previous === undefined ? '' : `\n-${hunkLine.previous.line}`}${ + hunkLine.current === undefined ? '' : `\n+${hunkLine.current.line}` + }\n\`\`\``; + } +} diff --git a/src/hovers/lineHoverController.ts b/src/hovers/lineHoverController.ts index 7b3c258..c79336c 100644 --- a/src/hovers/lineHoverController.ts +++ b/src/hovers/lineHoverController.ts @@ -12,9 +12,9 @@ import { Uri, window } from 'vscode'; -import { Annotations } from '../annotations/annotations'; import { configuration } from '../configuration'; import { Container } from '../container'; +import { Hovers } from './hovers'; import { LinesChangeEvent } from '../trackers/gitLineTracker'; import { debug } from '../system'; import { UriComparer } from '../comparers'; @@ -135,7 +135,7 @@ export class LineHoverController implements Disposable { const trackedDocument = await Container.tracker.get(document); if (trackedDocument === undefined) return undefined; - const message = await Annotations.detailsHoverMessage( + const message = await Hovers.detailsMessage( logCommit || commit, trackedDocument.uri, editorLine, @@ -181,7 +181,7 @@ export class LineHoverController implements Disposable { const trackedDocument = await Container.tracker.get(document); if (trackedDocument === undefined) return undefined; - const message = await Annotations.changesHoverMessage(commit, trackedDocument.uri, position.line); + const message = await Hovers.changesMessage(commit, trackedDocument.uri, position.line); if (message === undefined) return undefined; return new Hover(message, range); diff --git a/src/vsls/vsls.ts b/src/vsls/vsls.ts index e118a09..7507c1f 100644 --- a/src/vsls/vsls.ts +++ b/src/vsls/vsls.ts @@ -6,7 +6,7 @@ import { Container } from '../container'; import { Logger } from '../logger'; import { VslsGuestService } from './guest'; import { VslsHostService } from './host'; -import { debug } from '../system'; +import { debug, timeout } from '../system'; export const vslsUriPrefixRegex = /^[/|\\]~(?:\d+?|external)(?:[/|\\]|$)/; export const vslsUriRootRegex = /^[/|\\]~(?:\d+?|external)$/; @@ -150,6 +150,12 @@ export class VslsController implements Disposable { ); } + @debug() + @timeout(250) + maybeGetPresence(email: string | undefined) { + return Container.vsls.getContactPresence(email); + } + async invite(email: string | undefined) { if (email == null) return undefined;