@@ -1652,7 +1652,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16521652 const node = getParseTreeNode(nodeIn, isJsxAttributeLike);
16531653 return node && getContextualTypeForJsxAttribute(node, /*contextFlags*/ undefined);
16541654 },
1655- isContextSensitive ,
1655+ containsContextSensitive ,
16561656 getTypeOfPropertyOfContextualType,
16571657 getFullyQualifiedName,
16581658 getResolvedSignature: (node, candidatesOutArray, argumentCount) =>
@@ -6253,7 +6253,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
62536253 }
62546254
62556255 function symbolValueDeclarationIsContextSensitive(symbol: Symbol): boolean {
6256- return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !isContextSensitive (symbol.valueDeclaration);
6256+ return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !containsContextSensitive (symbol.valueDeclaration);
62576257 }
62586258
62596259 function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags {
@@ -19165,47 +19165,56 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1916519165 return createIndexInfo(info.keyType, instantiateType(info.type, mapper), info.isReadonly, info.declaration);
1916619166 }
1916719167
19168- // Returns true if the given expression contains (at any level of nesting) a function or arrow expression
19169- // that is subject to contextual typing.
19170- function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean {
19168+ function containsContextRelatedNode(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild, predicate: (node: Node) => boolean): boolean {
1917119169 Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
1917219170 switch (node.kind) {
1917319171 case SyntaxKind.FunctionExpression:
1917419172 case SyntaxKind.ArrowFunction:
1917519173 case SyntaxKind.MethodDeclaration:
19176- case SyntaxKind.FunctionDeclaration: // Function declarations can have context when annotated with a jsdoc @type
19177- return isContextSensitiveFunctionLikeDeclaration(node as FunctionExpression | ArrowFunction | MethodDeclaration);
19174+ case SyntaxKind.FunctionDeclaration:
19175+ case SyntaxKind.CallExpression:
19176+ case SyntaxKind.NewExpression:
19177+ return predicate(node);
1917819178 case SyntaxKind.ObjectLiteralExpression:
19179- return some((node as ObjectLiteralExpression).properties, isContextSensitive );
19179+ return some((node as ObjectLiteralExpression).properties, p => containsContextRelatedNode(p, predicate) );
1918019180 case SyntaxKind.ArrayLiteralExpression:
19181- return some((node as ArrayLiteralExpression).elements, isContextSensitive );
19181+ return some((node as ArrayLiteralExpression).elements, e => containsContextRelatedNode(e, predicate) );
1918219182 case SyntaxKind.ConditionalExpression:
19183- return isContextSensitive ((node as ConditionalExpression).whenTrue) ||
19184- isContextSensitive ((node as ConditionalExpression).whenFalse);
19183+ return containsContextRelatedNode ((node as ConditionalExpression).whenTrue, predicate ) ||
19184+ containsContextRelatedNode ((node as ConditionalExpression).whenFalse, predicate );
1918519185 case SyntaxKind.BinaryExpression:
1918619186 return ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken || (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken) &&
19187- (isContextSensitive ((node as BinaryExpression).left) || isContextSensitive ((node as BinaryExpression).right));
19187+ (containsContextRelatedNode ((node as BinaryExpression).left, predicate ) || containsContextRelatedNode ((node as BinaryExpression).right, predicate ));
1918819188 case SyntaxKind.PropertyAssignment:
19189- return isContextSensitive ((node as PropertyAssignment).initializer);
19189+ return containsContextRelatedNode ((node as PropertyAssignment).initializer, predicate );
1919019190 case SyntaxKind.ParenthesizedExpression:
19191- return isContextSensitive ((node as ParenthesizedExpression).expression);
19191+ return containsContextRelatedNode ((node as ParenthesizedExpression).expression, predicate );
1919219192 case SyntaxKind.JsxAttributes:
19193- return some((node as JsxAttributes).properties, isContextSensitive) || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, isContextSensitive );
19193+ return some((node as JsxAttributes).properties, p => containsContextRelatedNode(p, predicate)) || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, c => containsContextRelatedNode(c, predicate) );
1919419194 case SyntaxKind.JsxAttribute: {
19195- // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive.
1919619195 const { initializer } = node as JsxAttribute;
19197- return !!initializer && isContextSensitive (initializer);
19196+ return !!initializer && containsContextRelatedNode (initializer, predicate );
1919819197 }
1919919198 case SyntaxKind.JsxExpression: {
1920019199 // It is possible to that node.expression is undefined (e.g <div x={} />)
1920119200 const { expression } = node as JsxExpression;
19202- return !!expression && isContextSensitive (expression);
19201+ return !!expression && containsContextRelatedNode (expression, predicate );
1920319202 }
1920419203 }
1920519204
1920619205 return false;
1920719206 }
1920819207
19208+ // Returns true if the given expression contains (at any level of nesting) a function or arrow expression
19209+ // that is subject to contextual typing.
19210+ function containsContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean {
19211+ return containsContextRelatedNode(node, isContextSensitiveFunctionOrObjectLiteralMethod);
19212+ }
19213+
19214+ function containsContextSensitiveOrCallOrNewExpression(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean {
19215+ return containsContextRelatedNode(node, n => isContextSensitiveFunctionOrObjectLiteralMethod(n) || isCallOrNewExpression(n));
19216+ }
19217+
1920919218 function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
1921019219 return hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node);
1921119220 }
@@ -19215,9 +19224,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1921519224 return false;
1921619225 }
1921719226 if (node.body.kind !== SyntaxKind.Block) {
19218- return isContextSensitive (node.body);
19227+ return containsContextSensitive (node.body);
1921919228 }
19220- return !!forEachReturnStatement(node.body as Block, (statement) => !!statement.expression && isContextSensitive (statement.expression));
19229+ return !!forEachReturnStatement(node.body as Block, (statement) => !!statement.expression && containsContextSensitive (statement.expression));
1922119230 }
1922219231
1922319232 function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
@@ -29983,7 +29992,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2998329992 const type = checkExpressionForMutableLocation(e, checkMode, forceTuple);
2998429993 elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression));
2998529994 elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required);
29986- if (inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive (e)) {
29995+ if (inTupleContext && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && containsContextSensitiveOrCallOrNewExpression (e)) {
2998729996 const inferenceContext = getInferenceContext(node);
2998829997 Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
2998929998 addIntraExpressionInferenceSite(inferenceContext, e, type);
@@ -30208,8 +30217,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3020830217 member = prop;
3020930218 allPropertiesTable?.set(prop.escapedName, prop);
3021030219
30211- if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) &&
30212- (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive (memberDecl)) {
30220+ if (contextualType && checkMode && checkMode & CheckMode.Inferential && ( !(checkMode & CheckMode.SkipContextSensitive) &&
30221+ (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && containsContextSensitiveOrCallOrNewExpression (memberDecl) )) {
3021330222 const inferenceContext = getInferenceContext(node);
3021430223 Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
3021530224 const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl;
@@ -30465,7 +30474,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3046530474 addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string);
3046630475 }
3046730476 }
30468- if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive (attributeDecl)) {
30477+ if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && containsContextSensitiveOrCallOrNewExpression (attributeDecl)) {
3046930478 const inferenceContext = getInferenceContext(attributes);
3047030479 Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
3047130480 const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!;
@@ -33138,7 +33147,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3313833147 // For a decorator, no arguments are susceptible to contextual typing due to the fact
3313933148 // decorators are applied to a declaration by the emitter, and not to an expression.
3314033149 const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters;
33141- let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive ) ? CheckMode.SkipContextSensitive : CheckMode.Normal;
33150+ let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, containsContextSensitive ) ? CheckMode.SkipContextSensitive : CheckMode.Normal;
3314233151 argCheckMode |= checkMode & CheckMode.IsForStringLiteralArgumentCompletions;
3314333152
3314433153 // The following variables are captured and modified by calls to chooseOverload.
@@ -35865,7 +35874,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3586535874 }
3586635875
3586735876 // The identityMapper object is used to indicate that function expressions are wildcards
35868- if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive (node)) {
35877+ if (checkMode && checkMode & CheckMode.SkipContextSensitive && containsContextSensitive (node)) {
3586935878 // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage
3587035879 if (!getEffectiveReturnTypeNode(node) && !hasContextSensitiveParameters(node)) {
3587135880 // Return plain anyFunctionType if there is no possibility we'll make inferences from the return type
@@ -35910,7 +35919,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3591035919 if (!signature) {
3591135920 return;
3591235921 }
35913- if (isContextSensitive (node)) {
35922+ if (containsContextSensitive (node)) {
3591435923 if (contextualSignature) {
3591535924 const inferenceContext = getInferenceContext(node);
3591635925 let instantiatedContextualSignature: Signature | undefined;
0 commit comments