@@ -108,32 +108,41 @@ namespace ts.Completions.StringCompletions {
108
108
}
109
109
type StringLiteralCompletion = { readonly kind : StringLiteralCompletionKind . Paths , readonly paths : readonly PathCompletion [ ] } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes ;
110
110
function getStringLiteralCompletionEntries ( sourceFile : SourceFile , node : StringLiteralLike , position : number , typeChecker : TypeChecker , compilerOptions : CompilerOptions , host : LanguageServiceHost ) : StringLiteralCompletion | undefined {
111
- const { parent } = node ;
111
+ const parent = walkUpParentheses ( node . parent ) ;
112
112
switch ( parent . kind ) {
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 } ;
113
+ case SyntaxKind . LiteralType : {
114
+ const grandParent = walkUpParentheses ( parent . parent ) ;
115
+ switch ( grandParent . kind ) {
116
+ case SyntaxKind . TypeReference : {
117
+ const typeReference = grandParent as TypeReferenceNode ;
118
+ const typeArgument = findAncestor ( parent , n => n . parent === typeReference ) as LiteralTypeNode ;
119
+ if ( typeArgument ) {
120
+ return { kind : StringLiteralCompletionKind . Types , types : getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( typeArgument ) ) , isNewIdentifier : false } ;
121
+ }
122
+ return undefined ;
123
+ }
117
124
case SyntaxKind . IndexedAccessType :
118
125
// Get all apparent property names
119
126
// i.e. interface Foo {
120
127
// foo: string;
121
128
// bar: string;
122
129
// }
123
130
// let x: Foo["/*completion position*/"]
124
- return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( ( parent . parent as IndexedAccessTypeNode ) . objectType ) ) ;
131
+ return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( ( grandParent as IndexedAccessTypeNode ) . objectType ) ) ;
125
132
case SyntaxKind . ImportType :
126
133
return { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker ) } ;
127
134
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 ) ) ;
135
+ if ( ! isTypeReferenceNode ( grandParent . parent ) ) {
136
+ return undefined ;
137
+ }
138
+ const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion ( grandParent as UnionTypeNode , parent as LiteralTypeNode ) ;
139
+ const types = getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( grandParent as UnionTypeNode ) ) . filter ( t => ! contains ( alreadyUsedTypes , t . value ) ) ;
131
140
return { kind : StringLiteralCompletionKind . Types , types, isNewIdentifier : false } ;
132
141
}
133
142
default :
134
143
return undefined ;
135
144
}
136
-
145
+ }
137
146
case SyntaxKind . PropertyAssignment :
138
147
if ( isObjectLiteralExpression ( parent . parent ) && ( < PropertyAssignment > parent ) . name === node ) {
139
148
// Get quoted name of properties of the object literal expression
@@ -154,7 +163,7 @@ namespace ts.Completions.StringCompletions {
154
163
155
164
case SyntaxKind . ElementAccessExpression : {
156
165
const { expression, argumentExpression } = parent as ElementAccessExpression ;
157
- if ( node === argumentExpression ) {
166
+ if ( node === skipParentheses ( argumentExpression ) ) {
158
167
// Get all names of properties on the expression
159
168
// i.e. interface A {
160
169
// 'prop1': string
@@ -199,6 +208,17 @@ namespace ts.Completions.StringCompletions {
199
208
}
200
209
}
201
210
211
+ function walkUpParentheses ( node : Node ) {
212
+ switch ( node . kind ) {
213
+ case SyntaxKind . ParenthesizedType :
214
+ return walkUpParenthesizedTypes ( node ) ;
215
+ case SyntaxKind . ParenthesizedExpression :
216
+ return walkUpParenthesizedExpressions ( node ) ;
217
+ default :
218
+ return node ;
219
+ }
220
+ }
221
+
202
222
function getAlreadyUsedTypesInStringLiteralUnion ( union : UnionTypeNode , current : LiteralTypeNode ) : readonly string [ ] {
203
223
return mapDefined ( union . types , type =>
204
224
type !== current && isLiteralTypeNode ( type ) && isStringLiteral ( type . literal ) ? type . literal . text : undefined ) ;
0 commit comments