Skip to content

Commit 55d4f0f

Browse files
committed
Merge pull request #6083 from Microsoft/simplifyDeferredChecking
Simplify deferred function, class, and accessor checking
2 parents 2f447ee + 91b9343 commit 55d4f0f

4 files changed

+43
-131
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> = {};
@@ -10156,6 +10158,7 @@ namespace ts {
1015610158

1015710159
if (!contextChecked) {
1015810160
checkSignatureDeclaration(node);
10161+
checkNodeDeferred(node);
1015910162
}
1016010163
}
1016110164
}
@@ -10168,7 +10171,7 @@ namespace ts {
1016810171
return type;
1016910172
}
1017010173

10171-
function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
10174+
function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
1017210175
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
1017310176

1017410177
const isAsync = isAsyncFunctionLike(node);
@@ -10211,8 +10214,6 @@ namespace ts {
1021110214
checkTypeAssignableTo(exprType, returnOrPromisedType, node.body);
1021210215
}
1021310216
}
10214-
10215-
checkFunctionAndClassExpressionBodies(node.body);
1021610217
}
1021710218
}
1021810219
}
@@ -11461,13 +11462,13 @@ namespace ts {
1146111462
if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) {
1146211463
checkSourceElement(node.body);
1146311464
}
11465+
else {
11466+
checkNodeDeferred(node);
11467+
}
1146411468
}
1146511469

