@@ -232,6 +232,7 @@ namespace ts.Completions {
232
232
completionKind ,
233
233
preferences ,
234
234
propertyAccessToConvert ,
235
+ completionData . isJsxIdentifierExpected ,
235
236
isJsxInitializer ,
236
237
recommendedCompletion ,
237
238
symbolToOriginInfoMap ,
@@ -255,6 +256,7 @@ namespace ts.Completions {
255
256
completionKind ,
256
257
preferences ,
257
258
propertyAccessToConvert ,
259
+ completionData . isJsxIdentifierExpected ,
258
260
isJsxInitializer ,
259
261
recommendedCompletion ,
260
262
symbolToOriginInfoMap ,
@@ -441,6 +443,7 @@ namespace ts.Completions {
441
443
kind : CompletionKind ,
442
444
preferences : UserPreferences ,
443
445
propertyAccessToConvert ?: PropertyAccessExpression ,
446
+ jsxIdentifierExpected ?: boolean ,
444
447
isJsxInitializer ?: IsJsxInitializer ,
445
448
recommendedCompletion ?: Symbol ,
446
449
symbolToOriginInfoMap ?: SymbolOriginInfoMap ,
@@ -454,7 +457,7 @@ namespace ts.Completions {
454
457
const uniques = createMap < true > ( ) ;
455
458
for ( const symbol of symbols ) {
456
459
const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap [ getSymbolId ( symbol ) ] : undefined ;
457
- const info = getCompletionEntryDisplayNameForSymbol ( symbol , target , origin , kind ) ;
460
+ const info = getCompletionEntryDisplayNameForSymbol ( symbol , target , origin , kind , ! ! jsxIdentifierExpected ) ;
458
461
if ( ! info ) {
459
462
continue ;
460
463
}
@@ -564,7 +567,7 @@ namespace ts.Completions {
564
567
// completion entry.
565
568
return firstDefined ( symbols , ( symbol ) : SymbolCompletion | undefined => {
566
569
const origin = symbolToOriginInfoMap [ getSymbolId ( symbol ) ] ;
567
- const info = getCompletionEntryDisplayNameForSymbol ( symbol , compilerOptions . target ! , origin , completionKind ) ;
570
+ const info = getCompletionEntryDisplayNameForSymbol ( symbol , compilerOptions . target ! , origin , completionKind , completionData . isJsxIdentifierExpected ) ;
568
571
return info && info . name === entryId . name && getSourceFromOrigin ( origin ) === entryId . source
569
572
? { type : "symbol" as const , symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer, isTypeOnlyLocation }
570
573
: undefined ;
@@ -716,6 +719,8 @@ namespace ts.Completions {
716
719
readonly insideJsDocTagTypeExpression : boolean ;
717
720
readonly symbolToSortTextMap : SymbolSortTextMap ;
718
721
readonly isTypeOnlyLocation : boolean ;
722
+ /** In JSX tag name and attribute names, identifiers like "my-tag" or "aria-name" is valid identifier. */
723
+ readonly isJsxIdentifierExpected : boolean ;
719
724
}
720
725
type Request = { readonly kind : CompletionDataKind . JsDocTagName | CompletionDataKind . JsDocTag } | { readonly kind : CompletionDataKind . JsDocParameterName , tag : JSDocParameterTag } ;
721
726
@@ -895,6 +900,7 @@ namespace ts.Completions {
895
900
let isRightOfOpenTag = false ;
896
901
let isStartingCloseTag = false ;
897
902
let isJsxInitializer : IsJsxInitializer = false ;
903
+ let isJsxIdentifierExpected = false ;
898
904
899
905
let location = getTouchingPropertyName ( sourceFile , position ) ;
900
906
if ( contextToken ) {
@@ -975,11 +981,12 @@ namespace ts.Completions {
975
981
if ( ! binaryExpressionMayBeOpenTag ( parent as BinaryExpression ) ) {
976
982
break ;
977
983
}
978
- // falls through
984
+ // falls through
979
985
980
986
case SyntaxKind . JsxSelfClosingElement :
981
987
case SyntaxKind . JsxElement :
982
988
case SyntaxKind . JsxOpeningElement :
989
+ isJsxIdentifierExpected = true ;
983
990
if ( contextToken . kind === SyntaxKind . LessThanToken ) {
984
991
isRightOfOpenTag = true ;
985
992
location = contextToken ;
@@ -992,6 +999,7 @@ namespace ts.Completions {
992
999
isJsxInitializer = true ;
993
1000
break ;
994
1001
case SyntaxKind . Identifier :
1002
+ isJsxIdentifierExpected = true ;
995
1003
// For `<div x=[|f/**/|]`, `parent` will be `x` and `previousToken.parent` will be `f` (which is its own JsxAttribute)
996
1004
// Note for `<div someBool f>` we don't want to treat this as a jsx inializer, instead it's the attribute name.
997
1005
if ( parent !== previousToken . parent &&
@@ -1066,7 +1074,8 @@ namespace ts.Completions {
1066
1074
isJsxInitializer,
1067
1075
insideJsDocTagTypeExpression,
1068
1076
symbolToSortTextMap,
1069
- isTypeOnlyLocation : isTypeOnly
1077
+ isTypeOnlyLocation : isTypeOnly ,
1078
+ isJsxIdentifierExpected,
1070
1079
} ;
1071
1080
1072
1081
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag ;
@@ -1130,9 +1139,9 @@ namespace ts.Completions {
1130
1139
let insertQuestionDot = false ;
1131
1140
if ( type . isNullableType ( ) ) {
1132
1141
const canCorrectToQuestionDot =
1133
- isRightOfDot &&
1134
- ! isRightOfQuestionDot &&
1135
- preferences . includeAutomaticOptionalChainCompletions !== false ;
1142
+ isRightOfDot &&
1143
+ ! isRightOfQuestionDot &&
1144
+ preferences . includeAutomaticOptionalChainCompletions !== false ;
1136
1145
1137
1146
if ( canCorrectToQuestionDot || isRightOfQuestionDot ) {
1138
1147
type = type . getNonNullableType ( ) ;
@@ -1447,8 +1456,8 @@ namespace ts.Completions {
1447
1456
return insideJsDocTagTypeExpression
1448
1457
|| ! isContextTokenValueLocation ( contextToken ) &&
1449
1458
( isPossiblyTypeArgumentPosition ( contextToken , sourceFile , typeChecker )
1450
- || isPartOfTypeNode ( location )
1451
- || isContextTokenTypeLocation ( contextToken ) ) ;
1459
+ || isPartOfTypeNode ( location )
1460
+ || isContextTokenTypeLocation ( contextToken ) ) ;
1452
1461
}
1453
1462
1454
1463
function isContextTokenValueLocation ( contextToken : Node ) {
@@ -2399,6 +2408,7 @@ namespace ts.Completions {
2399
2408
target : ScriptTarget ,
2400
2409
origin : SymbolOriginInfo | undefined ,
2401
2410
kind : CompletionKind ,
2411
+ jsxIdentifierExpected : boolean ,
2402
2412
) : CompletionEntryDisplayNameForSymbol | undefined {
2403
2413
const name = originIsExport ( origin ) ? getNameForExportedSymbol ( symbol , target ) : symbol . name ;
2404
2414
if ( name === undefined
@@ -2411,7 +2421,7 @@ namespace ts.Completions {
2411
2421
}
2412
2422
2413
2423
const validNameResult : CompletionEntryDisplayNameForSymbol = { name, needsConvertPropertyAccess : false } ;
2414
- if ( isIdentifierText ( name , target ) || symbol . valueDeclaration && isPrivateIdentifierPropertyDeclaration ( symbol . valueDeclaration ) ) {
2424
+ if ( isIdentifierText ( name , target , jsxIdentifierExpected ? LanguageVariant . JSX : LanguageVariant . Standard ) || symbol . valueDeclaration && isPrivateIdentifierPropertyDeclaration ( symbol . valueDeclaration ) ) {
2415
2425
return validNameResult ;
2416
2426
}
2417
2427
switch ( kind ) {
0 commit comments