@@ -83,7 +83,6 @@ import {
8383 isString ,
8484 isStringLiteral ,
8585 isStringLiteralLike ,
86- isTypeReferenceNode ,
8786 isUrl ,
8887 JsxAttribute ,
8988 LanguageServiceHost ,
@@ -342,40 +341,10 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
342341 switch ( parent . kind ) {
343342 case SyntaxKind . LiteralType : {
344343 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 ) } ;
378346 }
347+ return fromUnionableLiteralType ( grandParent ) ;
379348 }
380349 case SyntaxKind . PropertyAssignment :
381350 if ( isObjectLiteralExpression ( parent . parent ) && ( parent as PropertyAssignment ) . name === node ) {
@@ -443,6 +412,44 @@ function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringL
443412 return fromContextualType ( ) || fromContextualType ( ContextFlags . None ) ;
444413 }
445414
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+
446453 function fromContextualType ( contextFlags : ContextFlags = ContextFlags . Completions ) : StringLiteralCompletionsFromTypes | undefined {
447454 // Get completion for string literal from string literal type
448455 // i.e. var x: "hi" | "hello" = "/*completion position*/"
0 commit comments