@@ -165,7 +165,7 @@ namespace ts.Completions {
165
165
isJsxInitializer ,
166
166
recommendedCompletion ,
167
167
symbolToOriginInfoMap ,
168
- symbolToSortTextMap ,
168
+ symbolToSortTextMap
169
169
) ;
170
170
}
171
171
@@ -926,7 +926,7 @@ namespace ts.Completions {
926
926
previousToken,
927
927
isJsxInitializer,
928
928
insideJsDocTagTypeExpression,
929
- symbolToSortTextMap,
929
+ symbolToSortTextMap
930
930
} ;
931
931
932
932
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag ;
@@ -985,6 +985,7 @@ namespace ts.Completions {
985
985
symbol . declarations . some ( d => d . kind !== SyntaxKind . SourceFile && d . kind !== SyntaxKind . ModuleDeclaration && d . kind !== SyntaxKind . EnumDeclaration ) ) {
986
986
addTypeProperties ( typeChecker . getTypeOfSymbolAtLocation ( symbol , node ) ) ;
987
987
}
988
+ setSortTextToOptionalMember ( ) ;
988
989
989
990
return ;
990
991
}
@@ -994,11 +995,13 @@ namespace ts.Completions {
994
995
if ( isMetaProperty ( node ) && ( node . keywordToken === SyntaxKind . NewKeyword || node . keywordToken === SyntaxKind . ImportKeyword ) ) {
995
996
const completion = ( node . keywordToken === SyntaxKind . NewKeyword ) ? "target" : "meta" ;
996
997
symbols . push ( typeChecker . createSymbol ( SymbolFlags . Property , escapeLeadingUnderscores ( completion ) ) ) ;
998
+ setSortTextToOptionalMember ( ) ;
997
999
return ;
998
1000
}
999
1001
1000
1002
if ( ! isTypeLocation ) {
1001
1003
addTypeProperties ( typeChecker . getTypeAtLocation ( node ) ) ;
1004
+ setSortTextToOptionalMember ( ) ;
1002
1005
}
1003
1006
}
1004
1007
@@ -1079,6 +1082,7 @@ namespace ts.Completions {
1079
1082
const attrsType = jsxContainer && typeChecker . getContextualType ( jsxContainer . attributes ) ;
1080
1083
if ( ! attrsType ) return GlobalsSearch . Continue ;
1081
1084
symbols = filterJsxAttributes ( getPropertiesForObjectExpression ( attrsType , jsxContainer ! . attributes , typeChecker ) , jsxContainer ! . attributes . properties ) ;
1085
+ setSortTextToOptionalMember ( ) ;
1082
1086
completionKind = CompletionKind . MemberLike ;
1083
1087
isNewIdentifierLocation = false ;
1084
1088
return GlobalsSearch . Success ;
@@ -1586,6 +1590,7 @@ namespace ts.Completions {
1586
1590
return type && typeChecker . getPropertiesOfType ( classElementModifierFlags & ModifierFlags . Static ? typeChecker . getTypeOfSymbolAtLocation ( type . symbol , decl ) : type ) ;
1587
1591
} ) ;
1588
1592
symbols = filterClassMembersList ( baseSymbols , decl . members , classElementModifierFlags ) ;
1593
+ setSortTextToOptionalMember ( ) ;
1589
1594
}
1590
1595
1591
1596
return GlobalsSearch . Success ;
@@ -1879,7 +1884,7 @@ namespace ts.Completions {
1879
1884
return contextualMemberSymbols ;
1880
1885
}
1881
1886
1882
- const fulfilledSymbols : Symbol [ ] = [ ] ;
1887
+ const membersDeclaredBySpreadAssignment : Symbol [ ] = [ ] ;
1883
1888
const existingMemberNames = createUnderscoreEscapedMap < boolean > ( ) ;
1884
1889
for ( const m of existingMembers ) {
1885
1890
// Ignore omitted expressions for missing members
@@ -1906,7 +1911,7 @@ namespace ts.Completions {
1906
1911
const type = symbol && typeChecker . getTypeOfSymbolAtLocation ( symbol , expression ) ;
1907
1912
const properties = type && ( < ObjectType > type ) . properties ;
1908
1913
if ( properties ) {
1909
- fulfilledSymbols . push ( ...properties ) ;
1914
+ membersDeclaredBySpreadAssignment . push ( ...properties ) ;
1910
1915
}
1911
1916
}
1912
1917
else if ( isBindingElement ( m ) && m . propertyName ) {
@@ -1927,17 +1932,20 @@ namespace ts.Completions {
1927
1932
}
1928
1933
1929
1934
const filteredSymbols = contextualMemberSymbols . filter ( m => ! existingMemberNames . get ( m . escapedName ) ) ;
1935
+ setSortTextToMemberDeclaredBySpreadAssignment ( membersDeclaredBySpreadAssignment , contextualMemberSymbols ) ;
1936
+
1937
+ return filteredSymbols ;
1938
+ }
1930
1939
1931
- // Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment
1932
- for ( const fulfilledSymbol of fulfilledSymbols ) {
1933
- for ( const contextualMemberSymbol of filteredSymbols ) {
1940
+ // Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment
1941
+ function setSortTextToMemberDeclaredBySpreadAssignment ( membersDeclaredBySpreadAssignment : Symbol [ ] , contextualMemberSymbols : Symbol [ ] ) : void {
1942
+ for ( const fulfilledSymbol of membersDeclaredBySpreadAssignment ) {
1943
+ for ( const contextualMemberSymbol of contextualMemberSymbols ) {
1934
1944
if ( contextualMemberSymbol . name === fulfilledSymbol . name ) {
1935
1945
symbolToSortTextMap [ getSymbolId ( contextualMemberSymbol ) ] = SortText . MemberDeclaredBySpreadAssignment ;
1936
1946
}
1937
1947
}
1938
1948
}
1939
-
1940
- return filteredSymbols ;
1941
1949
}
1942
1950
1943
1951
/**
@@ -1991,6 +1999,7 @@ namespace ts.Completions {
1991
1999
*/
1992
2000
function filterJsxAttributes ( symbols : Symbol [ ] , attributes : NodeArray < JsxAttribute | JsxSpreadAttribute > ) : Symbol [ ] {
1993
2001
const seenNames = createUnderscoreEscapedMap < boolean > ( ) ;
2002
+ const membersDeclaredBySpreadAssignment : Symbol [ ] = [ ] ;
1994
2003
for ( const attr of attributes ) {
1995
2004
// If this is the current item we are editing right now, do not filter it out
1996
2005
if ( isCurrentlyEditingNode ( attr ) ) {
@@ -2000,9 +2009,21 @@ namespace ts.Completions {
2000
2009
if ( attr . kind === SyntaxKind . JsxAttribute ) {
2001
2010
seenNames . set ( attr . name . escapedText , true ) ;
2002
2011
}
2012
+ else if ( isJsxSpreadAttribute ( attr ) ) {
2013
+ const expression = attr . expression ;
2014
+ const symbol = typeChecker . getSymbolAtLocation ( expression ) ;
2015
+ const type = symbol && typeChecker . getTypeOfSymbolAtLocation ( symbol , expression ) ;
2016
+ const properties = type && ( < ObjectType > type ) . properties ;
2017
+ if ( properties ) {
2018
+ membersDeclaredBySpreadAssignment . push ( ...properties ) ;
2019
+ }
2020
+ }
2003
2021
}
2022
+ const filteredSymbols = symbols . filter ( a => ! seenNames . get ( a . escapedName ) ) ;
2004
2023
2005
- return symbols . filter ( a => ! seenNames . get ( a . escapedName ) ) ;
2024
+ setSortTextToMemberDeclaredBySpreadAssignment ( membersDeclaredBySpreadAssignment , symbols ) ;
2025
+
2026
+ return filteredSymbols ;
2006
2027
}
2007
2028
2008
2029
function isCurrentlyEditingNode ( node : Node ) : boolean {
0 commit comments