@@ -469,6 +469,7 @@ import {
469
469
isCallChain,
470
470
isCallExpression,
471
471
isCallLikeExpression,
472
+ isCallLikeOrFunctionLikeExpression,
472
473
isCallOrNewExpression,
473
474
isCallSignatureDeclaration,
474
475
isCatchClause,
@@ -1653,12 +1654,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1653
1654
getTypeOfPropertyOfContextualType,
1654
1655
getFullyQualifiedName,
1655
1656
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,
1662
1658
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) => runWithoutResolvedSignatureCaching(node, () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp)),
1663
1659
getExpandedParameters,
1664
1660
hasEffectiveRestParameter,
@@ -1838,32 +1834,55 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1838
1834
typeHasCallOrConstructSignatures,
1839
1835
};
1840
1836
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
+
1841
1859
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) {
1846
1865
const nodeLinks = getNodeLinks(node);
1847
- const resolvedSignature = nodeLinks.resolvedSignature;
1848
- cachedResolvedSignatures.push([nodeLinks, resolvedSignature] as const);
1866
+ cachedResolvedSignatures.push([nodeLinks, nodeLinks.resolvedSignature] as const);
1849
1867
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);
1850
1875
}
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;
1856
1879
}
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;
1865
1884
}
1866
- return result ;
1885
+ return fn() ;
1867
1886
}
1868
1887
1869
1888
function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
@@ -33207,7 +33226,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
33207
33226
33208
33227
for (let i = 0; i < argCount; i++) {
33209
33228
const arg = args[i];
33210
- if (arg.kind !== SyntaxKind.OmittedExpression) {
33229
+ if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg)) ) {
33211
33230
const paramType = getTypeAtPosition(signature, i);
33212
33231
if (couldContainTypeVariables(paramType)) {
33213
33232
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
@@ -33849,6 +33868,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
33849
33868
// decorators are applied to a declaration by the emitter, and not to an expression.
33850
33869
const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
33851
33870
let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal;
33871
+ argCheckMode |= checkMode & CheckMode.IsForStringLiteralArgumentCompletions;
33852
33872
33853
33873
// The following variables are captured and modified by calls to chooseOverload.
33854
33874
// If overload resolution or type argument inference fails, we want to report the
0 commit comments