@@ -1199,31 +1199,59 @@ namespace ts.Completions {
11991199 function createSnippetPrinter (
12001200 printerOptions : PrinterOptions ,
12011201 ) {
1202+ let escapes : TextChange [ ] | undefined ;
12021203 const baseWriter = textChanges . createWriter ( getNewLineCharacter ( printerOptions ) ) ;
12031204 const printer = createPrinter ( printerOptions , baseWriter ) ;
12041205 const writer : EmitTextWriter = {
12051206 ...baseWriter ,
1206- write : s => baseWriter . write ( escapeSnippetText ( s ) ) ,
1207+ write : s => escapingWrite ( s , ( ) => baseWriter . write ( s ) ) ,
12071208 nonEscapingWrite : baseWriter . write ,
1208- writeLiteral : s => baseWriter . writeLiteral ( escapeSnippetText ( s ) ) ,
1209- writeStringLiteral : s => baseWriter . writeStringLiteral ( escapeSnippetText ( s ) ) ,
1210- writeSymbol : ( s , symbol ) => baseWriter . writeSymbol ( escapeSnippetText ( s ) , symbol ) ,
1211- writeParameter : s => baseWriter . writeParameter ( escapeSnippetText ( s ) ) ,
1212- writeComment : s => baseWriter . writeComment ( escapeSnippetText ( s ) ) ,
1213- writeProperty : s => baseWriter . writeProperty ( escapeSnippetText ( s ) ) ,
1209+ writeLiteral : s => escapingWrite ( s , ( ) => baseWriter . writeLiteral ( s ) ) ,
1210+ writeStringLiteral : s => escapingWrite ( s , ( ) => baseWriter . writeStringLiteral ( s ) ) ,
1211+ writeSymbol : ( s , symbol ) => escapingWrite ( s , ( ) => baseWriter . writeSymbol ( s , symbol ) ) ,
1212+ writeParameter : s => escapingWrite ( s , ( ) => baseWriter . writeParameter ( s ) ) ,
1213+ writeComment : s => escapingWrite ( s , ( ) => baseWriter . writeComment ( s ) ) ,
1214+ writeProperty : s => escapingWrite ( s , ( ) => baseWriter . writeProperty ( s ) ) ,
12141215 } ;
12151216
12161217 return {
12171218 printSnippetList,
12181219 printAndFormatSnippetList,
12191220 } ;
12201221
1222+ // The formatter/scanner will have issues with snippet-escaped text,
1223+ // so instead of writing the escaped text directly to the writer,
1224+ // generate a set of changes that can be applied to the unescaped text
1225+ // to escape it post-formatting.
1226+ function escapingWrite ( s : string , write : ( ) => void ) {
1227+ const escaped = escapeSnippetText ( s ) ;
1228+ if ( escaped !== s ) {
1229+ const start = baseWriter . getTextPos ( ) ;
1230+ write ( ) ;
1231+ const end = baseWriter . getTextPos ( ) ;
1232+ escapes = append ( escapes ||= [ ] , { newText : escaped , span : { start, length : end - start } } ) ;
1233+ }
1234+ else {
1235+ write ( ) ;
1236+ }
1237+ }
1238+
12211239 /* Snippet-escaping version of `printer.printList`. */
12221240 function printSnippetList (
12231241 format : ListFormat ,
12241242 list : NodeArray < Node > ,
12251243 sourceFile : SourceFile | undefined ,
12261244 ) : string {
1245+ const unescaped = printUnescapedSnippetList ( format , list , sourceFile ) ;
1246+ return escapes ? textChanges . applyChanges ( unescaped , escapes ) : unescaped ;
1247+ }
1248+
1249+ function printUnescapedSnippetList (
1250+ format : ListFormat ,
1251+ list : NodeArray < Node > ,
1252+ sourceFile : SourceFile | undefined ,
1253+ ) : string {
1254+ escapes = undefined ;
12271255 writer . clear ( ) ;
12281256 printer . writeList ( format , list , sourceFile , writer ) ;
12291257 return writer . getText ( ) ;
@@ -1236,7 +1264,7 @@ namespace ts.Completions {
12361264 formatContext : formatting . FormatContext ,
12371265 ) : string {
12381266 const syntheticFile = {
1239- text : printSnippetList (
1267+ text : printUnescapedSnippetList (
12401268 format ,
12411269 list ,
12421270 sourceFile ) ,
@@ -1256,7 +1284,11 @@ namespace ts.Completions {
12561284 /* delta */ 0 ,
12571285 { ...formatContext , options : formatOptions } ) ;
12581286 } ) ;
1259- return textChanges . applyChanges ( syntheticFile . text , changes ) ;
1287+
1288+ const allChanges = escapes
1289+ ? stableSort ( concatenate ( changes , escapes ) , ( a , b ) => compareTextSpans ( a . span , b . span ) )
1290+ : changes ;
1291+ return textChanges . applyChanges ( syntheticFile . text , allChanges ) ;
12601292 }
12611293 }
12621294
0 commit comments