Files
vscode-gitlens/src/gitBlameCodeLensProvider.ts
Eric Amodio f4410be30a Adds error messages for failed operations
Adds showHistory command support to CodeLens
Fixes and improve the showHistory explorer
Refactoring
2016-11-10 03:22:58 -05:00

94 lines
4.0 KiB
TypeScript

'use strict';
import { CancellationToken, CodeLens, CodeLensProvider, DocumentSelector, ExtensionContext, Range, TextDocument, Uri } from 'vscode';
import { Commands, DocumentSchemes } from './constants';
import GitProvider, { GitCommit } from './gitProvider';
import * as path from 'path';
export class GitDiffWithWorkingTreeCodeLens extends CodeLens {
constructor(git: GitProvider, public fileName: string, public commit: GitCommit, range: Range) {
super(range);
}
}
export class GitDiffWithPreviousCodeLens extends CodeLens {
constructor(git: GitProvider, public fileName: string, public commit: GitCommit, range: Range) {
super(range);
}
}
export default class GitBlameCodeLensProvider implements CodeLensProvider {
static selector: DocumentSelector = { scheme: DocumentSchemes.GitBlame };
constructor(context: ExtensionContext, private git: GitProvider) { }
provideCodeLenses(document: TextDocument, token: CancellationToken): CodeLens[] | Thenable<CodeLens[]> {
const data = GitProvider.fromBlameUri(document.uri);
const fileName = data.fileName;
const sha = data.sha;
return this.git.getBlameForFile(fileName).then(blame => {
const lenses: CodeLens[] = [];
if (!blame) return lenses;
const commit = blame.commits.get(sha);
const absoluteFileName = path.join(commit.repoPath, fileName);
// Add codelens to each "group" of blame lines
const lines = blame.lines.filter(l => l.sha === sha && l.originalLine >= data.range.start.line && l.originalLine <= data.range.end.line);
let lastLine = lines[0].originalLine;
lines.forEach(l => {
if (l.originalLine !== lastLine + 1) {
lenses.push(new GitDiffWithWorkingTreeCodeLens(this.git, absoluteFileName, commit, new Range(l.originalLine, 0, l.originalLine, 1)));
if (commit.previousSha) {
lenses.push(new GitDiffWithPreviousCodeLens(this.git, absoluteFileName, commit, new Range(l.originalLine, 1, l.originalLine, 2)));
}
}
lastLine = l.originalLine;
});
// 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)) {
lenses.push(new GitDiffWithWorkingTreeCodeLens(this.git, absoluteFileName, commit, new Range(0, 0, 0, 1)));
if (commit.previousSha) {
lenses.push(new GitDiffWithPreviousCodeLens(this.git, absoluteFileName, commit, new Range(0, 1, 0, 2)));
}
}
return lenses;
});
}
resolveCodeLens(lens: CodeLens, token: CancellationToken): Thenable<CodeLens> {
if (lens instanceof GitDiffWithWorkingTreeCodeLens) return this._resolveDiffWithWorkingTreeCodeLens(lens, token);
if (lens instanceof GitDiffWithPreviousCodeLens) return this._resolveGitDiffWithPreviousCodeLens(lens, token);
return Promise.reject<CodeLens>(null);
}
_resolveDiffWithWorkingTreeCodeLens(lens: GitDiffWithWorkingTreeCodeLens, token: CancellationToken): Thenable<CodeLens> {
lens.command = {
title: `Compare with Working Tree`,
command: Commands.DiffWithWorking,
arguments: [
Uri.file(lens.fileName),
lens.commit.sha,
lens.commit.uri,
lens.range.start.line
]
};
return Promise.resolve(lens);
}
_resolveGitDiffWithPreviousCodeLens(lens: GitDiffWithPreviousCodeLens, token: CancellationToken): Thenable<CodeLens> {
lens.command = {
title: `Compare with Previous (${lens.commit.previousSha})`,
command: Commands.DiffWithPrevious,
arguments: [
Uri.file(lens.fileName),
lens.commit,
lens.range.start.line
]
};
return Promise.resolve(lens);
}
}