@@ -272,7 +272,7 @@ namespace ts.Completions {
272272 }
273273
274274 for ( const literal of literals ) {
275- entries . push ( createCompletionEntryForLiteral ( literal ) ) ;
275+ entries . push ( createCompletionEntryForLiteral ( literal , preferences ) ) ;
276276 }
277277
278278 return { isGlobalCompletion : isInSnippetScope , isMemberCompletion : isMemberCompletionKind ( completionKind ) , isNewIdentifierLocation, entries } ;
@@ -317,10 +317,13 @@ namespace ts.Completions {
317317 } ) ;
318318 }
319319
320- const completionNameForLiteral = ( literal : string | number | PseudoBigInt ) =>
321- typeof literal === "object" ? pseudoBigIntToString ( literal ) + "n" : JSON . stringify ( literal ) ;
322- function createCompletionEntryForLiteral ( literal : string | number | PseudoBigInt ) : CompletionEntry {
323- return { name : completionNameForLiteral ( literal ) , kind : ScriptElementKind . string , kindModifiers : ScriptElementKindModifier . none , sortText : SortText . LocationPriority } ;
320+ function completionNameForLiteral ( literal : string | number | PseudoBigInt , preferences : UserPreferences ) : string {
321+ return typeof literal === "object" ? pseudoBigIntToString ( literal ) + "n" :
322+ isString ( literal ) ? quote ( literal , preferences ) : JSON . stringify ( literal ) ;
323+ }
324+
325+ function createCompletionEntryForLiteral ( literal : string | number | PseudoBigInt , preferences : UserPreferences ) : CompletionEntry {
326+ return { name : completionNameForLiteral ( literal , preferences ) , kind : ScriptElementKind . string , kindModifiers : ScriptElementKindModifier . none , sortText : SortText . LocationPriority } ;
324327 }
325328
326329 function createCompletionEntry (
@@ -344,13 +347,13 @@ namespace ts.Completions {
344347 const useBraces = origin && originIsSymbolMember ( origin ) || needsConvertPropertyAccess ;
345348 if ( origin && originIsThisType ( origin ) ) {
346349 insertText = needsConvertPropertyAccess
347- ? `this${ insertQuestionDot ? "?." : "" } [${ quote ( name , preferences ) } ]`
350+ ? `this${ insertQuestionDot ? "?." : "" } [${ quotePropertyName ( name , preferences ) } ]`
348351 : `this${ insertQuestionDot ? "?." : "." } ${ name } ` ;
349352 }
350353 // We should only have needsConvertPropertyAccess if there's a property access to convert. But see #21790.
351354 // Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro.
352355 else if ( ( useBraces || insertQuestionDot ) && propertyAccessToConvert ) {
353- insertText = useBraces ? needsConvertPropertyAccess ? `[${ quote ( name , preferences ) } ]` : `[${ name } ]` : name ;
356+ insertText = useBraces ? needsConvertPropertyAccess ? `[${ quotePropertyName ( name , preferences ) } ]` : `[${ name } ]` : name ;
354357 if ( insertQuestionDot || propertyAccessToConvert . questionDotToken ) {
355358 insertText = `?.${ insertText } ` ;
356359 }
@@ -410,6 +413,14 @@ namespace ts.Completions {
410413 } ;
411414 }
412415
416+ function quotePropertyName ( name : string , preferences : UserPreferences ) : string {
417+ if ( / ^ \d + $ / . test ( name ) ) {
418+ return name ;
419+ }
420+
421+ return quote ( name , preferences ) ;
422+ }
423+
413424 function isRecommendedCompletionMatch ( localSymbol : Symbol , recommendedCompletion : Symbol | undefined , checker : TypeChecker ) : boolean {
414425 return localSymbol === recommendedCompletion ||
415426 ! ! ( localSymbol . flags & SymbolFlags . ExportValue ) && checker . getExportSymbolOfSymbol ( localSymbol ) === recommendedCompletion ;
@@ -531,6 +542,7 @@ namespace ts.Completions {
531542 position : number ,
532543 entryId : CompletionEntryIdentifier ,
533544 host : LanguageServiceHost ,
545+ preferences : UserPreferences ,
534546 ) : SymbolCompletion | { type : "request" , request : Request } | { type : "literal" , literal : string | number | PseudoBigInt } | { type : "none" } {
535547 const compilerOptions = program . getCompilerOptions ( ) ;
536548 const completionData = getCompletionData ( program , log , sourceFile , isUncheckedFile ( sourceFile , compilerOptions ) , position , { includeCompletionsForModuleExports : true , includeCompletionsWithInsertText : true } , entryId , host ) ;
@@ -543,7 +555,7 @@ namespace ts.Completions {
543555
544556 const { symbols, literals, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer, isTypeOnlyLocation } = completionData ;
545557
546- const literal = find ( literals , l => completionNameForLiteral ( l ) === entryId . name ) ;
558+ const literal = find ( literals , l => completionNameForLiteral ( l , preferences ) === entryId . name ) ;
547559 if ( literal !== undefined ) return { type : "literal" , literal } ;
548560
549561 // Find the symbol with the matching entry name.
@@ -585,7 +597,7 @@ namespace ts.Completions {
585597 }
586598
587599 // Compute all the completion symbols again.
588- const symbolCompletion = getSymbolCompletionFromEntryId ( program , log , sourceFile , position , entryId , host ) ;
600+ const symbolCompletion = getSymbolCompletionFromEntryId ( program , log , sourceFile , position , entryId , host , preferences ) ;
589601 switch ( symbolCompletion . type ) {
590602 case "request" : {
591603 const { request } = symbolCompletion ;
@@ -607,7 +619,7 @@ namespace ts.Completions {
607619 }
608620 case "literal" : {
609621 const { literal } = symbolCompletion ;
610- return createSimpleDetails ( completionNameForLiteral ( literal ) , ScriptElementKind . string , typeof literal === "string" ? SymbolDisplayPartKind . stringLiteral : SymbolDisplayPartKind . numericLiteral ) ;
622+ return createSimpleDetails ( completionNameForLiteral ( literal , preferences ) , ScriptElementKind . string , typeof literal === "string" ? SymbolDisplayPartKind . stringLiteral : SymbolDisplayPartKind . numericLiteral ) ;
611623 }
612624 case "none" :
613625 // Didn't find a symbol with this name. See if we can find a keyword instead.
@@ -677,8 +689,9 @@ namespace ts.Completions {
677689 position : number ,
678690 entryId : CompletionEntryIdentifier ,
679691 host : LanguageServiceHost ,
692+ preferences : UserPreferences ,
680693 ) : Symbol | undefined {
681- const completion = getSymbolCompletionFromEntryId ( program , log , sourceFile , position , entryId , host ) ;
694+ const completion = getSymbolCompletionFromEntryId ( program , log , sourceFile , position , entryId , host , preferences ) ;
682695 return completion . type === "symbol" ? completion . symbol : undefined ;
683696 }
684697
0 commit comments