From ed81cad39a7dcec8c847776df49473420ab00470 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Dec 2014 22:52:21 -0800 Subject: [PATCH] Remove the 'FunctionBlock' ast kind. We don't want different AST forms for identical syntactic constructs ('Block' and 'FunctionBock'). This prevents reuse in incremental scenarios and forces the incremental parser to know when to change between the two. --- src/compiler/checker.ts | 19 +++---- src/compiler/emitter.ts | 12 ++--- src/compiler/parser.ts | 12 +++-- src/compiler/types.ts | 1 - src/services/breakpoints.ts | 17 +++++-- src/services/formatting.ts | 2 +- src/services/formatting/rules.ts | 2 - src/services/navigationBar.ts | 6 +-- src/services/outliningElementsCollector.ts | 59 +++++++++++----------- src/services/services.ts | 15 ++++-- src/services/signatureHelp.ts | 2 +- src/services/smartIndenter.ts | 5 +- 12 files changed, 79 insertions(+), 73 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cdb0babd587..3d2c64c7ced 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6024,7 +6024,7 @@ module ts { function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type { var contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func); - if (func.body.kind !== SyntaxKind.FunctionBlock) { + if (func.body.kind !== SyntaxKind.Block) { var unwidenedType = checkAndMarkExpression(func.body, contextualMapper); var widenedType = getWidenedType(unwidenedType); @@ -6111,7 +6111,7 @@ module ts { } // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. - if (!func.body || func.body.kind !== SyntaxKind.FunctionBlock) { + if (!func.body || func.body.kind !== SyntaxKind.Block) { return; } @@ -6177,7 +6177,7 @@ module ts { if (node.type) { checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type)); } - if (node.body.kind === SyntaxKind.FunctionBlock) { + if (node.body.kind === SyntaxKind.Block) { checkSourceElement(node.body); } else { @@ -7360,6 +7360,9 @@ module ts { function checkBlock(node: Block) { forEach(node.statements, checkSourceElement); + if (isFunctionBlock(node) || node.kind === SyntaxKind.ModuleBlock) { + checkFunctionExpressionBodies(node); + } } function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { @@ -8491,10 +8494,8 @@ module ts { case SyntaxKind.FunctionDeclaration: return checkFunctionDeclaration(node); case SyntaxKind.Block: - return checkBlock(node); - case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: - return checkBody(node); + return checkBlock(node); case SyntaxKind.VariableStatement: return checkVariableStatement(node); case SyntaxKind.ExpressionStatement: @@ -8589,7 +8590,6 @@ module ts { case SyntaxKind.BinaryExpression: case SyntaxKind.ConditionalExpression: case SyntaxKind.Block: - case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.VariableStatement: case SyntaxKind.ExpressionStatement: @@ -8620,11 +8620,6 @@ module ts { } } - function checkBody(node: Block) { - checkBlock(node); - checkFunctionExpressionBodies(node); - } - // Fully type check a source file and collect the relevant diagnostics. function checkSourceFile(node: SourceFile) { var links = getNodeLinks(node); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 38cd18aea07..08589c36923 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2841,17 +2841,17 @@ module ts { scopeEmitStart(node); increaseIndent(); - emitDetachedComments(node.body.kind === SyntaxKind.FunctionBlock ? (node.body).statements : node.body); + emitDetachedComments(node.body.kind === SyntaxKind.Block ? (node.body).statements : node.body); var startIndex = 0; - if (node.body.kind === SyntaxKind.FunctionBlock) { + if (node.body.kind === SyntaxKind.Block) { startIndex = emitDirectivePrologues((node.body).statements, /*startWithNewLine*/ true); } var outPos = writer.getTextPos(); emitCaptureThisForNodeIfNecessary(node); emitDefaultValueAssignments(node); emitRestParameter(node); - if (node.body.kind !== SyntaxKind.FunctionBlock && outPos === writer.getTextPos()) { + if (node.body.kind !== SyntaxKind.Block && outPos === writer.getTextPos()) { decreaseIndent(); write(" "); emitStart(node.body); @@ -2864,7 +2864,7 @@ module ts { emitEnd(node.body); } else { - if (node.body.kind === SyntaxKind.FunctionBlock) { + if (node.body.kind === SyntaxKind.Block) { emitLinesStartingAt((node.body).statements, startIndex); } else { @@ -2876,7 +2876,7 @@ module ts { emitTrailingComments(node.body); } writeLine(); - if (node.body.kind === SyntaxKind.FunctionBlock) { + if (node.body.kind === SyntaxKind.Block) { emitLeadingCommentsOfPosition((node.body).statements.end); decreaseIndent(); emitToken(SyntaxKind.CloseBraceToken, (node.body).statements.end); @@ -3566,7 +3566,7 @@ module ts { case SyntaxKind.Block: case SyntaxKind.TryBlock: case SyntaxKind.FinallyBlock: - case SyntaxKind.FunctionBlock: + case SyntaxKind.Block: case SyntaxKind.ModuleBlock: return emitBlock(node); case SyntaxKind.VariableStatement: diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 615f472aaa5..5414794f429 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -311,7 +311,6 @@ module ts { case SyntaxKind.Block: case SyntaxKind.TryBlock: case SyntaxKind.FinallyBlock: - case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: return children((node).statements); case SyntaxKind.SourceFile: @@ -435,7 +434,6 @@ module ts { case SyntaxKind.ReturnStatement: return visitor(node); case SyntaxKind.Block: - case SyntaxKind.FunctionBlock: case SyntaxKind.IfStatement: case SyntaxKind.DoStatement: case SyntaxKind.WhileStatement: @@ -472,6 +470,10 @@ module ts { return false; } + export function isFunctionBlock(node: Node) { + return node && node.kind === SyntaxKind.Block && isAnyFunction(node.parent); + } + export function getContainingFunction(node: Node): FunctionLikeDeclaration { while (true) { node = node.parent; @@ -3287,7 +3289,7 @@ module ts { var savedYieldContext = inYieldContext(); setYieldContext(allowYield); - var block = parseBlock(SyntaxKind.FunctionBlock, ignoreMissingOpenBrace, /*checkForStrictMode*/ true); + var block = parseBlock(SyntaxKind.Block, ignoreMissingOpenBrace, /*checkForStrictMode*/ true); setYieldContext(savedYieldContext); @@ -4360,7 +4362,7 @@ module ts { if (!checkModifiers(node)) { var savedInFunctionBlock = inFunctionBlock; - if (node.kind === SyntaxKind.FunctionBlock) { + if (isFunctionBlock(node)) { inFunctionBlock = true; } @@ -4996,7 +4998,7 @@ module ts { } function checkForBodyInAmbientContext(body: Block | Expression, isConstructor: boolean): boolean { - if (inAmbientContext && body && body.kind === SyntaxKind.FunctionBlock) { + if (inAmbientContext && body && body.kind === SyntaxKind.Block) { var diagnostic = isConstructor ? Diagnostics.A_constructor_implementation_cannot_be_declared_in_an_ambient_context : Diagnostics.A_function_implementation_cannot_be_declared_in_an_ambient_context; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index aa8a98db902..eadbb483319 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -212,7 +212,6 @@ module ts { DebuggerStatement, VariableDeclaration, FunctionDeclaration, - FunctionBlock, ClassDeclaration, InterfaceDeclaration, TypeAliasDeclaration, diff --git a/src/services/breakpoints.ts b/src/services/breakpoints.ts index d70884e5d87..4b7b276086f 100644 --- a/src/services/breakpoints.ts +++ b/src/services/breakpoints.ts @@ -101,10 +101,14 @@ module ts.BreakpointResolver { case SyntaxKind.ArrowFunction: return spanInFunctionDeclaration(node); - case SyntaxKind.FunctionBlock: - return spanInFunctionBlock(node); - case SyntaxKind.Block: + if (isFunctionBlock(node)) { + return spanInFunctionBlock(node); + } + else { + return spanInBlock(node); + } + case SyntaxKind.TryBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: @@ -414,13 +418,18 @@ module ts.BreakpointResolver { return undefined; } - case SyntaxKind.FunctionBlock: case SyntaxKind.EnumDeclaration: case SyntaxKind.ClassDeclaration: // Span on close brace token return textSpan(node); case SyntaxKind.Block: + if (isFunctionBlock(node.parent)) { + // Span on close brace token + return textSpan(node); + } + // fall through. + case SyntaxKind.TryBlock: case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: diff --git a/src/services/formatting.ts b/src/services/formatting.ts index 3322ea1e65b..9660d9af6df 100644 --- a/src/services/formatting.ts +++ b/src/services/formatting.ts @@ -897,7 +897,7 @@ module ts.formatting { function isSomeBlock(kind: SyntaxKind): boolean { switch (kind) { case SyntaxKind.Block: - case SyntaxKind.FunctionBlock: + case SyntaxKind.Block: case SyntaxKind.TryBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 2723b50af7b..5dc44650346 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -526,7 +526,6 @@ module ts.formatting { case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.TryBlock: case SyntaxKind.FinallyBlock: - case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: return true; } @@ -582,7 +581,6 @@ module ts.formatting { case SyntaxKind.TryBlock: case SyntaxKind.CatchClause: case SyntaxKind.FinallyBlock: - case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.SwitchStatement: return true; diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index deb779bea2c..aebd736d190 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -120,7 +120,7 @@ module ts.NavigationBar { if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) { // A function declaration is 'top level' if it contains any function declarations // within it. - if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.FunctionBlock) { + if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.Block) { // Proper function declarations can only have identifier names if (forEach((functionDeclaration.body).statements, s => s.kind === SyntaxKind.FunctionDeclaration && !isEmpty((s).name.text))) { @@ -130,7 +130,7 @@ module ts.NavigationBar { // Or if it is not parented by another function. i.e all functions // at module scope are 'top level'. - if (functionDeclaration.parent.kind !== SyntaxKind.FunctionBlock) { + if (!isFunctionBlock(functionDeclaration.parent)) { return true; } } @@ -333,7 +333,7 @@ module ts.NavigationBar { } function createFunctionItem(node: FunctionDeclaration) { - if (node.name && node.body && node.body.kind === SyntaxKind.FunctionBlock) { + if (node.name && node.body && node.body.kind === SyntaxKind.Block) { var childItems = getItemsWorker(sortNodes((node.body).statements), createChildItem); return getNavigationBarItem(node.name.text, diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 68f30bee781..83eef2f4378 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -67,38 +67,39 @@ module ts { } switch (n.kind) { case SyntaxKind.Block: - var parent = n.parent; - var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); - var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); + if (!isFunctionBlock(n)) { + var parent = n.parent; + var openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); + var closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); - // Check if the block is standalone, or 'attached' to some parent statement. - // If the latter, we want to collaps the block, but consider its hint span - // to be the entire span of the parent. - if (parent.kind === SyntaxKind.DoStatement || - parent.kind === SyntaxKind.ForInStatement || - parent.kind === SyntaxKind.ForStatement || - parent.kind === SyntaxKind.IfStatement || - parent.kind === SyntaxKind.WhileStatement || - parent.kind === SyntaxKind.WithStatement || - parent.kind === SyntaxKind.CatchClause) { - - addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n)); + // Check if the block is standalone, or 'attached' to some parent statement. + // If the latter, we want to collaps the block, but consider its hint span + // to be the entire span of the parent. + if (parent.kind === SyntaxKind.DoStatement || + parent.kind === SyntaxKind.ForInStatement || + parent.kind === SyntaxKind.ForStatement || + parent.kind === SyntaxKind.IfStatement || + parent.kind === SyntaxKind.WhileStatement || + parent.kind === SyntaxKind.WithStatement || + parent.kind === SyntaxKind.CatchClause) { + + addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n)); + } + else { + // Block was a standalone block. In this case we want to only collapse + // the span of the block, independent of any parent span. + var span = TextSpan.fromBounds(n.getStart(), n.end); + elements.push({ + textSpan: span, + hintSpan: span, + bannerText: collapseText, + autoCollapse: autoCollapse(n) + }); + } + break; } - else { - // Block was a standalone block. In this case we want to only collapse - // the span of the block, independent of any parent span. - var span = TextSpan.fromBounds(n.getStart(), n.end); - elements.push({ - textSpan: span, - hintSpan: span, - bannerText: collapseText, - autoCollapse: autoCollapse(n) - }); - } - break; + // Fallthrough. - - case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.TryBlock: case SyntaxKind.FinallyBlock: diff --git a/src/services/services.ts b/src/services/services.ts index a04c85071e2..15cc6639669 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -806,10 +806,15 @@ module ts { case SyntaxKind.Constructor: case SyntaxKind.VariableStatement: case SyntaxKind.ModuleBlock: - case SyntaxKind.FunctionBlock: forEachChild(node, visit); break; + case SyntaxKind.Block: + if (isFunctionBlock(node)) { + forEachChild(node, visit); + } + break; + case SyntaxKind.Parameter: // Only consider properties defined as constructor parameters if (!(node.flags & NodeFlags.AccessibilityModifier)) { @@ -1441,7 +1446,7 @@ module ts { } // If the parent is not sourceFile or module block it is local variable - for (var parent = declaration.parent; parent.kind !== SyntaxKind.FunctionBlock; parent = parent.parent) { + for (var parent = declaration.parent; !isFunctionBlock(parent); parent = parent.parent) { // Reached source file or module block if (parent.kind === SyntaxKind.SourceFile || parent.kind === SyntaxKind.ModuleBlock) { return false; @@ -3515,7 +3520,7 @@ module ts { var func = getContainingFunction(returnStatement); // If we didn't find a containing function with a block body, bail out. - if (!(func && hasKind(func.body, SyntaxKind.FunctionBlock))) { + if (!(func && hasKind(func.body, SyntaxKind.Block))) { return undefined; } @@ -3547,7 +3552,7 @@ module ts { // If the "owner" is a function, then we equate 'return' and 'throw' statements in their // ability to "jump out" of the function, and include occurrences for both. - if (owner.kind === SyntaxKind.FunctionBlock) { + if (isFunctionBlock(owner)) { forEachReturnStatement(owner, returnStatement => { pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword); }); @@ -3603,7 +3608,7 @@ module ts { while (child.parent) { var parent = child.parent; - if (parent.kind === SyntaxKind.FunctionBlock || parent.kind === SyntaxKind.SourceFile) { + if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) { return parent; } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 93363b4676b..bdb76b77e8a 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -396,7 +396,7 @@ module ts.SignatureHelp { function getContainingArgumentInfo(node: Node): ArgumentListInfo { for (var n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) { - if (n.kind === SyntaxKind.FunctionBlock) { + if (isFunctionBlock(n)) { return undefined; } diff --git a/src/services/smartIndenter.ts b/src/services/smartIndenter.ts index 82226449b96..e93cb5616a9 100644 --- a/src/services/smartIndenter.ts +++ b/src/services/smartIndenter.ts @@ -326,7 +326,6 @@ module ts.formatting { case SyntaxKind.EnumDeclaration: case SyntaxKind.ArrayLiteralExpression: case SyntaxKind.Block: - case SyntaxKind.FunctionBlock: case SyntaxKind.TryBlock: case SyntaxKind.FinallyBlock: case SyntaxKind.ModuleBlock: @@ -357,7 +356,6 @@ module ts.formatting { case SyntaxKind.ForInStatement: case SyntaxKind.ForStatement: case SyntaxKind.IfStatement: - return child !== SyntaxKind.Block; case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.Method: @@ -365,7 +363,7 @@ module ts.formatting { case SyntaxKind.Constructor: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return child !== SyntaxKind.FunctionBlock; + return child !== SyntaxKind.Block; default: return false; } @@ -404,7 +402,6 @@ module ts.formatting { case SyntaxKind.ObjectLiteralExpression: case SyntaxKind.Block: case SyntaxKind.FinallyBlock: - case SyntaxKind.FunctionBlock: case SyntaxKind.ModuleBlock: case SyntaxKind.SwitchStatement: return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile);