@@ -469,6 +469,7 @@ import {
469469 isCallChain,
470470 isCallExpression,
471471 isCallLikeExpression,
472+ isCallLikeOrFunctionLikeExpression,
472473 isCallOrNewExpression,
473474 isCallSignatureDeclaration,
474475 isCatchClause,
@@ -1653,12 +1654,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16531654 getTypeOfPropertyOfContextualType,
16541655 getFullyQualifiedName,
16551656 getResolvedSignature: (node, candidatesOutArray, argumentCount) => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal),
1656- getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray, checkMode = CheckMode.IsForStringLiteralArgumentCompletions) => {
1657- if (checkMode & CheckMode.IsForStringLiteralArgumentCompletions) {
1658- return runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, checkMode & ~CheckMode.IsForStringLiteralArgumentCompletions));
1659- }
1660- return runWithoutResolvedSignatureCaching(editingArgument, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, checkMode & ~CheckMode.IsForStringLiteralArgumentCompletions));
1661- },
1657+ getCandidateSignaturesForStringLiteralCompletions,
16621658 getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) => runWithoutResolvedSignatureCaching(node, () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp)),
16631659 getExpandedParameters,
16641660 hasEffectiveRestParameter,
@@ -1838,32 +1834,55 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
18381834 typeHasCallOrConstructSignatures,
18391835 };
18401836
1837+ function getCandidateSignaturesForStringLiteralCompletions(call: CallLikeExpression, editingArgument: Node) {
1838+ const candidatesSet = new Set<Signature>();
1839+ const candidates: Signature[] = [];
1840+
1841+ // first, get candidates when inference is blocked from the source node.
1842+ runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignatureWorker(call, candidates, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions));
1843+ for (const candidate of candidates) {
1844+ candidatesSet.add(candidate);
1845+ }
1846+
1847+ // reset candidates for second pass
1848+ candidates.length = 0;
1849+
1850+ // next, get candidates where the source node is considered for inference.
1851+ runWithoutResolvedSignatureCaching(editingArgument, () => getResolvedSignatureWorker(call, candidates, /*argumentCount*/ undefined, CheckMode.Normal));
1852+ for (const candidate of candidates) {
1853+ candidatesSet.add(candidate);
1854+ }
1855+
1856+ return arrayFrom(candidatesSet);
1857+ }
1858+
18411859 function runWithoutResolvedSignatureCaching<T>(node: Node | undefined, fn: () => T): T {
1842- const cachedResolvedSignatures = [];
1843- const cachedTypes = [];
1844- while (node) {
1845- if (isCallLikeExpression(node) || isFunctionLike(node)) {
1860+ node = findAncestor(node, isCallLikeOrFunctionLikeExpression);
1861+ if (node) {
1862+ const cachedResolvedSignatures = [];
1863+ const cachedTypes = [];
1864+ while (node) {
18461865 const nodeLinks = getNodeLinks(node);
1847- const resolvedSignature = nodeLinks.resolvedSignature;
1848- cachedResolvedSignatures.push([nodeLinks, resolvedSignature] as const);
1866+ cachedResolvedSignatures.push([nodeLinks, nodeLinks.resolvedSignature] as const);
18491867 nodeLinks.resolvedSignature = undefined;
1868+ if (isFunctionLike(node)) {
1869+ const symbolLinks = getSymbolLinks(getSymbolOfDeclaration(node));
1870+ const type = symbolLinks.type;
1871+ cachedTypes.push([symbolLinks, type] as const);
1872+ symbolLinks.type = undefined;
1873+ }
1874+ node = findAncestor(node.parent, isCallLikeOrFunctionLikeExpression);
18501875 }
1851- if (isFunctionLike(node)) {
1852- const symbolLinks = getSymbolLinks(getSymbolOfDeclaration(node));
1853- const type = symbolLinks.type;
1854- cachedTypes.push([symbolLinks, type] as const);
1855- symbolLinks.type = undefined;
1876+ const result = fn();
1877+ for (const [nodeLinks, resolvedSignature] of cachedResolvedSignatures) {
1878+ nodeLinks.resolvedSignature = resolvedSignature;
18561879 }
1857- node = node.parent;
1858- }
1859- const result = fn();
1860- for (const [nodeLinks, resolvedSignature] of cachedResolvedSignatures) {
1861- nodeLinks.resolvedSignature = resolvedSignature;
1862- }
1863- for (const [symbolLinks, type] of cachedTypes) {
1864- symbolLinks.type = type;
1880+ for (const [symbolLinks, type] of cachedTypes) {
1881+ symbolLinks.type = type;
1882+ }
1883+ return result;
18651884 }
1866- return result ;
1885+ return fn() ;
18671886 }
18681887
18691888 function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
@@ -33207,7 +33226,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3320733226
3320833227 for (let i = 0; i < argCount; i++) {
3320933228 const arg = args[i];
33210- if (arg.kind !== SyntaxKind.OmittedExpression) {
33229+ if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg)) ) {
3321133230 const paramType = getTypeAtPosition(signature, i);
3321233231 if (couldContainTypeVariables(paramType)) {
3321333232 const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
@@ -33849,6 +33868,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3384933868 // decorators are applied to a declaration by the emitter, and not to an expression.
3385033869 const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
3385133870 let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal;
33871+ argCheckMode |= checkMode & CheckMode.IsForStringLiteralArgumentCompletions;
3385233872
3385333873 // The following variables are captured and modified by calls to chooseOverload.
3385433874 // If overload resolution or type argument inference fails, we want to report the
0 commit comments