Skip to content

Commit b44f6e4

Browse files
committed
Simplify deferred checking of function, class, and accessor bodies.
1 parent 87036fe commit b44f6e4

File tree

1 file changed

+40
-115
lines changed

1 file changed

+40
-115
lines changed

src/compiler/checker.ts

Lines changed: 40 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ namespace ts {
161161

162162
let jsxElementClassType: Type;
163163

164+
let deferredNodes: Node[];
165+
164166
const tupleTypes: Map<TupleType> = {};
165167
const unionTypes: Map<UnionType> = {};
166168
const intersectionTypes: Map<IntersectionType> = {};
@@ -10123,6 +10125,7 @@ namespace ts {
1012310125

1012410126
if (!contextChecked) {
1012510127
checkSignatureDeclaration(node);
10128+
checkNodeDeferred(node);
1012610129
}
1012710130
}
1012810131
}
@@ -10135,7 +10138,7 @@ namespace ts {
1013510138
return type;
1013610139
}
1013710140

10138-
function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
10141+
function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
1013910142
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
1014010143

1014110144
const isAsync = isAsyncFunctionLike(node);
@@ -10178,8 +10181,6 @@ namespace ts {
1017810181
checkTypeAssignableTo(exprType, returnOrPromisedType, node.body);
1017910182
}
1018010183
}
10181-
10182-
checkFunctionAndClassExpressionBodies(node.body);
1018310184
}
1018410185
}
1018510186
}
@@ -11428,13 +11429,13 @@ namespace ts {
1142811429
if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) {
1142911430
checkSourceElement(node.body);
1143011431
}
11432+
else {
11433+
checkNodeDeferred(node);
11434+
}
1143111435
}
1143211436

