@@ -14,8 +14,6 @@ export default (
14
14
// plans to make it hihgly configurable! e.g. if user wants to make some subtype leading (e.g. from [] | {})
15
15
if ( ts . isIdentifier ( node ) ) node = node . parent
16
16
if ( ts . isShorthandPropertyAssignment ( node ) ) node = node . parent
17
- const addEntries : ts . CompletionEntry [ ] = [ ]
18
- const completionIndexesToRemove : number [ ] = [ ]
19
17
entries = [ ...entries ]
20
18
if ( ts . isObjectLiteralExpression ( node ) ) {
21
19
const typeChecker = languageService . getProgram ( ) ! . getTypeChecker ( ) !
@@ -28,7 +26,18 @@ export default (
28
26
const type = typeChecker . getTypeOfSymbolAtLocation ( property , node )
29
27
if ( ! type ) continue
30
28
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
+ }
32
41
continue
33
42
}
34
43
if ( ! enableMoreVariants ) continue
@@ -40,13 +49,15 @@ export default (
40
49
const completingStyleMap = [
41
50
[ getQuotedSnippet , isStringCompletion ] ,
42
51
[ [ `: [${ insertObjectArrayInnerText } ],$0` , `: [],` ] , isArrayCompletion ] ,
43
- [ [ `: {${ insertObjectArrayInnerText } },$0` , `: {}` ] , isObjectCompletion ] ,
52
+ [ [ `: {${ insertObjectArrayInnerText } },$0` , `: {}, ` ] , isObjectCompletion ] ,
44
53
] 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
46
56
if ( ! insertSnippetVariant ) continue
47
57
const [ insertSnippetText , insertSnippetPreview ] = typeof insertSnippetVariant === 'function' ? insertSnippetVariant ( ) : insertSnippetVariant
48
58
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 , {
50
61
...entry ,
51
62
// todo setting incompatible!!!
52
63
sortText : entry . sortText ,
@@ -56,48 +67,31 @@ export default (
56
67
insertText,
57
68
isSnippet : true ,
58
69
} )
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
- } )
82
70
}
83
- return keepOriginal === 'above' ? [ ... addEntries , ... entries ] : [ ... entries , ... addEntries ]
71
+ return entries
84
72
}
85
73
}
86
74
}
87
75
76
+ const isObjectLiteralMethodSnippet = ( entry : ts . CompletionEntry ) => {
77
+ const { detail } = entry . labelDetails ?? { }
78
+ return detail ?. startsWith ( '(' ) && detail . split ( '\n' ) [ 0 ] ! . trimEnd ( ) . endsWith ( ')' )
79
+ }
80
+
88
81
const isMethodCompletionCall = ( type : ts . Type , checker : ts . TypeChecker ) => {
89
82
if ( checker . getSignaturesOfType ( type , ts . SignatureKind . Call ) . length > 0 ) return true
90
83
if ( type . isUnion ( ) ) return type . types . some ( type => isMethodCompletionCall ( type , checker ) )
91
84
}
92
85
93
86
const isStringCompletion = ( type : ts . Type ) => {
94
87
if ( type . flags & ts . TypeFlags . Undefined ) return true
95
- if ( type . isStringLiteral ( ) ) return true
88
+ if ( type . flags & ts . TypeFlags . StringLike ) return true
96
89
if ( type . isUnion ( ) ) return type . types . every ( type => isStringCompletion ( type ) )
97
90
return false
98
91
}
99
92
100
93
const isArrayCompletion = ( type : ts . Type , checker : ts . TypeChecker ) => {
94
+ if ( type . flags & ts . TypeFlags . Any ) return false
101
95
if ( type . flags & ts . TypeFlags . Undefined ) return true
102
96
if ( checker [ 'isArrayLikeType' ] ( type ) ) return true
103
97
if ( type . isUnion ( ) ) return type . types . every ( type => isArrayCompletion ( type , checker ) )
0 commit comments