@@ -1652,7 +1652,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1652
1652
const node = getParseTreeNode(nodeIn, isJsxAttributeLike);
1653
1653
return node && getContextualTypeForJsxAttribute(node, /*contextFlags*/ undefined);
1654
1654
},
1655
- isContextSensitive ,
1655
+ containsContextSensitive ,
1656
1656
getTypeOfPropertyOfContextualType,
1657
1657
getFullyQualifiedName,
1658
1658
getResolvedSignature: (node, candidatesOutArray, argumentCount) =>
@@ -6253,7 +6253,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
6253
6253
}
6254
6254
6255
6255
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);
6257
6257
}
6258
6258
6259
6259
function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags {
@@ -19165,47 +19165,56 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19165
19165
return createIndexInfo(info.keyType, instantiateType(info.type, mapper), info.isReadonly, info.declaration);
19166
19166
}
19167
19167
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 {
19171
19169
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
19172
19170
switch (node.kind) {
19173
19171
case SyntaxKind.FunctionExpression:
19174
19172
case SyntaxKind.ArrowFunction:
19175
19173
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);
19178
19178
case SyntaxKind.ObjectLiteralExpression:
19179
- return some((node as ObjectLiteralExpression).properties, isContextSensitive );
19179
+ return some((node as ObjectLiteralExpression).properties, p => containsContextRelatedNode(p, predicate) );
19180
19180
case SyntaxKind.ArrayLiteralExpression:
19181
- return some((node as ArrayLiteralExpression).elements, isContextSensitive );
19181
+ return some((node as ArrayLiteralExpression).elements, e => containsContextRelatedNode(e, predicate) );
19182
19182
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 );
19185
19185
case SyntaxKind.BinaryExpression:
19186
19186
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 ));
19188
19188
case SyntaxKind.PropertyAssignment:
19189
- return isContextSensitive ((node as PropertyAssignment).initializer);
19189
+ return containsContextRelatedNode ((node as PropertyAssignment).initializer, predicate );
19190
19190
case SyntaxKind.ParenthesizedExpression:
19191
- return isContextSensitive ((node as ParenthesizedExpression).expression);
19191
+ return containsContextRelatedNode ((node as ParenthesizedExpression).expression, predicate );
19192
19192
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) );
19194
19194
case SyntaxKind.JsxAttribute: {
19195
- // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive.
19196
19195
const { initializer } = node as JsxAttribute;
19197
- return !!initializer && isContextSensitive (initializer);
19196
+ return !!initializer && containsContextRelatedNode (initializer, predicate );
19198
19197
}
19199
19198
case SyntaxKind.JsxExpression: {
19200
19199
// It is possible to that node.expression is undefined (e.g <div x={} />)
19201
19200
const { expression } = node as JsxExpression;
19202
- return !!expression && isContextSensitive (expression);
19201
+ return !!expression && containsContextRelatedNode (expression, predicate );
19203
19202
}
19204
19203
}
19205
19204
19206
19205
return false;
19207
19206
}
19208
19207
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
+
19209
19218
function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
19210
19219
return hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node);
19211
19220
}
@@ -19215,9 +19224,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
19215
19224
return false;
19216
19225
}
19217
19226
if (node.body.kind !== SyntaxKind.Block) {
19218
- return isContextSensitive (node.body);
19227
+ return containsContextSensitive (node.body);
19219
19228
}
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));
19221
19230
}
19222
19231
19223
19232
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
@@ -29983,7 +29992,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
29983
29992
const type = checkExpressionForMutableLocation(e, checkMode, forceTuple);
29984
29993
elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression));
29985
29994
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)) {
29987
29996
const inferenceContext = getInferenceContext(node);
29988
29997
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
29989
29998
addIntraExpressionInferenceSite(inferenceContext, e, type);
@@ -30208,8 +30217,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30208
30217
member = prop;
30209
30218
allPropertiesTable?.set(prop.escapedName, prop);
30210
30219
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) )) {
30213
30222
const inferenceContext = getInferenceContext(node);
30214
30223
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
30215
30224
const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl;
@@ -30465,7 +30474,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
30465
30474
addDeprecatedSuggestion(attributeDecl.name, prop.declarations, attributeDecl.name.escapedText as string);
30466
30475
}
30467
30476
}
30468
- if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive (attributeDecl)) {
30477
+ if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && containsContextSensitiveOrCallOrNewExpression (attributeDecl)) {
30469
30478
const inferenceContext = getInferenceContext(attributes);
30470
30479
Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context
30471
30480
const inferenceNode = (attributeDecl.initializer as JsxExpression).expression!;
@@ -33138,7 +33147,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
33138
33147
// For a decorator, no arguments are susceptible to contextual typing due to the fact
33139
33148
// decorators are applied to a declaration by the emitter, and not to an expression.
33140
33149
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;
33142
33151
argCheckMode |= checkMode & CheckMode.IsForStringLiteralArgumentCompletions;
33143
33152
33144
33153
// The following variables are captured and modified by calls to chooseOverload.
@@ -35865,7 +35874,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
35865
35874
}
35866
35875
35867
35876
// 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)) {
35869
35878
// Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage
35870
35879
if (!getEffectiveReturnTypeNode(node) && !hasContextSensitiveParameters(node)) {
35871
35880
// 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 {
35910
35919
if (!signature) {
35911
35920
return;
35912
35921
}
35913
- if (isContextSensitive (node)) {
35922
+ if (containsContextSensitive (node)) {
35914
35923
if (contextualSignature) {
35915
35924
const inferenceContext = getInferenceContext(node);
35916
35925
let instantiatedContextualSignature: Signature | undefined;
0 commit comments