diff --git a/src/annotations/annotationController.ts b/src/annotations/annotationController.ts index 2fa55a6..ad9af50 100644 --- a/src/annotations/annotationController.ts +++ b/src/annotations/annotationController.ts @@ -58,9 +58,9 @@ export class AnnotationController extends Disposable { private _keyboardScope: KeyboardScope | undefined = undefined; constructor( - private context: ExtensionContext, - private git: GitService, - private gitContextTracker: GitContextTracker + private readonly context: ExtensionContext, + private readonly git: GitService, + private readonly gitContextTracker: GitContextTracker ) { super(() => this.dispose()); diff --git a/src/annotations/blameAnnotationProvider.ts b/src/annotations/blameAnnotationProvider.ts index 52e3269..239f888 100644 --- a/src/annotations/blameAnnotationProvider.ts +++ b/src/annotations/blameAnnotationProvider.ts @@ -16,8 +16,8 @@ export abstract class BlameAnnotationProviderBase extends AnnotationProviderBase editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, - protected git: GitService, - protected uri: GitUri + protected readonly git: GitService, + protected readonly uri: GitUri ) { super(context, editor, decoration, highlightDecoration); diff --git a/src/annotations/recentChangesAnnotationProvider.ts b/src/annotations/recentChangesAnnotationProvider.ts index c488de7..1835f0a 100644 --- a/src/annotations/recentChangesAnnotationProvider.ts +++ b/src/annotations/recentChangesAnnotationProvider.ts @@ -13,8 +13,8 @@ export class RecentChangesAnnotationProvider extends AnnotationProviderBase { editor: TextEditor, decoration: TextEditorDecorationType | undefined, highlightDecoration: TextEditorDecorationType | undefined, - private git: GitService, - private uri: GitUri + private readonly git: GitService, + private readonly uri: GitUri ) { super(context, editor, decoration, highlightDecoration); } diff --git a/src/codeLensController.ts b/src/codeLensController.ts index b21b694..de2508a 100644 --- a/src/codeLensController.ts +++ b/src/codeLensController.ts @@ -15,9 +15,9 @@ export class CodeLensController extends Disposable { private _disposable: Disposable | undefined; constructor( - private context: ExtensionContext, - private git: GitService, - private gitContextTracker: GitContextTracker + private readonly context: ExtensionContext, + private readonly git: GitService, + private readonly gitContextTracker: GitContextTracker ) { super(() => this.dispose()); diff --git a/src/commands/clearFileAnnotations.ts b/src/commands/clearFileAnnotations.ts index 185ded2..0beb060 100644 --- a/src/commands/clearFileAnnotations.ts +++ b/src/commands/clearFileAnnotations.ts @@ -6,7 +6,9 @@ import { Logger } from '../logger'; export class ClearFileAnnotationsCommand extends EditorCommand { - constructor(private annotationController: AnnotationController) { + constructor( + private readonly annotationController: AnnotationController + ) { super(Commands.ClearFileAnnotations); } diff --git a/src/commands/closeUnchangedFiles.ts b/src/commands/closeUnchangedFiles.ts index 0fed4ba..f1514e5 100644 --- a/src/commands/closeUnchangedFiles.ts +++ b/src/commands/closeUnchangedFiles.ts @@ -14,7 +14,9 @@ export interface CloseUnchangedFilesCommandArgs { export class CloseUnchangedFilesCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.CloseUnchangedFiles); } diff --git a/src/commands/copyMessageToClipboard.ts b/src/commands/copyMessageToClipboard.ts index 9e5796b..53ea4b8 100644 --- a/src/commands/copyMessageToClipboard.ts +++ b/src/commands/copyMessageToClipboard.ts @@ -13,7 +13,9 @@ export interface CopyMessageToClipboardCommandArgs { export class CopyMessageToClipboardCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.CopyMessageToClipboard); } diff --git a/src/commands/copyShaToClipboard.ts b/src/commands/copyShaToClipboard.ts index 45d5a4a..568153f 100644 --- a/src/commands/copyShaToClipboard.ts +++ b/src/commands/copyShaToClipboard.ts @@ -12,7 +12,9 @@ export interface CopyShaToClipboardCommandArgs { export class CopyShaToClipboardCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.CopyShaToClipboard); } diff --git a/src/commands/diffDirectory.ts b/src/commands/diffDirectory.ts index 44eced8..142a288 100644 --- a/src/commands/diffDirectory.ts +++ b/src/commands/diffDirectory.ts @@ -16,7 +16,9 @@ export interface DiffDirectoryCommandCommandArgs { export class DiffDirectoryCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super([Commands.DiffDirectory, Commands.ExternalDiffAll]); } diff --git a/src/commands/diffLineWithPrevious.ts b/src/commands/diffLineWithPrevious.ts index 7ecbf26..692356a 100644 --- a/src/commands/diffLineWithPrevious.ts +++ b/src/commands/diffLineWithPrevious.ts @@ -15,7 +15,9 @@ export interface DiffLineWithPreviousCommandArgs { export class DiffLineWithPreviousCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffLineWithPrevious); } diff --git a/src/commands/diffLineWithWorking.ts b/src/commands/diffLineWithWorking.ts index 6c65b3f..4f6659a 100644 --- a/src/commands/diffLineWithWorking.ts +++ b/src/commands/diffLineWithWorking.ts @@ -15,7 +15,9 @@ export interface DiffLineWithWorkingCommandArgs { export class DiffLineWithWorkingCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffLineWithWorking); } diff --git a/src/commands/diffWith.ts b/src/commands/diffWith.ts index 4ac1813..acb474c 100644 --- a/src/commands/diffWith.ts +++ b/src/commands/diffWith.ts @@ -79,7 +79,9 @@ export class DiffWithCommand extends ActiveEditorCommand { return super.getMarkdownCommandArgsCore(Commands.DiffWith, args); } - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffWith); } diff --git a/src/commands/diffWithBranch.ts b/src/commands/diffWithBranch.ts index 90a2dbf..0bb9e9d 100644 --- a/src/commands/diffWithBranch.ts +++ b/src/commands/diffWithBranch.ts @@ -17,7 +17,9 @@ export interface DiffWithBranchCommandArgs { export class DiffWithBranchCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffWithBranch); } diff --git a/src/commands/diffWithNext.ts b/src/commands/diffWithNext.ts index 29999b3..5ef4e4e 100644 --- a/src/commands/diffWithNext.ts +++ b/src/commands/diffWithNext.ts @@ -17,7 +17,9 @@ export interface DiffWithNextCommandArgs { export class DiffWithNextCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffWithNext); } diff --git a/src/commands/diffWithPrevious.ts b/src/commands/diffWithPrevious.ts index 7136afc..87a626e 100644 --- a/src/commands/diffWithPrevious.ts +++ b/src/commands/diffWithPrevious.ts @@ -18,7 +18,9 @@ export interface DiffWithPreviousCommandArgs { export class DiffWithPreviousCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffWithPrevious); } diff --git a/src/commands/diffWithRevision.ts b/src/commands/diffWithRevision.ts index 8a6e17f..7c37175 100644 --- a/src/commands/diffWithRevision.ts +++ b/src/commands/diffWithRevision.ts @@ -16,7 +16,9 @@ export interface DiffWithRevisionCommandArgs { export class DiffWithRevisionCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffWithRevision); } diff --git a/src/commands/diffWithWorking.ts b/src/commands/diffWithWorking.ts index 574c230..cf43d99 100644 --- a/src/commands/diffWithWorking.ts +++ b/src/commands/diffWithWorking.ts @@ -15,7 +15,9 @@ export interface DiffWithWorkingCommandArgs { export class DiffWithWorkingCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.DiffWithWorking); } diff --git a/src/commands/externalDiff.ts b/src/commands/externalDiff.ts index 719e7ed..c83ab7b 100644 --- a/src/commands/externalDiff.ts +++ b/src/commands/externalDiff.ts @@ -41,7 +41,10 @@ interface Resource extends SourceControlResourceState { class ExternalDiffFile { - constructor(public uri: Uri, public staged: boolean) { } + constructor( + public readonly uri: Uri, + public readonly staged: boolean + ) { } } export interface ExternalDiffCommandArgs { @@ -50,7 +53,9 @@ export interface ExternalDiffCommandArgs { export class ExternalDiffCommand extends Command { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ExternalDiff); } diff --git a/src/commands/openBranchInRemote.ts b/src/commands/openBranchInRemote.ts index 16d05ec..8d1f51d 100644 --- a/src/commands/openBranchInRemote.ts +++ b/src/commands/openBranchInRemote.ts @@ -14,7 +14,9 @@ export interface OpenBranchInRemoteCommandArgs { export class OpenBranchInRemoteCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.OpenBranchInRemote); } diff --git a/src/commands/openBranchesInRemote.ts b/src/commands/openBranchesInRemote.ts index 3db97e4..86d58dd 100644 --- a/src/commands/openBranchesInRemote.ts +++ b/src/commands/openBranchesInRemote.ts @@ -11,7 +11,9 @@ export interface OpenBranchesInRemoteCommandArgs { export class OpenBranchesInRemoteCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.OpenBranchesInRemote); } diff --git a/src/commands/openChangedFiles.ts b/src/commands/openChangedFiles.ts index 7979f30..05426ae 100644 --- a/src/commands/openChangedFiles.ts +++ b/src/commands/openChangedFiles.ts @@ -11,7 +11,9 @@ export interface OpenChangedFilesCommandArgs { export class OpenChangedFilesCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.OpenChangedFiles); } diff --git a/src/commands/openCommitInRemote.ts b/src/commands/openCommitInRemote.ts index 8b13ad6..a3af7df 100644 --- a/src/commands/openCommitInRemote.ts +++ b/src/commands/openCommitInRemote.ts @@ -21,7 +21,9 @@ export class OpenCommitInRemoteCommand extends ActiveEditorCommand { return super.getMarkdownCommandArgsCore(Commands.OpenCommitInRemote, args); } - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.OpenCommitInRemote); } diff --git a/src/commands/openFileInRemote.ts b/src/commands/openFileInRemote.ts index 36f46f5..078085d 100644 --- a/src/commands/openFileInRemote.ts +++ b/src/commands/openFileInRemote.ts @@ -12,7 +12,9 @@ export interface OpenFileInRemoteCommandArgs { export class OpenFileInRemoteCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.OpenFileInRemote); } diff --git a/src/commands/openFileRevision.ts b/src/commands/openFileRevision.ts index 706cfcc..e622f22 100644 --- a/src/commands/openFileRevision.ts +++ b/src/commands/openFileRevision.ts @@ -33,7 +33,9 @@ export class OpenFileRevisionCommand extends ActiveEditorCommand { return super.getMarkdownCommandArgsCore(Commands.OpenFileRevision, args); } - constructor(private annotationController: AnnotationController) { + constructor( + private readonly annotationController: AnnotationController + ) { super(Commands.OpenFileRevision); } diff --git a/src/commands/openRepoInRemote.ts b/src/commands/openRepoInRemote.ts index 7dc43fc..760d7f7 100644 --- a/src/commands/openRepoInRemote.ts +++ b/src/commands/openRepoInRemote.ts @@ -11,7 +11,9 @@ export interface OpenRepoInRemoteCommandArgs { export class OpenRepoInRemoteCommand extends ActiveEditorCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.OpenRepoInRemote); } diff --git a/src/commands/resetSuppressedWarnings.ts b/src/commands/resetSuppressedWarnings.ts index b8f2408..e438d83 100644 --- a/src/commands/resetSuppressedWarnings.ts +++ b/src/commands/resetSuppressedWarnings.ts @@ -6,7 +6,9 @@ import { SuppressedKeys } from '../messages'; export class ResetSuppressedWarningsCommand extends Command { - constructor(private context: ExtensionContext) { + constructor( + private readonly context: ExtensionContext + ) { super(Commands.ResetSuppressedWarnings); } diff --git a/src/commands/showCommitSearch.ts b/src/commands/showCommitSearch.ts index 9185803..7c217a6 100644 --- a/src/commands/showCommitSearch.ts +++ b/src/commands/showCommitSearch.ts @@ -27,7 +27,9 @@ export interface ShowCommitSearchCommandArgs { export class ShowCommitSearchCommand extends ActiveEditorCachedCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowCommitSearch); } diff --git a/src/commands/showFileBlame.ts b/src/commands/showFileBlame.ts index 4f00db2..b8c8a23 100644 --- a/src/commands/showFileBlame.ts +++ b/src/commands/showFileBlame.ts @@ -12,7 +12,9 @@ export interface ShowFileBlameCommandArgs { export class ShowFileBlameCommand extends EditorCommand { - constructor(private annotationController: AnnotationController) { + constructor( + private readonly annotationController: AnnotationController + ) { super(Commands.ShowFileBlame); } diff --git a/src/commands/showLineBlame.ts b/src/commands/showLineBlame.ts index 53f4e21..a8c0a2b 100644 --- a/src/commands/showLineBlame.ts +++ b/src/commands/showLineBlame.ts @@ -11,7 +11,9 @@ export interface ShowLineBlameCommandArgs { export class ShowLineBlameCommand extends EditorCommand { - constructor(private currentLineController: CurrentLineController) { + constructor( + private readonly currentLineController: CurrentLineController + ) { super(Commands.ShowLineBlame); } diff --git a/src/commands/showQuickBranchHistory.ts b/src/commands/showQuickBranchHistory.ts index ccf1546..c7fd242 100644 --- a/src/commands/showQuickBranchHistory.ts +++ b/src/commands/showQuickBranchHistory.ts @@ -20,7 +20,9 @@ export interface ShowQuickBranchHistoryCommandArgs { export class ShowQuickBranchHistoryCommand extends ActiveEditorCachedCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowQuickBranchHistory); } diff --git a/src/commands/showQuickCommitDetails.ts b/src/commands/showQuickCommitDetails.ts index d87783a..a18f9cd 100644 --- a/src/commands/showQuickCommitDetails.ts +++ b/src/commands/showQuickCommitDetails.ts @@ -29,7 +29,9 @@ export class ShowQuickCommitDetailsCommand extends ActiveEditorCachedCommand { return super.getMarkdownCommandArgsCore(Commands.ShowQuickCommitDetails, args); } - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowQuickCommitDetails); } diff --git a/src/commands/showQuickCommitFileDetails.ts b/src/commands/showQuickCommitFileDetails.ts index c0eb677..dc97747 100644 --- a/src/commands/showQuickCommitFileDetails.ts +++ b/src/commands/showQuickCommitFileDetails.ts @@ -29,7 +29,9 @@ export class ShowQuickCommitFileDetailsCommand extends ActiveEditorCachedCommand return super.getMarkdownCommandArgsCore(Commands.ShowQuickCommitFileDetails, args); } - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowQuickCommitFileDetails); } diff --git a/src/commands/showQuickCurrentBranchHistory.ts b/src/commands/showQuickCurrentBranchHistory.ts index d4d256a..0f1f498 100644 --- a/src/commands/showQuickCurrentBranchHistory.ts +++ b/src/commands/showQuickCurrentBranchHistory.ts @@ -13,7 +13,9 @@ export interface ShowQuickCurrentBranchHistoryCommandArgs { export class ShowQuickCurrentBranchHistoryCommand extends ActiveEditorCachedCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowQuickCurrentBranchHistory); } diff --git a/src/commands/showQuickFileHistory.ts b/src/commands/showQuickFileHistory.ts index 5ad366f..19d819c 100644 --- a/src/commands/showQuickFileHistory.ts +++ b/src/commands/showQuickFileHistory.ts @@ -21,7 +21,9 @@ export interface ShowQuickFileHistoryCommandArgs { export class ShowQuickFileHistoryCommand extends ActiveEditorCachedCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowQuickFileHistory); } diff --git a/src/commands/showQuickRepoStatus.ts b/src/commands/showQuickRepoStatus.ts index 140eadc..7155c53 100644 --- a/src/commands/showQuickRepoStatus.ts +++ b/src/commands/showQuickRepoStatus.ts @@ -12,7 +12,9 @@ export interface ShowQuickRepoStatusCommandArgs { export class ShowQuickRepoStatusCommand extends ActiveEditorCachedCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowQuickRepoStatus); } diff --git a/src/commands/showQuickStashList.ts b/src/commands/showQuickStashList.ts index 8dcc84f..8f659de 100644 --- a/src/commands/showQuickStashList.ts +++ b/src/commands/showQuickStashList.ts @@ -15,7 +15,9 @@ export interface ShowQuickStashListCommandArgs { export class ShowQuickStashListCommand extends ActiveEditorCachedCommand { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.ShowQuickStashList); } diff --git a/src/commands/stashApply.ts b/src/commands/stashApply.ts index 60ee50c..4a83b32 100644 --- a/src/commands/stashApply.ts +++ b/src/commands/stashApply.ts @@ -17,7 +17,9 @@ export interface StashApplyCommandArgs { export class StashApplyCommand extends Command { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.StashApply); } diff --git a/src/commands/stashDelete.ts b/src/commands/stashDelete.ts index cd75fca..31cb58c 100644 --- a/src/commands/stashDelete.ts +++ b/src/commands/stashDelete.ts @@ -15,7 +15,9 @@ export interface StashDeleteCommandArgs { export class StashDeleteCommand extends Command { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.StashDelete); } diff --git a/src/commands/stashSave.ts b/src/commands/stashSave.ts index 5e5814d..2b6e058 100644 --- a/src/commands/stashSave.ts +++ b/src/commands/stashSave.ts @@ -15,7 +15,9 @@ export interface StashSaveCommandArgs { export class StashSaveCommand extends Command { - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(Commands.StashSave); } diff --git a/src/commands/toggleCodeLens.ts b/src/commands/toggleCodeLens.ts index aef3c54..080af97 100644 --- a/src/commands/toggleCodeLens.ts +++ b/src/commands/toggleCodeLens.ts @@ -5,7 +5,9 @@ import { Commands, EditorCommand } from './common'; export class ToggleCodeLensCommand extends EditorCommand { - constructor(private codeLensController: CodeLensController) { + constructor( + private readonly codeLensController: CodeLensController + ) { super(Commands.ToggleCodeLens); } diff --git a/src/commands/toggleFileBlame.ts b/src/commands/toggleFileBlame.ts index 9a334fc..830dfae 100644 --- a/src/commands/toggleFileBlame.ts +++ b/src/commands/toggleFileBlame.ts @@ -13,7 +13,9 @@ export interface ToggleFileBlameCommandArgs { export class ToggleFileBlameCommand extends EditorCommand { - constructor(private annotationController: AnnotationController) { + constructor( + private readonly annotationController: AnnotationController + ) { super(Commands.ToggleFileBlame); } diff --git a/src/commands/toggleFileRecentChanges.ts b/src/commands/toggleFileRecentChanges.ts index 62a5ef9..4a9a153 100644 --- a/src/commands/toggleFileRecentChanges.ts +++ b/src/commands/toggleFileRecentChanges.ts @@ -7,7 +7,9 @@ import { Logger } from '../logger'; export class ToggleFileRecentChangesCommand extends EditorCommand { - constructor(private annotationController: AnnotationController) { + constructor( + private readonly annotationController: AnnotationController + ) { super(Commands.ToggleFileRecentChanges); } diff --git a/src/commands/toggleLineBlame.ts b/src/commands/toggleLineBlame.ts index e55f8db..1926c10 100644 --- a/src/commands/toggleLineBlame.ts +++ b/src/commands/toggleLineBlame.ts @@ -11,7 +11,9 @@ export interface ToggleLineBlameCommandArgs { export class ToggleLineBlameCommand extends EditorCommand { - constructor(private currentLineController: CurrentLineController) { + constructor( + private readonly currentLineController: CurrentLineController + ) { super(Commands.ToggleLineBlame); } diff --git a/src/currentLineController.ts b/src/currentLineController.ts index f196dfa..37bc4da 100644 --- a/src/currentLineController.ts +++ b/src/currentLineController.ts @@ -1,456 +1,456 @@ -'use strict'; -import { Functions, Objects } from './system'; -import { CancellationToken, debug, DecorationRangeBehavior, DecorationRenderOptions, Disposable, ExtensionContext, Hover, HoverProvider, languages, Position, Range, StatusBarAlignment, StatusBarItem, TextDocument, TextEditor, TextEditorDecorationType, TextEditorSelectionChangeEvent, window, workspace } from 'vscode'; -import { AnnotationController, FileAnnotationType } from './annotations/annotationController'; -import { Annotations, endOfLineIndex } from './annotations/annotations'; -import { Commands } from './commands'; -import { TextEditorComparer } from './comparers'; -import { IConfig, StatusBarCommand } from './configuration'; -import { DocumentSchemes, ExtensionKey, isTextEditor } from './constants'; -import { BlameabilityChangeEvent, CommitFormatter, GitCommit, GitCommitLine, GitContextTracker, GitLogCommit, GitService, GitUri, ICommitFormatOptions } from './gitService'; -// import { Logger } from './logger'; - -const annotationDecoration: TextEditorDecorationType = window.createTextEditorDecorationType({ - after: { - margin: '0 0 0 3em', - textDecoration: 'none' - }, - rangeBehavior: DecorationRangeBehavior.ClosedClosed -} as DecorationRenderOptions); - -export enum LineAnnotationType { - Trailing = 'trailing', - Hover = 'hover' -} - -export class CurrentLineController extends Disposable { - - private _blameable: boolean; - private _blameLineAnnotationState: { enabled: boolean, annotationType: LineAnnotationType, reason: 'user' | 'debugging' } | undefined = undefined; - private _config: IConfig; - private _currentLine: { line: number, commit?: GitCommit, logCommit?: GitLogCommit } = { line: -1 }; - private _debugSessionEndDisposable: Disposable | undefined; - private _disposable: Disposable; - private _editor: TextEditor | undefined; - private _hoverProviderDisposable: Disposable | undefined; - private _isAnnotating: boolean = false; - private _statusBarItem: StatusBarItem | undefined; - private _trackCurrentLineDisposable: Disposable | undefined; - private _updateBlameDebounced: (line: number, editor: TextEditor) => Promise; - private _uri: GitUri; - - constructor( - context: ExtensionContext, - private git: GitService, - private gitContextTracker: GitContextTracker, - private annotationController: AnnotationController - ) { - super(() => this.dispose()); - - this._updateBlameDebounced = Functions.debounce(this.updateBlame, 250); - - this.onConfigurationChanged(); - - this._disposable = Disposable.from( - workspace.onDidChangeConfiguration(this.onConfigurationChanged, this), - annotationController.onDidToggleAnnotations(this.onFileAnnotationsToggled, this), - debug.onDidStartDebugSession(this.onDebugSessionStarted, this) - ); - } - - dispose() { - this.clearAnnotations(this._editor, true); - - this.unregisterHoverProviders(); - this._trackCurrentLineDisposable && this._trackCurrentLineDisposable.dispose(); - this._statusBarItem && this._statusBarItem.dispose(); - this._debugSessionEndDisposable && this._debugSessionEndDisposable.dispose(); - this._disposable && this._disposable.dispose(); - } - - private onConfigurationChanged() { - const cfg = workspace.getConfiguration().get(ExtensionKey)!; - - let changed = false; - let clear = false; - - if (!Objects.areEquivalent(cfg.blame.line, this._config && this._config.blame.line)) { - changed = true; - this._blameLineAnnotationState = undefined; - clear = (this._config !== undefined); - } - - if (!Objects.areEquivalent(cfg.annotations.line.trailing, this._config && this._config.annotations.line.trailing) || - !Objects.areEquivalent(cfg.annotations.line.hover, this._config && this._config.annotations.line.hover) || - !Objects.areEquivalent(cfg.theme.annotations.line.trailing, this._config && this._config.theme.annotations.line.trailing)) { - changed = true; - clear = (this._config !== undefined); - } - - if (!Objects.areEquivalent(cfg.statusBar, this._config && this._config.statusBar)) { - changed = true; - if (cfg.statusBar.enabled) { - const alignment = cfg.statusBar.alignment !== 'left' ? StatusBarAlignment.Right : StatusBarAlignment.Left; - if (this._statusBarItem !== undefined && this._statusBarItem.alignment !== alignment) { - this._statusBarItem.dispose(); - this._statusBarItem = undefined; - } - - this._statusBarItem = this._statusBarItem || window.createStatusBarItem(alignment, alignment === StatusBarAlignment.Right ? 1000 : 0); - this._statusBarItem.command = cfg.statusBar.command; - } - else if (!cfg.statusBar.enabled && this._statusBarItem) { - this._statusBarItem.dispose(); - this._statusBarItem = undefined; - } - } - - this._config = cfg; - - if (!changed) return; - - if (clear) { - this.clearAnnotations(this._editor); - } - - const trackCurrentLine = cfg.statusBar.enabled || cfg.blame.line.enabled || (this._blameLineAnnotationState !== undefined && this._blameLineAnnotationState.enabled); - if (trackCurrentLine && !this._trackCurrentLineDisposable) { - this._trackCurrentLineDisposable = Disposable.from( - window.onDidChangeActiveTextEditor(Functions.debounce(this.onActiveTextEditorChanged, 50), this), - window.onDidChangeTextEditorSelection(this.onTextEditorSelectionChanged, this), - this.gitContextTracker.onDidChangeBlameability(this.onBlameabilityChanged, this) - ); - } - else if (!trackCurrentLine && this._trackCurrentLineDisposable) { - this._trackCurrentLineDisposable.dispose(); - this._trackCurrentLineDisposable = undefined; - } - - this.refresh(window.activeTextEditor); - } - - private onActiveTextEditorChanged(editor: TextEditor | undefined) { - if (this._editor === editor) return; - if (editor !== undefined && !isTextEditor(editor)) return; - - // Logger.log('CurrentLineController.onActiveTextEditorChanged', editor && editor.document.uri.fsPath); - - this.refresh(editor); - } - - private onBlameabilityChanged(e: BlameabilityChangeEvent) { - if (!this._blameable && !e.blameable) return; - - this._blameable = e.blameable; - if (!e.blameable || this._editor === undefined) { - this.clear(e.editor); - return; - } - - // Make sure this is for the editor we are tracking - if (!TextEditorComparer.equals(this._editor, e.editor)) return; - - this._updateBlameDebounced(this._editor.selection.active.line, this._editor); - } - - private onDebugSessionStarted() { - const state = this.getLineAnnotationState(); - if (!state.enabled) return; - - this._debugSessionEndDisposable = debug.onDidTerminateDebugSession(this.onDebugSessionEnded, this); - this.toggleAnnotations(window.activeTextEditor, state.annotationType, 'debugging'); - } - - private onDebugSessionEnded() { - this._debugSessionEndDisposable && this._debugSessionEndDisposable.dispose(); - this._debugSessionEndDisposable = undefined; - - if (this._blameLineAnnotationState === undefined || this._blameLineAnnotationState.enabled || this._blameLineAnnotationState.reason !== 'debugging') return; - - this.toggleAnnotations(window.activeTextEditor, this._blameLineAnnotationState.annotationType); - } - - private onFileAnnotationsToggled() { - this.refresh(window.activeTextEditor); - } - - private async onTextEditorSelectionChanged(e: TextEditorSelectionChangeEvent): Promise { - // Make sure this is for the editor we are tracking - if (!this._blameable || !TextEditorComparer.equals(this._editor, e.textEditor)) return; - - const line = e.selections[0].active.line; - if (line === this._currentLine.line) return; - - this._currentLine.line = line; - this._currentLine.commit = undefined; - this._currentLine.logCommit = undefined; - - if (this._uri === undefined && e.textEditor !== undefined) { - this._uri = await GitUri.fromUri(e.textEditor.document.uri, this.git); - } - - this.clearAnnotations(e.textEditor); - this._updateBlameDebounced(line, e.textEditor); - } - - private getLineAnnotationState() { - return this._blameLineAnnotationState !== undefined ? this._blameLineAnnotationState : this._config.blame.line; - } - - private isEditorBlameable(editor: TextEditor | undefined): boolean { - if (editor === undefined || editor.document === undefined) return false; - - if (!this.git.isTrackable(editor.document.uri)) return false; - if (editor.document.isUntitled && editor.document.uri.scheme === DocumentSchemes.File) return false; - - return this.git.isEditorBlameable(editor); - } - - private async updateBlame(line: number, editor: TextEditor) { - this._currentLine.line = line; - this._currentLine.commit = undefined; - this._currentLine.logCommit = undefined; - - let commit: GitCommit | undefined = undefined; - let commitLine: GitCommitLine | undefined = undefined; - // Since blame information isn't valid when there are unsaved changes -- don't show any status - if (this._blameable && line >= 0) { - const blameLine = await this.git.getBlameForLine(this._uri, line); - commitLine = blameLine === undefined ? undefined : blameLine.line; - commit = blameLine === undefined ? undefined : blameLine.commit; - } - - this._currentLine.commit = commit; - - if (commit !== undefined && commitLine !== undefined) { - this.show(commit, commitLine, editor, line); - } - else { - this.clear(editor); - } - } - - async clear(editor: TextEditor | undefined) { - this.unregisterHoverProviders(); - this.clearAnnotations(editor, true); - this._statusBarItem && this._statusBarItem.hide(); - } - - private async clearAnnotations(editor: TextEditor | undefined, force: boolean = false) { - if (editor === undefined || (!this._isAnnotating && !force)) return; - - editor.setDecorations(annotationDecoration, []); - this._isAnnotating = false; - - if (!force) return; - - // I have no idea why the decorators sometimes don't get removed, but if they don't try again with a tiny delay - await Functions.wait(1); - editor.setDecorations(annotationDecoration, []); - } - - async refresh(editor?: TextEditor) { - this._currentLine.line = -1; - this.clearAnnotations(this._editor); - - if (editor === undefined || !this.isEditorBlameable(editor)) { - this.clear(editor); - this._editor = undefined; - - return; - } - - this._blameable = editor !== undefined && editor.document !== undefined && !editor.document.isDirty; - this._editor = editor; - this._uri = await GitUri.fromUri(editor.document.uri, this.git); - - const maxLines = this._config.advanced.caching.maxLines; - // If caching is on and the file is small enough -- kick off a blame for the whole file - if (this._config.advanced.caching.enabled && (maxLines <= 0 || editor.document.lineCount <= maxLines)) { - this.git.getBlameForFile(this._uri); - } - - const state = this.getLineAnnotationState(); - if (state.enabled && this._blameable) { - const cfg = this._config.annotations.line; - this.registerHoverProviders(state.annotationType === LineAnnotationType.Trailing ? cfg.trailing.hover : cfg.hover); - } - else { - this.unregisterHoverProviders(); - } - - this._updateBlameDebounced(editor.selection.active.line, editor); - } - - async show(commit: GitCommit, blameLine: GitCommitLine, editor: TextEditor, line: number) { - // I have no idea why I need this protection -- but it happens - if (editor.document === undefined) return; - - this.updateStatusBar(commit); - this.updateTrailingAnnotation(commit, blameLine, editor, line); - } - - async showAnnotations(editor: TextEditor | undefined, type: LineAnnotationType, reason: 'user' | 'debugging' = 'user') { - if (editor === undefined) return; - - const state = this.getLineAnnotationState(); - if (!state.enabled || state.annotationType !== type) { - this._blameLineAnnotationState = { enabled: true, annotationType: type, reason: reason }; - - await this.clearAnnotations(editor); - await this.updateBlame(editor.selection.active.line, editor); - } - } - - async toggleAnnotations(editor: TextEditor | undefined, type: LineAnnotationType, reason: 'user' | 'debugging' = 'user') { - if (editor === undefined) return; - - const state = this.getLineAnnotationState(); - this._blameLineAnnotationState = { enabled: !state.enabled, annotationType: type, reason: reason }; - - await this.clearAnnotations(editor); - await this.updateBlame(editor.selection.active.line, editor); - } - - private updateStatusBar(commit: GitCommit) { - const cfg = this._config.statusBar; - if (!cfg.enabled || this._statusBarItem === undefined) return; - - this._statusBarItem.text = `$(git-commit) ${CommitFormatter.fromTemplate(cfg.format, commit, { - truncateMessageAtNewLine: true, - dateFormat: cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat - } as ICommitFormatOptions)}`; - - switch (cfg.command) { - case StatusBarCommand.ToggleFileBlame: - this._statusBarItem.tooltip = 'Toggle Blame Annotations'; - break; - case StatusBarCommand.DiffWithPrevious: - this._statusBarItem.command = Commands.DiffLineWithPrevious; - this._statusBarItem.tooltip = 'Compare Line Revision with Previous'; - break; - case StatusBarCommand.DiffWithWorking: - this._statusBarItem.command = Commands.DiffLineWithWorking; - this._statusBarItem.tooltip = 'Compare Line Revision with Working'; - break; - case StatusBarCommand.ToggleCodeLens: - this._statusBarItem.tooltip = 'Toggle Git CodeLens'; - break; - case StatusBarCommand.ShowQuickCommitDetails: - this._statusBarItem.tooltip = 'Show Commit Details'; - break; - case StatusBarCommand.ShowQuickCommitFileDetails: - this._statusBarItem.tooltip = 'Show Line Commit Details'; - break; - case StatusBarCommand.ShowQuickFileHistory: - this._statusBarItem.tooltip = 'Show File History'; - break; - case StatusBarCommand.ShowQuickCurrentBranchHistory: - this._statusBarItem.tooltip = 'Show Branch History'; - break; - } - - this._statusBarItem.show(); - } - - private async updateTrailingAnnotation(commit: GitCommit, blameLine: GitCommitLine, editor: TextEditor, line?: number) { - const state = this.getLineAnnotationState(); - if (!state.enabled || state.annotationType !== LineAnnotationType.Trailing) return; - - line = line === undefined ? blameLine.line : line; - - const cfg = this._config.annotations.line.trailing; - const decoration = Annotations.trailing(commit, cfg.format, cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat, this._config.theme); - decoration.range = editor.document.validateRange(new Range(line, endOfLineIndex, line, endOfLineIndex)); - - editor.setDecorations(annotationDecoration, [decoration]); - this._isAnnotating = true; - } - - registerHoverProviders(providers: { details: boolean, changes: boolean }) { - this.unregisterHoverProviders(); - - if (this._editor === undefined) return; - if (!providers.details && !providers.changes) return; - - const subscriptions: Disposable[] = []; - if (providers.changes) { - subscriptions.push(languages.registerHoverProvider({ pattern: this._editor.document.uri.fsPath }, { provideHover: this.provideChangesHover.bind(this) } as HoverProvider)); - } - if (providers.details) { - subscriptions.push(languages.registerHoverProvider({ pattern: this._editor.document.uri.fsPath }, { provideHover: this.provideDetailsHover.bind(this) } as HoverProvider)); - } - - this._hoverProviderDisposable = Disposable.from(...subscriptions); - } - - unregisterHoverProviders() { - if (this._hoverProviderDisposable !== undefined) { - this._hoverProviderDisposable.dispose(); - this._hoverProviderDisposable = undefined; - } - } - - async provideDetailsHover(document: TextDocument, position: Position, token: CancellationToken): Promise { - if (this._editor === undefined || this._editor.document !== document) return undefined; - if (this._currentLine.line !== position.line) return undefined; - - const commit = this._currentLine.commit; - if (commit === undefined) return undefined; - - const fileAnnotations = this.annotationController.getAnnotationType(this._editor); - // Avoid double annotations if we are showing the whole-file hover blame annotations - if ((fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.details) || - (fileAnnotations === FileAnnotationType.Hover && this._config.annotations.file.hover.details)) { - return undefined; - } - - const state = this.getLineAnnotationState(); - const wholeLine = state.annotationType === LineAnnotationType.Hover || (state.annotationType === LineAnnotationType.Trailing && this._config.annotations.line.trailing.hover.wholeLine) || - fileAnnotations === FileAnnotationType.Hover || (fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.wholeLine); - - const range = document.validateRange(new Range(position.line, wholeLine ? 0 : endOfLineIndex, position.line, endOfLineIndex)); - if (!wholeLine && range.start.character !== position.character) return undefined; - - // Get the full commit message -- since blame only returns the summary - let logCommit = this._currentLine.logCommit; - if (logCommit === undefined && !commit.isUncommitted) { - logCommit = await this.git.getLogCommit(commit.repoPath, commit.uri.fsPath, commit.sha); - if (logCommit !== undefined) { - // Preserve the previous commit from the blame commit - logCommit.previousFileName = commit.previousFileName; - logCommit.previousSha = commit.previousSha; - - this._currentLine.logCommit = logCommit; - } - } - - const message = Annotations.getHoverMessage(logCommit || commit, this._config.defaultDateFormat, this.git.hasRemotes(commit.repoPath), this._config.blame.file.annotationType); - return new Hover(message, range); - } - - async provideChangesHover(document: TextDocument, position: Position, token: CancellationToken): Promise { - if (this._editor === undefined || this._editor.document !== document) return undefined; - if (this._currentLine.line !== position.line) return undefined; - - const commit = this._currentLine.commit; - if (commit === undefined) return undefined; - - const fileAnnotations = this.annotationController.getAnnotationType(this._editor); - // Avoid double annotations if we are showing the whole-file hover blame annotations - if ((fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.changes) || - (fileAnnotations === FileAnnotationType.Hover && this._config.annotations.file.hover.changes)) { - return undefined; - } - - const state = this.getLineAnnotationState(); - const wholeLine = state.annotationType === LineAnnotationType.Hover || (state.annotationType === LineAnnotationType.Trailing && this._config.annotations.line.trailing.hover.wholeLine) || - fileAnnotations === FileAnnotationType.Hover || (fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.wholeLine); - - const range = document.validateRange(new Range(position.line, wholeLine ? 0 : endOfLineIndex, position.line, endOfLineIndex)); - if (!wholeLine && range.start.character !== position.character) return undefined; - - const hover = await Annotations.changesHover(commit, position.line, this._uri, this.git); - return new Hover(hover.hoverMessage!, range); - } +'use strict'; +import { Functions, Objects } from './system'; +import { CancellationToken, debug, DecorationRangeBehavior, DecorationRenderOptions, Disposable, ExtensionContext, Hover, HoverProvider, languages, Position, Range, StatusBarAlignment, StatusBarItem, TextDocument, TextEditor, TextEditorDecorationType, TextEditorSelectionChangeEvent, window, workspace } from 'vscode'; +import { AnnotationController, FileAnnotationType } from './annotations/annotationController'; +import { Annotations, endOfLineIndex } from './annotations/annotations'; +import { Commands } from './commands'; +import { TextEditorComparer } from './comparers'; +import { IConfig, StatusBarCommand } from './configuration'; +import { DocumentSchemes, ExtensionKey, isTextEditor } from './constants'; +import { BlameabilityChangeEvent, CommitFormatter, GitCommit, GitCommitLine, GitContextTracker, GitLogCommit, GitService, GitUri, ICommitFormatOptions } from './gitService'; +// import { Logger } from './logger'; + +const annotationDecoration: TextEditorDecorationType = window.createTextEditorDecorationType({ + after: { + margin: '0 0 0 3em', + textDecoration: 'none' + }, + rangeBehavior: DecorationRangeBehavior.ClosedClosed +} as DecorationRenderOptions); + +export enum LineAnnotationType { + Trailing = 'trailing', + Hover = 'hover' +} + +export class CurrentLineController extends Disposable { + + private _blameable: boolean; + private _blameLineAnnotationState: { enabled: boolean, annotationType: LineAnnotationType, reason: 'user' | 'debugging' } | undefined = undefined; + private _config: IConfig; + private _currentLine: { line: number, commit?: GitCommit, logCommit?: GitLogCommit } = { line: -1 }; + private _debugSessionEndDisposable: Disposable | undefined; + private _disposable: Disposable; + private _editor: TextEditor | undefined; + private _hoverProviderDisposable: Disposable | undefined; + private _isAnnotating: boolean = false; + private _statusBarItem: StatusBarItem | undefined; + private _trackCurrentLineDisposable: Disposable | undefined; + private _updateBlameDebounced: (line: number, editor: TextEditor) => Promise; + private _uri: GitUri; + + constructor( + context: ExtensionContext, + private readonly git: GitService, + private readonly gitContextTracker: GitContextTracker, + private readonly annotationController: AnnotationController + ) { + super(() => this.dispose()); + + this._updateBlameDebounced = Functions.debounce(this.updateBlame, 250); + + this.onConfigurationChanged(); + + this._disposable = Disposable.from( + workspace.onDidChangeConfiguration(this.onConfigurationChanged, this), + annotationController.onDidToggleAnnotations(this.onFileAnnotationsToggled, this), + debug.onDidStartDebugSession(this.onDebugSessionStarted, this) + ); + } + + dispose() { + this.clearAnnotations(this._editor, true); + + this.unregisterHoverProviders(); + this._trackCurrentLineDisposable && this._trackCurrentLineDisposable.dispose(); + this._statusBarItem && this._statusBarItem.dispose(); + this._debugSessionEndDisposable && this._debugSessionEndDisposable.dispose(); + this._disposable && this._disposable.dispose(); + } + + private onConfigurationChanged() { + const cfg = workspace.getConfiguration().get(ExtensionKey)!; + + let changed = false; + let clear = false; + + if (!Objects.areEquivalent(cfg.blame.line, this._config && this._config.blame.line)) { + changed = true; + this._blameLineAnnotationState = undefined; + clear = (this._config !== undefined); + } + + if (!Objects.areEquivalent(cfg.annotations.line.trailing, this._config && this._config.annotations.line.trailing) || + !Objects.areEquivalent(cfg.annotations.line.hover, this._config && this._config.annotations.line.hover) || + !Objects.areEquivalent(cfg.theme.annotations.line.trailing, this._config && this._config.theme.annotations.line.trailing)) { + changed = true; + clear = (this._config !== undefined); + } + + if (!Objects.areEquivalent(cfg.statusBar, this._config && this._config.statusBar)) { + changed = true; + if (cfg.statusBar.enabled) { + const alignment = cfg.statusBar.alignment !== 'left' ? StatusBarAlignment.Right : StatusBarAlignment.Left; + if (this._statusBarItem !== undefined && this._statusBarItem.alignment !== alignment) { + this._statusBarItem.dispose(); + this._statusBarItem = undefined; + } + + this._statusBarItem = this._statusBarItem || window.createStatusBarItem(alignment, alignment === StatusBarAlignment.Right ? 1000 : 0); + this._statusBarItem.command = cfg.statusBar.command; + } + else if (!cfg.statusBar.enabled && this._statusBarItem) { + this._statusBarItem.dispose(); + this._statusBarItem = undefined; + } + } + + this._config = cfg; + + if (!changed) return; + + if (clear) { + this.clearAnnotations(this._editor); + } + + const trackCurrentLine = cfg.statusBar.enabled || cfg.blame.line.enabled || (this._blameLineAnnotationState !== undefined && this._blameLineAnnotationState.enabled); + if (trackCurrentLine && !this._trackCurrentLineDisposable) { + this._trackCurrentLineDisposable = Disposable.from( + window.onDidChangeActiveTextEditor(Functions.debounce(this.onActiveTextEditorChanged, 50), this), + window.onDidChangeTextEditorSelection(this.onTextEditorSelectionChanged, this), + this.gitContextTracker.onDidChangeBlameability(this.onBlameabilityChanged, this) + ); + } + else if (!trackCurrentLine && this._trackCurrentLineDisposable) { + this._trackCurrentLineDisposable.dispose(); + this._trackCurrentLineDisposable = undefined; + } + + this.refresh(window.activeTextEditor); + } + + private onActiveTextEditorChanged(editor: TextEditor | undefined) { + if (this._editor === editor) return; + if (editor !== undefined && !isTextEditor(editor)) return; + + // Logger.log('CurrentLineController.onActiveTextEditorChanged', editor && editor.document.uri.fsPath); + + this.refresh(editor); + } + + private onBlameabilityChanged(e: BlameabilityChangeEvent) { + if (!this._blameable && !e.blameable) return; + + this._blameable = e.blameable; + if (!e.blameable || this._editor === undefined) { + this.clear(e.editor); + return; + } + + // Make sure this is for the editor we are tracking + if (!TextEditorComparer.equals(this._editor, e.editor)) return; + + this._updateBlameDebounced(this._editor.selection.active.line, this._editor); + } + + private onDebugSessionStarted() { + const state = this.getLineAnnotationState(); + if (!state.enabled) return; + + this._debugSessionEndDisposable = debug.onDidTerminateDebugSession(this.onDebugSessionEnded, this); + this.toggleAnnotations(window.activeTextEditor, state.annotationType, 'debugging'); + } + + private onDebugSessionEnded() { + this._debugSessionEndDisposable && this._debugSessionEndDisposable.dispose(); + this._debugSessionEndDisposable = undefined; + + if (this._blameLineAnnotationState === undefined || this._blameLineAnnotationState.enabled || this._blameLineAnnotationState.reason !== 'debugging') return; + + this.toggleAnnotations(window.activeTextEditor, this._blameLineAnnotationState.annotationType); + } + + private onFileAnnotationsToggled() { + this.refresh(window.activeTextEditor); + } + + private async onTextEditorSelectionChanged(e: TextEditorSelectionChangeEvent): Promise { + // Make sure this is for the editor we are tracking + if (!this._blameable || !TextEditorComparer.equals(this._editor, e.textEditor)) return; + + const line = e.selections[0].active.line; + if (line === this._currentLine.line) return; + + this._currentLine.line = line; + this._currentLine.commit = undefined; + this._currentLine.logCommit = undefined; + + if (this._uri === undefined && e.textEditor !== undefined) { + this._uri = await GitUri.fromUri(e.textEditor.document.uri, this.git); + } + + this.clearAnnotations(e.textEditor); + this._updateBlameDebounced(line, e.textEditor); + } + + private getLineAnnotationState() { + return this._blameLineAnnotationState !== undefined ? this._blameLineAnnotationState : this._config.blame.line; + } + + private isEditorBlameable(editor: TextEditor | undefined): boolean { + if (editor === undefined || editor.document === undefined) return false; + + if (!this.git.isTrackable(editor.document.uri)) return false; + if (editor.document.isUntitled && editor.document.uri.scheme === DocumentSchemes.File) return false; + + return this.git.isEditorBlameable(editor); + } + + private async updateBlame(line: number, editor: TextEditor) { + this._currentLine.line = line; + this._currentLine.commit = undefined; + this._currentLine.logCommit = undefined; + + let commit: GitCommit | undefined = undefined; + let commitLine: GitCommitLine | undefined = undefined; + // Since blame information isn't valid when there are unsaved changes -- don't show any status + if (this._blameable && line >= 0) { + const blameLine = await this.git.getBlameForLine(this._uri, line); + commitLine = blameLine === undefined ? undefined : blameLine.line; + commit = blameLine === undefined ? undefined : blameLine.commit; + } + + this._currentLine.commit = commit; + + if (commit !== undefined && commitLine !== undefined) { + this.show(commit, commitLine, editor, line); + } + else { + this.clear(editor); + } + } + + async clear(editor: TextEditor | undefined) { + this.unregisterHoverProviders(); + this.clearAnnotations(editor, true); + this._statusBarItem && this._statusBarItem.hide(); + } + + private async clearAnnotations(editor: TextEditor | undefined, force: boolean = false) { + if (editor === undefined || (!this._isAnnotating && !force)) return; + + editor.setDecorations(annotationDecoration, []); + this._isAnnotating = false; + + if (!force) return; + + // I have no idea why the decorators sometimes don't get removed, but if they don't try again with a tiny delay + await Functions.wait(1); + editor.setDecorations(annotationDecoration, []); + } + + async refresh(editor?: TextEditor) { + this._currentLine.line = -1; + this.clearAnnotations(this._editor); + + if (editor === undefined || !this.isEditorBlameable(editor)) { + this.clear(editor); + this._editor = undefined; + + return; + } + + this._blameable = editor !== undefined && editor.document !== undefined && !editor.document.isDirty; + this._editor = editor; + this._uri = await GitUri.fromUri(editor.document.uri, this.git); + + const maxLines = this._config.advanced.caching.maxLines; + // If caching is on and the file is small enough -- kick off a blame for the whole file + if (this._config.advanced.caching.enabled && (maxLines <= 0 || editor.document.lineCount <= maxLines)) { + this.git.getBlameForFile(this._uri); + } + + const state = this.getLineAnnotationState(); + if (state.enabled && this._blameable) { + const cfg = this._config.annotations.line; + this.registerHoverProviders(state.annotationType === LineAnnotationType.Trailing ? cfg.trailing.hover : cfg.hover); + } + else { + this.unregisterHoverProviders(); + } + + this._updateBlameDebounced(editor.selection.active.line, editor); + } + + async show(commit: GitCommit, blameLine: GitCommitLine, editor: TextEditor, line: number) { + // I have no idea why I need this protection -- but it happens + if (editor.document === undefined) return; + + this.updateStatusBar(commit); + this.updateTrailingAnnotation(commit, blameLine, editor, line); + } + + async showAnnotations(editor: TextEditor | undefined, type: LineAnnotationType, reason: 'user' | 'debugging' = 'user') { + if (editor === undefined) return; + + const state = this.getLineAnnotationState(); + if (!state.enabled || state.annotationType !== type) { + this._blameLineAnnotationState = { enabled: true, annotationType: type, reason: reason }; + + await this.clearAnnotations(editor); + await this.updateBlame(editor.selection.active.line, editor); + } + } + + async toggleAnnotations(editor: TextEditor | undefined, type: LineAnnotationType, reason: 'user' | 'debugging' = 'user') { + if (editor === undefined) return; + + const state = this.getLineAnnotationState(); + this._blameLineAnnotationState = { enabled: !state.enabled, annotationType: type, reason: reason }; + + await this.clearAnnotations(editor); + await this.updateBlame(editor.selection.active.line, editor); + } + + private updateStatusBar(commit: GitCommit) { + const cfg = this._config.statusBar; + if (!cfg.enabled || this._statusBarItem === undefined) return; + + this._statusBarItem.text = `$(git-commit) ${CommitFormatter.fromTemplate(cfg.format, commit, { + truncateMessageAtNewLine: true, + dateFormat: cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat + } as ICommitFormatOptions)}`; + + switch (cfg.command) { + case StatusBarCommand.ToggleFileBlame: + this._statusBarItem.tooltip = 'Toggle Blame Annotations'; + break; + case StatusBarCommand.DiffWithPrevious: + this._statusBarItem.command = Commands.DiffLineWithPrevious; + this._statusBarItem.tooltip = 'Compare Line Revision with Previous'; + break; + case StatusBarCommand.DiffWithWorking: + this._statusBarItem.command = Commands.DiffLineWithWorking; + this._statusBarItem.tooltip = 'Compare Line Revision with Working'; + break; + case StatusBarCommand.ToggleCodeLens: + this._statusBarItem.tooltip = 'Toggle Git CodeLens'; + break; + case StatusBarCommand.ShowQuickCommitDetails: + this._statusBarItem.tooltip = 'Show Commit Details'; + break; + case StatusBarCommand.ShowQuickCommitFileDetails: + this._statusBarItem.tooltip = 'Show Line Commit Details'; + break; + case StatusBarCommand.ShowQuickFileHistory: + this._statusBarItem.tooltip = 'Show File History'; + break; + case StatusBarCommand.ShowQuickCurrentBranchHistory: + this._statusBarItem.tooltip = 'Show Branch History'; + break; + } + + this._statusBarItem.show(); + } + + private async updateTrailingAnnotation(commit: GitCommit, blameLine: GitCommitLine, editor: TextEditor, line?: number) { + const state = this.getLineAnnotationState(); + if (!state.enabled || state.annotationType !== LineAnnotationType.Trailing) return; + + line = line === undefined ? blameLine.line : line; + + const cfg = this._config.annotations.line.trailing; + const decoration = Annotations.trailing(commit, cfg.format, cfg.dateFormat === null ? this._config.defaultDateFormat : cfg.dateFormat, this._config.theme); + decoration.range = editor.document.validateRange(new Range(line, endOfLineIndex, line, endOfLineIndex)); + + editor.setDecorations(annotationDecoration, [decoration]); + this._isAnnotating = true; + } + + registerHoverProviders(providers: { details: boolean, changes: boolean }) { + this.unregisterHoverProviders(); + + if (this._editor === undefined) return; + if (!providers.details && !providers.changes) return; + + const subscriptions: Disposable[] = []; + if (providers.changes) { + subscriptions.push(languages.registerHoverProvider({ pattern: this._editor.document.uri.fsPath }, { provideHover: this.provideChangesHover.bind(this) } as HoverProvider)); + } + if (providers.details) { + subscriptions.push(languages.registerHoverProvider({ pattern: this._editor.document.uri.fsPath }, { provideHover: this.provideDetailsHover.bind(this) } as HoverProvider)); + } + + this._hoverProviderDisposable = Disposable.from(...subscriptions); + } + + unregisterHoverProviders() { + if (this._hoverProviderDisposable !== undefined) { + this._hoverProviderDisposable.dispose(); + this._hoverProviderDisposable = undefined; + } + } + + async provideDetailsHover(document: TextDocument, position: Position, token: CancellationToken): Promise { + if (this._editor === undefined || this._editor.document !== document) return undefined; + if (this._currentLine.line !== position.line) return undefined; + + const commit = this._currentLine.commit; + if (commit === undefined) return undefined; + + const fileAnnotations = this.annotationController.getAnnotationType(this._editor); + // Avoid double annotations if we are showing the whole-file hover blame annotations + if ((fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.details) || + (fileAnnotations === FileAnnotationType.Hover && this._config.annotations.file.hover.details)) { + return undefined; + } + + const state = this.getLineAnnotationState(); + const wholeLine = state.annotationType === LineAnnotationType.Hover || (state.annotationType === LineAnnotationType.Trailing && this._config.annotations.line.trailing.hover.wholeLine) || + fileAnnotations === FileAnnotationType.Hover || (fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.wholeLine); + + const range = document.validateRange(new Range(position.line, wholeLine ? 0 : endOfLineIndex, position.line, endOfLineIndex)); + if (!wholeLine && range.start.character !== position.character) return undefined; + + // Get the full commit message -- since blame only returns the summary + let logCommit = this._currentLine.logCommit; + if (logCommit === undefined && !commit.isUncommitted) { + logCommit = await this.git.getLogCommit(commit.repoPath, commit.uri.fsPath, commit.sha); + if (logCommit !== undefined) { + // Preserve the previous commit from the blame commit + logCommit.previousFileName = commit.previousFileName; + logCommit.previousSha = commit.previousSha; + + this._currentLine.logCommit = logCommit; + } + } + + const message = Annotations.getHoverMessage(logCommit || commit, this._config.defaultDateFormat, this.git.hasRemotes(commit.repoPath), this._config.blame.file.annotationType); + return new Hover(message, range); + } + + async provideChangesHover(document: TextDocument, position: Position, token: CancellationToken): Promise { + if (this._editor === undefined || this._editor.document !== document) return undefined; + if (this._currentLine.line !== position.line) return undefined; + + const commit = this._currentLine.commit; + if (commit === undefined) return undefined; + + const fileAnnotations = this.annotationController.getAnnotationType(this._editor); + // Avoid double annotations if we are showing the whole-file hover blame annotations + if ((fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.changes) || + (fileAnnotations === FileAnnotationType.Hover && this._config.annotations.file.hover.changes)) { + return undefined; + } + + const state = this.getLineAnnotationState(); + const wholeLine = state.annotationType === LineAnnotationType.Hover || (state.annotationType === LineAnnotationType.Trailing && this._config.annotations.line.trailing.hover.wholeLine) || + fileAnnotations === FileAnnotationType.Hover || (fileAnnotations === FileAnnotationType.Gutter && this._config.annotations.file.gutter.hover.wholeLine); + + const range = document.validateRange(new Range(position.line, wholeLine ? 0 : endOfLineIndex, position.line, endOfLineIndex)); + if (!wholeLine && range.start.character !== position.character) return undefined; + + const hover = await Annotations.changesHover(commit, position.line, this._uri, this.git); + return new Hover(hover.hoverMessage!, range); + } } \ No newline at end of file diff --git a/src/git/gitContextTracker.ts b/src/git/gitContextTracker.ts index ef7263d..3aaca09 100644 --- a/src/git/gitContextTracker.ts +++ b/src/git/gitContextTracker.ts @@ -44,7 +44,9 @@ export class GitContextTracker extends Disposable { private _disposable: Disposable | undefined; private _gitEnabled: boolean; - constructor(private git: GitService) { + constructor( + private readonly git: GitService + ) { super(() => this.dispose()); this.onConfigurationChanged(); diff --git a/src/git/models/branch.ts b/src/git/models/branch.ts index 2f55c19..a3304bd 100644 --- a/src/git/models/branch.ts +++ b/src/git/models/branch.ts @@ -7,7 +7,12 @@ export class GitBranch { remote: boolean; tracking?: string; - constructor(public readonly repoPath: string, branch: string, current: boolean = false, tracking?: string) { + constructor( + public readonly repoPath: string, + branch: string, + current: boolean = false, + tracking?: string + ) { if (branch.startsWith('remotes/')) { branch = branch.substring(8); this.remote = true; diff --git a/src/git/models/diff.ts b/src/git/models/diff.ts index ce6b90d..cc76fdc 100644 --- a/src/git/models/diff.ts +++ b/src/git/models/diff.ts @@ -15,7 +15,11 @@ export class GitDiffChunk { private _chunk: string | undefined; private _lines: GitDiffChunkLine[] | undefined; - constructor(chunk: string, public currentPosition: { start: number, end: number }, public previousPosition: { start: number, end: number }) { + constructor( + chunk: string, + public currentPosition: { start: number, end: number }, + public previousPosition: { start: number, end: number } + ) { this._chunk = chunk; } diff --git a/src/git/models/repository.ts b/src/git/models/repository.ts index b09b959..325d1f6 100644 --- a/src/git/models/repository.ts +++ b/src/git/models/repository.ts @@ -12,7 +12,9 @@ export class RepositoryChangeEvent { readonly changes: RepositoryChange[] = []; - constructor(public repository?: Repository) { } + constructor( + public repository?: Repository + ) { } changed(change: RepositoryChange, solely: boolean = false) { if (solely) return this.changes.length === 1 && this.changes[0] === change; diff --git a/src/git/models/status.ts b/src/git/models/status.ts index 6b506a4..22fb53e 100644 --- a/src/git/models/status.ts +++ b/src/git/models/status.ts @@ -38,7 +38,15 @@ export class GitStatusFile implements IGitStatusFile { originalFileName?: string; - constructor(public repoPath: string, public status: GitStatusFileStatus, public workTreeStatus: GitStatusFileStatus, public indexStatus: GitStatusFileStatus, public fileName: string, public staged: boolean, originalFileName?: string) { + constructor( + public repoPath: string, + public status: GitStatusFileStatus, + public workTreeStatus: GitStatusFileStatus, + public indexStatus: GitStatusFileStatus, + public fileName: string, + public staged: boolean, + originalFileName?: string + ) { this.originalFileName = originalFileName; } diff --git a/src/git/remotes/bitbucket-server.ts b/src/git/remotes/bitbucket-server.ts index 2b25c8a..8fd8e82 100644 --- a/src/git/remotes/bitbucket-server.ts +++ b/src/git/remotes/bitbucket-server.ts @@ -4,7 +4,12 @@ import { RemoteProvider } from './provider'; export class BitbucketServerService extends RemoteProvider { - constructor(domain: string, path: string, name?: string, custom: boolean = false) { + constructor( + domain: string, + path: string, + name?: string, + custom: boolean = false + ) { super(domain, path, name, custom); } diff --git a/src/git/remotes/bitbucket.ts b/src/git/remotes/bitbucket.ts index c6accbe..0cc11dd 100644 --- a/src/git/remotes/bitbucket.ts +++ b/src/git/remotes/bitbucket.ts @@ -4,7 +4,12 @@ import { RemoteProvider } from './provider'; export class BitbucketService extends RemoteProvider { - constructor(domain: string, path: string, name?: string, custom: boolean = false) { + constructor( + domain: string, + path: string, + name?: string, + custom: boolean = false + ) { super(domain, path, name, custom); } diff --git a/src/git/remotes/custom.ts b/src/git/remotes/custom.ts index 7d7d68b..6f5c2ce 100644 --- a/src/git/remotes/custom.ts +++ b/src/git/remotes/custom.ts @@ -6,7 +6,11 @@ import { RemoteProvider } from './provider'; export class CustomService extends RemoteProvider { - constructor(domain: string, path: string, private readonly config: IRemotesConfig) { + constructor( + domain: string, + path: string, + private readonly config: IRemotesConfig + ) { super(domain, path, config.name, true); } diff --git a/src/git/remotes/github.ts b/src/git/remotes/github.ts index 804d9b8..6a855be 100644 --- a/src/git/remotes/github.ts +++ b/src/git/remotes/github.ts @@ -4,7 +4,12 @@ import { RemoteProvider } from './provider'; export class GitHubService extends RemoteProvider { - constructor(domain: string, path: string, name?: string, custom: boolean = false) { + constructor( + domain: string, + path: string, + name?: string, + custom: boolean = false + ) { super(domain, path, name, custom); } diff --git a/src/git/remotes/gitlab.ts b/src/git/remotes/gitlab.ts index 7062846..57f7b24 100644 --- a/src/git/remotes/gitlab.ts +++ b/src/git/remotes/gitlab.ts @@ -4,7 +4,12 @@ import { RemoteProvider } from './provider'; export class GitLabService extends RemoteProvider { - constructor(domain: string, path: string, name?: string, custom: boolean = false) { + constructor( + domain: string, + path: string, + name?: string, + custom: boolean = false + ) { super(domain, path, name, custom); } diff --git a/src/git/remotes/visualStudio.ts b/src/git/remotes/visualStudio.ts index d28fd43..6ae57d0 100644 --- a/src/git/remotes/visualStudio.ts +++ b/src/git/remotes/visualStudio.ts @@ -4,7 +4,11 @@ import { RemoteProvider } from './provider'; export class VisualStudioService extends RemoteProvider { - constructor(domain: string, path: string, name?: string) { + constructor( + domain: string, + path: string, + name?: string + ) { super(domain, path, name); } diff --git a/src/gitCodeLensProvider.ts b/src/gitCodeLensProvider.ts index f969d14..a7aa4a4 100644 --- a/src/gitCodeLensProvider.ts +++ b/src/gitCodeLensProvider.ts @@ -10,11 +10,11 @@ import { Logger } from './logger'; export class GitRecentChangeCodeLens extends CodeLens { constructor( - public symbolKind: SymbolKind, - public uri: GitUri | undefined, - private blame: (() => GitBlameLines | undefined) | undefined, - public blameRange: Range, - public isFullRange: boolean, + public readonly symbolKind: SymbolKind, + public readonly uri: GitUri | undefined, + private readonly blame: (() => GitBlameLines | undefined) | undefined, + public readonly blameRange: Range, + public readonly isFullRange: boolean, range: Range, public dirty: boolean ) { @@ -29,11 +29,11 @@ export class GitRecentChangeCodeLens extends CodeLens { export class GitAuthorsCodeLens extends CodeLens { constructor( - public symbolKind: SymbolKind, - public uri: GitUri | undefined, - private blame: () => GitBlameLines | undefined, - public blameRange: Range, - public isFullRange: boolean, + public readonly symbolKind: SymbolKind, + public readonly uri: GitUri | undefined, + private readonly blame: () => GitBlameLines | undefined, + public readonly blameRange: Range, + public readonly isFullRange: boolean, range: Range ) { super(range); @@ -55,7 +55,10 @@ export class GitCodeLensProvider implements CodeLensProvider { private _config: IConfig; - constructor(context: ExtensionContext, private git: GitService) { + constructor( + context: ExtensionContext, + private readonly git: GitService + ) { this._config = workspace.getConfiguration().get(ExtensionKey)!; } diff --git a/src/gitContentProvider.ts b/src/gitContentProvider.ts index 359112a..b4e5aad 100644 --- a/src/gitContentProvider.ts +++ b/src/gitContentProvider.ts @@ -9,7 +9,10 @@ export class GitContentProvider implements TextDocumentContentProvider { static scheme = DocumentSchemes.GitLensGit; - constructor(context: ExtensionContext, private git: GitService) { } + constructor( + context: ExtensionContext, + private readonly git: GitService + ) { } async provideTextDocumentContent(uri: Uri, token: CancellationToken): Promise { const data = GitService.fromGitContentUri(uri); diff --git a/src/gitRevisionCodeLensProvider.ts b/src/gitRevisionCodeLensProvider.ts index 0bbd3af..51507ca 100644 --- a/src/gitRevisionCodeLensProvider.ts +++ b/src/gitRevisionCodeLensProvider.ts @@ -7,14 +7,24 @@ import { GitCommit, GitService, GitUri } from './gitService'; export class GitDiffWithWorkingCodeLens extends CodeLens { - constructor(git: GitService, public fileName: string, public commit: GitCommit, range: Range) { + constructor( + git: GitService, + public fileName: string, + public commit: GitCommit, + range: Range + ) { super(range); } } export class GitDiffWithPreviousCodeLens extends CodeLens { - constructor(git: GitService, public fileName: string, public commit: GitCommit, range: Range) { + constructor( + git: GitService, + public fileName: string, + public commit: GitCommit, + range: Range + ) { super(range); } } diff --git a/src/gitService.ts b/src/gitService.ts index a641a9d..da577ac 100644 --- a/src/gitService.ts +++ b/src/gitService.ts @@ -20,14 +20,18 @@ export * from './git/gitContextTracker'; class UriCacheEntry { - constructor(public readonly uri: GitUri) { } + constructor( + public readonly uri: GitUri + ) { } } class GitCacheEntry { private cache: Map = new Map(); - constructor(public readonly key: string) { } + constructor( + public readonly key: string + ) { } get hasErrors(): boolean { return Iterables.every(this.cache.values(), entry => entry.errorMessage !== undefined); diff --git a/src/keyboard.ts b/src/keyboard.ts index d9cef98..fed5446 100644 --- a/src/keyboard.ts +++ b/src/keyboard.ts @@ -29,7 +29,9 @@ let _instance: Keyboard; export class KeyboardScope extends Disposable { - constructor(private mapping: KeyMapping) { + constructor( + private readonly mapping: KeyMapping + ) { super(() => this.dispose()); for (const key in mapping) { diff --git a/src/quickPicks/branches.ts b/src/quickPicks/branches.ts index f5a72a1..c098681 100644 --- a/src/quickPicks/branches.ts +++ b/src/quickPicks/branches.ts @@ -10,7 +10,9 @@ export class BranchQuickPickItem implements QuickPickItem { description: string; detail: string; - constructor(public branch: GitBranch) { + constructor( + public readonly branch: GitBranch + ) { this.label = `${branch.current ? `$(check)${GlyphChars.Space}` : GlyphChars.Space.repeat(4)} ${branch.name}`; this.description = branch.remote ? `${GlyphChars.Space.repeat(2)} remote branch` : ''; } diff --git a/src/quickPicks/commitDetails.ts b/src/quickPicks/commitDetails.ts index f5d79a3..a0cf7a4 100644 --- a/src/quickPicks/commitDetails.ts +++ b/src/quickPicks/commitDetails.ts @@ -18,7 +18,10 @@ export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickI shortSha: string; status: GitStatusFileStatus; - constructor(commit: GitCommit, status: IGitStatusFile) { + constructor( + commit: GitCommit, + status: IGitStatusFile + ) { const octicon = getGitStatusOcticon(status.status); const description = GitStatusFile.getFormattedDirectory(status, true); @@ -65,7 +68,11 @@ export class CommitWithFileStatusQuickPickItem extends OpenFileCommandQuickPickI export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPickItem { - constructor(commit: GitLogCommit, versioned: boolean = false, item?: QuickPickItem) { + constructor( + commit: GitLogCommit, + versioned: boolean = false, + item?: QuickPickItem + ) { const repoPath = commit.repoPath; const uris = commit.fileStatuses .filter(s => s.status !== 'D') @@ -81,7 +88,10 @@ export class OpenCommitFilesCommandQuickPickItem extends OpenFilesCommandQuickPi export class OpenCommitFileRevisionsCommandQuickPickItem extends OpenFilesCommandQuickPickItem { - constructor(commit: GitLogCommit, item?: QuickPickItem) { + constructor( + commit: GitLogCommit, + item?: QuickPickItem + ) { const uris = commit.fileStatuses .filter(s => s.status !== 'D') .map(s => GitService.toGitContentUri(commit.sha, s.fileName, commit.repoPath, s.originalFileName)); diff --git a/src/quickPicks/commitFileDetails.ts b/src/quickPicks/commitFileDetails.ts index ede08fc..eee9f51 100644 --- a/src/quickPicks/commitFileDetails.ts +++ b/src/quickPicks/commitFileDetails.ts @@ -11,7 +11,10 @@ import * as path from 'path'; export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { - constructor(commit: GitLogCommit, item?: QuickPickItem) { + constructor( + commit: GitLogCommit, + item?: QuickPickItem + ) { const uri = Uri.file(path.resolve(commit.repoPath, commit.fileName)); super(uri, item || { label: `$(file-symlink-file) Open File`, @@ -22,7 +25,10 @@ export class OpenCommitFileCommandQuickPickItem extends OpenFileCommandQuickPick export class OpenCommitFileRevisionCommandQuickPickItem extends OpenFileCommandQuickPickItem { - constructor(commit: GitLogCommit, item?: QuickPickItem) { + constructor( + commit: GitLogCommit, + item?: QuickPickItem + ) { let description: string; let uri: Uri; if (commit.status === 'D') { diff --git a/src/quickPicks/remotes.ts b/src/quickPicks/remotes.ts index e784bdc..9f1833b 100644 --- a/src/quickPicks/remotes.ts +++ b/src/quickPicks/remotes.ts @@ -12,7 +12,10 @@ export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem { private remote: GitRemote; private resource: RemoteResource; - constructor(remote: GitRemote, resource: RemoteResource) { + constructor( + remote: GitRemote, + resource: RemoteResource + ) { super({ label: `$(link-external) Open ${getNameFromRemoteResource(resource)} in ${remote.provider!.name}`, description: `${Strings.pad(GlyphChars.Dash, 2, 3)} $(repo) ${remote.provider!.path}` @@ -29,7 +32,11 @@ export class OpenRemoteCommandQuickPickItem extends CommandQuickPickItem { export class OpenRemotesCommandQuickPickItem extends CommandQuickPickItem { - constructor(remotes: GitRemote[], resource: RemoteResource, goBackCommand?: CommandQuickPickItem) { + constructor( + remotes: GitRemote[], + resource: RemoteResource, + goBackCommand?: CommandQuickPickItem + ) { const name = getNameFromRemoteResource(resource); let description = ''; diff --git a/src/quickPicks/repoStatus.ts b/src/quickPicks/repoStatus.ts index 2dc3da0..458efa6 100644 --- a/src/quickPicks/repoStatus.ts +++ b/src/quickPicks/repoStatus.ts @@ -10,7 +10,10 @@ import * as path from 'path'; export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPickItem { - constructor(status: GitStatusFile, item?: QuickPickItem) { + constructor( + status: GitStatusFile, + item?: QuickPickItem + ) { const octicon = status.getOcticon(); const description = status.getFormattedDirectory(true); @@ -34,7 +37,10 @@ export class OpenStatusFileCommandQuickPickItem extends OpenFileCommandQuickPick export class OpenStatusFilesCommandQuickPickItem extends CommandQuickPickItem { - constructor(statuses: GitStatusFile[], item?: QuickPickItem) { + constructor( + statuses: GitStatusFile[], + item?: QuickPickItem + ) { const uris = statuses.map(f => f.Uri); super(item || { diff --git a/src/views/explorerNode.ts b/src/views/explorerNode.ts index ac5b0a8..a5a7f1c 100644 --- a/src/views/explorerNode.ts +++ b/src/views/explorerNode.ts @@ -34,7 +34,9 @@ export abstract class ExplorerNode extends Disposable { protected children: ExplorerNode[] | undefined; protected disposable: Disposable | undefined; - constructor(public readonly uri: GitUri) { + constructor( + public readonly uri: GitUri + ) { super(() => this.dispose()); } @@ -66,7 +68,9 @@ export class MessageNode extends ExplorerNode { readonly resourceType: ResourceType = 'gitlens:message'; - constructor(private message: string) { + constructor( + private readonly message: string + ) { super(new GitUri()); } @@ -86,7 +90,11 @@ export class PagerNode extends ExplorerNode { readonly resourceType: ResourceType = 'gitlens:pager'; args: RefreshNodeCommandArgs = {}; - constructor(private message: string, private node: ExplorerNode, protected readonly context: ExtensionContext) { + constructor( + private readonly message: string, + private readonly node: ExplorerNode, + protected readonly context: ExtensionContext + ) { super(new GitUri()); } @@ -118,7 +126,11 @@ export class ShowAllNode extends PagerNode { args: RefreshNodeCommandArgs = { maxCount: 0 }; - constructor(message: string, node: ExplorerNode, context: ExtensionContext) { + constructor( + message: string, + node: ExplorerNode, + context: ExtensionContext + ) { super(`${message} ${GlyphChars.Space}${GlyphChars.Dash}${GlyphChars.Space} this may take a while`, node, context); } } \ No newline at end of file diff --git a/src/views/fileHistoryNode.ts b/src/views/fileHistoryNode.ts index 3daea90..8568eb9 100644 --- a/src/views/fileHistoryNode.ts +++ b/src/views/fileHistoryNode.ts @@ -13,7 +13,7 @@ export class FileHistoryNode extends ExplorerNode { constructor( uri: GitUri, - private repo: Repository, + private readonly repo: Repository, private readonly explorer: GitExplorer ) { super(uri); diff --git a/src/views/folderNode.ts b/src/views/folderNode.ts index be2648f..8a88e08 100644 --- a/src/views/folderNode.ts +++ b/src/views/folderNode.ts @@ -20,8 +20,8 @@ export class FolderNode extends ExplorerNode { constructor( public readonly repoPath: string, - public folderName: string, - public relativePath: string | undefined, + public readonly folderName: string, + public readonly relativePath: string | undefined, public readonly root: Arrays.IHierarchicalItem, private readonly config: IGitExplorerConfig ) { diff --git a/src/views/gitExplorer.ts b/src/views/gitExplorer.ts index 469f8c4..d653101 100644 --- a/src/views/gitExplorer.ts +++ b/src/views/gitExplorer.ts @@ -52,7 +52,10 @@ export class GitExplorer implements TreeDataProvider { return this._onDidChangeTreeData.event; } - constructor(public readonly context: ExtensionContext, public readonly git: GitService) { + constructor( + public readonly context: ExtensionContext, + public readonly git: GitService + ) { commands.registerCommand('gitlens.gitExplorer.setAutoRefreshToOn', () => this.setAutoRefresh(this.git.config.gitExplorer.autoRefresh, true), this); commands.registerCommand('gitlens.gitExplorer.setAutoRefreshToOff', () => this.setAutoRefresh(this.git.config.gitExplorer.autoRefresh, false), this); commands.registerCommand('gitlens.gitExplorer.setFilesLayoutToAuto', () => this.setFilesLayout(GitExplorerFilesLayout.Auto), this); diff --git a/src/views/historyNode.ts b/src/views/historyNode.ts index 3746c13..07806c1 100644 --- a/src/views/historyNode.ts +++ b/src/views/historyNode.ts @@ -11,7 +11,7 @@ export class HistoryNode extends ExplorerNode { constructor( uri: GitUri, - private repo: Repository, + private readonly repo: Repository, private readonly explorer: GitExplorer ) { super(uri); diff --git a/src/views/repositoryNode.ts b/src/views/repositoryNode.ts index 145f244..d2f5648 100644 --- a/src/views/repositoryNode.ts +++ b/src/views/repositoryNode.ts @@ -17,7 +17,7 @@ export class RepositoryNode extends ExplorerNode { constructor( uri: GitUri, - private repo: Repository, + private readonly repo: Repository, private readonly explorer: GitExplorer ) { super(uri); diff --git a/src/views/statusFileCommitsNode.ts b/src/views/statusFileCommitsNode.ts index 557a356..5658b4a 100644 --- a/src/views/statusFileCommitsNode.ts +++ b/src/views/statusFileCommitsNode.ts @@ -13,7 +13,7 @@ export class StatusFileCommitsNode extends ExplorerNode { constructor( public readonly repoPath: string, public readonly status: IGitStatusFile, - public commits: GitLogCommit[], + public readonly commits: GitLogCommit[], protected readonly context: ExtensionContext, protected readonly git: GitService, public readonly branch?: GitBranch diff --git a/src/views/statusNode.ts b/src/views/statusNode.ts index c403d48..ccd7e4e 100644 --- a/src/views/statusNode.ts +++ b/src/views/statusNode.ts @@ -12,8 +12,8 @@ export class StatusNode extends ExplorerNode { constructor( uri: GitUri, - private repo: Repository, - private parent: ExplorerNode, + private readonly repo: Repository, + private readonly parent: ExplorerNode, private readonly explorer: GitExplorer ) { super(uri);