@@ -14,8 +14,6 @@ export default (
1414 // plans to make it hihgly configurable! e.g. if user wants to make some subtype leading (e.g. from [] | {})
1515 if ( ts . isIdentifier ( node ) ) node = node . parent
1616 if ( ts . isShorthandPropertyAssignment ( node ) ) node = node . parent
17- const addEntries : ts . CompletionEntry [ ] = [ ]
18- const completionIndexesToRemove : number [ ] = [ ]
1917 entries = [ ...entries ]
2018 if ( ts . isObjectLiteralExpression ( node ) ) {
2119 const typeChecker = languageService . getProgram ( ) ! . getTypeChecker ( ) !
@@ -28,7 +26,18 @@ export default (
2826 const type = typeChecker . getTypeOfSymbolAtLocation ( property , node )
2927 if ( ! type ) continue
3028 if ( isMethodCompletionCall ( type , typeChecker ) ) {
31- if ( keepOriginal === 'remove' ) completionIndexesToRemove . push ( entries . indexOf ( entry ) )
29+ if ( [ 'above' , 'remove' ] . includes ( keepOriginal ) && preferences . includeCompletionsWithObjectLiteralMethodSnippets ) {
30+ const methodEntryIndex = entries . findIndex ( e => e . name === entry . name && isObjectLiteralMethodSnippet ( e ) )
31+ const methodEntry = entries [ methodEntryIndex ]
32+ if ( methodEntry ) {
33+ entries . splice ( methodEntryIndex , 1 )
34+ entries . splice ( entries . indexOf ( entry ) + ( keepOriginal === 'below' ? 1 : 0 ) , keepOriginal === 'remove' ? 1 : 0 , {
35+ ...methodEntry ,
36+ // let correctSorting.enable sort it
37+ sortText : entry . sortText ,
38+ } )
39+ }
40+ }
3241 continue
3342 }
3443 if ( ! enableMoreVariants ) continue
@@ -40,13 +49,15 @@ export default (
4049 const completingStyleMap = [
4150 [ getQuotedSnippet , isStringCompletion ] ,
4251 [ [ `: [${ insertObjectArrayInnerText } ],$0` , `: [],` ] , isArrayCompletion ] ,
43- [ [ `: {${ insertObjectArrayInnerText } },$0` , `: {}` ] , isObjectCompletion ] ,
52+ [ [ `: {${ insertObjectArrayInnerText } },$0` , `: {}, ` ] , isObjectCompletion ] ,
4453 ] as const
45- const insertSnippetVariant = completingStyleMap . find ( ( [ , detector ] ) => detector ( type , typeChecker ) ) ?. [ 0 ]
54+ const fallbackSnippet = c ( 'objectLiteralCompletions.fallbackVariant' ) ? ( [ ': $0,' , ': ,' ] as const ) : undefined
55+ const insertSnippetVariant = completingStyleMap . find ( ( [ , detector ] ) => detector ( type , typeChecker ) ) ?. [ 0 ] ?? fallbackSnippet
4656 if ( ! insertSnippetVariant ) continue
4757 const [ insertSnippetText , insertSnippetPreview ] = typeof insertSnippetVariant === 'function' ? insertSnippetVariant ( ) : insertSnippetVariant
4858 const insertText = entry . name + insertSnippetText
49- addEntries . push ( {
59+ const index = entries . indexOf ( entry )
60+ entries . splice ( index + ( keepOriginal === 'below' ? 1 : 0 ) , keepOriginal === 'remove' ? 1 : 0 , {
5061 ...entry ,
5162 // todo setting incompatible!!!
5263 sortText : entry . sortText ,
@@ -56,48 +67,31 @@ export default (
5667 insertText,
5768 isSnippet : true ,
5869 } )
59- if ( keepOriginal === 'remove' ) entries . splice ( entries . indexOf ( entry ) , 1 )
60- }
61- if ( ( keepOriginal === 'above' || keepOriginal === 'remove' ) && preferences . includeCompletionsWithObjectLiteralMethodSnippets ) {
62- const metMethodCompletions : string [ ] = [ ]
63- entries = entries . filter ( ( entry , i ) => {
64- if ( completionIndexesToRemove . includes ( i ) ) return false
65-
66- const { detail } = entry . labelDetails ?? { }
67- if ( detail ?. startsWith ( '(' ) && detail . split ( '\n' ) [ 0 ] ! . trimEnd ( ) . endsWith ( ')' ) ) {
68- addEntries . push ( entry )
69- metMethodCompletions . push ( entry . name )
70- return false
71- }
72- if (
73- keepOriginal === 'remove' &&
74- entry . kind === ts . ScriptElementKind . memberFunctionElement &&
75- ! detail &&
76- metMethodCompletions . includes ( entry . name )
77- ) {
78- return false
79- }
80- return true
81- } )
8270 }
83- return keepOriginal === 'above' ? [ ... addEntries , ... entries ] : [ ... entries , ... addEntries ]
71+ return entries
8472 }
8573 }
8674}
8775
76+ const isObjectLiteralMethodSnippet = ( entry : ts . CompletionEntry ) => {
77+ const { detail } = entry . labelDetails ?? { }
78+ return detail ?. startsWith ( '(' ) && detail . split ( '\n' ) [ 0 ] ! . trimEnd ( ) . endsWith ( ')' )
79+ }
80+
8881const isMethodCompletionCall = ( type : ts . Type , checker : ts . TypeChecker ) => {
8982 if ( checker . getSignaturesOfType ( type , ts . SignatureKind . Call ) . length > 0 ) return true
9083 if ( type . isUnion ( ) ) return type . types . some ( type => isMethodCompletionCall ( type , checker ) )
9184}
9285
9386const isStringCompletion = ( type : ts . Type ) => {
9487 if ( type . flags & ts . TypeFlags . Undefined ) return true
95- if ( type . isStringLiteral ( ) ) return true
88+ if ( type . flags & ts . TypeFlags . StringLike ) return true
9689 if ( type . isUnion ( ) ) return type . types . every ( type => isStringCompletion ( type ) )
9790 return false
9891}
9992
10093const isArrayCompletion = ( type : ts . Type , checker : ts . TypeChecker ) => {
94+ if ( type . flags & ts . TypeFlags . Any ) return false
10195 if ( type . flags & ts . TypeFlags . Undefined ) return true
10296 if ( checker [ 'isArrayLikeType' ] ( type ) ) return true
10397 if ( type . isUnion ( ) ) return type . types . every ( type => isArrayCompletion ( type , checker ) )
0 commit comments