1
1
import { GetConfig } from '../types'
2
- import { getFullTypeChecker } from '../utils'
2
+ import { getFullTypeChecker , isTs5 } from '../utils'
3
3
import { sharedCompletionContext } from './sharedContext'
4
4
5
5
export default (
@@ -24,12 +24,20 @@ export default (
24
24
entries = [ ...entries ]
25
25
const typeChecker = languageService . getProgram ( ) ! . getTypeChecker ( ) !
26
26
const objType = typeChecker . getContextualType ( node )
27
- if ( ! objType ) return
28
- const properties = getAllPropertiesOfType ( objType , typeChecker )
29
- for ( const property of properties ) {
30
- const entry = entries . find ( ( { name } ) => name === property . name )
31
- if ( ! entry ) continue
32
- const type = typeChecker . getTypeOfSymbolAtLocation ( property , node )
27
+ let oldProperties : ts . Symbol [ ] | undefined
28
+ if ( ! isTs5 ( ) ) {
29
+ if ( ! objType ) return
30
+ oldProperties = getAllPropertiesOfType ( objType , typeChecker )
31
+ }
32
+ for ( const entry of entries ) {
33
+ let type : ts . Type | undefined
34
+ if ( ! isTs5 ( ) ) {
35
+ const property = oldProperties ! . find ( property => property . name === entry . name )
36
+ if ( ! property ) continue
37
+ type = typeChecker . getTypeOfSymbolAtLocation ( property , node )
38
+ } else if ( entry . symbol ) {
39
+ type = typeChecker . getTypeOfSymbol ( entry . symbol )
40
+ }
33
41
if ( ! type ) continue
34
42
if ( isFunctionType ( type , typeChecker ) ) {
35
43
if ( [ 'above' , 'remove' ] . includes ( keepOriginal ) && preferences . includeCompletionsWithObjectLiteralMethodSnippets ) {
@@ -52,14 +60,16 @@ export default (
52
60
return [ `: ${ quote } $1${ quote } ,$0` , `: ${ quote } ${ quote } ,` ]
53
61
}
54
62
const insertObjectArrayInnerText = c ( 'objectLiteralCompletions.insertNewLine' ) ? '\n\t$1\n' : '$1'
63
+ const booleanCompletion = getBooleanCompletion ( type , typeChecker )
55
64
const completingStyleMap = [
56
65
[ getQuotedSnippet , isStringCompletion ] ,
57
- [ [ ': ${1|true,false|},$0' , `: true/false,` ] , isBooleanCompletion ] ,
66
+ [ [ `: ${ booleanCompletion ?. [ 0 ] ?? '' } ,` , `: ${ booleanCompletion ?. [ 0 ] ?? '' } ` ] , ( ) => booleanCompletion ?. length === 1 ] ,
67
+ [ [ ': ${1|true,false|},$0' , `: true/false,` ] , ( ) => booleanCompletion ?. length === 2 ] ,
58
68
[ [ `: [${ insertObjectArrayInnerText } ],$0` , `: [],` ] , isArrayCompletion ] ,
59
69
[ [ `: {${ insertObjectArrayInnerText } },$0` , `: {},` ] , isObjectCompletion ] ,
60
70
] as const
61
71
const fallbackSnippet = c ( 'objectLiteralCompletions.fallbackVariant' ) ? ( [ ': $0,' , ': ,' ] as const ) : undefined
62
- const insertSnippetVariant = completingStyleMap . find ( ( [ , detector ] ) => detector ( type , typeChecker ) ) ?. [ 0 ] ?? fallbackSnippet
72
+ const insertSnippetVariant = completingStyleMap . find ( ( [ , detector ] ) => detector ( type ! , typeChecker ) ) ?. [ 0 ] ?? fallbackSnippet
63
73
if ( ! insertSnippetVariant ) continue
64
74
const [ insertSnippetText , insertSnippetPreview ] = typeof insertSnippetVariant === 'function' ? insertSnippetVariant ( ) : insertSnippetVariant
65
75
const insertText = entry . name + insertSnippetText
@@ -104,31 +114,36 @@ const isStringCompletion = (type: ts.Type) => {
104
114
return false
105
115
}
106
116
107
- const isBooleanCompletion = ( type : ts . Type , checker : ts . TypeChecker ) => {
108
- if ( type . flags & ts . TypeFlags . Undefined ) return false
117
+ const getBooleanCompletion = ( type : ts . Type , checker : ts . TypeChecker ) => {
118
+ if ( type . flags & ts . TypeFlags . Undefined ) return
109
119
// todo support boolean literals (boolean like)
110
- if ( type . flags & ts . TypeFlags . Boolean ) return true
111
120
const trueType = getFullTypeChecker ( checker ) . getTrueType ( ) as any
112
121
const falseType = getFullTypeChecker ( checker ) . getFalseType ( ) as any
113
- let seenTrueType = false
114
- let seenFalseType = false
115
- if ( type . isUnion ( ) ) {
116
- const match = isEverySubtype ( type , type => {
117
- if ( type . flags & ts . TypeFlags . Boolean ) return true
118
- if ( type === trueType ) {
119
- seenTrueType = true
120
- return true
121
- }
122
- if ( type === falseType ) {
123
- seenFalseType = true
124
- return true
125
- }
126
- return false
127
- } )
128
- if ( seenFalseType !== seenTrueType ) return false
129
- return match
122
+ const seenTypes = new Set < string > ( )
123
+ if ( type . flags & ts . TypeFlags . Boolean ) {
124
+ seenTypes . add ( 'true' )
125
+ seenTypes . add ( 'false' )
130
126
}
131
- return false
127
+ const match = isEverySubtype ( { types : type . isUnion ( ) ? type . types : [ type ] } as any , type => {
128
+ if ( type . flags & ts . TypeFlags . Boolean ) {
129
+ seenTypes . add ( 'true' )
130
+ seenTypes . add ( 'false' )
131
+ return true
132
+ }
133
+ if ( type === trueType ) {
134
+ seenTypes . add ( 'true' )
135
+ return true
136
+ }
137
+ if ( type === falseType ) {
138
+ seenTypes . add ( 'false' )
139
+ return true
140
+ }
141
+ return false
142
+ } )
143
+ if ( ! match ) return
144
+
145
+ if ( seenTypes . size === 0 ) return
146
+ return [ ...seenTypes . keys ( ) ]
132
147
}
133
148
134
149
const isArrayCompletion = ( type : ts . Type , checker : ts . TypeChecker ) => {
0 commit comments