@@ -675,6 +675,37 @@ namespace ts.Completions {
675
675
hasAction = ! importCompletionNode ;
676
676
}
677
677
678
+ const kind = SymbolDisplay . getSymbolKind ( typeChecker , symbol , location ) ;
679
+ if ( kind === ScriptElementKind . jsxAttribute && preferences . includeCompletionsWithSnippetText && preferences . jsxAttributeCompletionStyle && preferences . jsxAttributeCompletionStyle !== "none" ) {
680
+ let useBraces = preferences . jsxAttributeCompletionStyle === "braces" ;
681
+ const type = typeChecker . getTypeOfSymbolAtLocation ( symbol , location ) ;
682
+
683
+ // If is boolean like or undefined, don't return a snippet we want just to return the completion.
684
+ if ( preferences . jsxAttributeCompletionStyle === "auto"
685
+ && ! ( type . flags & TypeFlags . BooleanLike )
686
+ && ! ( type . flags & TypeFlags . Union && find ( ( type as UnionType ) . types , type => ! ! ( type . flags & TypeFlags . BooleanLike ) ) )
687
+ ) {
688
+ if ( type . flags & TypeFlags . StringLike || ( type . flags & TypeFlags . Union && every ( ( type as UnionType ) . types , type => ! ! ( type . flags & ( TypeFlags . StringLike | TypeFlags . Undefined ) ) ) ) ) {
689
+ // If is string like or undefined use quotes
690
+ insertText = `${ escapeSnippetText ( name ) } =${ quote ( sourceFile , preferences , "$1" ) } ` ;
691
+ isSnippet = true ;
692
+ }
693
+ else {
694
+ // Use braces for everything else
695
+ useBraces = true ;
696
+ }
697
+ }
698
+
699
+ if ( useBraces ) {
700
+ insertText = `${ escapeSnippetText ( name ) } ={$1}` ;
701
+ isSnippet = true ;
702
+ }
703
+
704
+ if ( isSnippet ) {
705
+ replacementSpan = createTextSpanFromNode ( location , sourceFile ) ;
706
+ }
707
+ }
708
+
678
709
// TODO(drosen): Right now we just permit *all* semantic meanings when calling
679
710
// 'getSymbolKind' which is permissible given that it is backwards compatible; but
680
711
// really we should consider passing the meaning for the node so that we don't report
@@ -685,7 +716,7 @@ namespace ts.Completions {
685
716
// entries (like JavaScript identifier entries).
686
717
return {
687
718
name,
688
- kind : SymbolDisplay . getSymbolKind ( typeChecker , symbol , location ) , // TODO: GH#18217
719
+ kind,
689
720
kindModifiers : SymbolDisplay . getSymbolModifiers ( typeChecker , symbol ) ,
690
721
sortText,
691
722
source : getSourceFromOrigin ( origin ) ,
@@ -701,6 +732,10 @@ namespace ts.Completions {
701
732
} ;
702
733
}
703
734
735
+ function escapeSnippetText ( text : string ) : string {
736
+ return text . replace ( / \$ / gm, "\\$" ) ;
737
+ }
738
+
704
739
function originToCompletionEntryData ( origin : SymbolOriginInfoExport ) : CompletionEntryData | undefined {
705
740
return {
706
741
exportName : origin . exportName ,
@@ -723,10 +758,10 @@ namespace ts.Completions {
723
758
const importKind = codefix . getImportKind ( sourceFile , exportKind , options , /*forceImportKeyword*/ true ) ;
724
759
const suffix = useSemicolons ? ";" : "" ;
725
760
switch ( importKind ) {
726
- case ImportKind . CommonJS : return { replacementSpan, insertText : `import ${ name } ${ tabStop } = require(${ quotedModuleSpecifier } )${ suffix } ` } ;
727
- case ImportKind . Default : return { replacementSpan, insertText : `import ${ name } ${ tabStop } from ${ quotedModuleSpecifier } ${ suffix } ` } ;
728
- case ImportKind . Namespace : return { replacementSpan, insertText : `import * as ${ name } from ${ quotedModuleSpecifier } ${ suffix } ` } ;
729
- case ImportKind . Named : return { replacementSpan, insertText : `import { ${ name } ${ tabStop } } from ${ quotedModuleSpecifier } ${ suffix } ` } ;
761
+ case ImportKind . CommonJS : return { replacementSpan, insertText : `import ${ escapeSnippetText ( name ) } ${ tabStop } = require(${ quotedModuleSpecifier } )${ suffix } ` } ;
762
+ case ImportKind . Default : return { replacementSpan, insertText : `import ${ escapeSnippetText ( name ) } ${ tabStop } from ${ quotedModuleSpecifier } ${ suffix } ` } ;
763
+ case ImportKind . Namespace : return { replacementSpan, insertText : `import * as ${ escapeSnippetText ( name ) } from ${ quotedModuleSpecifier } ${ suffix } ` } ;
764
+ case ImportKind . Named : return { replacementSpan, insertText : `import { ${ escapeSnippetText ( name ) } ${ tabStop } } from ${ quotedModuleSpecifier } ${ suffix } ` } ;
730
765
}
731
766
}
732
767
0 commit comments