@@ -107,32 +107,11 @@ namespace ts.Completions.StringCompletions {
107
107
readonly isNewIdentifier : boolean ;
108
108
}
109
109
type StringLiteralCompletion = { readonly kind : StringLiteralCompletionKind . Paths , readonly paths : readonly PathCompletion [ ] } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes ;
110
- function getStringLiteralCompletionEntries ( sourceFile : SourceFile , node : StringLiteralLike , position : number , typeChecker : TypeChecker , compilerOptions : CompilerOptions , host : LanguageServiceHost ) : StringLiteralCompletion | undefined {
110
+ function getStringLiteralCompletionEntries ( sourceFile : SourceFile , node : StringLiteralLike | ParenthesizedExpression , position : number , typeChecker : TypeChecker , compilerOptions : CompilerOptions , host : LanguageServiceHost ) : StringLiteralCompletion | undefined {
111
111
const { parent } = node ;
112
112
switch ( parent . kind ) {
113
113
case SyntaxKind . LiteralType :
114
- switch ( parent . parent . kind ) {
115
- case SyntaxKind . TypeReference :
116
- return { kind : StringLiteralCompletionKind . Types , types : getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( parent as LiteralTypeNode ) ) , isNewIdentifier : false } ;
117
- case SyntaxKind . IndexedAccessType :
118
- // Get all apparent property names
119
- // i.e. interface Foo {
120
- // foo: string;
121
- // bar: string;
122
- // }
123
- // let x: Foo["/*completion position*/"]
124
- return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( ( parent . parent as IndexedAccessTypeNode ) . objectType ) ) ;
125
- case SyntaxKind . ImportType :
126
- return { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker ) } ;
127
- case SyntaxKind . UnionType : {
128
- if ( ! isTypeReferenceNode ( parent . parent . parent ) ) return undefined ;
129
- const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion ( parent . parent as UnionTypeNode , parent as LiteralTypeNode ) ;
130
- const types = getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( parent . parent as UnionTypeNode ) ) . filter ( t => ! contains ( alreadyUsedTypes , t . value ) ) ;
131
- return { kind : StringLiteralCompletionKind . Types , types, isNewIdentifier : false } ;
132
- }
133
- default :
134
- return undefined ;
135
- }
114
+ return isStringLiteralLike ( node ) ? getCompletionEntriesFromLiteral ( sourceFile , node , typeChecker , compilerOptions , host ) : undefined ;
136
115
137
116
case SyntaxKind . PropertyAssignment :
138
117
if ( isObjectLiteralExpression ( parent . parent ) && ( < PropertyAssignment > parent ) . name === node ) {
@@ -186,8 +165,9 @@ namespace ts.Completions.StringCompletions {
186
165
// import x = require("/*completion position*/");
187
166
// var y = require("/*completion position*/");
188
167
// export * from "/*completion position*/";
189
- return { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker ) } ;
190
-
168
+ return isStringLiteralLike ( node ) ? { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker ) } : undefined ;
169
+ case SyntaxKind . ParenthesizedExpression :
170
+ return getStringLiteralCompletionEntries ( sourceFile , parent as ParenthesizedExpression , position , typeChecker , compilerOptions , host ) ;
191
171
default :
192
172
return fromContextualType ( ) ;
193
173
}
@@ -199,6 +179,41 @@ namespace ts.Completions.StringCompletions {
199
179
}
200
180
}
201
181
182
+ function getCompletionEntriesFromLiteral ( sourceFile : SourceFile , node : StringLiteralLike | ParenthesizedTypeNode , typeChecker : TypeChecker , compilerOptions : CompilerOptions , host : LanguageServiceHost ) : StringLiteralCompletion | undefined {
183
+ const parent = node . parent ;
184
+ switch ( parent . parent . kind ) {
185
+ case SyntaxKind . TypeReference :
186
+ if ( isLiteralTypeNode ( parent ) || isParenthesizedTypeNode ( parent ) ) {
187
+ return { kind : StringLiteralCompletionKind . Types , types : getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( parent ) ) , isNewIdentifier : false } ;
188
+ }
189
+ return undefined ;
190
+ case SyntaxKind . IndexedAccessType :
191
+ // Get all apparent property names
192
+ // i.e. interface Foo {
193
+ // foo: string;
194
+ // bar: string;
195
+ // }
196
+ // let x: Foo["/*completion position*/"]
197
+ return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( ( parent . parent as IndexedAccessTypeNode ) . objectType ) ) ;
198
+ case SyntaxKind . ImportType :
199
+ return isStringLiteralLike ( node ) ? { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker ) } : undefined ;
200
+ case SyntaxKind . UnionType : {
201
+ if ( ! isTypeReferenceNode ( parent . parent . parent ) ) {
202
+ return undefined ;
203
+ }
204
+ const unionType = parent . parent as UnionTypeNode ;
205
+ const alreadyUsedTypes = isLiteralTypeNode ( parent ) ? getAlreadyUsedTypesInStringLiteralUnion ( unionType , parent ) : [ ] ;
206
+ const types = getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( unionType ) ) . filter ( t => ! contains ( alreadyUsedTypes , t . value ) ) ;
207
+ return { kind : StringLiteralCompletionKind . Types , types, isNewIdentifier : false } ;
208
+ }
209
+ case SyntaxKind . ParenthesizedType :
210
+ return getCompletionEntriesFromLiteral ( sourceFile , parent as ParenthesizedTypeNode , typeChecker , compilerOptions , host ) ;
211
+ default :
212
+ return undefined ;
213
+ }
214
+
215
+ }
216
+
202
217
function getAlreadyUsedTypesInStringLiteralUnion ( union : UnionTypeNode , current : LiteralTypeNode ) : readonly string [ ] {
203
218
return mapDefined ( union . types , type =>
204
219
type !== current && isLiteralTypeNode ( type ) && isStringLiteral ( type . literal ) ? type . literal . text : undefined ) ;
0 commit comments