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