11433-
function checkObjectLiteralAccessorBody(node: AccessorDeclaration) {
11434-
if (node.body) {
11435-
checkSourceElement(node.body);
11436-
checkFunctionAndClassExpressionBodies(node.body);
11437-
}
11437+
function checkAccessorDeferred(node: AccessorDeclaration) {
11438+
checkSourceElement(node.body);
1143811439
}
1143911440

1144011441
function checkMissingDeclaration(node: Node) {
@@ -12373,11 +12374,7 @@ namespace ts {
1237312374
if (node.kind === SyntaxKind.Block) {
1237412375
checkGrammarStatementInAmbientContext(node);
1237512376
}
12376-
1237712377
forEach(node.statements, checkSourceElement);
12378-
if (isFunctionBlock(node) || node.kind === SyntaxKind.ModuleBlock) {
12379-
checkFunctionAndClassExpressionBodies(node);
12380-
}
1238112378
}
1238212379

1238312380
function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) {
@@ -13406,15 +13403,19 @@ namespace ts {
1340613403

1340713404
function checkClassExpression(node: ClassExpression): Type {
1340813405
checkClassLikeDeclaration(node);
13406+
checkNodeDeferred(node);
1340913407
return getTypeOfSymbol(getSymbolOfNode(node));
1341013408
}
1341113409

13410+
function checkClassExpressionDeferred(node: ClassExpression) {
13411+
forEach(node.members, checkSourceElement);
13412+
}
13413+
1341213414
function checkClassDeclaration(node: ClassDeclaration) {
1341313415
if (!node.name && !(node.flags & NodeFlags.Default)) {
1341413416
grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
1341513417
}
1341613418
checkClassLikeDeclaration(node);
13417-
1341813419
forEach(node.members, checkSourceElement);
1341913420
}
1342013421

@@ -14478,107 +14479,29 @@ namespace ts {
1447814479
// Here, performing a full type check of the body of the function expression whilst in the process of
1447914480
// determining the type of foo would cause foo to be given type any because of the recursive reference.
1448014481
// Delaying the type check of the body ensures foo has been assigned a type.
14481-
function checkFunctionAndClassExpressionBodies(node: Node): void {
14482-
switch (node.kind) {
14483-
case SyntaxKind.FunctionExpression:
14484-
case SyntaxKind.ArrowFunction:
14485-
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14486-
checkFunctionExpressionOrObjectLiteralMethodBody(<FunctionExpression>node);
14487-
break;
14488-
case SyntaxKind.ClassExpression:
14489-
forEach((<ClassExpression>node).members, checkSourceElement);
14490-
forEachChild(node, checkFunctionAndClassExpressionBodies);
14491-
break;
14492-
case SyntaxKind.MethodDeclaration:
14493-
case SyntaxKind.MethodSignature:
14494-
forEach(node.decorators, checkFunctionAndClassExpressionBodies);
14495-
forEach((<MethodDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14496-
if (isObjectLiteralMethod(node)) {
14497-
checkFunctionExpressionOrObjectLiteralMethodBody(node);
14498-
}
14499-
break;
14500-
case SyntaxKind.Constructor:
14501-
case SyntaxKind.FunctionDeclaration:
14502-
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14503-
break;
14504-
case SyntaxKind.GetAccessor:
14505-
case SyntaxKind.SetAccessor:
14506-
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14507-
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
14508-
checkObjectLiteralAccessorBody(<AccessorDeclaration>node);
14509-
}
14510-
break;
14511-
case SyntaxKind.WithStatement:
14512-
checkFunctionAndClassExpressionBodies((<WithStatement>node).expression);
14513-
break;
14514-
case SyntaxKind.Decorator:
14515-
case SyntaxKind.Parameter:
14516-
case SyntaxKind.PropertyDeclaration:
14517-
case SyntaxKind.PropertySignature:
14518-
case SyntaxKind.ObjectBindingPattern:
14519-
case SyntaxKind.ArrayBindingPattern:
14520-
case SyntaxKind.BindingElement:
14521-
case SyntaxKind.ArrayLiteralExpression:
14522-
case SyntaxKind.ObjectLiteralExpression:
14523-
case SyntaxKind.PropertyAssignment:
14524-
case SyntaxKind.PropertyAccessExpression:
14525-
case SyntaxKind.ElementAccessExpression:
14526-
case SyntaxKind.CallExpression:
14527-
case SyntaxKind.NewExpression:
14528-
case SyntaxKind.TaggedTemplateExpression:
14529-
case SyntaxKind.TemplateExpression:
14530-
case SyntaxKind.TemplateSpan:
14531-
case SyntaxKind.TypeAssertionExpression:
14532-
case SyntaxKind.AsExpression:
14533-
case SyntaxKind.ParenthesizedExpression:
14534-
case SyntaxKind.TypeOfExpression:
14535-
case SyntaxKind.VoidExpression:
14536-
case SyntaxKind.AwaitExpression:
14537-
case SyntaxKind.DeleteExpression:
14538-
case SyntaxKind.PrefixUnaryExpression:
14539-
case SyntaxKind.PostfixUnaryExpression:
14540-
case SyntaxKind.BinaryExpression:
14541-
case SyntaxKind.ConditionalExpression:
14542-
case SyntaxKind.SpreadElementExpression:
14543-
case SyntaxKind.YieldExpression:
14544-
case SyntaxKind.Block:
14545-
case SyntaxKind.ModuleBlock:
14546-
case SyntaxKind.VariableStatement:
14547-
case SyntaxKind.ExpressionStatement:
14548-
case SyntaxKind.IfStatement:
14549-
case SyntaxKind.DoStatement:
14550-
case SyntaxKind.WhileStatement:
14551-
case SyntaxKind.ForStatement:
14552-
case SyntaxKind.ForInStatement:
14553-
case SyntaxKind.ForOfStatement:
14554-
case SyntaxKind.ContinueStatement:
14555-
case SyntaxKind.BreakStatement:
14556-
case SyntaxKind.ReturnStatement:
14557-
case SyntaxKind.SwitchStatement:
14558-
case SyntaxKind.CaseBlock:
14559-
case SyntaxKind.CaseClause:
14560-
case SyntaxKind.DefaultClause:
14561-
case SyntaxKind.LabeledStatement:
14562-
case SyntaxKind.ThrowStatement:
14563-
case SyntaxKind.TryStatement:
14564-
case SyntaxKind.CatchClause:
14565-
case SyntaxKind.VariableDeclaration:
14566-
case SyntaxKind.VariableDeclarationList:
14567-
case SyntaxKind.ClassDeclaration:
14568-
case SyntaxKind.HeritageClause:
14569-
case SyntaxKind.ExpressionWithTypeArguments:
14570-
case SyntaxKind.EnumDeclaration:
14571-
case SyntaxKind.EnumMember:
14572-
case SyntaxKind.ExportAssignment:
14573-
case SyntaxKind.SourceFile:
14574-
case SyntaxKind.JsxExpression:
14575-
case SyntaxKind.JsxElement:
14576-
case SyntaxKind.JsxSelfClosingElement:
14577-
case SyntaxKind.JsxAttribute:
14578-
case SyntaxKind.JsxSpreadAttribute:
14579-
case SyntaxKind.JsxOpeningElement:
14580-
forEachChild(node, checkFunctionAndClassExpressionBodies);
14581-
break;
14482+
function checkNodeDeferred(node: Node) {
14483+
if (deferredNodes) {
14484+
deferredNodes.push(node);
14485+
}
14486+
}
14487+
14488+
function checkDeferredNodes() {
14489+
for (const node of deferredNodes) {
14490+
switch (node.kind) {
14491+
case SyntaxKind.FunctionExpression:
14492+
case SyntaxKind.ArrowFunction:
14493+
case SyntaxKind.MethodDeclaration:
14494+
case SyntaxKind.MethodSignature:
14495+
checkFunctionExpressionOrObjectLiteralMethodDeferred(<FunctionExpression>node);
14496+
break;
14497+
case SyntaxKind.GetAccessor:
14498+
case SyntaxKind.SetAccessor:
14499+
checkAccessorDeferred(<AccessorDeclaration>node);
14500+
break;
14501+
case SyntaxKind.ClassExpression:
14502+
checkClassExpressionDeferred(<ClassExpression>node);
14503+
break;
14504+
}
1458214505
}
1458314506
}
1458414507

@@ -14613,8 +14536,10 @@ namespace ts {
1461314536
emitAwaiter = false;
1461414537
potentialThisCollisions.length = 0;
1461514538

14539+
deferredNodes = [];
1461614540
forEach(node.statements, checkSourceElement);
14617-
checkFunctionAndClassExpressionBodies(node);
14541+
checkDeferredNodes();
14542+
deferredNodes = undefined;
1461814543

1461914544
if (isExternalOrCommonJsModule(node)) {
1462014545
checkExternalModuleExports(node);

0 commit comments

Comments
 (0)