Merge pull request #6083 from Microsoft/simplifyDeferredChecking

Simplify deferred function, class, and accessor checking
This commit is contained in:
Anders Hejlsberg 2015-12-15 09:07:07 -08:00
commit 55d4f0f7e4
4 changed files with 43 additions and 131 deletions

View File

@ -161,6 +161,8 @@ namespace ts {
let jsxElementClassType: Type;
let deferredNodes: Node[];
const tupleTypes: Map<TupleType> = {};
const unionTypes: Map<UnionType> = {};
const intersectionTypes: Map<IntersectionType> = {};
@ -10156,6 +10158,7 @@ namespace ts {
if (!contextChecked) {
checkSignatureDeclaration(node);
checkNodeDeferred(node);
}
}
}
@ -10168,7 +10171,7 @@ namespace ts {
return type;
}
function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
const isAsync = isAsyncFunctionLike(node);
@ -10211,8 +10214,6 @@ namespace ts {
checkTypeAssignableTo(exprType, returnOrPromisedType, node.body);
}
}
checkFunctionAndClassExpressionBodies(node.body);
}
}
}
@ -11461,13 +11462,13 @@ namespace ts {
if (node.parent.kind !== SyntaxKind.ObjectLiteralExpression) {
checkSourceElement(node.body);
}
else {
checkNodeDeferred(node);
}
}
function checkObjectLiteralAccessorBody(node: AccessorDeclaration) {
if (node.body) {
checkSourceElement(node.body);
checkFunctionAndClassExpressionBodies(node.body);
}
function checkAccessorDeferred(node: AccessorDeclaration) {
checkSourceElement(node.body);
}
function checkMissingDeclaration(node: Node) {
@ -12406,11 +12407,7 @@ namespace ts {
if (node.kind === SyntaxKind.Block) {
checkGrammarStatementInAmbientContext(node);
}
forEach(node.statements, checkSourceElement);
if (isFunctionBlock(node) || node.kind === SyntaxKind.ModuleBlock) {
checkFunctionAndClassExpressionBodies(node);
}
}
function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) {
@ -13439,15 +13436,19 @@ namespace ts {
function checkClassExpression(node: ClassExpression): Type {
checkClassLikeDeclaration(node);
checkNodeDeferred(node);
return getTypeOfSymbol(getSymbolOfNode(node));
}
function checkClassExpressionDeferred(node: ClassExpression) {
forEach(node.members, checkSourceElement);
}
function checkClassDeclaration(node: ClassDeclaration) {
if (!node.name && !(node.flags & NodeFlags.Default)) {
grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
}
checkClassLikeDeclaration(node);
forEach(node.members, checkSourceElement);
}
@ -14511,107 +14512,29 @@ namespace ts {
// Here, performing a full type check of the body of the function expression whilst in the process of
// determining the type of foo would cause foo to be given type any because of the recursive reference.
// Delaying the type check of the body ensures foo has been assigned a type.
function checkFunctionAndClassExpressionBodies(node: Node): void {
switch (node.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
checkFunctionExpressionOrObjectLiteralMethodBody(<FunctionExpression>node);
break;
case SyntaxKind.ClassExpression:
forEach((<ClassExpression>node).members, checkSourceElement);
forEachChild(node, checkFunctionAndClassExpressionBodies);
break;
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
forEach(node.decorators, checkFunctionAndClassExpressionBodies);
forEach((<MethodDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
if (isObjectLiteralMethod(node)) {
checkFunctionExpressionOrObjectLiteralMethodBody(node);
}
break;
case SyntaxKind.Constructor:
case SyntaxKind.FunctionDeclaration:
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
break;
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
checkObjectLiteralAccessorBody(<AccessorDeclaration>node);
}
break;
case SyntaxKind.WithStatement:
checkFunctionAndClassExpressionBodies((<WithStatement>node).expression);
break;
case SyntaxKind.Decorator:
case SyntaxKind.Parameter:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.BindingElement:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TemplateExpression:
case SyntaxKind.TemplateSpan:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.SpreadElementExpression:
case SyntaxKind.YieldExpression:
case SyntaxKind.Block:
case SyntaxKind.ModuleBlock:
case SyntaxKind.VariableStatement:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.BreakStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseBlock:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabeledStatement:
case SyntaxKind.ThrowStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.CatchClause:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.VariableDeclarationList:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.HeritageClause:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
case SyntaxKind.ExportAssignment:
case SyntaxKind.SourceFile:
case SyntaxKind.JsxExpression:
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxSpreadAttribute:
case SyntaxKind.JsxOpeningElement:
forEachChild(node, checkFunctionAndClassExpressionBodies);
break;
function checkNodeDeferred(node: Node) {
if (deferredNodes) {
deferredNodes.push(node);
}
}
function checkDeferredNodes() {
for (const node of deferredNodes) {
switch (node.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
checkFunctionExpressionOrObjectLiteralMethodDeferred(<FunctionExpression>node);
break;
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
checkAccessorDeferred(<AccessorDeclaration>node);
break;
case SyntaxKind.ClassExpression:
checkClassExpressionDeferred(<ClassExpression>node);
break;
}
}
}
@ -14646,8 +14569,10 @@ namespace ts {
emitAwaiter = false;
potentialThisCollisions.length = 0;
deferredNodes = [];
forEach(node.statements, checkSourceElement);
checkFunctionAndClassExpressionBodies(node);
checkDeferredNodes();
deferredNodes = undefined;
if (isExternalOrCommonJsModule(node)) {
checkExternalModuleExports(node);

View File

@ -1,20 +1,11 @@
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(1,1): error TS1108: A 'return' statement can only be used within a function body.
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(1,18): error TS2304: Cannot find name 'role'.
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(2,18): error TS2304: Cannot find name 'Role'.
tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts(4,26): error TS2503: Cannot find namespace 'ng'.
==== tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts (4 errors) ====
==== tests/cases/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.ts (1 errors) ====
return this.edit(role)
~~~~~~
!!! error TS1108: A 'return' statement can only be used within a function body.
~~~~
!!! error TS2304: Cannot find name 'role'.
.then((role: Role) =>
~~~~
!!! error TS2304: Cannot find name 'Role'.
this.roleService.add(role)
.then((data: ng.IHttpPromiseCallbackArg<Role>) => data.data));
~~
!!! error TS2503: Cannot find namespace 'ng'.

View File

@ -6,9 +6,8 @@ return this.edit(role)
//// [multiLinePropertyAccessAndArrowFunctionIndent1.js]
var _this = this;
return this.edit(role)
.then(function (role) {
return _this.roleService.add(role)
return this.roleService.add(role)
.then(function (data) { return data.data; });
});

View File

@ -1,8 +1,7 @@
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts(1,1): error TS1108: A 'return' statement can only be used within a function body.
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts(6,5): error TS2304: Cannot find name 'private'.
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts (2 errors) ====
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMemberVariableDeclaration1.ts (1 errors) ====
return {
~~~~~~
!!! error TS1108: A 'return' statement can only be used within a function body.
@ -11,8 +10,6 @@ tests/cases/conformance/parser/ecmascript5/ErrorRecovery/parserStatementIsNotAMe
// 'private' should not be considered a member variable here.
private[key] = value;
~~~~~~~
!!! error TS2304: Cannot find name 'private'.
}