@@ -108,32 +108,41 @@ namespace ts.Completions.StringCompletions {
108108 }
109109 type StringLiteralCompletion = { readonly kind : StringLiteralCompletionKind . Paths , readonly paths : readonly PathCompletion [ ] } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes ;
110110 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 ) ;
112112 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+ }
117124 case SyntaxKind . IndexedAccessType :
118125 // Get all apparent property names
119126 // i.e. interface Foo {
120127 // foo: string;
121128 // bar: string;
122129 // }
123130 // let x: Foo["/*completion position*/"]
124- return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( ( parent . parent as IndexedAccessTypeNode ) . objectType ) ) ;
131+ return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( ( grandParent as IndexedAccessTypeNode ) . objectType ) ) ;
125132 case SyntaxKind . ImportType :
126133 return { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker ) } ;
127134 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 ) ) ;
131140 return { kind : StringLiteralCompletionKind . Types , types, isNewIdentifier : false } ;
132141 }
133142 default :
134143 return undefined ;
135144 }
136-
145+ }
137146 case SyntaxKind . PropertyAssignment :
138147 if ( isObjectLiteralExpression ( parent . parent ) && ( < PropertyAssignment > parent ) . name === node ) {
139148 // Get quoted name of properties of the object literal expression
@@ -154,7 +163,7 @@ namespace ts.Completions.StringCompletions {
154163
155164 case SyntaxKind . ElementAccessExpression : {
156165 const { expression, argumentExpression } = parent as ElementAccessExpression ;
157- if ( node === argumentExpression ) {
166+ if ( node === skipParentheses ( argumentExpression ) ) {
158167 // Get all names of properties on the expression
159168 // i.e. interface A {
160169 // 'prop1': string
@@ -199,6 +208,17 @@ namespace ts.Completions.StringCompletions {
199208 }
200209 }
201210
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+
202222 function getAlreadyUsedTypesInStringLiteralUnion ( union : UnionTypeNode , current : LiteralTypeNode ) : readonly string [ ] {
203223 return mapDefined ( union . types , type =>
204224 type !== current && isLiteralTypeNode ( type ) && isStringLiteral ( type . literal ) ? type . literal . text : undefined ) ;
0 commit comments