25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

426 satır
20 KiB

Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
7 yıl önce
Major refactor/rework -- many new features and breaking changes Adds all-new, beautiful, highly customizable and themeable, file blame annotations Adds all-new configurability and themeability to the current line blame annotations Adds all-new configurability to the status bar blame information Adds all-new configurability over which commands are added to which menus via the `gitlens.advanced.menus` setting Adds better configurability over where Git code lens will be shown -- both by default and per language Adds an all-new `changes` (diff) hover annotation to the current line - provides instant access to the line's previous version Adds `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) - toggles the current line blame annotations on and off Adds `Show Line Blame Annotations` command (`gitlens.showLineBlame`) - shows the current line blame annotations Adds `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) - toggles the file blame annotations on and off Adds `Show File Blame Annotations` command (`gitlens.showFileBlame`) - shows the file blame annotations Adds `Open File in Remote` command (`gitlens.openFileInRemote`) to the `editor/title` context menu Adds `Open Repo in Remote` command (`gitlens.openRepoInRemote`) to the `editor/title` context menu Changes the position of the `Open File in Remote` command (`gitlens.openFileInRemote`) in the context menus - now in the `navigation` group Changes the `Toggle Git Code Lens` command (`gitlens.toggleCodeLens`) to always toggle the Git code lens on and off Removes the on-demand `trailing` file blame annotations -- didn't work out and just ended up with a ton of visual noise Removes `Toggle Blame Annotations` command (`gitlens.toggleBlame`) - replaced by the `Toggle File Blame Annotations` command (`gitlens.toggleFileBlame`) Removes `Show Blame Annotations` command (`gitlens.showBlame`) - replaced by the `Show File Blame Annotations` command (`gitlens.showFileBlame`)
7 yıl önce
  1. 'use strict';
  2. import { Functions, Iterables } from './system';
  3. import { CancellationToken, CodeLens, CodeLensProvider, Command, commands, DocumentSelector, Event, EventEmitter, ExtensionContext, Position, Range, SymbolInformation, SymbolKind, TextDocument, Uri, workspace } from 'vscode';
  4. import { Commands, DiffWithPreviousCommandArgs, ShowBlameHistoryCommandArgs, ShowFileHistoryCommandArgs, ShowQuickCommitDetailsCommandArgs, ShowQuickCommitFileDetailsCommandArgs, ShowQuickFileHistoryCommandArgs } from './commands';
  5. import { BuiltInCommands, DocumentSchemes, ExtensionKey } from './constants';
  6. import { CodeLensCommand, CodeLensLocations, ICodeLensLanguageLocation, IConfig } from './configuration';
  7. import { GitBlame, GitBlameCommit, GitBlameLines, GitService, GitUri } from './gitService';
  8. import { Logger } from './logger';
  9. export class GitRecentChangeCodeLens extends CodeLens {
  10. constructor(private blame: () => GitBlameLines | undefined, public uri: GitUri, public symbolKind: SymbolKind, public blameRange: Range, public isFullRange: boolean, range: Range) {
  11. super(range);
  12. }
  13. getBlame(): GitBlameLines | undefined {
  14. return this.blame();
  15. }
  16. }
  17. export class GitAuthorsCodeLens extends CodeLens {
  18. constructor(private blame: () => GitBlameLines | undefined, public uri: GitUri, public symbolKind: SymbolKind, public blameRange: Range, public isFullRange: boolean, range: Range) {
  19. super(range);
  20. }
  21. getBlame(): GitBlameLines | undefined {
  22. return this.blame();
  23. }
  24. }
  25. export class GitCodeLensProvider implements CodeLensProvider {
  26. private _onDidChangeCodeLenses = new EventEmitter<void>();
  27. public get onDidChangeCodeLenses(): Event<void> {
  28. return this._onDidChangeCodeLenses.event;
  29. }
  30. static selector: DocumentSelector = { scheme: DocumentSchemes.File };
  31. private _config: IConfig;
  32. private _documentIsDirty: boolean;
  33. constructor(context: ExtensionContext, private git: GitService) {
  34. this._config = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
  35. }
  36. reset() {
  37. this._config = workspace.getConfiguration().get<IConfig>(ExtensionKey)!;
  38. Logger.log('Triggering a reset of the git CodeLens provider');
  39. this._onDidChangeCodeLenses.fire();
  40. }
  41. async provideCodeLenses(document: TextDocument, token: CancellationToken): Promise<CodeLens[]> {
  42. this._documentIsDirty = document.isDirty;
  43. let languageLocations = this._config.codeLens.perLanguageLocations.find(_ => _.language !== undefined && _.language.toLowerCase() === document.languageId);
  44. if (languageLocations == null) {
  45. languageLocations = {
  46. language: undefined,
  47. locations: this._config.codeLens.locations,
  48. customSymbols: this._config.codeLens.customLocationSymbols
  49. } as ICodeLensLanguageLocation;
  50. }
  51. const lenses: CodeLens[] = [];
  52. const gitUri = await GitUri.fromUri(document.uri, this.git);
  53. const blamePromise = this.git.getBlameForFile(gitUri);
  54. let blame: GitBlame | undefined;
  55. if (languageLocations.locations.length === 1 && languageLocations.locations.includes(CodeLensLocations.Document)) {
  56. blame = await blamePromise;
  57. if (blame === undefined || blame.lines.length === 0) return lenses;
  58. }
  59. else {
  60. const values = await Promise.all([
  61. blamePromise as Promise<any>,
  62. commands.executeCommand(BuiltInCommands.ExecuteDocumentSymbolProvider, document.uri) as Promise<any>
  63. ]);
  64. blame = values[0] as GitBlame;
  65. if (blame === undefined || blame.lines.length === 0) return lenses;
  66. const symbols = values[1] as SymbolInformation[];
  67. Logger.log('GitCodeLensProvider.provideCodeLenses:', `${symbols.length} symbol(s) found`);
  68. symbols.forEach(sym => this._provideCodeLens(gitUri, document, sym, languageLocations!, blame!, lenses));
  69. }
  70. if (languageLocations.locations.includes(CodeLensLocations.Document) ||
  71. (languageLocations.locations.includes(CodeLensLocations.Custom) && (languageLocations.customSymbols || []).find(_ => _.toLowerCase() === 'file'))) {
  72. // Check if we have a lens for the whole document -- if not add one
  73. if (!lenses.find(l => l.range.start.line === 0 && l.range.end.line === 0)) {
  74. const blameRange = document.validateRange(new Range(0, 1000000, 1000000, 1000000));
  75. let blameForRangeFn: (() => GitBlameLines | undefined) | undefined = undefined;
  76. if (this._documentIsDirty || this._config.codeLens.recentChange.enabled) {
  77. blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame!, gitUri, blameRange));
  78. lenses.push(new GitRecentChangeCodeLens(blameForRangeFn, gitUri, SymbolKind.File, blameRange, true, new Range(0, 0, 0, blameRange.start.character)));
  79. }
  80. if (this._config.codeLens.authors.enabled) {
  81. if (blameForRangeFn === undefined) {
  82. blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame!, gitUri, blameRange));
  83. }
  84. if (!this._documentIsDirty) {
  85. lenses.push(new GitAuthorsCodeLens(blameForRangeFn, gitUri, SymbolKind.File, blameRange, true, new Range(0, 1, 0, blameRange.start.character)));
  86. }
  87. }
  88. }
  89. }
  90. return lenses;
  91. }
  92. private _validateSymbolAndGetBlameRange(document: TextDocument, symbol: SymbolInformation, languageLocation: ICodeLensLanguageLocation): Range | undefined {
  93. let valid = false;
  94. let range: Range | undefined;
  95. switch (symbol.kind) {
  96. case SymbolKind.File:
  97. if (languageLocation.locations.includes(CodeLensLocations.Containers)) {
  98. valid = true;
  99. }
  100. else if (languageLocation.locations.includes(CodeLensLocations.Custom)) {
  101. valid = !!(languageLocation.customSymbols || []).find(_ => _.toLowerCase() === SymbolKind[symbol.kind].toLowerCase());
  102. }
  103. if (valid) {
  104. // Adjust the range to be for the whole file
  105. range = document.validateRange(new Range(0, 1000000, 1000000, 1000000));
  106. }
  107. break;
  108. case SymbolKind.Package:
  109. if (languageLocation.locations.includes(CodeLensLocations.Containers)) {
  110. valid = true;
  111. }
  112. else if (languageLocation.locations.includes(CodeLensLocations.Custom)) {
  113. valid = !!(languageLocation.customSymbols || []).find(_ => _.toLowerCase() === SymbolKind[symbol.kind].toLowerCase());
  114. }
  115. if (valid) {
  116. // Adjust the range to be for the whole file
  117. if (symbol.location.range.start.line === 0 && symbol.location.range.end.line === 0) {
  118. range = document.validateRange(new Range(0, 1000000, 1000000, 1000000));
  119. }
  120. }
  121. break;
  122. case SymbolKind.Class:
  123. case SymbolKind.Interface:
  124. case SymbolKind.Module:
  125. case SymbolKind.Namespace:
  126. case SymbolKind.Struct:
  127. if (languageLocation.locations.includes(CodeLensLocations.Containers)) {
  128. valid = true;
  129. }
  130. break;
  131. case SymbolKind.Constructor:
  132. case SymbolKind.Enum:
  133. case SymbolKind.Function:
  134. case SymbolKind.Method:
  135. case SymbolKind.Property:
  136. if (languageLocation.locations.includes(CodeLensLocations.Blocks)) {
  137. valid = true;
  138. }
  139. break;
  140. }
  141. if (!valid && languageLocation.locations.includes(CodeLensLocations.Custom)) {
  142. valid = !!(languageLocation.customSymbols || []).find(_ => _.toLowerCase() === SymbolKind[symbol.kind].toLowerCase());
  143. }
  144. return valid ? range || symbol.location.range : undefined;
  145. }
  146. private _provideCodeLens(gitUri: GitUri, document: TextDocument, symbol: SymbolInformation, languageLocation: ICodeLensLanguageLocation, blame: GitBlame, lenses: CodeLens[]): void {
  147. const blameRange = this._validateSymbolAndGetBlameRange(document, symbol, languageLocation);
  148. if (!blameRange) return;
  149. const line = document.lineAt(symbol.location.range.start);
  150. // Make sure there is only 1 lens per line
  151. if (lenses.length && lenses[lenses.length - 1].range.start.line === line.lineNumber) return;
  152. // Anchor the code lens to the end of the line -- so they are somewhat consistently placed
  153. let startChar = line.range.end.character - 1;
  154. let blameForRangeFn: (() => GitBlameLines | undefined) | undefined = undefined;
  155. if (this._documentIsDirty || this._config.codeLens.recentChange.enabled) {
  156. blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame, gitUri, blameRange));
  157. lenses.push(new GitRecentChangeCodeLens(blameForRangeFn, gitUri, symbol.kind, blameRange, false, line.range.with(new Position(line.range.start.line, startChar))));
  158. startChar++;
  159. }
  160. if (this._config.codeLens.authors.enabled) {
  161. let multiline = !blameRange.isSingleLine;
  162. // HACK for Omnisharp, since it doesn't return full ranges
  163. if (!multiline && document.languageId === 'csharp') {
  164. switch (symbol.kind) {
  165. case SymbolKind.File:
  166. break;
  167. case SymbolKind.Package:
  168. case SymbolKind.Module:
  169. case SymbolKind.Namespace:
  170. case SymbolKind.Class:
  171. case SymbolKind.Interface:
  172. case SymbolKind.Constructor:
  173. case SymbolKind.Method:
  174. case SymbolKind.Function:
  175. case SymbolKind.Enum:
  176. multiline = true;
  177. break;
  178. }
  179. }
  180. if (multiline) {
  181. if (blameForRangeFn === undefined) {
  182. blameForRangeFn = Functions.once(() => this.git.getBlameForRangeSync(blame, gitUri, blameRange));
  183. }
  184. if (!this._documentIsDirty) {
  185. lenses.push(new GitAuthorsCodeLens(blameForRangeFn, gitUri, symbol.kind, blameRange, false, line.range.with(new Position(line.range.start.line, startChar))));
  186. }
  187. }
  188. }
  189. }
  190. resolveCodeLens(lens: CodeLens, token: CancellationToken): CodeLens | Thenable<CodeLens> {
  191. if (lens instanceof GitRecentChangeCodeLens) return this._resolveGitRecentChangeCodeLens(lens, token);
  192. if (lens instanceof GitAuthorsCodeLens) return this._resolveGitAuthorsCodeLens(lens, token);
  193. return Promise.reject<CodeLens>(undefined);
  194. }
  195. _resolveGitRecentChangeCodeLens(lens: GitRecentChangeCodeLens, token: CancellationToken): CodeLens {
  196. // Since blame information isn't valid when there are unsaved changes -- update the lenses appropriately
  197. let title: string;
  198. if (this._documentIsDirty) {
  199. if (this._config.codeLens.recentChange.enabled && this._config.codeLens.authors.enabled) {
  200. title = this._config.strings.codeLens.unsavedChanges.recentChangeAndAuthors;
  201. }
  202. else if (this._config.codeLens.recentChange.enabled) {
  203. title = this._config.strings.codeLens.unsavedChanges.recentChangeOnly;
  204. }
  205. else {
  206. title = this._config.strings.codeLens.unsavedChanges.authorsOnly;
  207. }
  208. lens.command = { title: title } as Command;
  209. return lens;
  210. }
  211. const blame = lens.getBlame();
  212. if (blame === undefined) return lens;
  213. const recentCommit = Iterables.first(blame.commits.values());
  214. title = `${recentCommit.author}, ${recentCommit.fromNow()}`;
  215. if (this._config.codeLens.debug) {
  216. title += ` [${SymbolKind[lens.symbolKind]}(${lens.range.start.character}-${lens.range.end.character}), Lines (${lens.blameRange.start.line + 1}-${lens.blameRange.end.line + 1}), Commit (${recentCommit.shortSha})]`;
  217. }
  218. switch (this._config.codeLens.recentChange.command) {
  219. case CodeLensCommand.BlameAnnotate: return this._applyBlameAnnotateCommand<GitRecentChangeCodeLens>(title, lens, blame);
  220. case CodeLensCommand.ShowBlameHistory: return this._applyShowBlameHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
  221. case CodeLensCommand.ShowFileHistory: return this._applyShowFileHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
  222. case CodeLensCommand.DiffWithPrevious: return this._applyDiffWithPreviousCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
  223. case CodeLensCommand.ShowQuickCommitDetails: return this._applyShowQuickCommitDetailsCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
  224. case CodeLensCommand.ShowQuickCommitFileDetails: return this._applyShowQuickCommitFileDetailsCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
  225. case CodeLensCommand.ShowQuickFileHistory: return this._applyShowQuickFileHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
  226. case CodeLensCommand.ShowQuickCurrentBranchHistory: return this._applyShowQuickBranchHistoryCommand<GitRecentChangeCodeLens>(title, lens, blame, recentCommit);
  227. default: return lens;
  228. }
  229. }
  230. _resolveGitAuthorsCodeLens(lens: GitAuthorsCodeLens, token: CancellationToken): CodeLens {
  231. const blame = lens.getBlame();
  232. if (blame === undefined) return lens;
  233. const count = blame.authors.size;
  234. let title = `${count} ${count > 1 ? 'authors' : 'author'} (${Iterables.first(blame.authors.values()).name}${count > 1 ? ' and others' : ''})`;
  235. if (this._config.codeLens.debug) {
  236. title += ` [${SymbolKind[lens.symbolKind]}(${lens.range.start.character}-${lens.range.end.character}), Lines (${lens.blameRange.start.line + 1}-${lens.blameRange.end.line + 1}), Authors (${Iterables.join(Iterables.map(blame.authors.values(), _ => _.name), ', ')})]`;
  237. }
  238. switch (this._config.codeLens.authors.command) {
  239. case CodeLensCommand.BlameAnnotate: return this._applyBlameAnnotateCommand<GitAuthorsCodeLens>(title, lens, blame);
  240. case CodeLensCommand.ShowBlameHistory: return this._applyShowBlameHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
  241. case CodeLensCommand.ShowFileHistory: return this._applyShowFileHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
  242. case CodeLensCommand.DiffWithPrevious: return this._applyDiffWithPreviousCommand<GitAuthorsCodeLens>(title, lens, blame);
  243. case CodeLensCommand.ShowQuickCommitDetails: return this._applyShowQuickCommitDetailsCommand<GitAuthorsCodeLens>(title, lens, blame);
  244. case CodeLensCommand.ShowQuickCommitFileDetails: return this._applyShowQuickCommitFileDetailsCommand<GitAuthorsCodeLens>(title, lens, blame);
  245. case CodeLensCommand.ShowQuickFileHistory: return this._applyShowQuickFileHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
  246. case CodeLensCommand.ShowQuickCurrentBranchHistory: return this._applyShowQuickBranchHistoryCommand<GitAuthorsCodeLens>(title, lens, blame);
  247. default: return lens;
  248. }
  249. }
  250. _applyBlameAnnotateCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines): T {
  251. lens.command = {
  252. title: title,
  253. command: Commands.ToggleFileBlame,
  254. arguments: [Uri.file(lens.uri.fsPath)]
  255. };
  256. return lens;
  257. }
  258. _applyShowBlameHistoryCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit): T {
  259. let line = lens.range.start.line;
  260. if (commit) {
  261. const blameLine = commit.lines.find(_ => _.line === line);
  262. if (blameLine) {
  263. line = blameLine.originalLine;
  264. }
  265. }
  266. const position = lens.isFullRange ? new Position(1, 0) : lens.range.start;
  267. lens.command = {
  268. title: title,
  269. command: Commands.ShowBlameHistory,
  270. arguments: [
  271. Uri.file(lens.uri.fsPath),
  272. {
  273. line,
  274. position,
  275. range: lens.blameRange,
  276. sha: commit && commit.sha
  277. } as ShowBlameHistoryCommandArgs
  278. ]
  279. };
  280. return lens;
  281. }
  282. _applyShowFileHistoryCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit): T {
  283. let line = lens.range.start.line;
  284. if (commit) {
  285. const blameLine = commit.lines.find(_ => _.line === line);
  286. if (blameLine) {
  287. line = blameLine.originalLine;
  288. }
  289. }
  290. const position = lens.isFullRange ? new Position(1, 0) : lens.range.start;
  291. lens.command = {
  292. title: title,
  293. command: Commands.ShowFileHistory,
  294. arguments: [
  295. Uri.file(lens.uri.fsPath),
  296. {
  297. line,
  298. position,
  299. sha: commit && commit.sha
  300. } as ShowFileHistoryCommandArgs
  301. ]
  302. };
  303. return lens;
  304. }
  305. _applyDiffWithPreviousCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit): T {
  306. if (commit === undefined) {
  307. const blameLine = blame.allLines[lens.range.start.line];
  308. commit = blame.commits.get(blameLine.sha);
  309. }
  310. lens.command = {
  311. title: title,
  312. command: Commands.DiffWithPrevious,
  313. arguments: [
  314. Uri.file(lens.uri.fsPath),
  315. {
  316. commit: commit,
  317. range: lens.isFullRange ? undefined : lens.blameRange
  318. } as DiffWithPreviousCommandArgs
  319. ]
  320. };
  321. return lens;
  322. }
  323. _applyShowQuickCommitDetailsCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit): T {
  324. lens.command = {
  325. title: title,
  326. command: commit !== undefined && commit.isUncommitted ? '' : CodeLensCommand.ShowQuickCommitDetails,
  327. arguments: [
  328. Uri.file(lens.uri.fsPath),
  329. {
  330. commit,
  331. sha: commit === undefined ? undefined : commit.sha
  332. } as ShowQuickCommitDetailsCommandArgs]
  333. };
  334. return lens;
  335. }
  336. _applyShowQuickCommitFileDetailsCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit): T {
  337. lens.command = {
  338. title: title,
  339. command: commit !== undefined && commit.isUncommitted ? '' : CodeLensCommand.ShowQuickCommitFileDetails,
  340. arguments: [
  341. Uri.file(lens.uri.fsPath),
  342. {
  343. commit,
  344. sha: commit === undefined ? undefined : commit.sha
  345. } as ShowQuickCommitFileDetailsCommandArgs]
  346. };
  347. return lens;
  348. }
  349. _applyShowQuickFileHistoryCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit): T {
  350. lens.command = {
  351. title: title,
  352. command: CodeLensCommand.ShowQuickFileHistory,
  353. arguments: [
  354. Uri.file(lens.uri.fsPath),
  355. {
  356. range: lens.isFullRange ? undefined : lens.blameRange
  357. } as ShowQuickFileHistoryCommandArgs
  358. ]
  359. };
  360. return lens;
  361. }
  362. _applyShowQuickBranchHistoryCommand<T extends GitRecentChangeCodeLens | GitAuthorsCodeLens>(title: string, lens: T, blame: GitBlameLines, commit?: GitBlameCommit): T {
  363. lens.command = {
  364. title: title,
  365. command: CodeLensCommand.ShowQuickCurrentBranchHistory,
  366. arguments: [Uri.file(lens.uri.fsPath)]
  367. };
  368. return lens;
  369. }
  370. }