11import { GetConfig } from '../types'
2- import { getFullTypeChecker } from '../utils'
2+ import { getFullTypeChecker , isTs5 } from '../utils'
33import { sharedCompletionContext } from './sharedContext'
44
55export default (
@@ -24,12 +24,20 @@ export default (
2424 entries = [ ...entries ]
2525 const typeChecker = languageService . getProgram ( ) ! . getTypeChecker ( ) !
2626 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+ }
3341 if ( ! type ) continue
3442 if ( isFunctionType ( type , typeChecker ) ) {
3543 if ( [ 'above' , 'remove' ] . includes ( keepOriginal ) && preferences . includeCompletionsWithObjectLiteralMethodSnippets ) {
@@ -52,14 +60,16 @@ export default (
5260 return [ `: ${ quote } $1${ quote } ,$0` , `: ${ quote } ${ quote } ,` ]
5361 }
5462 const insertObjectArrayInnerText = c ( 'objectLiteralCompletions.insertNewLine' ) ? '\n\t$1\n' : '$1'
63+ const booleanCompletion = getBooleanCompletion ( type , typeChecker )
5564 const completingStyleMap = [
5665 [ 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 ] ,
5868 [ [ `: [${ insertObjectArrayInnerText } ],$0` , `: [],` ] , isArrayCompletion ] ,
5969 [ [ `: {${ insertObjectArrayInnerText } },$0` , `: {},` ] , isObjectCompletion ] ,
6070 ] as const
6171 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
6373 if ( ! insertSnippetVariant ) continue
6474 const [ insertSnippetText , insertSnippetPreview ] = typeof insertSnippetVariant === 'function' ? insertSnippetVariant ( ) : insertSnippetVariant
6575 const insertText = entry . name + insertSnippetText
@@ -104,31 +114,36 @@ const isStringCompletion = (type: ts.Type) => {
104114 return false
105115}
106116
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
109119 // todo support boolean literals (boolean like)
110- if ( type . flags & ts . TypeFlags . Boolean ) return true
111120 const trueType = getFullTypeChecker ( checker ) . getTrueType ( ) as any
112121 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' )
130126 }
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 ( ) ]
132147}
133148
134149const isArrayCompletion = ( type : ts . Type , checker : ts . TypeChecker ) => {
0 commit comments