Adds underlines to differences in strings (#36409)

This commit is contained in:
Orta 2020-02-27 12:46:15 -05:00 committed by GitHub
parent f883bf3acb
commit 2c4155c351
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -4205,10 +4205,57 @@ namespace FourSlash {
const actualMsg = "\x1b[1mActual\x1b[0m\x1b[31m";
const expectedString = quoted ? "\"" + expected + "\"" : expected;
const actualString = quoted ? "\"" + actual + "\"" : actual;
return `\n${expectMsg}:\n${expectedString}\n\n${actualMsg}:\n${actualString}`;
return `\n${expectMsg}:\n${expectedString}\n\n${actualMsg}:\n${highlightDifferenceBetweenStrings(expected, actualString)}`;
}
function templateToRegExp(template: string) {
return new RegExp(`^${ts.regExpEscape(template).replace(/\\\{\d+\\\}/g, ".*?")}$`);
}
function rangesOfDiffBetweenTwoStrings(source: string, target: string) {
const ranges = [] as { start: number; length: number }[];
const addToIndex = (index: number) => {
const closestIndex = ranges[ranges.length - 1];
if (closestIndex) {
const doesAddToIndex = closestIndex.start + closestIndex.length === index - 1;
if (doesAddToIndex) {
closestIndex.length = closestIndex.length + 1;
}
else {
ranges.push({ start: index - 1, length: 1 });
}
}
else {
ranges.push({ start: index - 1, length: 1 });
}
};
for (let index = 0; index < Math.max(source.length, target.length); index++) {
const srcChar = source[index];
const targetChar = target[index];
if (srcChar !== targetChar) addToIndex(index);
}
return ranges;
}
// Adds an _ when the source string and the target string have a whitespace difference
function highlightDifferenceBetweenStrings(source: string, target: string) {
const ranges = rangesOfDiffBetweenTwoStrings(source, target);
let emTarget = target;
ranges.forEach((range, index) => {
const lhs = `\x1b[4m`;
const rhs = `\x1b[0m\x1b[31m`;
const additionalOffset = index * lhs.length + index * rhs.length;
const before = emTarget.slice(0, range.start + 1 + additionalOffset);
const between = emTarget.slice(
range.start + 1 + additionalOffset,
range.start + range.length + 1 + additionalOffset
);
const after = emTarget.slice(range.start + range.length + 1 + additionalOffset, emTarget.length);
emTarget = before + lhs + between + rhs + after;
});
return emTarget;
}
}