Skip to content

Commit 2c4155c

Browse files
author
Orta
authored
Adds underlines to differences in strings (microsoft#36409)
1 parent f883bf3 commit 2c4155c

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

src/harness/fourslashImpl.ts

+48-1
Original file line numberDiff line numberDiff line change
@@ -4205,10 +4205,57 @@ namespace FourSlash {
42054205
const actualMsg = "\x1b[1mActual\x1b[0m\x1b[31m";
42064206
const expectedString = quoted ? "\"" + expected + "\"" : expected;
42074207
const actualString = quoted ? "\"" + actual + "\"" : actual;
4208-
return `\n${expectMsg}:\n${expectedString}\n\n${actualMsg}:\n${actualString}`;
4208+
return `\n${expectMsg}:\n${expectedString}\n\n${actualMsg}:\n${highlightDifferenceBetweenStrings(expected, actualString)}`;
42094209
}
42104210

42114211
function templateToRegExp(template: string) {
42124212
return new RegExp(`^${ts.regExpEscape(template).replace(/\\\{\d+\\\}/g, ".*?")}$`);
42134213
}
4214+
4215+
function rangesOfDiffBetweenTwoStrings(source: string, target: string) {
4216+
const ranges = [] as { start: number; length: number }[];
4217+
4218+
const addToIndex = (index: number) => {
4219+
const closestIndex = ranges[ranges.length - 1];
4220+
if (closestIndex) {
4221+
const doesAddToIndex = closestIndex.start + closestIndex.length === index - 1;
4222+
if (doesAddToIndex) {
4223+
closestIndex.length = closestIndex.length + 1;
4224+
}
4225+
else {
4226+
ranges.push({ start: index - 1, length: 1 });
4227+
}
4228+
}
4229+
else {
4230+
ranges.push({ start: index - 1, length: 1 });
4231+
}
4232+
};
4233+
4234+
for (let index = 0; index < Math.max(source.length, target.length); index++) {
4235+
const srcChar = source[index];
4236+
const targetChar = target[index];
4237+
if (srcChar !== targetChar) addToIndex(index);
4238+
}
4239+
4240+
return ranges;
4241+
}
4242+
4243+
// Adds an _ when the source string and the target string have a whitespace difference
4244+
function highlightDifferenceBetweenStrings(source: string, target: string) {
4245+
const ranges = rangesOfDiffBetweenTwoStrings(source, target);
4246+
let emTarget = target;
4247+
ranges.forEach((range, index) => {
4248+
const lhs = `\x1b[4m`;
4249+
const rhs = `\x1b[0m\x1b[31m`;
4250+
const additionalOffset = index * lhs.length + index * rhs.length;
4251+
const before = emTarget.slice(0, range.start + 1 + additionalOffset);
4252+
const between = emTarget.slice(
4253+
range.start + 1 + additionalOffset,
4254+
range.start + range.length + 1 + additionalOffset
4255+
);
4256+
const after = emTarget.slice(range.start + range.length + 1 + additionalOffset, emTarget.length);
4257+
emTarget = before + lhs + between + rhs + after;
4258+
});
4259+
return emTarget;
4260+
}
42144261
}

0 commit comments

Comments
 (0)