@@ -175,15 +175,16 @@ namespace ts {
175
175
}
176
176
177
177
const enum CheckMode {
178
- Normal = 0, // Normal type checking
179
- Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable
180
- Inferential = 1 << 1, // Inferential typing
181
- SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions
182
- SkipGenericFunctions = 1 << 3, // Skip single signature generic functions
183
- IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help
184
- RestBindingElement = 1 << 5, // Checking a type that is going to be used to determine the type of a rest binding element
185
- // e.g. in `const { a, ...rest } = foo`, when checking the type of `foo` to determine the type of `rest`,
186
- // we need to preserve generic types instead of substituting them for constraints
178
+ Normal = 0, // Normal type checking
179
+ Contextual = 1 << 0, // Explicitly assigned contextual type, therefore not cacheable
180
+ Inferential = 1 << 1, // Inferential typing
181
+ SkipContextSensitive = 1 << 2, // Skip context sensitive function expressions
182
+ SkipGenericFunctions = 1 << 3, // Skip single signature generic functions
183
+ IsForSignatureHelp = 1 << 4, // Call resolution for purposes of signature help
184
+ IsForStringLiteralArgumentCompletions = 1 << 5, // Do not infer from the argument currently being typed
185
+ RestBindingElement = 1 << 6, // 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
187
188
}
188
189
189
190
const enum SignatureCheckMode {
@@ -532,26 +533,10 @@ namespace ts {
532
533
if (!node) {
533
534
return undefined;
534
535
}
535
- const containingCall = findAncestor(node, isCallLikeExpression);
536
- const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
537
- if (contextFlags! & ContextFlags.Completions && containingCall) {
538
- let toMarkSkip = node as Node;
539
- do {
540
- getNodeLinks(toMarkSkip).skipDirectInference = true;
541
- toMarkSkip = toMarkSkip.parent;
542
- } while (toMarkSkip && toMarkSkip !== containingCall);
543
- getNodeLinks(containingCall).resolvedSignature = undefined;
544
- }
545
- const result = getContextualType(node, contextFlags);
546
- if (contextFlags! & ContextFlags.Completions && containingCall) {
547
- let toMarkSkip = node as Node;
548
- do {
549
- getNodeLinks(toMarkSkip).skipDirectInference = undefined;
550
- toMarkSkip = toMarkSkip.parent;
551
- } while (toMarkSkip && toMarkSkip !== containingCall);
552
- getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
536
+ if (contextFlags! & ContextFlags.Completions) {
537
+ return runWithInferenceBlockedFromSourceNode(node, () => getContextualType(node, contextFlags));
553
538
}
554
- return result ;
539
+ return getContextualType(node, contextFlags) ;
555
540
},
556
541
getContextualTypeForObjectLiteralElement: nodeIn => {
557
542
const node = getParseTreeNode(nodeIn, isObjectLiteralElementLike);
@@ -570,6 +555,8 @@ namespace ts {
570
555
getFullyQualifiedName,
571
556
getResolvedSignature: (node, candidatesOutArray, argumentCount) =>
572
557
getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal),
558
+ getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray) =>
559
+ getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions, editingArgument),
573
560
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) =>
574
561
getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp),
575
562
getExpandedParameters,
@@ -739,10 +726,36 @@ namespace ts {
739
726
getMemberOverrideModifierStatus,
740
727
};
741
728
742
- function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode): Signature | undefined {
729
+ function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
730
+ const containingCall = findAncestor(node, isCallLikeExpression);
731
+ const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
732
+ if (containingCall) {
733
+ let toMarkSkip = node!;
734
+ do {
735
+ getNodeLinks(toMarkSkip).skipDirectInference = true;
736
+ toMarkSkip = toMarkSkip.parent;
737
+ } while (toMarkSkip && toMarkSkip !== containingCall);
738
+ getNodeLinks(containingCall).resolvedSignature = undefined;
739
+ }
740
+ const result = fn();
741
+ if (containingCall) {
742
+ let toMarkSkip = node!;
743
+ do {
744
+ getNodeLinks(toMarkSkip).skipDirectInference = undefined;
745
+ toMarkSkip = toMarkSkip.parent;
746
+ } while (toMarkSkip && toMarkSkip !== containingCall);
747
+ getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
748
+ }
749
+ return result;
750
+ }
751
+
752
+ function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, editingArgument?: Node): Signature | undefined {
743
753
const node = getParseTreeNode(nodeIn, isCallLikeExpression);
744
754
apparentArgumentCount = argumentCount;
745
- const res = node ? getResolvedSignature(node, candidatesOutArray, checkMode) : undefined;
755
+ const res =
756
+ !node ? undefined :
757
+ editingArgument ? runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignature(node, candidatesOutArray, checkMode)) :
758
+ getResolvedSignature(node, candidatesOutArray, checkMode);
746
759
apparentArgumentCount = undefined;
747
760
return res;
748
761
}
@@ -22662,7 +22675,7 @@ namespace ts {
22662
22675
const properties = getPropertiesOfObjectType(target);
22663
22676
for (const targetProp of properties) {
22664
22677
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
22665
- if (sourceProp) {
22678
+ if (sourceProp && !some(sourceProp.declarations, hasSkipDirectInferenceFlag) ) {
22666
22679
inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
22667
22680
}
22668
22681
}
@@ -29760,7 +29773,7 @@ namespace ts {
29760
29773
29761
29774
for (let i = 0; i < argCount; i++) {
29762
29775
const arg = args[i];
29763
- if (arg.kind !== SyntaxKind.OmittedExpression) {
29776
+ if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg)) ) {
29764
29777
const paramType = getTypeAtPosition(signature, i);
29765
29778
const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode);
29766
29779
inferTypes(context.inferences, argType, paramType);
@@ -30500,7 +30513,7 @@ namespace ts {
30500
30513
}
30501
30514
}
30502
30515
30503
- return getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
30516
+ return getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray, checkMode );
30504
30517
30505
30518
function addImplementationSuccessElaboration(failed: Signature, diagnostic: Diagnostic) {
30506
30519
const oldCandidatesForArgumentError = candidatesForArgumentError;
@@ -30614,14 +30627,15 @@ namespace ts {
30614
30627
candidates: Signature[],
30615
30628
args: readonly Expression[],
30616
30629
hasCandidatesOutArray: boolean,
30630
+ checkMode: CheckMode,
30617
30631
): Signature {
30618
30632
Debug.assert(candidates.length > 0); // Else should not have called this.
30619
30633
checkNodeDeferred(node);
30620
30634
// Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
30621
30635
// Don't do this if there is a `candidatesOutArray`,
30622
30636
// because then we want the chosen best candidate to be one of the overloads, not a combination.
30623
30637
return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
30624
- ? pickLongestCandidateSignature(node, candidates, args)
30638
+ ? pickLongestCandidateSignature(node, candidates, args, checkMode )
30625
30639
: createUnionOfSignaturesForOverloadFailure(candidates);
30626
30640
}
30627
30641
@@ -30675,7 +30689,7 @@ namespace ts {
30675
30689
return createSymbolWithType(first(sources), type);
30676
30690
}
30677
30691
30678
- function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: readonly Expression[]): Signature {
30692
+ function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: readonly Expression[], checkMode: CheckMode ): Signature {
30679
30693
// Pick the longest signature. This way we can get a contextual type for cases like:
30680
30694
// declare function f(a: { xa: number; xb: number; }, b: number);
30681
30695
// f({ |
@@ -30692,7 +30706,7 @@ namespace ts {
30692
30706
const typeArgumentNodes: readonly TypeNode[] | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined;
30693
30707
const instantiated = typeArgumentNodes
30694
30708
? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJSFile(node)))
30695
- : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args);
30709
+ : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args, checkMode );
30696
30710
candidates[bestIndex] = instantiated;
30697
30711
return instantiated;
30698
30712
}
@@ -30708,9 +30722,9 @@ namespace ts {
30708
30722
return typeArguments;
30709
30723
}
30710
30724
30711
- function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: readonly TypeParameter[], candidate: Signature, args: readonly Expression[]): Signature {
30725
+ function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: readonly TypeParameter[], candidate: Signature, args: readonly Expression[], checkMode: CheckMode ): Signature {
30712
30726
const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None);
30713
- const typeArgumentTypes = inferTypeArguments(node, candidate, args, CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext);
30727
+ const typeArgumentTypes = inferTypeArguments(node, candidate, args, checkMode | CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext);
30714
30728
return createSignatureInstantiation(candidate, typeArgumentTypes);
30715
30729
}
30716
30730
0 commit comments