@@ -176,15 +176,16 @@ namespace ts {
176
176
}
177
177
178
178
const enum CheckMode {
179
- Normal = 0, // Normal type checking
180
- Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable
181
- Inferential = 1 << 1, // Inferential typing
182
- SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions
183
- SkipGenericFunctions = 1 << 3, // Skip single signature generic functions
184
- IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help
185
- RestBindingElement = 1 << 5, // Checking a type that is going to be used to determine the type of a rest binding element
186
- // e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`,
187
- // we need to preserve generic types instead of substituting them for constraints
179
+ Normal = 0, // Normal type checking
180
+ Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable
181
+ Inferential = 1 << 1, // Inferential typing
182
+ SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions
183
+ SkipGenericFunctions = 1 << 3, // Skip single signature generic functions
184
+ IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help
185
+ IsForStringLiteralArgumentCompletions = 1 << 5, // Do not infer from the argument currently being typed
186
+ RestBindingElement = 1 << 6, // Checking a type that is going to be used to determine the type of a rest binding element
187
+ // e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`,
188
+ // we need to preserve generic types instead of substituting them for constraints
188
189
}
189
190
190
191
const enum SignatureCheckMode {
@@ -540,26 +541,10 @@ namespace ts {
540
541
if (!node) {
541
542
return undefined;
542
543
}
543
- const containingCall = findAncestor(node, isCallLikeExpression);
544
- const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
545
- if (contextFlags! & ContextFlags.Completions && containingCall) {
546
- let toMarkSkip = node as Node;
547
- do {
548
- getNodeLinks(toMarkSkip).skipDirectInference = true;
549
- toMarkSkip = toMarkSkip.parent;
550
- } while (toMarkSkip && toMarkSkip !== containingCall);
551
- getNodeLinks(containingCall).resolvedSignature = undefined;
552
- }
553
- const result = getContextualType(node, contextFlags);
554
- if (contextFlags! & ContextFlags.Completions && containingCall) {
555
- let toMarkSkip = node as Node;
556
- do {
557
- getNodeLinks(toMarkSkip).skipDirectInference = undefined;
558
- toMarkSkip = toMarkSkip.parent;
559
- } while (toMarkSkip && toMarkSkip !== containingCall);
560
- getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
544
+ if (contextFlags! & ContextFlags.Completions) {
545
+ return runWithInferenceBlockedFromSourceNode(node, () => getContextualType(node, contextFlags));
561
546
}
562
- return result ;
547
+ return getContextualType(node, contextFlags) ;
563
548
},
564
549
getContextualTypeForObjectLiteralElement: nodeIn => {
565
550
const node = getParseTreeNode(nodeIn, isObjectLiteralElementLike);
@@ -578,6 +563,8 @@ namespace ts {
578
563
getFullyQualifiedName,
579
564
getResolvedSignature: (node, candidatesOutArray, argumentCount) =>
580
565
getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal),
566
+ getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray) =>
567
+ getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions, editingArgument),
581
568
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) =>
582
569
getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp),
583
570
getExpandedParameters,
@@ -747,10 +734,36 @@ namespace ts {
747
734
getMemberOverrideModifierStatus,
748
735
};
749
736
750
- function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode): Signature | undefined {
737
+ function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
738
+ const containingCall = findAncestor(node, isCallLikeExpression);
739
+ const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
740
+ if (containingCall) {
741
+ let toMarkSkip = node!;
742
+ do {
743
+ getNodeLinks(toMarkSkip).skipDirectInference = true;
744
+ toMarkSkip = toMarkSkip.parent;
745
+ } while (toMarkSkip && toMarkSkip !== containingCall);
746
+ getNodeLinks(containingCall).resolvedSignature = undefined;
747
+ }
748
+ const result = fn();
749
+ if (containingCall) {
750
+ let toMarkSkip = node!;
751
+ do {
752
+ getNodeLinks(toMarkSkip).skipDirectInference = undefined;
753
+ toMarkSkip = toMarkSkip.parent;
754
+ } while (toMarkSkip && toMarkSkip !== containingCall);
755
+ getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
756
+ }
757
+ return result;
758
+ }
759
+
760
+ function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, editingArgument?: Node): Signature | undefined {
751
761
const node = getParseTreeNode(nodeIn, isCallLikeExpression);
752
762
apparentArgumentCount = argumentCount;
753
- const res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined;
763
+ const res =
764
+ !node ? undefined :
765
+ editingArgument ? runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignature(node, candidatesOutArray, checkMode)) :
766
+ getResolvedSignature(node, candidatesOutArray, checkMode);
754
767
apparentArgumentCount = undefined;
755
768
return res;
756
769
}
@@ -22664,7 +22677,7 @@ namespace ts {
22664
22677
const properties = getPropertiesOfObjectType(target);
22665
22678
for (const targetProp of properties) {
22666
22679
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
22667
- if (sourceProp) {
22680
+ if (sourceProp && !some(sourceProp.declarations, hasSkipDirectInferenceFlag) ) {
22668
22681
inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
22669
22682
}
22670
22683
}
@@ -29746,7 +29759,7 @@ namespace ts {
29746
29759
29747
29760
for (let i = 0; i < argCount; i++) {
29748
29761
const arg = args[i];
29749
- if (arg.kind !== SyntaxKind.OmittedExpression) {
29762
+ if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg)) ) {
29750
29763
const paramType = getTypeAtPosition(signature, i);
29751
29764
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
29752
29765
inferTypes(context.inferences, argType, paramType);
@@ -30486,7 +30499,7 @@ namespace ts {
30486
30499
}
30487
30500
}
30488
30501
30489
- return getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
30502
+ return getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray, checkMode );
30490
30503
30491
30504
function addImplementationSuccessElaboration(failed: Signature, diagnostic: Diagnostic) {
30492
30505
const oldCandidatesForArgumentError = candidatesForArgumentError;
@@ -30600,14 +30613,15 @@ namespace ts {
30600
30613
candidates: Signature[],
30601
30614
args: readonly Expression[],
30602
30615
hasCandidatesOutArray: boolean,
30616
+ checkMode: CheckMode,
30603
30617
): Signature {
30604
30618
Debug.assert(candidates.length > 0); // Else should not have called this.
30605
30619
checkNodeDeferred(node);
30606
30620
// Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
30607
30621
// Don't do this if there is a `candidatesOutArray`,
30608
30622
// because then we want the chosen best candidate to be one of the overloads, not a combination.
30609
30623
return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
30610
- ? pickLongestCandidateSignature(node, candidates, args)
30624
+ ? pickLongestCandidateSignature(node, candidates, args, checkMode )
30611
30625
: createUnionOfSignaturesForOverloadFailure(candidates);
30612
30626
}
30613
30627
@@ -30661,7 +30675,7 @@ namespace ts {
30661
30675
return createSymbolWithType(first(sources), type);
30662
30676
}
30663
30677
30664
- function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: readonly Expression[]): Signature {
30678
+ function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: readonly Expression[], checkMode: CheckMode ): Signature {
30665
30679
// Pick the longest signature. This way we can get a contextual type for cases like:
30666
30680
// declare function f(a: { xa: number; xb: number; }, b: number);
30667
30681
// f({ |
@@ -30678,7 +30692,7 @@ namespace ts {
30678
30692
const typeArgumentNodes: readonly TypeNode[] | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined;
30679
30693
const instantiated = typeArgumentNodes
30680
30694
? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJSFile(node)))
30681
- : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args);
30695
+ : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args, checkMode );
30682
30696
candidates[bestIndex] = instantiated;
30683
30697
return instantiated;
30684
30698
}
@@ -30694,9 +30708,9 @@ namespace ts {
30694
30708
return typeArguments;
30695
30709
}
30696
30710
30697
- function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: readonly TypeParameter[], candidate: Signature, args: readonly Expression[]): Signature {
30711
+ function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: readonly TypeParameter[], candidate: Signature, args: readonly Expression[], checkMode: CheckMode ): Signature {
30698
30712
const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
30699
- const typeArgumentTypes = inferTypeArguments(node, candidate, args, CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext);
30713
+ const typeArgumentTypes = inferTypeArguments(node, candidate, args, checkMode | CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext);
30700
30714
return createSignatureInstantiation(candidate, typeArgumentTypes);
30701
30715
}
30702
30716
0 commit comments