|
| 1 | +'use strict'; |
| 2 | +import {CancellationToken, CodeLens, CodeLensProvider, commands, Range, SymbolInformation, SymbolKind, TextDocument, Uri} from 'vscode'; |
| 3 | +import {IBlameLine, gitBlame} from './git'; |
| 4 | +import * as moment from 'moment'; |
| 5 | + |
| 6 | +export class GitCodeLens extends CodeLens { |
| 7 | + constructor(public blame: Promise<IBlameLine[]>, public fileName: string, public blameRange: Range, range: Range) { |
| 8 | + super(range); |
| 9 | + |
| 10 | + this.blame = blame; |
| 11 | + this.fileName = fileName; |
| 12 | + this.blameRange = blameRange; |
| 13 | + } |
| 14 | +} |
| 15 | + |
| 16 | +export default class GitCodeLensProvider implements CodeLensProvider { |
| 17 | + constructor(public repoPath: string) { } |
| 18 | + |
| 19 | + provideCodeLenses(document: TextDocument, token: CancellationToken): CodeLens[] | Thenable<CodeLens[]> { |
| 20 | + // TODO: Should I wait here? |
| 21 | + let blame = gitBlame(document.fileName); |
| 22 | + |
| 23 | + return (commands.executeCommand('vscode.executeDocumentSymbolProvider', document.uri) as Promise<SymbolInformation[]>).then(symbols => { |
| 24 | + let lenses: CodeLens[] = []; |
| 25 | + symbols.forEach(sym => this._provideCodeLens(document, sym, blame, lenses)); |
| 26 | + return lenses; |
| 27 | + }); |
| 28 | + } |
| 29 | + |
| 30 | + private _provideCodeLens(document: TextDocument, symbol: SymbolInformation, blame: Promise<IBlameLine[]>, lenses: CodeLens[]): void { |
| 31 | + switch (symbol.kind) { |
| 32 | + case SymbolKind.Module: |
| 33 | + case SymbolKind.Class: |
| 34 | + case SymbolKind.Interface: |
| 35 | + case SymbolKind.Method: |
| 36 | + case SymbolKind.Function: |
| 37 | + case SymbolKind.Constructor: |
| 38 | + case SymbolKind.Field: |
| 39 | + case SymbolKind.Property: |
| 40 | + break; |
| 41 | + default: |
| 42 | + return; |
| 43 | + } |
| 44 | + |
| 45 | + var line = document.lineAt(symbol.location.range.start); |
| 46 | + // if (line.text.includes(symbol.name)) { |
| 47 | + // } |
| 48 | + |
| 49 | + let lens = new GitCodeLens(blame, document.fileName, symbol.location.range, line.range); |
| 50 | + lenses.push(lens); |
| 51 | + } |
| 52 | + |
| 53 | + resolveCodeLens(codeLens: CodeLens, token: CancellationToken): Thenable<CodeLens> { |
| 54 | + if (codeLens instanceof GitCodeLens) { |
| 55 | + return codeLens.blame.then(allLines => { |
| 56 | + let lines = allLines.slice(codeLens.blameRange.start.line, codeLens.blameRange.end.line + 1); |
| 57 | + let line = lines[0]; |
| 58 | + if (lines.length > 1) { |
| 59 | + let sorted = lines.sort((a, b) => b.date.getTime() - a.date.getTime()); |
| 60 | + line = sorted[0]; |
| 61 | + } |
| 62 | + |
| 63 | + codeLens.command = { |
| 64 | + title: `${line.author}, ${moment(line.date).fromNow()}`, |
| 65 | + command: 'git.viewFileHistory', |
| 66 | + arguments: [Uri.file(codeLens.fileName)] |
| 67 | + }; |
| 68 | + return codeLens; |
| 69 | + });//.catch(ex => Promise.reject(ex)); // TODO: Figure out a better way to stop the codelens from appearing |
| 70 | + } |
| 71 | + } |
| 72 | +} |
0 commit comments