2
2
namespace ts . Completions {
3
3
export enum SortText {
4
4
LocationPriority = "0" ,
5
- LocationPriorityOptional = "1" ,
6
- LocationPriorityFulfilled = "2" ,
5
+ OptionalMember = "1" ,
6
+ MemberDeclaredBySpreadAssignment = "2" ,
7
7
SuggestedClassMembers = "3" ,
8
8
GlobalsOrKeywords = "4" ,
9
9
AutoImportSuggestions = "5" ,
@@ -105,7 +105,6 @@ namespace ts.Completions {
105
105
isJsxInitializer,
106
106
insideJsDocTagTypeExpression,
107
107
symbolToSortTextMap,
108
- fulfilledSymbols,
109
108
} = completionData ;
110
109
111
110
if ( location && location . parent && isJsxClosingElement ( location . parent ) ) {
@@ -167,7 +166,6 @@ namespace ts.Completions {
167
166
recommendedCompletion ,
168
167
symbolToOriginInfoMap ,
169
168
symbolToSortTextMap ,
170
- fulfilledSymbols
171
169
) ;
172
170
}
173
171
@@ -321,7 +319,6 @@ namespace ts.Completions {
321
319
recommendedCompletion ?: Symbol ,
322
320
symbolToOriginInfoMap ?: SymbolOriginInfoMap ,
323
321
symbolToSortTextMap ?: SymbolSortTextMap ,
324
- fulfilledSymbols ?: ReadonlyArray < Symbol > ,
325
322
) : Map < true > {
326
323
const start = timestamp ( ) ;
327
324
// Tracks unique names.
@@ -340,23 +337,9 @@ namespace ts.Completions {
340
337
continue ;
341
338
}
342
339
343
- let sortText = symbolToSortTextMap && symbolToSortTextMap [ getSymbolId ( symbol ) ] ;
344
- if ( ! sortText ) {
345
- if ( fulfilledSymbols && fulfilledSymbols . length > 0 ) {
346
- fulfilledSymbols . forEach ( fulfilledSymbol => {
347
- if ( fulfilledSymbol . name === symbol . name ) {
348
- sortText = SortText . LocationPriorityFulfilled ;
349
- }
350
- } ) ;
351
- }
352
- }
353
- if ( ! sortText ) {
354
- sortText = SymbolDisplay . getSymbolModifiers ( symbol ) === "optional" ? SortText . LocationPriorityOptional : SortText . LocationPriority ;
355
- }
356
-
357
340
const entry = createCompletionEntry (
358
341
symbol ,
359
- sortText ,
342
+ symbolToSortTextMap && symbolToSortTextMap [ getSymbolId ( symbol ) ] || SortText . LocationPriority ,
360
343
location ,
361
344
sourceFile ,
362
345
typeChecker ,
@@ -366,7 +349,7 @@ namespace ts.Completions {
366
349
recommendedCompletion ,
367
350
propertyAccessToConvert ,
368
351
isJsxInitializer ,
369
- preferences ,
352
+ preferences
370
353
) ;
371
354
if ( ! entry ) {
372
355
continue ;
@@ -600,7 +583,6 @@ namespace ts.Completions {
600
583
readonly isJsxInitializer : IsJsxInitializer ;
601
584
readonly insideJsDocTagTypeExpression : boolean ;
602
585
readonly symbolToSortTextMap : SymbolSortTextMap ;
603
- readonly fulfilledSymbols ?: ReadonlyArray < Symbol > ;
604
586
}
605
587
type Request = { readonly kind : CompletionDataKind . JsDocTagName | CompletionDataKind . JsDocTag } | { readonly kind : CompletionDataKind . JsDocParameterName , tag : JSDocParameterTag } ;
606
588
@@ -892,7 +874,6 @@ namespace ts.Completions {
892
874
let isNewIdentifierLocation = false ;
893
875
let keywordFilters = KeywordCompletionFilters . None ;
894
876
let symbols : Symbol [ ] = [ ] ;
895
- let fulfilledSymbols : Symbol [ ] | undefined = [ ] ;
896
877
const symbolToOriginInfoMap : SymbolOriginInfoMap = [ ] ;
897
878
const symbolToSortTextMap : SymbolSortTextMap = [ ] ;
898
879
@@ -946,7 +927,6 @@ namespace ts.Completions {
946
927
isJsxInitializer,
947
928
insideJsDocTagTypeExpression,
948
929
symbolToSortTextMap,
949
- fulfilledSymbols
950
930
} ;
951
931
952
932
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag ;
@@ -1516,20 +1496,21 @@ namespace ts.Completions {
1516
1496
if ( typeMembers && typeMembers . length > 0 ) {
1517
1497
// Add filtered items to the completion list
1518
1498
symbols = filterObjectMembersList ( typeMembers , Debug . assertDefined ( existingMembers ) ) ;
1519
- if ( existingMembers && existingMembers . length > 0 ) {
1520
- existingMembers . forEach ( member => {
1521
- if ( member . kind === SyntaxKind . SpreadAssignment ) {
1522
- const expression = ( < SpreadAssignment > member ) . expression ;
1523
- const symbol = typeChecker . getSymbolAtLocation ( expression ) ;
1524
- const type = symbol && typeChecker . getTypeOfSymbolAtLocation ( symbol , expression ) ;
1525
- fulfilledSymbols = type && ( < ObjectType > type ) . properties ;
1526
- }
1527
- } ) ;
1528
- }
1529
1499
}
1500
+ setSortTextToOptionalMember ( ) ;
1501
+
1530
1502
return GlobalsSearch . Success ;
1531
1503
}
1532
1504
1505
+ // Set SortText to OptionalMember if it is an optinoal member
1506
+ function setSortTextToOptionalMember ( ) {
1507
+ symbols . forEach ( m => {
1508
+ if ( SymbolDisplay . getSymbolModifiers ( m ) === "optional" ) {
1509
+ symbolToSortTextMap [ getSymbolId ( m ) ] = symbolToSortTextMap [ getSymbolId ( m ) ] || SortText . OptionalMember ;
1510
+ }
1511
+ } ) ;
1512
+ }
1513
+
1533
1514
/**
1534
1515
* Aggregates relevant symbols for completion in import clauses and export clauses
1535
1516
* whose declarations have a module specifier; for instance, symbols will be aggregated for
@@ -1898,6 +1879,7 @@ namespace ts.Completions {
1898
1879
return contextualMemberSymbols ;
1899
1880
}
1900
1881
1882
+ const fulfilledSymbols : Symbol [ ] = [ ] ;
1901
1883
const existingMemberNames = createUnderscoreEscapedMap < boolean > ( ) ;
1902
1884
for ( const m of existingMembers ) {
1903
1885
// Ignore omitted expressions for missing members
@@ -1906,7 +1888,8 @@ namespace ts.Completions {
1906
1888
m . kind !== SyntaxKind . BindingElement &&
1907
1889
m . kind !== SyntaxKind . MethodDeclaration &&
1908
1890
m . kind !== SyntaxKind . GetAccessor &&
1909
- m . kind !== SyntaxKind . SetAccessor ) {
1891
+ m . kind !== SyntaxKind . SetAccessor &&
1892
+ m . kind !== SyntaxKind . SpreadAssignment ) {
1910
1893
continue ;
1911
1894
}
1912
1895
@@ -1917,7 +1900,16 @@ namespace ts.Completions {
1917
1900
1918
1901
let existingName : __String | undefined ;
1919
1902
1920
- if ( isBindingElement ( m ) && m . propertyName ) {
1903
+ if ( isSpreadAssignment ( m ) ) {
1904
+ const expression = m . expression ;
1905
+ const symbol = typeChecker . getSymbolAtLocation ( expression ) ;
1906
+ const type = symbol && typeChecker . getTypeOfSymbolAtLocation ( symbol , expression ) ;
1907
+ const properties = type && ( < ObjectType > type ) . properties ;
1908
+ if ( properties ) {
1909
+ fulfilledSymbols . push ( ...properties ) ;
1910
+ }
1911
+ }
1912
+ else if ( isBindingElement ( m ) && m . propertyName ) {
1921
1913
// include only identifiers in completion list
1922
1914
if ( m . propertyName . kind === SyntaxKind . Identifier ) {
1923
1915
existingName = m . propertyName . escapedText ;
@@ -1934,7 +1926,18 @@ namespace ts.Completions {
1934
1926
existingMemberNames . set ( existingName ! , true ) ; // TODO: GH#18217
1935
1927
}
1936
1928
1937
- return contextualMemberSymbols . filter ( m => ! existingMemberNames . get ( m . escapedName ) ) ;
1929
+ const filteredSymbols = contextualMemberSymbols . filter ( m => ! existingMemberNames . get ( m . escapedName ) ) ;
1930
+
1931
+ // Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment
1932
+ for ( const fulfilledSymbol of fulfilledSymbols ) {
1933
+ for ( const contextualMemberSymbol of filteredSymbols ) {
1934
+ if ( contextualMemberSymbol . name === fulfilledSymbol . name ) {
1935
+ symbolToSortTextMap [ getSymbolId ( contextualMemberSymbol ) ] = SortText . MemberDeclaredBySpreadAssignment ;
1936
+ }
1937
+ }
1938
+ }
1939
+
1940
+ return filteredSymbols ;
1938
1941
}
1939
1942
1940
1943
/**
0 commit comments