@@ -83,7 +83,6 @@ import {
83
83
isString ,
84
84
isStringLiteral ,
85
85
isStringLiteralLike ,
86
- isTypeReferenceNode ,
87
86
isUrl ,
88
87
JsxAttribute ,
89
88
LanguageServiceHost ,
@@ -342,40 +341,10 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
342
341
switch ( parent . kind ) {
343
342
case SyntaxKind . LiteralType : {
344
343
const grandParent = walkUpParentheses ( parent . parent ) ;
345
- switch ( grandParent . kind ) {
346
- case SyntaxKind . ExpressionWithTypeArguments :
347
- case SyntaxKind . TypeReference : {
348
- const typeArgument = findAncestor ( parent , n => n . parent === grandParent ) as LiteralTypeNode ;
349
- if ( typeArgument ) {
350
- return { kind : StringLiteralCompletionKind . Types , types : getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( typeArgument ) ) , isNewIdentifier : false } ;
351
- }
352
- return undefined ;
353
- }
354
- case SyntaxKind . IndexedAccessType :
355
- // Get all apparent property names
356
- // i.e. interface Foo {
357
- // foo: string;
358
- // bar: string;
359
- // }
360
- // let x: Foo["/*completion position*/"]
361
- const { indexType, objectType } = grandParent as IndexedAccessTypeNode ;
362
- if ( ! rangeContainsPosition ( indexType , position ) ) {
363
- return undefined ;
364
- }
365
- return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( objectType ) ) ;
366
- case SyntaxKind . ImportType :
367
- return { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker , preferences ) } ;
368
- case SyntaxKind . UnionType : {
369
- if ( ! isTypeReferenceNode ( grandParent . parent ) ) {
370
- return undefined ;
371
- }
372
- const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion ( grandParent as UnionTypeNode , parent as LiteralTypeNode ) ;
373
- const types = getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( grandParent as UnionTypeNode ) ) . filter ( t => ! contains ( alreadyUsedTypes , t . value ) ) ;
374
- return { kind : StringLiteralCompletionKind . Types , types, isNewIdentifier : false } ;
375
- }
376
- default :
377
- return undefined ;
344
+ if ( grandParent . kind === SyntaxKind . ImportType ) {
345
+ return { kind : StringLiteralCompletionKind . Paths , paths : getStringLiteralCompletionsFromModuleNames ( sourceFile , node , compilerOptions , host , typeChecker , preferences ) } ;
378
346
}
347
+ return fromUnionableLiteralType ( grandParent ) ;
379
348
}
380
349
case SyntaxKind . PropertyAssignment :
381
350
if ( isObjectLiteralExpression ( parent . parent ) && ( parent as PropertyAssignment ) . name === node ) {
@@ -443,6 +412,44 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
443
412
return fromContextualType ( ) || fromContextualType ( ContextFlags . None ) ;
444
413
}
445
414
415
+ function fromUnionableLiteralType ( grandParent : Node ) : StringLiteralCompletionsFromTypes | StringLiteralCompletionsFromProperties | undefined {
416
+ switch ( grandParent . kind ) {
417
+ case SyntaxKind . ExpressionWithTypeArguments :
418
+ case SyntaxKind . TypeReference : {
419
+ const typeArgument = findAncestor ( parent , n => n . parent === grandParent ) as LiteralTypeNode ;
420
+ if ( typeArgument ) {
421
+ return { kind : StringLiteralCompletionKind . Types , types : getStringLiteralTypes ( typeChecker . getTypeArgumentConstraint ( typeArgument ) ) , isNewIdentifier : false } ;
422
+ }
423
+ return undefined ;
424
+ }
425
+ case SyntaxKind . IndexedAccessType :
426
+ // Get all apparent property names
427
+ // i.e. interface Foo {
428
+ // foo: string;
429
+ // bar: string;
430
+ // }
431
+ // let x: Foo["/*completion position*/"]
432
+ const { indexType, objectType } = grandParent as IndexedAccessTypeNode ;
433
+ if ( ! rangeContainsPosition ( indexType , position ) ) {
434
+ return undefined ;
435
+ }
436
+ return stringLiteralCompletionsFromProperties ( typeChecker . getTypeFromTypeNode ( objectType ) ) ;
437
+ case SyntaxKind . UnionType : {
438
+ const result = fromUnionableLiteralType ( walkUpParentheses ( grandParent . parent ) ) ;
439
+ if ( ! result ) {
440
+ return undefined ;
441
+ }
442
+ const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion ( grandParent as UnionTypeNode , parent as LiteralTypeNode ) ;
443
+ if ( result . kind === StringLiteralCompletionKind . Properties ) {
444
+ return { kind : StringLiteralCompletionKind . Properties , symbols : result . symbols . filter ( sym => ! contains ( alreadyUsedTypes , sym . name ) ) , hasIndexSignature : result . hasIndexSignature } ;
445
+ }
446
+ return { kind : StringLiteralCompletionKind . Types , types : result . types . filter ( t => ! contains ( alreadyUsedTypes , t . value ) ) , isNewIdentifier : false } ;
447
+ }
448
+ default :
449
+ return undefined ;
450
+ }
451
+ }
452
+
446
453
function fromContextualType ( contextFlags : ContextFlags = ContextFlags . Completions ) : StringLiteralCompletionsFromTypes | undefined {
447
454
// Get completion for string literal from string literal type
448
455
// i.e. var x: "hi" | "hello" = "/*completion position*/"
0 commit comments