11466-
function checkObjectLiteralAccessorBody(node: AccessorDeclaration) {
11467-
if (node.body) {
11468-
checkSourceElement(node.body);
11469-
checkFunctionAndClassExpressionBodies(node.body);
11470-
}
11470+
function checkAccessorDeferred(node: AccessorDeclaration) {
11471+
checkSourceElement(node.body);
1147111472
}
1147211473

1147311474
function checkMissingDeclaration(node: Node) {
@@ -12406,11 +12407,7 @@ namespace ts {
1240612407
if (node.kind === SyntaxKind.Block) {
1240712408
checkGrammarStatementInAmbientContext(node);
1240812409
}
12409-
1241012410
forEach(node.statements, checkSourceElement);
12411-
if (isFunctionBlock(node) || node.kind === SyntaxKind.ModuleBlock) {
12412-
checkFunctionAndClassExpressionBodies(node);
12413-
}
1241412411
}
1241512412

1241612413
function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) {
@@ -13439,15 +13436,19 @@ namespace ts {
1343913436

1344013437
function checkClassExpression(node: ClassExpression): Type {
1344113438
checkClassLikeDeclaration(node);
13439+
checkNodeDeferred(node);
1344213440
return getTypeOfSymbol(getSymbolOfNode(node));
1344313441
}
1344413442

13443+
function checkClassExpressionDeferred(node: ClassExpression) {
13444+
forEach(node.members, checkSourceElement);
13445+
}
13446+
1344513447
function checkClassDeclaration(node: ClassDeclaration) {
1344613448
if (!node.name && !(node.flags & NodeFlags.Default)) {
1344713449
grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
1344813450
}
1344913451
checkClassLikeDeclaration(node);
13450-
1345113452
forEach(node.members, checkSourceElement);
1345213453
}
1345313454

@@ -14511,107 +14512,29 @@ namespace ts {
1451114512
// Here, performing a full type check of the body of the function expression whilst in the process of
1451214513
// determining the type of foo would cause foo to be given type any because of the recursive reference.
1451314514
// Delaying the type check of the body ensures foo has been assigned a type.
14514-
function checkFunctionAndClassExpressionBodies(node: Node): void {
14515-
switch (node.kind) {
14516-
case SyntaxKind.FunctionExpression:
14517-
case SyntaxKind.ArrowFunction:
14518-
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14519-
checkFunctionExpressionOrObjectLiteralMethodBody(<FunctionExpression>node);
14520-
break;
14521-
case SyntaxKind.ClassExpression:
14522-
forEach((<ClassExpression>node).members, checkSourceElement);
14523-
forEachChild(node, checkFunctionAndClassExpressionBodies);
14524-
break;
14525-
case SyntaxKind.MethodDeclaration:
14526-
case SyntaxKind.MethodSignature:
14527-
forEach(node.decorators, checkFunctionAndClassExpressionBodies);
14528-
forEach((<MethodDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14529-
if (isObjectLiteralMethod(node)) {
14530-
checkFunctionExpressionOrObjectLiteralMethodBody(node);
14531-
}
14532-
break;
14533-
case SyntaxKind.Constructor:
14534-
case SyntaxKind.FunctionDeclaration:
14535-
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14536-
break;
14537-
case SyntaxKind.GetAccessor:
14538-
case SyntaxKind.SetAccessor:
14539-
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
14540-
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
14541-
checkObjectLiteralAccessorBody(<AccessorDeclaration>node);
14542-
}
14543-
break;
14544-
case SyntaxKind.WithStatement:
14545-
checkFunctionAndClassExpressionBodies((<WithStatement>node).expression);
14546-
break;
14547-
case SyntaxKind.Decorator:
14548-
case SyntaxKind.Parameter:
14549-
case SyntaxKind.PropertyDeclaration:
14550-
case SyntaxKind.PropertySignature:
14551-
case SyntaxKind.ObjectBindingPattern:
14552-
case SyntaxKind.ArrayBindingPattern:
14553-
case SyntaxKind.BindingElement:
14554-
case SyntaxKind.ArrayLiteralExpression:
14555-
case SyntaxKind.ObjectLiteralExpression:
14556-
case SyntaxKind.PropertyAssignment:
14557-
case SyntaxKind.PropertyAccessExpression:
14558-
case SyntaxKind.ElementAccessExpression:
14559-
case SyntaxKind.CallExpression:
14560-
case SyntaxKind.NewExpression:
14561-
case SyntaxKind.TaggedTemplateExpression:
14562-
case SyntaxKind.TemplateExpression:
14563-
case SyntaxKind.TemplateSpan:
14564-
case SyntaxKind.TypeAssertionExpression:
14565-
case SyntaxKind.AsExpression:
14566-
case SyntaxKind.ParenthesizedExpression:
14567-
case SyntaxKind.TypeOfExpression:
14568-
case SyntaxKind.VoidExpression:
14569-
case SyntaxKind.AwaitExpression:
14570-
case SyntaxKind.DeleteExpression:
14571-
case SyntaxKind.PrefixUnaryExpression:
14572-
case SyntaxKind.PostfixUnaryExpression:
14573-
case SyntaxKind.BinaryExpression:
14574-
case SyntaxKind.ConditionalExpression:
14575-
case SyntaxKind.SpreadElementExpression:
14576-
case SyntaxKind.YieldExpression:
14577-
case SyntaxKind.Block:
14578-
case SyntaxKind.ModuleBlock:
14579-
case SyntaxKind.VariableStatement:
14580-
case SyntaxKind.ExpressionStatement:
14581-
case SyntaxKind.IfStatement:
14582-
case SyntaxKind.DoStatement:
14583-
case SyntaxKind.WhileStatement:
14584-
case SyntaxKind.ForStatement:
14585-
case SyntaxKind.ForInStatement:
14586-
case SyntaxKind.ForOfStatement:
14587-
case SyntaxKind.ContinueStatement:
14588-
case SyntaxKind.BreakStatement:
14589-
case SyntaxKind.ReturnStatement:
14590-
case SyntaxKind.SwitchStatement:
14591-
case SyntaxKind.CaseBlock:
14592-
case SyntaxKind.CaseClause:
14593-
case SyntaxKind.DefaultClause:
14594-
case SyntaxKind.LabeledStatement:
14595-
case SyntaxKind.ThrowStatement:
14596-
case SyntaxKind.TryStatement:
14597-
case SyntaxKind.CatchClause:
14598-
case SyntaxKind.VariableDeclaration:
14599-
case SyntaxKind.VariableDeclarationList:
14600-
case SyntaxKind.ClassDeclaration:
14601-
case SyntaxKind.HeritageClause:
14602-
case SyntaxKind.ExpressionWithTypeArguments:
14603-
case SyntaxKind.EnumDeclaration:
14604-
case SyntaxKind.EnumMember:
14605-
case SyntaxKind.ExportAssignment:
14606-
case SyntaxKind.SourceFile:
14607-
case SyntaxKind.JsxExpression:
14608-
case SyntaxKind.JsxElement:
14609-
case SyntaxKind.JsxSelfClosingElement:
14610-
case SyntaxKind.JsxAttribute:
14611-
case SyntaxKind.JsxSpreadAttribute:
14612-
case SyntaxKind.JsxOpeningElement:
14613-
forEachChild(node, checkFunctionAndClassExpressionBodies);
14614-
break;
14515+
function checkNodeDeferred(node: Node) {
14516+
if (deferredNodes) {
14517+
deferredNodes.push(node);
14518+
}
14519+
}
14520+
14521+
function checkDeferredNodes() {
14522+
for (const node of deferredNodes) {
14523+
switch (node.kind) {
14524+
case SyntaxKind.FunctionExpression:
14525+
case SyntaxKind.ArrowFunction:
14526+
case SyntaxKind.MethodDeclaration:
14527+
case SyntaxKind.MethodSignature:
14528+
checkFunctionExpressionOrObjectLiteralMethodDeferred(<FunctionExpression>node);
14529+
break;
14530+
case SyntaxKind.GetAccessor:
14531+
case SyntaxKind.SetAccessor:
14532+
checkAccessorDeferred(<AccessorDeclaration>node);
14533+
break;
14534+
case SyntaxKind.ClassExpression:
14535+
checkClassExpressionDeferred(<ClassExpression>node);
14536+
break;
14537+
}
1461514538
}
1461614539
}
1461714540

@@ -14646,8 +14569,10 @@ namespace ts {
1464614569
emitAwaiter = false;
1464714570
potentialThisCollisions.length = 0;
1464814571

14572+
deferredNodes = [];
1464914573
forEach(node.statements, checkSourceElement);
14650-
checkFunctionAndClassExpressionBodies(node);
14574+
checkDeferredNodes();
14575+
deferredNodes = undefined;
1465114576

1465214577
if (isExternalOrCommonJsModule(node)) {
1465314578
checkExternalModuleExports(node);
Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(1,1): error TS1108: A 'return' statement can only be used within a function body.
2-
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(1,18): error TS2304: Cannot find name 'role'.
3-
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(2,18): error TS2304: Cannot find name 'Role'.
4-
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(4,26): error TS2503: Cannot find namespace 'ng'.
52

63

7-
==== tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts (4 errors) ====
4+
==== tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts (1 errors) ====
85
return this.edit(role)
96
~~~~~~
107
!!! error TS1108: A 'return' statement can only be used within a function body.
11-
~~~~
12-
!!! error TS2304: Cannot find name 'role'.
138
.then((role: Role) =>
14-
~~~~
15-
!!! error TS2304: Cannot find name 'Role'.
169
this.roleService.add(role)
1710
.then((data: ng.IHttpPromiseCallbackArg<Role>) => data.data));
18-
~~
19-
!!! error TS2503: Cannot find namespace 'ng'.
2011

tests/baselines/reference/multiLinePropertyAccessAndArrowFunctionIndent1.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ return this.edit(role)
66

77

88
//// [multiLinePropertyAccessAndArrowFunctionIndent1.js]
9-
var _this = this;
109
return this.edit(role)
1110
.then(function (role) {
12-
return _this.roleService.add(role)
11+
return this.roleService.add(role)
1312
.then(function (data) { return data.data; });
1413
});

tests/baselines/reference/parserStatementIsNotAMemberVariableDeclaration1.errors.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts(1,1): error TS1108: A 'return' statement can only be used within a function body.
2-
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts(6,5): error TS2304: Cannot find name 'private'.
32

43

5-
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts (2 errors) ====
4+
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts (1 errors) ====
65
return {
76
~~~~~~
87
!!! error TS1108: A 'return' statement can only be used within a function body.
@@ -11,8 +10,6 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMe
1110

1211
// 'private' should not be considered a member variable here.
1312
private[key] = value;
14-
~~~~~~~
15-
!!! error TS2304: Cannot find name 'private'.
1613

1714
}
1815

0 commit comments

Comments
 (0)