@@ -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