@@ -4205,10 +4205,57 @@ namespace FourSlash {
4205
4205
const actualMsg = "\x1b[1mActual\x1b[0m\x1b[31m" ;
4206
4206
const expectedString = quoted ? "\"" + expected + "\"" : expected ;
4207
4207
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 ) } ` ;
4209
4209
}
4210
4210
4211
4211
function templateToRegExp ( template : string ) {
4212
4212
return new RegExp ( `^${ ts . regExpEscape ( template ) . replace ( / \\ \{ \d + \\ \} / g, ".*?" ) } $` ) ;
4213
4213
}
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
+ }
4214
4261
}
0 commit comments