TypeScript/src/compiler/visitor.ts
Ron Buckton d07e866a28
Fix for jsdoc modifiers on constructor params (#38403)
* Fix for jsdoc modifiers on constructor params

* Update Public API baseline and fix unique symbol grammar check for js
2020-05-11 15:07:43 -07:00

706 lines
36 KiB
TypeScript

/* @internal */
namespace ts {
function reduceNode<T>(node: Node | undefined, f: (memo: T, node: Node) => T, initial: T) {
return node ? f(initial, node) : initial;
}
function reduceNodeArray<T>(nodes: NodeArray<Node> | undefined, f: (memo: T, nodes: NodeArray<Node>) => T, initial: T) {
return nodes ? f(initial, nodes) : initial;
}
/**
* Similar to `reduceLeft`, performs a reduction against each child of a node.
* NOTE: Unlike `forEachChild`, this does *not* visit every node.
*
* @param node The node containing the children to reduce.
* @param initial The initial value to supply to the reduction.
* @param f The callback function
*/
export function reduceEachChild<T>(node: Node | undefined, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: NodeArray<Node>) => T): T {
if (node === undefined) {
return initial;
}
const reduceNodes: (nodes: NodeArray<Node> | undefined, f: ((memo: T, node: Node) => T) | ((memo: T, node: NodeArray<Node>) => T), initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft;
const cbNodes = cbNodeArray || cbNode;
const kind = node.kind;
// No need to visit nodes with no children.
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken)) {
return initial;
}
// We do not yet support types.
if ((kind >= SyntaxKind.TypePredicate && kind <= SyntaxKind.LiteralType)) {
return initial;
}
let result = initial;
switch (node.kind) {
// Leaf nodes
case SyntaxKind.SemicolonClassElement:
case SyntaxKind.EmptyStatement:
case SyntaxKind.OmittedExpression:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.NotEmittedStatement:
// No need to visit nodes with no children.
break;
// Names
case SyntaxKind.QualifiedName:
result = reduceNode((<QualifiedName>node).left, cbNode, result);
result = reduceNode((<QualifiedName>node).right, cbNode, result);
break;
case SyntaxKind.ComputedPropertyName:
result = reduceNode((<ComputedPropertyName>node).expression, cbNode, result);
break;
// Signature elements
case SyntaxKind.Parameter:
result = reduceNodes((<ParameterDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ParameterDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ParameterDeclaration>node).name, cbNode, result);
result = reduceNode((<ParameterDeclaration>node).type, cbNode, result);
result = reduceNode((<ParameterDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.Decorator:
result = reduceNode((<Decorator>node).expression, cbNode, result);
break;
// Type member
case SyntaxKind.PropertySignature:
result = reduceNodes((<PropertySignature>node).modifiers, cbNodes, result);
result = reduceNode((<PropertySignature>node).name, cbNode, result);
result = reduceNode((<PropertySignature>node).questionToken, cbNode, result);
result = reduceNode((<PropertySignature>node).type, cbNode, result);
result = reduceNode((<PropertySignature>node).initializer, cbNode, result);
break;
case SyntaxKind.PropertyDeclaration:
result = reduceNodes((<PropertyDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<PropertyDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<PropertyDeclaration>node).name, cbNode, result);
result = reduceNode((<PropertyDeclaration>node).type, cbNode, result);
result = reduceNode((<PropertyDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.MethodDeclaration:
result = reduceNodes((<MethodDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<MethodDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<MethodDeclaration>node).name, cbNode, result);
result = reduceNodes((<MethodDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<MethodDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<MethodDeclaration>node).type, cbNode, result);
result = reduceNode((<MethodDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.Constructor:
result = reduceNodes((<ConstructorDeclaration>node).modifiers, cbNodes, result);
result = reduceNodes((<ConstructorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<ConstructorDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.GetAccessor:
result = reduceNodes((<GetAccessorDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<GetAccessorDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).name, cbNode, result);
result = reduceNodes((<GetAccessorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).type, cbNode, result);
result = reduceNode((<GetAccessorDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.SetAccessor:
result = reduceNodes((<GetAccessorDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<GetAccessorDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).name, cbNode, result);
result = reduceNodes((<GetAccessorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).body, cbNode, result);
break;
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
result = reduceNodes((<BindingPattern>node).elements, cbNodes, result);
break;
case SyntaxKind.BindingElement:
result = reduceNode((<BindingElement>node).propertyName, cbNode, result);
result = reduceNode((<BindingElement>node).name, cbNode, result);
result = reduceNode((<BindingElement>node).initializer, cbNode, result);
break;
// Expression
case SyntaxKind.ArrayLiteralExpression:
result = reduceNodes((<ArrayLiteralExpression>node).elements, cbNodes, result);
break;
case SyntaxKind.ObjectLiteralExpression:
result = reduceNodes((<ObjectLiteralExpression>node).properties, cbNodes, result);
break;
case SyntaxKind.PropertyAccessExpression:
result = reduceNode((<PropertyAccessExpression>node).expression, cbNode, result);
result = reduceNode((<PropertyAccessExpression>node).name, cbNode, result);
break;
case SyntaxKind.ElementAccessExpression:
result = reduceNode((<ElementAccessExpression>node).expression, cbNode, result);
result = reduceNode((<ElementAccessExpression>node).argumentExpression, cbNode, result);
break;
case SyntaxKind.CallExpression:
result = reduceNode((<CallExpression>node).expression, cbNode, result);
result = reduceNodes((<CallExpression>node).typeArguments, cbNodes, result);
result = reduceNodes((<CallExpression>node).arguments, cbNodes, result);
break;
case SyntaxKind.NewExpression:
result = reduceNode((<NewExpression>node).expression, cbNode, result);
result = reduceNodes((<NewExpression>node).typeArguments, cbNodes, result);
result = reduceNodes((<NewExpression>node).arguments, cbNodes, result);
break;
case SyntaxKind.TaggedTemplateExpression:
result = reduceNode((<TaggedTemplateExpression>node).tag, cbNode, result);
result = reduceNodes((<TaggedTemplateExpression>node).typeArguments, cbNodes, result);
result = reduceNode((<TaggedTemplateExpression>node).template, cbNode, result);
break;
case SyntaxKind.TypeAssertionExpression:
result = reduceNode((<TypeAssertion>node).type, cbNode, result);
result = reduceNode((<TypeAssertion>node).expression, cbNode, result);
break;
case SyntaxKind.FunctionExpression:
result = reduceNodes((<FunctionExpression>node).modifiers, cbNodes, result);
result = reduceNode((<FunctionExpression>node).name, cbNode, result);
result = reduceNodes((<FunctionExpression>node).typeParameters, cbNodes, result);
result = reduceNodes((<FunctionExpression>node).parameters, cbNodes, result);
result = reduceNode((<FunctionExpression>node).type, cbNode, result);
result = reduceNode((<FunctionExpression>node).body, cbNode, result);
break;
case SyntaxKind.ArrowFunction:
result = reduceNodes((<ArrowFunction>node).modifiers, cbNodes, result);
result = reduceNodes((<ArrowFunction>node).typeParameters, cbNodes, result);
result = reduceNodes((<ArrowFunction>node).parameters, cbNodes, result);
result = reduceNode((<ArrowFunction>node).type, cbNode, result);
result = reduceNode((<ArrowFunction>node).body, cbNode, result);
break;
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.YieldExpression:
case SyntaxKind.SpreadElement:
case SyntaxKind.NonNullExpression:
result = reduceNode((<ParenthesizedExpression | DeleteExpression | TypeOfExpression | VoidExpression | AwaitExpression | YieldExpression | SpreadElement | NonNullExpression>node).expression, cbNode, result);
break;
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
result = reduceNode((<PrefixUnaryExpression | PostfixUnaryExpression>node).operand, cbNode, result);
break;
case SyntaxKind.BinaryExpression:
result = reduceNode((<BinaryExpression>node).left, cbNode, result);
result = reduceNode((<BinaryExpression>node).right, cbNode, result);
break;
case SyntaxKind.ConditionalExpression:
result = reduceNode((<ConditionalExpression>node).condition, cbNode, result);
result = reduceNode((<ConditionalExpression>node).whenTrue, cbNode, result);
result = reduceNode((<ConditionalExpression>node).whenFalse, cbNode, result);
break;
case SyntaxKind.TemplateExpression:
result = reduceNode((<TemplateExpression>node).head, cbNode, result);
result = reduceNodes((<TemplateExpression>node).templateSpans, cbNodes, result);
break;
case SyntaxKind.ClassExpression:
result = reduceNodes((<ClassExpression>node).modifiers, cbNodes, result);
result = reduceNode((<ClassExpression>node).name, cbNode, result);
result = reduceNodes((<ClassExpression>node).typeParameters, cbNodes, result);
result = reduceNodes((<ClassExpression>node).heritageClauses, cbNodes, result);
result = reduceNodes((<ClassExpression>node).members, cbNodes, result);
break;
case SyntaxKind.ExpressionWithTypeArguments:
result = reduceNode((<ExpressionWithTypeArguments>node).expression, cbNode, result);
result = reduceNodes((<ExpressionWithTypeArguments>node).typeArguments, cbNodes, result);
break;
case SyntaxKind.AsExpression:
result = reduceNode((<AsExpression>node).expression, cbNode, result);
result = reduceNode((<AsExpression>node).type, cbNode, result);
break;
// Misc
case SyntaxKind.TemplateSpan:
result = reduceNode((<TemplateSpan>node).expression, cbNode, result);
result = reduceNode((<TemplateSpan>node).literal, cbNode, result);
break;
// Element
case SyntaxKind.Block:
result = reduceNodes((<Block>node).statements, cbNodes, result);
break;
case SyntaxKind.VariableStatement:
result = reduceNodes((<VariableStatement>node).modifiers, cbNodes, result);
result = reduceNode((<VariableStatement>node).declarationList, cbNode, result);
break;
case SyntaxKind.ExpressionStatement:
result = reduceNode((<ExpressionStatement>node).expression, cbNode, result);
break;
case SyntaxKind.IfStatement:
result = reduceNode((<IfStatement>node).expression, cbNode, result);
result = reduceNode((<IfStatement>node).thenStatement, cbNode, result);
result = reduceNode((<IfStatement>node).elseStatement, cbNode, result);
break;
case SyntaxKind.DoStatement:
result = reduceNode((<DoStatement>node).statement, cbNode, result);
result = reduceNode((<DoStatement>node).expression, cbNode, result);
break;
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
result = reduceNode((<WhileStatement | WithStatement>node).expression, cbNode, result);
result = reduceNode((<WhileStatement | WithStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ForStatement:
result = reduceNode((<ForStatement>node).initializer, cbNode, result);
result = reduceNode((<ForStatement>node).condition, cbNode, result);
result = reduceNode((<ForStatement>node).incrementor, cbNode, result);
result = reduceNode((<ForStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
result = reduceNode((<ForInOrOfStatement>node).initializer, cbNode, result);
result = reduceNode((<ForInOrOfStatement>node).expression, cbNode, result);
result = reduceNode((<ForInOrOfStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ReturnStatement:
case SyntaxKind.ThrowStatement:
result = reduceNode((<ReturnStatement>node).expression, cbNode, result);
break;
case SyntaxKind.SwitchStatement:
result = reduceNode((<SwitchStatement>node).expression, cbNode, result);
result = reduceNode((<SwitchStatement>node).caseBlock, cbNode, result);
break;
case SyntaxKind.LabeledStatement:
result = reduceNode((<LabeledStatement>node).label, cbNode, result);
result = reduceNode((<LabeledStatement>node).statement, cbNode, result);
break;
case SyntaxKind.TryStatement:
result = reduceNode((<TryStatement>node).tryBlock, cbNode, result);
result = reduceNode((<TryStatement>node).catchClause, cbNode, result);
result = reduceNode((<TryStatement>node).finallyBlock, cbNode, result);
break;
case SyntaxKind.VariableDeclaration:
result = reduceNode((<VariableDeclaration>node).name, cbNode, result);
result = reduceNode((<VariableDeclaration>node).type, cbNode, result);
result = reduceNode((<VariableDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.VariableDeclarationList:
result = reduceNodes((<VariableDeclarationList>node).declarations, cbNodes, result);
break;
case SyntaxKind.FunctionDeclaration:
result = reduceNodes((<FunctionDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<FunctionDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<FunctionDeclaration>node).name, cbNode, result);
result = reduceNodes((<FunctionDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<FunctionDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<FunctionDeclaration>node).type, cbNode, result);
result = reduceNode((<FunctionDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.ClassDeclaration:
result = reduceNodes((<ClassDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ClassDeclaration>node).name, cbNode, result);
result = reduceNodes((<ClassDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).heritageClauses, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).members, cbNodes, result);
break;
case SyntaxKind.EnumDeclaration:
result = reduceNodes((<EnumDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<EnumDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<EnumDeclaration>node).name, cbNode, result);
result = reduceNodes((<EnumDeclaration>node).members, cbNodes, result);
break;
case SyntaxKind.ModuleDeclaration:
result = reduceNodes((<ModuleDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ModuleDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ModuleDeclaration>node).name, cbNode, result);
result = reduceNode((<ModuleDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.ModuleBlock:
result = reduceNodes((<ModuleBlock>node).statements, cbNodes, result);
break;
case SyntaxKind.CaseBlock:
result = reduceNodes((<CaseBlock>node).clauses, cbNodes, result);
break;
case SyntaxKind.ImportEqualsDeclaration:
result = reduceNodes((<ImportEqualsDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ImportEqualsDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ImportEqualsDeclaration>node).name, cbNode, result);
result = reduceNode((<ImportEqualsDeclaration>node).moduleReference, cbNode, result);
break;
case SyntaxKind.ImportDeclaration:
result = reduceNodes((<ImportDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ImportDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ImportDeclaration>node).importClause, cbNode, result);
result = reduceNode((<ImportDeclaration>node).moduleSpecifier, cbNode, result);
break;
case SyntaxKind.ImportClause:
result = reduceNode((<ImportClause>node).name, cbNode, result);
result = reduceNode((<ImportClause>node).namedBindings, cbNode, result);
break;
case SyntaxKind.NamespaceImport:
result = reduceNode((<NamespaceImport>node).name, cbNode, result);
break;
case SyntaxKind.NamespaceExport:
result = reduceNode((<NamespaceExport>node).name, cbNode, result);
break;
case SyntaxKind.NamedImports:
case SyntaxKind.NamedExports:
result = reduceNodes((<NamedImports | NamedExports>node).elements, cbNodes, result);
break;
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).propertyName, cbNode, result);
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).name, cbNode, result);
break;
case SyntaxKind.ExportAssignment:
result = reduceLeft((<ExportAssignment>node).decorators, cbNode, result);
result = reduceLeft((<ExportAssignment>node).modifiers, cbNode, result);
result = reduceNode((<ExportAssignment>node).expression, cbNode, result);
break;
case SyntaxKind.ExportDeclaration:
result = reduceLeft((<ExportDeclaration>node).decorators, cbNode, result);
result = reduceLeft((<ExportDeclaration>node).modifiers, cbNode, result);
result = reduceNode((<ExportDeclaration>node).exportClause, cbNode, result);
result = reduceNode((<ExportDeclaration>node).moduleSpecifier, cbNode, result);
break;
// Module references
case SyntaxKind.ExternalModuleReference:
result = reduceNode((<ExternalModuleReference>node).expression, cbNode, result);
break;
// JSX
case SyntaxKind.JsxElement:
result = reduceNode((<JsxElement>node).openingElement, cbNode, result);
result = reduceLeft((<JsxElement>node).children, cbNode, result);
result = reduceNode((<JsxElement>node).closingElement, cbNode, result);
break;
case SyntaxKind.JsxFragment:
result = reduceNode((<JsxFragment>node).openingFragment, cbNode, result);
result = reduceLeft((<JsxFragment>node).children, cbNode, result);
result = reduceNode((<JsxFragment>node).closingFragment, cbNode, result);
break;
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).tagName, cbNode, result);
result = reduceNodes((<JsxSelfClosingElement | JsxOpeningElement>node).typeArguments, cbNode, result);
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNode, result);
break;
case SyntaxKind.JsxAttributes:
result = reduceNodes((<JsxAttributes>node).properties, cbNodes, result);
break;
case SyntaxKind.JsxClosingElement:
result = reduceNode((<JsxClosingElement>node).tagName, cbNode, result);
break;
case SyntaxKind.JsxAttribute:
result = reduceNode((<JsxAttribute>node).name, cbNode, result);
result = reduceNode((<JsxAttribute>node).initializer, cbNode, result);
break;
case SyntaxKind.JsxSpreadAttribute:
result = reduceNode((<JsxSpreadAttribute>node).expression, cbNode, result);
break;
case SyntaxKind.JsxExpression:
result = reduceNode((<JsxExpression>node).expression, cbNode, result);
break;
// Clauses
case SyntaxKind.CaseClause:
result = reduceNode((<CaseClause>node).expression, cbNode, result);
// falls through
case SyntaxKind.DefaultClause:
result = reduceNodes((<CaseClause | DefaultClause>node).statements, cbNodes, result);
break;
case SyntaxKind.HeritageClause:
result = reduceNodes((<HeritageClause>node).types, cbNodes, result);
break;
case SyntaxKind.CatchClause:
result = reduceNode((<CatchClause>node).variableDeclaration, cbNode, result);
result = reduceNode((<CatchClause>node).block, cbNode, result);
break;
// Property assignments
case SyntaxKind.PropertyAssignment:
result = reduceNode((<PropertyAssignment>node).name, cbNode, result);
result = reduceNode((<PropertyAssignment>node).initializer, cbNode, result);
break;
case SyntaxKind.ShorthandPropertyAssignment:
result = reduceNode((<ShorthandPropertyAssignment>node).name, cbNode, result);
result = reduceNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, cbNode, result);
break;
case SyntaxKind.SpreadAssignment:
result = reduceNode((<SpreadAssignment>node).expression, cbNode, result);
break;
// Enum
case SyntaxKind.EnumMember:
result = reduceNode((<EnumMember>node).name, cbNode, result);
result = reduceNode((<EnumMember>node).initializer, cbNode, result);
break;
// Top-level nodes
case SyntaxKind.SourceFile:
result = reduceNodes((<SourceFile>node).statements, cbNodes, result);
break;
// Transformation nodes
case SyntaxKind.PartiallyEmittedExpression:
result = reduceNode((<PartiallyEmittedExpression>node).expression, cbNode, result);
break;
case SyntaxKind.CommaListExpression:
result = reduceNodes((<CommaListExpression>node).elements, cbNodes, result);
break;
default:
break;
}
return result;
}
function findSpanEnd<T>(array: readonly T[], test: (value: T) => boolean, start: number) {
let i = start;
while (i < array.length && test(array[i])) {
i++;
}
return i;
}
/**
* Merges generated lexical declarations into a new statement list.
*/
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: readonly Statement[] | undefined): NodeArray<Statement>;
/**
* Appends generated lexical declarations to an array of statements.
*/
export function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined): Statement[];
export function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: readonly Statement[] | undefined) {
if (!some(declarations)) {
return statements;
}
// When we merge new lexical statements into an existing statement list, we merge them in the following manner:
//
// Given:
//
// | Left | Right |
// |------------------------------------|-------------------------------------|
// | [standard prologues (left)] | [standard prologues (right)] |
// | [hoisted functions (left)] | [hoisted functions (right)] |
// | [hoisted variables (left)] | [hoisted variables (right)] |
// | [lexical init statements (left)] | [lexical init statements (right)] |
// | [other statements (left)] | |
//
// The resulting statement list will be:
//
// | Result |
// |-------------------------------------|
// | [standard prologues (right)] |
// | [standard prologues (left)] |
// | [hoisted functions (right)] |
// | [hoisted functions (left)] |
// | [hoisted variables (right)] |
// | [hoisted variables (left)] |
// | [lexical init statements (right)] |
// | [lexical init statements (left)] |
// | [other statements (left)] |
//
// NOTE: It is expected that new lexical init statements must be evaluated before existing lexical init statements,
// as the prior transformation may depend on the evaluation of the lexical init statements to be in the correct state.
// find standard prologues on left in the following order: standard directives, hoisted functions, hoisted variables, other custom
const leftStandardPrologueEnd = findSpanEnd(statements, isPrologueDirective, 0);
const leftHoistedFunctionsEnd = findSpanEnd(statements, isHoistedFunction, leftStandardPrologueEnd);
const leftHoistedVariablesEnd = findSpanEnd(statements, isHoistedVariableStatement, leftHoistedFunctionsEnd);
// find standard prologues on right in the following order: standard directives, hoisted functions, hoisted variables, other custom
const rightStandardPrologueEnd = findSpanEnd(declarations, isPrologueDirective, 0);
const rightHoistedFunctionsEnd = findSpanEnd(declarations, isHoistedFunction, rightStandardPrologueEnd);
const rightHoistedVariablesEnd = findSpanEnd(declarations, isHoistedVariableStatement, rightHoistedFunctionsEnd);
const rightCustomPrologueEnd = findSpanEnd(declarations, isCustomPrologue, rightHoistedVariablesEnd);
Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues");
// splice prologues from the right into the left. We do this in reverse order
// so that we don't need to recompute the index on the left when we insert items.
const left = isNodeArray(statements) ? statements.slice() : statements;
// splice other custom prologues from right into left
if (rightCustomPrologueEnd > rightHoistedVariablesEnd) {
left.splice(leftHoistedVariablesEnd, 0, ...declarations.slice(rightHoistedVariablesEnd, rightCustomPrologueEnd));
}
// splice hoisted variables from right into left
if (rightHoistedVariablesEnd > rightHoistedFunctionsEnd) {
left.splice(leftHoistedFunctionsEnd, 0, ...declarations.slice(rightHoistedFunctionsEnd, rightHoistedVariablesEnd));
}
// splice hoisted functions from right into left
if (rightHoistedFunctionsEnd > rightStandardPrologueEnd) {
left.splice(leftStandardPrologueEnd, 0, ...declarations.slice(rightStandardPrologueEnd, rightHoistedFunctionsEnd));
}
// splice standard prologues from right into left (that are not already in left)
if (rightStandardPrologueEnd > 0) {
if (leftStandardPrologueEnd === 0) {
left.splice(0, 0, ...declarations.slice(0, rightStandardPrologueEnd));
}
else {
const leftPrologues = createMap<boolean>();
for (let i = 0; i < leftStandardPrologueEnd; i++) {
const leftPrologue = statements[i] as PrologueDirective;
leftPrologues.set(leftPrologue.expression.text, true);
}
for (let i = rightStandardPrologueEnd - 1; i >= 0; i--) {
const rightPrologue = declarations[i] as PrologueDirective;
if (!leftPrologues.has(rightPrologue.expression.text)) {
left.unshift(rightPrologue);
}
}
}
}
if (isNodeArray(statements)) {
return setTextRange(createNodeArray(left, statements.hasTrailingComma), statements);
}
return statements;
}
/**
* Lifts a NodeArray containing only Statement nodes to a block.
*
* @param nodes The NodeArray.
*/
export function liftToBlock(nodes: readonly Node[]): Statement {
Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block.");
return <Statement>singleOrUndefined(nodes) || createBlock(<NodeArray<Statement>>nodes);
}
/**
* Aggregates the TransformFlags for a Node and its subtree.
*/
export function aggregateTransformFlags<T extends Node>(node: T): T {
aggregateTransformFlagsForNode(node);
return node;
}
/**
* Aggregates the TransformFlags for a Node and its subtree. The flags for the subtree are
* computed first, then the transform flags for the current node are computed from the subtree
* flags and the state of the current node. Finally, the transform flags of the node are
* returned, excluding any flags that should not be included in its parent node's subtree
* flags.
*/
function aggregateTransformFlagsForNode(node: Node): TransformFlags {
if (node === undefined) {
return TransformFlags.None;
}
if (node.transformFlags & TransformFlags.HasComputedFlags) {
return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind);
}
const subtreeFlags = aggregateTransformFlagsForSubtree(node);
return computeTransformFlagsForNode(node, subtreeFlags);
}
function aggregateTransformFlagsForNodeArray(nodes: NodeArray<Node>): TransformFlags {
if (nodes === undefined) {
return TransformFlags.None;
}
let subtreeFlags = TransformFlags.None;
let nodeArrayFlags = TransformFlags.None;
for (const node of nodes) {
subtreeFlags |= aggregateTransformFlagsForNode(node);
nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags;
}
nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags;
return subtreeFlags;
}
/**
* Aggregates the transform flags for the subtree of a node.
*/
function aggregateTransformFlagsForSubtree(node: Node): TransformFlags {
// We do not transform ambient declarations or types, so there is no need to
// recursively aggregate transform flags.
if (hasSyntacticModifier(node, ModifierFlags.Ambient) || (isTypeNode(node) && node.kind !== SyntaxKind.ExpressionWithTypeArguments)) {
return TransformFlags.None;
}
// Aggregate the transform flags of each child.
return reduceEachChild(node, TransformFlags.None, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes);
}
/**
* Aggregates the TransformFlags of a child node with the TransformFlags of its
* siblings.
*/
function aggregateTransformFlagsForChildNode(transformFlags: TransformFlags, node: Node): TransformFlags {
return transformFlags | aggregateTransformFlagsForNode(node);
}
function aggregateTransformFlagsForChildNodes(transformFlags: TransformFlags, nodes: NodeArray<Node>): TransformFlags {
return transformFlags | aggregateTransformFlagsForNodeArray(nodes);
}
}