@ -1,11 +1,11 @@
'use strict' ;
import { CancellationToken , CodeLens , CodeLensProvider , commands , Location , Range , SymbolInformation , SymbolKind , TextDocument , Uri } from 'vscode' ;
import { CancellationToken , CodeLens , CodeLensProvider , commands , Location , Position , Range, SymbolInformation , SymbolKind , TextDocument , Uri } from 'vscode' ;
import { Commands , VsCodeCommands } from './constants' ;
import { IGitBlameLine , gitBlame } from './git' ;
import { toGitBlameUri } from './contentProvider' ;
import * as moment from 'moment' ;
export class GitCodeLens extends CodeLens {
export class GitBlame CodeLens extends CodeLens {
constructor ( private blame : Promise < IGitBlameLine [ ] > , public repoPath : string , public fileName : string , private blameRange : Range , range : Range ) {
super ( range ) ;
}
@ -14,11 +14,21 @@ export class GitCodeLens extends CodeLens {
return this . blame . then ( allLines = > allLines . slice ( this . blameRange . start . line , this . blameRange . end . line + 1 ) ) ;
}
static toUri ( lens : GitCodeLens , line : IGitBlameLine , lines : IGitBlameLine [ ] ) : Uri {
return toGitBlameUri ( Object . assign ( { repoPath : lens.repoPath , range : lens.blameRange , lines : lines } , line ) ) ;
static toUri ( lens : GitBlame CodeLens , index : number , line : IGitBlameLine , lines : IGitBlameLine [ ] ) : Uri {
return toGitBlameUri ( Object . assign ( { repoPath : lens.repoPath , index : index , range : lens.blameRange , lines : lines } , line ) ) ;
}
}
export class GitHistoryCodeLens extends CodeLens {
constructor ( public repoPath : string , public fileName : string , range : Range ) {
super ( range ) ;
}
// static toUri(lens: GitHistoryCodeLens, index: number): Uri {
// return toGitBlameUri(Object.assign({ repoPath: lens.repoPath, index: index, range: lens.blameRange, lines: lines }, line));
// }
}
export default class GitCodeLensProvider implements CodeLensProvider {
constructor ( public repoPath : string ) { }
@ -29,39 +39,52 @@ export default class GitCodeLensProvider implements CodeLensProvider {
return ( commands . executeCommand ( VsCodeCommands . ExecuteDocumentSymbolProvider , document . uri ) as Promise < SymbolInformation [ ] > ) . then ( symbols = > {
let lenses : CodeLens [ ] = [ ] ;
symbols . forEach ( sym = > this . _provideCodeLens ( document , sym , blame , lenses ) ) ;
// Check if we have a lens for the whole document -- if not add one
if ( ! lenses . find ( l = > l . range . start . line === 0 && l . range . end . line === 0 ) ) {
const docRange = document . validateRange ( new Range ( 0 , 1000000 , 1000000 , 1000000 ) ) ;
lenses . push ( new GitBlameCodeLens ( blame , this . repoPath , document . fileName , docRange , new Range ( 0 , 0 , 0 , docRange . start . character ) ) ) ;
}
return lenses ;
} ) ;
}
private _provideCodeLens ( document : TextDocument , symbol : SymbolInformation , blame : Promise < IGitBlameLine [ ] > , lenses : CodeLens [ ] ) : void {
switch ( symbol . kind ) {
case SymbolKind . Package :
case SymbolKind . Module :
case SymbolKind . Class :
case SymbolKind . Interface :
case SymbolKind . Method :
case SymbolKind . Function :
case SymbolKind . Constructor :
case SymbolKind . Fiel d:
case SymbolKind . Method :
case SymbolKind . Property :
case SymbolKind . Field :
case SymbolKind . Function :
case SymbolKind . Enum :
break ;
default :
return ;
}
var line = document . lineAt ( symbol . location . range . start ) ;
let lens = new Git CodeLens( blame , this . repoPath , document . fileName , symbol . location . range , line . range ) ;
lenses . push ( lens ) ;
lenses . push ( new GitBlame CodeLens( blame , this . repoPath , document . fileName , symbol . location . range , line . range . with ( new Position ( line . range . start . line , line . firstNonWhitespaceCharacterIndex ) ) ) ) ;
lenses . push ( new GitHistoryCodeLens lass="p">( this . r epoPathn>, < span class="nb">document . fileName , line . range . with ( new Position ( line . range . start . line , line . firstNonWhitespaceCharacterIndex + 1 ) ) ) ) ;
}
resolveCodeLens ( lens : CodeLens , token : CancellationToken ) : Thenable < CodeLens > {
if ( lens instanceof GitCodeLens ) {
if ( lens instanceof GitBlame CodeLens ) {
return lens . getBlameLines ( ) . then ( lines = > {
if ( ! lines . length ) {
console . error ( 'No blame lines found' , lens ) ;
throw new Error ( 'No blame lines found' ) ;
}
let recentLine = lines [ 0 ] ;
let locations : Location [ ] = [ ] ;
if ( lines . length > 1 ) {
let sorted = lines . sort ( ( a , b ) = > a . date . getTime ( ) - b . date . getTime ( ) ) ;
recentLine = sorted [ sorted . length - 1 ] ;
let sorted = lines . sort ( ( a , b ) = > b . date . getTime ( ) - a . date . getTime ( ) ) ;
recentLine = sorted [ 0 ] ;
console . log ( lens . fileName , 'Blame lines:' , sorted ) ;
@ -75,20 +98,35 @@ export default class GitCodeLensProvider implements CodeLensProvider {
}
} ) ;
locations = Array . from ( map . values ( ) ) . map ( l = > new Location ( GitCodeLens . toUri ( lens , l [ 0 ] , l ) , lens . range . start ) )
Array . from ( map . values ( ) ) . forEach ( ( lines , i ) = > {
const uri = GitBlameCodeLens . toUri ( lens , i + 1 , lines [ 0 ] , lines ) ;
lines . forEach ( l = > {
locations . push ( new Location ( uri , new Position ( l . originalLine , 0 ) ) ) ;
} ) ;
} ) ;
//locations = Array.from(map.values()).map((l, i) => new Location(GitBlameCodeLens.toUri(lens, i, l[0], l), new Position(l[0].originalLine, 0)));//lens.range.start))
} else {
locations = [ new Location ( GitCodeLens . toUri ( lens , recentLine , lines ) , lens . range . start ) ] ;
locations = [ new Location ( GitBlame CodeLens . toUri ( lens , 1 , recentLine , lines ) , lens . range . start ) ] ;
}
lens . command = {
title : ` ${ recentLine . author } , ${ moment ( recentLine . date ) . fromNow ( ) } ` ,
command : Commands.ShowBlameHistory ,
arguments : [ Uri . file ( lens . fileName ) , lens . range . start , locations ]
// command: 'git.viewFileHistory',
// arguments: [Uri.file(codeLens.fileName)]
} ;
return lens ;
} ) . catch ( ex = > Promise . reject ( ex ) ) ; // TODO: Figure out a better way to stop the codelens from appearing
}
// TODO: Play with this more -- get this to open the correct diff to the right place
if ( lens instanceof GitHistoryCodeLens ) {
lens . command = {
title : ` View Diff ` ,
command : 'git.viewFileHistory' , // viewLineHistory
arguments : [ Uri . file ( lens . fileName ) ]
} ;
return Promise . resolve ( lens ) ;
}
}
}