Files
vscode-gitlens/src/git/parsers/diffParser.ts
2017-06-10 00:49:22 -04:00

74 lines
2.4 KiB
TypeScript

'use strict';
import { Iterables, Strings } from '../../system';
import { GitDiff, GitDiffChunk, GitDiffLine } from './../git';
const unifiedDiffRegex = /^@@ -([\d]+),([\d]+) [+]([\d]+),([\d]+) @@([\s\S]*?)(?=^@@)/gm;
export class GitDiffParser {
static parse(data: string, debug: boolean = false): GitDiff | undefined {
if (!data) return undefined;
const chunks: GitDiffChunk[] = [];
let match: RegExpExecArray | null = null;
let chunk: string;
let currentStart: number;
let previousStart: number;
do {
match = unifiedDiffRegex.exec(`${data}\n@@`);
if (match == null) break;
// Stops excessive memory usage
// https://bugs.chromium.org/p/v8/issues/detail?id=2869
chunk = (' ' + match[5]).substr(1);
currentStart = parseInt(match[3], 10);
previousStart = parseInt(match[1], 10);
chunks.push(new GitDiffChunk(chunk, { start: currentStart, end: currentStart + parseInt(match[4], 10) }, { start: previousStart, end: previousStart + parseInt(match[2], 10) }));
} while (match != null);
if (!chunks.length) return undefined;
const diff = {
diff: debug ? data : undefined,
chunks: chunks
} as GitDiff;
return diff;
}
static parseChunk(chunk: string): [(GitDiffLine | undefined)[], (GitDiffLine | undefined)[]] {
const lines = Iterables.skip(Strings.lines(chunk), 1);
const current: (GitDiffLine | undefined)[] = [];
const previous: (GitDiffLine | undefined)[] = [];
for (const l of lines) {
switch (l[0]) {
case '+':
current.push({
line: ` ${l.substring(1)}`,
state: 'added'
});
previous.push(undefined);
break;
case '-':
current.push(undefined);
previous.push({
line: ` ${l.substring(1)}`,
state: 'removed'
});
break;
default:
current.push({ line: l, state: 'unchanged' });
previous.push({ line: l, state: 'unchanged' });
break;
}
}
return [current, previous];
}
}