mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'transforms-transformer' into transforms-transformer-ts
This commit is contained in:
+18
-15
@@ -1968,16 +1968,20 @@ namespace ts {
|
||||
transformFlags = TransformFlags.AssertTypeScript;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
// if (node.flags & NodeFlags.Generated) {
|
||||
// let expression = (<ExpressionStatement>node).expression;
|
||||
// if (expression.kind === SyntaxKind.CallExpression
|
||||
// && (<CallExpression>expression).expression.kind === SyntaxKind.SuperKeyword) {
|
||||
// transformFlags |= TransformFlags.AssertES6;
|
||||
// }
|
||||
// }
|
||||
if (nodeIsSynthesized(node)) {
|
||||
const expression = (<ExpressionStatement>node).expression;
|
||||
if (nodeIsSynthesized(expression)
|
||||
&& isCallExpression(expression)
|
||||
&& expression.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
// A synthesized call to `super` should be transformed to a cleaner emit
|
||||
// when transpiling to ES5/3.
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -2088,17 +2092,16 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
// If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax.
|
||||
if (node.flags & NodeFlags.Let
|
||||
|| node.flags & NodeFlags.Const) {
|
||||
if (node.flags & NodeFlags.BlockScoped) {
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
// If a VariableStatement is exported, then it is ES6 syntax.
|
||||
// If a VariableStatement is exported, then it is either ES6 or TypeScript syntax.
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
transformFlags |= TransformFlags.AssertES6 | TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -2120,13 +2123,13 @@ namespace ts {
|
||||
break;
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
// An `extends` HertiageClause is ES6 syntax.
|
||||
if ((<HeritageClause>node).token === SyntaxKind.ExtendsKeyword) {
|
||||
// An `extends` HeritageClause is ES6 syntax.
|
||||
transformFlags |= TransformFlags.AssertES6;
|
||||
}
|
||||
|
||||
// An `implements` HeritageClause is TypeScript syntax.
|
||||
else if ((<HeritageClause>node).token === SyntaxKind.ImplementsKeyword) {
|
||||
else {
|
||||
// An `implements` HeritageClause is TypeScript syntax.
|
||||
Debug.assert((<HeritageClause>node).token === SyntaxKind.ImplementsKeyword);
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -188,8 +188,19 @@ namespace ts {
|
||||
export function concatenate<T>(array1: T[], array2: T[]): T[] {
|
||||
if (!array2 || !array2.length) return array1;
|
||||
if (!array1 || !array1.length) return array2;
|
||||
return [...array1, ...array2];
|
||||
}
|
||||
|
||||
return array1.concat(array2);
|
||||
export function append<T>(array: T[], value: T): T[] {
|
||||
if (value === undefined) return array;
|
||||
if (!array || !array.length) return [value];
|
||||
return [...array, value];
|
||||
}
|
||||
|
||||
export function prepend<T>(array: T[], value: T): T[] {
|
||||
if (value === undefined) return array;
|
||||
if (!array || !array.length) return [value];
|
||||
return [value, ...array];
|
||||
}
|
||||
|
||||
export function deduplicate<T>(array: T[]): T[] {
|
||||
|
||||
+149
-91
@@ -78,14 +78,17 @@ namespace ts {
|
||||
return array;
|
||||
}
|
||||
|
||||
function setModifiers(node: Node, modifiers: Modifier[]) {
|
||||
export function setModifiers<T extends Node>(node: T, modifiers: Modifier[]) {
|
||||
if (modifiers) {
|
||||
node.modifiers = createSynthesizedModifiersArray(modifiers);
|
||||
node.flags |= node.modifiers.flags;
|
||||
const array = createModifiersArray(modifiers);
|
||||
node.modifiers = array;
|
||||
node.flags |= array.flags;
|
||||
}
|
||||
else {
|
||||
node.modifiers = undefined;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node {
|
||||
@@ -153,17 +156,17 @@ namespace ts {
|
||||
export function createLiteral(value: string): StringLiteral;
|
||||
export function createLiteral(value: number): LiteralExpression;
|
||||
export function createLiteral(value: string | number | boolean): PrimaryExpression;
|
||||
export function createLiteral<T extends PrimaryExpression>(value: string | number | boolean): T {
|
||||
export function createLiteral(value: string | number | boolean): PrimaryExpression {
|
||||
if (typeof value === "number") {
|
||||
const node = <T & LiteralExpression>createNode(SyntaxKind.NumericLiteral);
|
||||
const node = <LiteralExpression>createNode(SyntaxKind.NumericLiteral);
|
||||
node.text = value.toString();
|
||||
return node;
|
||||
}
|
||||
else if (typeof value === "boolean") {
|
||||
return <T>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword);
|
||||
return <PrimaryExpression>createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword);
|
||||
}
|
||||
else {
|
||||
const node = <T & StringLiteral>createNode(SyntaxKind.StringLiteral);
|
||||
const node = <StringLiteral>createNode(SyntaxKind.StringLiteral);
|
||||
node.text = String(value);
|
||||
return node;
|
||||
}
|
||||
@@ -224,7 +227,7 @@ namespace ts {
|
||||
const node = <MethodDeclaration>createNode(SyntaxKind.MethodDeclaration, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = coercePropertyName(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.body = body;
|
||||
@@ -246,7 +249,7 @@ namespace ts {
|
||||
const node = <GetAccessorDeclaration>createNode(SyntaxKind.GetAccessor, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = coercePropertyName(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray<ParameterDeclaration>();
|
||||
node.body = body;
|
||||
@@ -257,7 +260,7 @@ namespace ts {
|
||||
const node = <SetAccessorDeclaration>createNode(SyntaxKind.SetAccessor, location);
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.name = coercePropertyName(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray([parameter]);
|
||||
node.body = body;
|
||||
@@ -269,7 +272,7 @@ namespace ts {
|
||||
node.decorators = undefined;
|
||||
node.modifiers = undefined;
|
||||
node.dotDotDotToken = undefined;
|
||||
node.name = coerceBindingName(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.questionToken = undefined;
|
||||
node.type = undefined;
|
||||
node.initializer = initializer;
|
||||
@@ -295,14 +298,14 @@ namespace ts {
|
||||
const node = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, location);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
node.dotToken = createSynthesizedNode(SyntaxKind.DotToken);
|
||||
node.name = coerceIdentifier(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createElementAccess(expression: Expression, index: string | number | Expression, location?: TextRange) {
|
||||
export function createElementAccess(expression: Expression, index: number | Expression, location?: TextRange) {
|
||||
const node = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, location);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
node.argumentExpression = coerceExpression(index);
|
||||
node.argumentExpression = typeof index === "number" ? createLiteral(index) : index;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -323,7 +326,7 @@ namespace ts {
|
||||
const node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression, location);
|
||||
node.modifiers = undefined;
|
||||
node.asteriskToken = asteriskToken;
|
||||
node.name = coerceIdentifier(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.type = undefined;
|
||||
@@ -356,9 +359,9 @@ namespace ts {
|
||||
|
||||
export function createBinary(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange) {
|
||||
const node = <BinaryExpression>createNode(SyntaxKind.BinaryExpression, location);
|
||||
node.left = parenthesizeForBinary(left, operator, BinaryOperand.Left);
|
||||
node.left = parenthesizeBinaryOperand(operator, left, /*isLeftSideOfBinary*/ true);
|
||||
node.operatorToken = createSynthesizedNode(operator);
|
||||
node.right = parenthesizeForBinary(right, operator, BinaryOperand.Right);
|
||||
node.right = parenthesizeBinaryOperand(operator, right, /*isLeftSideOfBinary*/ false);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -434,7 +437,7 @@ namespace ts {
|
||||
|
||||
export function createVariableDeclaration(name: string | BindingPattern | Identifier, initializer?: Expression, location?: TextRange): VariableDeclaration {
|
||||
const node = <VariableDeclaration>createNode(SyntaxKind.VariableDeclaration, location);
|
||||
node.name = coerceBindingName(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.initializer = initializer;
|
||||
return node;
|
||||
}
|
||||
@@ -456,7 +459,7 @@ namespace ts {
|
||||
node.decorators = undefined;
|
||||
setModifiers(node, modifiers);
|
||||
node.asteriskToken = asteriskToken;
|
||||
node.name = coerceIdentifier(name);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.typeParameters = undefined;
|
||||
node.parameters = createNodeArray(parameters);
|
||||
node.type = undefined;
|
||||
@@ -497,8 +500,8 @@ namespace ts {
|
||||
|
||||
export function createExportSpecifier(name: string | Identifier, propertyName?: string | Identifier) {
|
||||
const node = <ExportSpecifier>createNode(SyntaxKind.ExportSpecifier);
|
||||
node.name = coerceIdentifier(name);
|
||||
node.propertyName = coerceIdentifier(propertyName);
|
||||
node.name = typeof name === "string" ? createIdentifier(name) : name;
|
||||
node.propertyName = typeof propertyName === "string" ? createIdentifier(propertyName) : propertyName;
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -554,7 +557,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function createArraySlice(array: Expression, start?: number | Expression) {
|
||||
const argumentsList: Expression[] = start !== undefined ? [coerceExpression(start)] : [];
|
||||
const argumentsList: Expression[] = [];
|
||||
if (start !== undefined) {
|
||||
argumentsList.push(typeof start === "number" ? createLiteral(start) : start);
|
||||
}
|
||||
|
||||
return createCall(createPropertyAccess(array, "slice"), argumentsList);
|
||||
}
|
||||
|
||||
@@ -791,111 +798,150 @@ namespace ts {
|
||||
|
||||
|
||||
// Utilities
|
||||
|
||||
function coerceIdentifier(value: string | Identifier) {
|
||||
if (typeof value === "string") {
|
||||
return createIdentifier(value);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function coerceBindingName(value: string | BindingName) {
|
||||
if (typeof value === "string") {
|
||||
return createIdentifier(value);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function coercePropertyName(value: string | PropertyName) {
|
||||
if (typeof value === "string") {
|
||||
return createIdentifier(value);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function coerceExpression(value: string | number | boolean | Expression): Expression {
|
||||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||||
return createLiteral(value);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
const enum BinaryOperand {
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
function parenthesizeForBinary(operand: Expression, operator: SyntaxKind, side: BinaryOperand) {
|
||||
/**
|
||||
* Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended
|
||||
* order of operations.
|
||||
*
|
||||
* @param binaryOperator The operator for the BinaryExpression.
|
||||
* @param operand The operand for the BinaryExpression.
|
||||
* @param isLeftSideOfBinary A value indicating whether the operand is the left side of the
|
||||
* BinaryExpression.
|
||||
*/
|
||||
function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean) {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
while (operand.kind === SyntaxKind.TypeAssertionExpression || operand.kind === SyntaxKind.AsExpression) {
|
||||
operand = (<AssertionExpression>operand).expression;
|
||||
}
|
||||
operand = skipAssertions(operand);
|
||||
|
||||
// If the resulting expression is already parenthesized, we do not need to do any further processing.
|
||||
if (operand.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
return operand;
|
||||
}
|
||||
|
||||
return needsParenthesesForBinary(operand, operator, side)
|
||||
return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary)
|
||||
? createParen(operand)
|
||||
: operand;
|
||||
}
|
||||
|
||||
function needsParenthesesForBinary(operand: Expression, operator: SyntaxKind, side: BinaryOperand) {
|
||||
/**
|
||||
* Determines whether the operand to a BinaryExpression needs to be parenthesized.
|
||||
*
|
||||
* @param binaryOperator The operator for the BinaryExpression.
|
||||
* @param operand The operand for the BinaryExpression.
|
||||
* @param isLeftSideOfBinary A value indicating whether the operand is the left side of the
|
||||
* BinaryExpression.
|
||||
*/
|
||||
function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean) {
|
||||
// If the operand has lower precedence, then it needs to be parenthesized to preserve the
|
||||
// intent of the expression. For example, if the operand is `a + b` and the operator is
|
||||
// `*`, then we need to parenthesize the operand to preserve the intended order of
|
||||
// operations: `(a + b) * x`.
|
||||
//
|
||||
// If the operand has higher precedence, then it does not need to be parenthesized. For
|
||||
// example, if the operand is `a * b` and the operator is `+`, then we do not need to
|
||||
// parenthesize to preserve the intended order of operations: `a * b + x`.
|
||||
//
|
||||
// If the operand has the same precedence, then we need to check the associativity of
|
||||
// the operator based on whether this is the left or right operand of the expression.
|
||||
//
|
||||
// For example, if `a / d` is on the right of operator `*`, we need to parenthesize
|
||||
// to preserve the intended order of operations: `x * (a / d)`
|
||||
//
|
||||
// If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve
|
||||
// the intended order of operations: `(a ** b) ** c`
|
||||
const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator);
|
||||
const operandPrecedence = getExpressionPrecedence(operand);
|
||||
const operatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, operator);
|
||||
switch (compareValues(operandPrecedence, operatorPrecedence)) {
|
||||
switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) {
|
||||
case Comparison.LessThan:
|
||||
return true;
|
||||
case Comparison.EqualTo:
|
||||
return isRightAssociativeOperandOnLeftHandSide(operand, side)
|
||||
|| isModuloOperandOnRightHandSide(operand, operator, side);
|
||||
|
||||
case Comparison.GreaterThan:
|
||||
return false;
|
||||
|
||||
case Comparison.EqualTo:
|
||||
if (isLeftSideOfBinary) {
|
||||
// No need to parenthesize the left operand when the binary operator is
|
||||
// left associative:
|
||||
// (a*b)/x -> a*b/x
|
||||
// (a**b)/x -> a**b/x
|
||||
|
||||
// Parentheses are needed for the left operand when the binary operator is
|
||||
// right associative:
|
||||
// (a/b)**x -> (a/b)**x
|
||||
// (a**b)**x -> (a**b)**x
|
||||
const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator);
|
||||
return binaryOperatorAssociativity === Associativity.Right;
|
||||
}
|
||||
else {
|
||||
// No need to parenthesize the right operand when the binary operator and
|
||||
// operand are the same and one of the following:
|
||||
// x*(a*b) => x*a*b
|
||||
// x|(a|b) => x|a|b
|
||||
// x&(a&b) => x&a&b
|
||||
// x^(a^b) => x^a^b
|
||||
if (isBinaryExpression(operand)
|
||||
&& operand.operatorToken.kind === binaryOperator
|
||||
&& isMathAssociativeOperator(binaryOperator)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No need to parenthesize the right operand when the operand is right
|
||||
// associative:
|
||||
// x/(a**b) -> x/a**b
|
||||
// x**(a**b) -> x**a**b
|
||||
|
||||
// Parentheses are needed for the right operand when the operand is left
|
||||
// associative:
|
||||
// x/(a*b) -> x/(a*b)
|
||||
// x**(a/b) -> x**(a/b)
|
||||
const operandAssociativity = getExpressionAssociativity(operand);
|
||||
return operandAssociativity === Associativity.Left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isRightAssociativeOperandOnLeftHandSide(operand: Expression, side: BinaryOperand) {
|
||||
return side === BinaryOperand.Left
|
||||
&& getExpressionAssociativity(operand) === Associativity.Right;
|
||||
}
|
||||
|
||||
function isModuloOperandOnRightHandSide(operand: Expression, operator: SyntaxKind, side: BinaryOperand) {
|
||||
return side === BinaryOperand.Right
|
||||
&& operator !== SyntaxKind.PercentToken
|
||||
&& operand.kind === SyntaxKind.BinaryExpression
|
||||
&& (<BinaryExpression>operand).operatorToken.kind === SyntaxKind.PercentToken;
|
||||
/**
|
||||
* Determines whether a binary operator is mathematically associative.
|
||||
*
|
||||
* @param binaryOperator The binary operator.
|
||||
*/
|
||||
function isMathAssociativeOperator(binaryOperator: SyntaxKind) {
|
||||
// The following operators are associative in JavaScript:
|
||||
// (a*b)*c -> a*(b*c) -> a*b*c
|
||||
// (a|b)|c -> a|(b|c) -> a|b|c
|
||||
// (a&b)&c -> a&(b&c) -> a&b&c
|
||||
// (a^b)^c -> a^(b^c) -> a^b^c
|
||||
//
|
||||
// While addition is associative in mathematics, JavaScript's `+` is not
|
||||
// guaranteed to be associative as it is overloaded with string concatenation.
|
||||
return binaryOperator === SyntaxKind.AsteriskToken
|
||||
|| binaryOperator === SyntaxKind.BarToken
|
||||
|| binaryOperator === SyntaxKind.AmpersandToken
|
||||
|| binaryOperator === SyntaxKind.CaretToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an expression in parentheses if it is needed in order to use the expression for
|
||||
* property or element access.
|
||||
*
|
||||
* @param expr The expression node.
|
||||
*/
|
||||
function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
while (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) {
|
||||
expr = (<AssertionExpression>expr).expression;
|
||||
}
|
||||
expr = skipAssertions(expr);
|
||||
|
||||
// isLeftHandSideExpression is almost the correct criterion for when it is not necessary
|
||||
// to parenthesize the expression before a dot. The known exceptions are:
|
||||
//
|
||||
// NewExpression:
|
||||
// new C.x -> not the same as (new C).x
|
||||
// NumberLiteral
|
||||
// NumericLiteral
|
||||
// 1.x -> not the same as (1).x
|
||||
//
|
||||
if (isLeftHandSideExpression(expr) &&
|
||||
expr.kind !== SyntaxKind.NewExpression &&
|
||||
expr.kind !== SyntaxKind.NumericLiteral) {
|
||||
|
||||
return <LeftHandSideExpression>expr;
|
||||
return expr;
|
||||
}
|
||||
|
||||
return createParen(expr);
|
||||
@@ -909,6 +955,18 @@ namespace ts {
|
||||
return createParen(operand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips past any TypeAssertionExpression or AsExpression nodes to their inner expression.
|
||||
*
|
||||
* @param node The expression node.
|
||||
*/
|
||||
function skipAssertions(node: Expression) {
|
||||
while (node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
|
||||
node = (<AssertionExpression>node).expression;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function startOnNewLine<T extends Node>(node: T): T {
|
||||
(<SynthesizedNode>node).startsOnNewLine = true;
|
||||
|
||||
@@ -85,8 +85,8 @@ const _super = (function (geti, seti) {
|
||||
})(name => super[name], (name, value) => super[name] = value);`;
|
||||
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const languageVersion = getLanguageVersion(compilerOptions);
|
||||
const moduleKind = getModuleKind(compilerOptions);
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined;
|
||||
const emitterDiagnostics = createDiagnosticCollection();
|
||||
|
||||
|
||||
+30
-23
@@ -19,10 +19,16 @@ namespace ts {
|
||||
[ModuleKind.None]: transformModule
|
||||
};
|
||||
|
||||
const enum SyntaxKindFeatureFlags {
|
||||
ExpressionSubstitution = 1 << 0,
|
||||
EmitNotifications = 1 << 1,
|
||||
}
|
||||
|
||||
|
||||
export function getTransformers(compilerOptions: CompilerOptions) {
|
||||
const jsx = compilerOptions.jsx;
|
||||
const languageVersion = getLanguageVersion(compilerOptions);
|
||||
const moduleKind = getModuleKind(compilerOptions);
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
const transformers: Transformer[] = [];
|
||||
|
||||
transformers.push(transformTypeScript);
|
||||
@@ -56,8 +62,7 @@ namespace ts {
|
||||
const nodeEmitFlags: NodeEmitFlags[] = [];
|
||||
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
|
||||
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
|
||||
const enabledExpressionSubstitutions = new Array<boolean>(SyntaxKind.Count);
|
||||
const enabledEmitNotifications = new Array<boolean>(SyntaxKind.Count);
|
||||
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
|
||||
|
||||
let lexicalEnvironmentStackOffset = 0;
|
||||
let hoistedVariableDeclarations: VariableDeclaration[];
|
||||
@@ -108,19 +113,19 @@ namespace ts {
|
||||
}
|
||||
|
||||
function enableExpressionSubstitution(kind: SyntaxKind) {
|
||||
enabledExpressionSubstitutions[kind] = true;
|
||||
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.ExpressionSubstitution;
|
||||
}
|
||||
|
||||
function isExpressionSubstitutionEnabled(node: Node) {
|
||||
return enabledExpressionSubstitutions[node.kind];
|
||||
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.ExpressionSubstitution) !== 0;
|
||||
}
|
||||
|
||||
function enableEmitNotification(kind: SyntaxKind) {
|
||||
enabledEmitNotifications[kind] = true;
|
||||
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications;
|
||||
}
|
||||
|
||||
function isEmitNotificationEnabled(node: Node) {
|
||||
return enabledEmitNotifications[node.kind]
|
||||
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.EmitNotifications) !== 0
|
||||
|| (getNodeEmitFlags(node) & NodeEmitFlags.AdviseOnEmitNode) !== 0;
|
||||
}
|
||||
|
||||
@@ -226,6 +231,8 @@ namespace ts {
|
||||
return generateNameForImportOrExportDeclaration(<ImportDeclaration | ExportDeclaration>node);
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
Debug.assert((node.flags & NodeFlags.Default) !== 0, "Can only generate a name for a default export.");
|
||||
return generateNameForExportDefault();
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return generateNameForExportDefault();
|
||||
case SyntaxKind.ClassExpression:
|
||||
@@ -258,14 +265,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a hoisted variable declaration within a lexical environment.
|
||||
* Records a hoisted variable declaration for the provided name within a lexical environment.
|
||||
*/
|
||||
function hoistVariableDeclaration(name: Identifier): void {
|
||||
const decl = createVariableDeclaration(name);
|
||||
if (!hoistedVariableDeclarations) {
|
||||
hoistedVariableDeclarations = [];
|
||||
hoistedVariableDeclarations = [decl];
|
||||
}
|
||||
else {
|
||||
hoistedVariableDeclarations.push(decl);
|
||||
}
|
||||
|
||||
hoistedVariableDeclarations.push(createVariableDeclaration(name));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,10 +282,11 @@ namespace ts {
|
||||
*/
|
||||
function hoistFunctionDeclaration(func: FunctionDeclaration): void {
|
||||
if (!hoistedFunctionDeclarations) {
|
||||
hoistedFunctionDeclarations = [];
|
||||
hoistedFunctionDeclarations = [func];
|
||||
}
|
||||
else {
|
||||
hoistedFunctionDeclarations.push(func);
|
||||
}
|
||||
|
||||
hoistedFunctionDeclarations.push(func);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,7 +301,6 @@ namespace ts {
|
||||
lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedVariableDeclarations;
|
||||
lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedFunctionDeclarations;
|
||||
lexicalEnvironmentStackOffset++;
|
||||
|
||||
hoistedVariableDeclarations = undefined;
|
||||
hoistedFunctionDeclarations = undefined;
|
||||
}
|
||||
@@ -303,15 +312,12 @@ namespace ts {
|
||||
function endLexicalEnvironment(): Statement[] {
|
||||
let statements: Statement[];
|
||||
if (hoistedVariableDeclarations || hoistedFunctionDeclarations) {
|
||||
statements = [];
|
||||
if (hoistedFunctionDeclarations) {
|
||||
for (const declaration of hoistedFunctionDeclarations) {
|
||||
statements.push(declaration);
|
||||
}
|
||||
statements = [...hoistedFunctionDeclarations];
|
||||
}
|
||||
|
||||
if (hoistedVariableDeclarations) {
|
||||
statements.push(
|
||||
statements = append(statements,
|
||||
createVariableStatement(
|
||||
/*modifiers*/ undefined,
|
||||
createVariableDeclarationList(hoistedVariableDeclarations)
|
||||
@@ -390,8 +396,9 @@ namespace ts {
|
||||
* Makes an array from an ArrayLike.
|
||||
*/
|
||||
function arrayOf<T>(arrayLike: ArrayLike<T>) {
|
||||
const array: T[] = [];
|
||||
for (let i = 0; i < arrayLike.length; i++) {
|
||||
const length = arrayLike.length;
|
||||
const array: T[] = new Array<T>(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
array[i] = arrayLike[i];
|
||||
}
|
||||
return array;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ts {
|
||||
|
||||
const resolver = context.getEmitResolver();
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
const languageVersion = getLanguageVersion(compilerOptions);
|
||||
const languageVersion = getEmitScriptTarget(compilerOptions);
|
||||
const decoratedClassAliases: Map<Identifier> = {};
|
||||
const currentDecoratedClassAliases: Map<Identifier> = {};
|
||||
const previousExpressionSubstitution = context.expressionSubstitution;
|
||||
@@ -755,8 +755,8 @@ namespace ts {
|
||||
function findInitialSuperCall(ctor: ConstructorDeclaration): ExpressionStatement {
|
||||
if (ctor.body) {
|
||||
const statements = ctor.body.statements;
|
||||
const statement = statements.length ? statements[0] : undefined;
|
||||
if (statement.kind === SyntaxKind.ExpressionStatement) {
|
||||
const statement = firstOrUndefined(statements);
|
||||
if (statement && statement.kind === SyntaxKind.ExpressionStatement) {
|
||||
const expression = (<ExpressionStatement>statement).expression;
|
||||
if (expression.kind === SyntaxKind.CallExpression) {
|
||||
if ((<CallExpression>expression).expression.kind === SyntaxKind.SuperKeyword) {
|
||||
@@ -1853,7 +1853,7 @@ namespace ts {
|
||||
const visited = visitEachChild(body, visitor, context);
|
||||
const declarations = endLexicalEnvironment();
|
||||
currentScope = savedCurrentScope;
|
||||
return mergeFunctionBodyLexicalEnvironment(visited, declarations, visited !== body);
|
||||
return mergeFunctionBodyLexicalEnvironment(visited, declarations);
|
||||
}
|
||||
|
||||
function transformConciseBody(node: ArrowFunction): ConciseBody {
|
||||
@@ -1872,7 +1872,7 @@ namespace ts {
|
||||
startLexicalEnvironment();
|
||||
const visited: Expression | Block = visitNode(body, visitor, isConciseBody);
|
||||
const declarations = endLexicalEnvironment();
|
||||
const merged = mergeConciseBodyLexicalEnvironment(visited, declarations, visited !== body);
|
||||
const merged = mergeConciseBodyLexicalEnvironment(visited, declarations);
|
||||
if (forceBlockFunctionBody && !isBlock(merged)) {
|
||||
return createBlock([
|
||||
createReturn(<Expression>merged)
|
||||
|
||||
+43
-3
@@ -2797,7 +2797,7 @@ namespace ts {
|
||||
EmitSuperHelper = 1 << 2, // Emit the basic _super helper for async methods.
|
||||
EmitAdvancedSuperHelper = 1 << 3, // Emit the advanced _super helper for async methods.
|
||||
UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper.
|
||||
NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node.
|
||||
NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node, this is primarily used when printing a SystemJS module.
|
||||
SingleLine = 1 << 6, // The contents of this node should be emit on a single line.
|
||||
MultiLine = 1 << 7, // The contents of this node should be emit on multiple lines.
|
||||
AdviseOnEmitNode = 1 << 8, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
|
||||
@@ -2824,13 +2824,53 @@ namespace ts {
|
||||
getGeneratedNameForNode(node: Node): Identifier;
|
||||
nodeHasGeneratedName(node: Node): boolean;
|
||||
makeUniqueName(baseName: string): Identifier;
|
||||
enableExpressionSubstitution(kind: SyntaxKind): void;
|
||||
isExpressionSubstitutionEnabled(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* Hook used by transformers to substitute non-expression identifiers
|
||||
* just before theyare emitted by the pretty printer.
|
||||
*/
|
||||
identifierSubstitution?: (node: Identifier) => Identifier;
|
||||
|
||||
/**
|
||||
* Enables expression substitutions in the pretty printer for
|
||||
* the provided SyntaxKind.
|
||||
*/
|
||||
enableExpressionSubstitution(kind: SyntaxKind): void;
|
||||
|
||||
/**
|
||||
* Determines whether expression substitutions are enabled for the
|
||||
* provided node.
|
||||
*/
|
||||
isExpressionSubstitutionEnabled(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* Hook used by transformers to substitute expressions just before they
|
||||
* are emitted by the pretty printer.
|
||||
*/
|
||||
expressionSubstitution?: (node: Expression) => Expression;
|
||||
|
||||
/**
|
||||
* Enables before/after emit notifications in the pretty printer for
|
||||
* the provided SyntaxKind.
|
||||
*/
|
||||
enableEmitNotification(kind: SyntaxKind): void;
|
||||
|
||||
/**
|
||||
* Determines whether before/after emit notifications should be raised
|
||||
* in the pretty printer when it emits a node.
|
||||
*/
|
||||
isEmitNotificationEnabled(node: Node): boolean;
|
||||
|
||||
/**
|
||||
* Hook used to notify transformers immediately before the pretty printer
|
||||
* emits a node.
|
||||
*/
|
||||
onBeforeEmitNode?: (node: Node) => void;
|
||||
|
||||
/**
|
||||
* Hook used to notify transformers immediately after the pretty printer
|
||||
* emits a node.
|
||||
*/
|
||||
onAfterEmitNode?: (node: Node) => void;
|
||||
}
|
||||
|
||||
|
||||
+269
-268
@@ -103,22 +103,6 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function getLanguageVersion(compilerOptions: CompilerOptions) {
|
||||
return compilerOptions.target || ScriptTarget.ES3;
|
||||
}
|
||||
|
||||
export function getModuleKind(compilerOptions: CompilerOptions) {
|
||||
if (compilerOptions.module) {
|
||||
return compilerOptions.module;
|
||||
}
|
||||
|
||||
if (getLanguageVersion(compilerOptions) === ScriptTarget.ES6) {
|
||||
return ModuleKind.ES6;
|
||||
}
|
||||
|
||||
return ModuleKind.None;
|
||||
}
|
||||
|
||||
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean {
|
||||
return sourceFile.resolvedModules && hasProperty(sourceFile.resolvedModules, moduleNameText);
|
||||
}
|
||||
@@ -1369,17 +1353,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isLiteralKind(kind: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
|
||||
}
|
||||
|
||||
export function isTextualLiteralKind(kind: SyntaxKind): boolean {
|
||||
return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
|
||||
}
|
||||
|
||||
export function isNodeDescendentOf(node: Node, ancestor: Node): boolean {
|
||||
while (node) {
|
||||
@@ -1648,8 +1622,17 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function nodeStartsNewLexicalEnvironment(n: Node): boolean {
|
||||
return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile;
|
||||
export function nodeStartsNewLexicalEnvironment(node: Node): boolean {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Constructor
|
||||
|| kind === SyntaxKind.FunctionExpression
|
||||
|| kind === SyntaxKind.FunctionDeclaration
|
||||
|| kind === SyntaxKind.ArrowFunction
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor
|
||||
|| kind === SyntaxKind.ModuleDeclaration
|
||||
|| kind === SyntaxKind.SourceFile;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2813,23 +2796,111 @@ namespace ts {
|
||||
// All node tests in the following list should *not* reference parent pointers so that
|
||||
// they may be used with transformations.
|
||||
|
||||
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
|
||||
return node.kind === SyntaxKind.PropertyAccessExpression;
|
||||
// Node Arrays
|
||||
|
||||
export function isNodeArray<T extends Node>(array: T[]): array is NodeArray<T> {
|
||||
return (<NodeArray<T>>array).arrayKind === ArrayKind.NodeArray;
|
||||
}
|
||||
|
||||
export function isElementAccessExpression(node: Node): node is ElementAccessExpression {
|
||||
return node.kind === SyntaxKind.ElementAccessExpression;
|
||||
export function isModifiersArray(array: Modifier[]): array is ModifiersArray {
|
||||
return (<ModifiersArray>array).arrayKind === ArrayKind.ModifiersArray;
|
||||
}
|
||||
|
||||
function isBindingPatternKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.ArrayBindingPattern
|
||||
|| kind === SyntaxKind.ObjectBindingPattern;
|
||||
// Literals
|
||||
|
||||
export function isLiteralKind(kind: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
|
||||
}
|
||||
|
||||
export function isBindingPattern(node: Node): node is BindingPattern {
|
||||
return node && isBindingPatternKind(node.kind);
|
||||
export function isTextualLiteralKind(kind: SyntaxKind): boolean {
|
||||
return kind === SyntaxKind.StringLiteral || kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
export function isLiteralExpression(node: Node): node is LiteralExpression {
|
||||
return isLiteralKind(node.kind);
|
||||
}
|
||||
|
||||
// Pseudo-literals
|
||||
|
||||
export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
|
||||
}
|
||||
|
||||
function isTemplateLiteralFragmentKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.TemplateHead
|
||||
|| kind === SyntaxKind.TemplateMiddle
|
||||
|| kind === SyntaxKind.TemplateTail;
|
||||
}
|
||||
|
||||
export function isTemplateLiteralFragment(node: Node): node is TemplateLiteralFragment {
|
||||
return isTemplateLiteralFragmentKind(node.kind);
|
||||
}
|
||||
|
||||
// Identifiers
|
||||
|
||||
export function isIdentifier(node: Node): node is Identifier {
|
||||
return node.kind === SyntaxKind.Identifier;
|
||||
}
|
||||
|
||||
// Keywords
|
||||
|
||||
export function isModifier(node: Node): node is Modifier {
|
||||
return isModifierKind(node.kind);
|
||||
}
|
||||
|
||||
// Names
|
||||
|
||||
export function isQualifiedName(node: Node): node is QualifiedName {
|
||||
return node.kind === SyntaxKind.QualifiedName;
|
||||
}
|
||||
|
||||
export function isComputedPropertyName(node: Node): node is ComputedPropertyName {
|
||||
return node.kind === SyntaxKind.ComputedPropertyName;
|
||||
}
|
||||
|
||||
export function isEntityName(node: Node): node is EntityName {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.QualifiedName
|
||||
|| kind === SyntaxKind.Identifier;
|
||||
}
|
||||
|
||||
export function isPropertyName(node: Node): node is PropertyName {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| kind === SyntaxKind.StringLiteral
|
||||
|| kind === SyntaxKind.NumericLiteral
|
||||
|| kind === SyntaxKind.ComputedPropertyName;
|
||||
}
|
||||
|
||||
export function isModuleName(node: Node): node is ModuleName {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| kind === SyntaxKind.StringLiteral;
|
||||
}
|
||||
|
||||
export function isBindingName(node: Node): node is BindingName {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| kind === SyntaxKind.ObjectBindingPattern
|
||||
|| kind === SyntaxKind.ArrayBindingPattern;
|
||||
}
|
||||
|
||||
// Signature elements
|
||||
|
||||
export function isTypeParameter(node: Node): node is TypeParameterDeclaration {
|
||||
return node.kind === SyntaxKind.TypeParameter;
|
||||
}
|
||||
|
||||
export function isParameter(node: Node): node is ParameterDeclaration {
|
||||
return node.kind === SyntaxKind.Parameter;
|
||||
}
|
||||
|
||||
export function isDecorator(node: Node): node is Decorator {
|
||||
return node.kind === SyntaxKind.Decorator;
|
||||
}
|
||||
|
||||
// Type members
|
||||
|
||||
export function isClassElement(node: Node): node is ClassElement {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.Constructor
|
||||
@@ -2840,29 +2911,62 @@ namespace ts {
|
||||
|| kind === SyntaxKind.IndexSignature;
|
||||
}
|
||||
|
||||
export function isQualifiedName(node: Node): node is QualifiedName {
|
||||
return node.kind === SyntaxKind.QualifiedName;
|
||||
export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.PropertyAssignment
|
||||
|| kind === SyntaxKind.ShorthandPropertyAssignment
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor
|
||||
|| kind === SyntaxKind.MissingDeclaration;
|
||||
}
|
||||
|
||||
export function isLiteralExpression(node: Node): node is LiteralExpression {
|
||||
return isLiteralKind(node.kind);
|
||||
// Type
|
||||
|
||||
function isTypeNodeKind(kind: SyntaxKind) {
|
||||
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|
||||
|| kind === SyntaxKind.AnyKeyword
|
||||
|| kind === SyntaxKind.NumberKeyword
|
||||
|| kind === SyntaxKind.BooleanKeyword
|
||||
|| kind === SyntaxKind.StringKeyword
|
||||
|| kind === SyntaxKind.SymbolKeyword
|
||||
|| kind === SyntaxKind.VoidKeyword
|
||||
|| kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
}
|
||||
|
||||
function isEntityNameKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.QualifiedName
|
||||
|| kind === SyntaxKind.Identifier;
|
||||
/**
|
||||
* Node test that determines whether a node is a valid type node.
|
||||
* This differs from the `isPartOfTypeNode` function which determines whether a node is *part*
|
||||
* of a TypeNode.
|
||||
*/
|
||||
export function isTypeNode(node: Node): node is TypeNode {
|
||||
return isTypeNodeKind(node.kind);
|
||||
}
|
||||
|
||||
export function isEntityName(node: Node): node is EntityName {
|
||||
return isEntityNameKind(node.kind);
|
||||
// Binding patterns
|
||||
|
||||
export function isBindingPattern(node: Node): node is BindingPattern {
|
||||
if (node) {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ArrayBindingPattern
|
||||
|| kind === SyntaxKind.ObjectBindingPattern;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isIdentifier(node: Node): node is Identifier {
|
||||
return node.kind === SyntaxKind.Identifier;
|
||||
export function isBindingElement(node: Node): node is BindingElement {
|
||||
return node.kind === SyntaxKind.BindingElement;
|
||||
}
|
||||
|
||||
export function isComputedPropertyName(node: Node): node is ComputedPropertyName {
|
||||
return node.kind === SyntaxKind.ComputedPropertyName;
|
||||
// Expression
|
||||
|
||||
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
|
||||
return node.kind === SyntaxKind.PropertyAccessExpression;
|
||||
}
|
||||
|
||||
export function isElementAccessExpression(node: Node): node is ElementAccessExpression {
|
||||
return node.kind === SyntaxKind.ElementAccessExpression;
|
||||
}
|
||||
|
||||
export function isBinaryExpression(node: Node): node is BinaryExpression {
|
||||
@@ -2873,8 +2977,18 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.ConditionalExpression;
|
||||
}
|
||||
|
||||
export function isShortHandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
|
||||
return node.kind === SyntaxKind.ShorthandPropertyAssignment;
|
||||
export function isCallExpression(node: Node): node is CallExpression {
|
||||
return node.kind === SyntaxKind.CallExpression;
|
||||
}
|
||||
|
||||
export function isTemplate(node: Node): node is Template {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.TemplateExpression
|
||||
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
|
||||
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
}
|
||||
|
||||
function isLeftHandSideExpressionKind(kind: SyntaxKind) {
|
||||
@@ -2901,7 +3015,7 @@ namespace ts {
|
||||
|| kind === SyntaxKind.ThisKeyword
|
||||
|| kind === SyntaxKind.TrueKeyword
|
||||
|| kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
|
||||
return isLeftHandSideExpressionKind(node.kind);
|
||||
@@ -2937,32 +3051,70 @@ namespace ts {
|
||||
return isExpressionKind(node.kind);
|
||||
}
|
||||
|
||||
export function isDecorator(node: Node): node is Decorator {
|
||||
return node.kind === SyntaxKind.Decorator;
|
||||
// Misc
|
||||
|
||||
export function isTemplateSpan(node: Node): node is TemplateSpan {
|
||||
return node.kind === SyntaxKind.TemplateSpan;
|
||||
}
|
||||
|
||||
export function isModifier(node: Node): node is Modifier {
|
||||
return isModifierKind(node.kind);
|
||||
// Element
|
||||
|
||||
export function isBlock(node: Node): node is Block {
|
||||
return node.kind === SyntaxKind.Block;
|
||||
}
|
||||
|
||||
function isTypeNodeKind(kind: SyntaxKind) {
|
||||
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|
||||
|| kind === SyntaxKind.AnyKeyword
|
||||
|| kind === SyntaxKind.NumberKeyword
|
||||
|| kind === SyntaxKind.BooleanKeyword
|
||||
|| kind === SyntaxKind.StringKeyword
|
||||
|| kind === SyntaxKind.SymbolKeyword
|
||||
|| kind === SyntaxKind.VoidKeyword
|
||||
|| kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
export function isConciseBody(node: Node): node is ConciseBody {
|
||||
return isBlock(node)
|
||||
|| isExpression(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Node test that determines whether a node is a valid type node.
|
||||
* This differs from the `isPartOfTypeNode` function which determines whether a node is *part*
|
||||
* of a TypeNode.
|
||||
*/
|
||||
export function isTypeNode(node: Node): node is TypeNode {
|
||||
return isTypeNodeKind(node.kind);
|
||||
export function isFunctionBody(node: Node): node is FunctionBody {
|
||||
return isBlock(node);
|
||||
}
|
||||
|
||||
export function isForInitializer(node: Node): node is ForInitializer {
|
||||
return isVariableDeclarationList(node)
|
||||
|| isExpression(node);
|
||||
}
|
||||
|
||||
export function isVariableDeclaration(node: Node): node is VariableDeclaration {
|
||||
return node.kind === SyntaxKind.VariableDeclaration;
|
||||
}
|
||||
|
||||
export function isVariableDeclarationList(node: Node): node is VariableDeclarationList {
|
||||
return node.kind === SyntaxKind.VariableDeclarationList;
|
||||
}
|
||||
|
||||
export function isCaseBlock(node: Node): node is CaseBlock {
|
||||
return node.kind === SyntaxKind.CaseBlock;
|
||||
}
|
||||
|
||||
export function isModuleBody(node: Node): node is ModuleBody {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ModuleBlock
|
||||
|| kind === SyntaxKind.ModuleDeclaration;
|
||||
}
|
||||
|
||||
export function isImportClause(node: Node): node is ImportClause {
|
||||
return node.kind === SyntaxKind.ImportClause;
|
||||
}
|
||||
|
||||
export function isNamedImportBindings(node: Node): node is NamedImportBindings {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.NamedImports
|
||||
|| kind === SyntaxKind.NamespaceImport;
|
||||
}
|
||||
|
||||
export function isImportSpecifier(node: Node): node is ImportSpecifier {
|
||||
return node.kind === SyntaxKind.ImportSpecifier;
|
||||
}
|
||||
|
||||
export function isNamedExports(node: Node): node is NamedExports {
|
||||
return node.kind === SyntaxKind.NamedExports;
|
||||
}
|
||||
|
||||
export function isExportSpecifier(node: Node): node is ExportSpecifier {
|
||||
return node.kind === SyntaxKind.ExportSpecifier;
|
||||
}
|
||||
|
||||
function isDeclarationKind(kind: SyntaxKind) {
|
||||
@@ -2996,10 +3148,6 @@ namespace ts {
|
||||
|| kind === SyntaxKind.VariableDeclaration;
|
||||
}
|
||||
|
||||
export function isDeclaration(node: Node): node is Declaration {
|
||||
return isDeclarationKind(node.kind);
|
||||
}
|
||||
|
||||
function isDeclarationStatementKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.FunctionDeclaration
|
||||
|| kind === SyntaxKind.MissingDeclaration
|
||||
@@ -3013,10 +3161,6 @@ namespace ts {
|
||||
|| kind === SyntaxKind.ExportAssignment;
|
||||
}
|
||||
|
||||
export function isDeclarationStatement(node: Node): node is DeclarationStatement {
|
||||
return isDeclarationStatementKind(node.kind);
|
||||
}
|
||||
|
||||
function isStatementKindButNotDeclarationKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.BreakStatement
|
||||
|| kind === SyntaxKind.ContinueStatement
|
||||
@@ -3038,6 +3182,14 @@ namespace ts {
|
||||
|| kind === SyntaxKind.WithStatement;
|
||||
}
|
||||
|
||||
export function isDeclaration(node: Node): node is Declaration {
|
||||
return isDeclarationKind(node.kind);
|
||||
}
|
||||
|
||||
export function isDeclarationStatement(node: Node): node is DeclarationStatement {
|
||||
return isDeclarationStatementKind(node.kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the node is a statement that is not also a declaration
|
||||
*/
|
||||
@@ -3045,171 +3197,23 @@ namespace ts {
|
||||
return isStatementKindButNotDeclarationKind(node.kind);
|
||||
}
|
||||
|
||||
function isStatementKind(kind: SyntaxKind) {
|
||||
return isStatementKindButNotDeclarationKind(kind)
|
||||
|| isDeclarationStatementKind(kind);
|
||||
}
|
||||
|
||||
export function isStatement(node: Node): node is Statement {
|
||||
return isStatementKind(node.kind);
|
||||
const kind = node.kind;
|
||||
return isStatementKindButNotDeclarationKind(kind)
|
||||
|| isDeclarationStatementKind(kind)
|
||||
|| kind === SyntaxKind.Block;
|
||||
}
|
||||
|
||||
function isPropertyNameKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| kind === SyntaxKind.StringLiteral
|
||||
|| kind === SyntaxKind.NumericLiteral
|
||||
|| kind === SyntaxKind.ComputedPropertyName;
|
||||
}
|
||||
|
||||
export function isPropertyName(node: Node): node is PropertyName {
|
||||
return isPropertyNameKind(node.kind);
|
||||
}
|
||||
|
||||
function isConciseBodyKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.Block
|
||||
|| isExpressionKind(kind);
|
||||
}
|
||||
|
||||
export function isConciseBody(node: Node): node is ConciseBody {
|
||||
return isConciseBodyKind(node.kind);
|
||||
}
|
||||
|
||||
export function isTypeParameter(node: Node): node is TypeParameterDeclaration {
|
||||
return node.kind === SyntaxKind.TypeParameter;
|
||||
}
|
||||
|
||||
export function isParameter(node: Node): node is ParameterDeclaration {
|
||||
return node.kind === SyntaxKind.Parameter;
|
||||
}
|
||||
|
||||
export function isBindingElement(node: Node): node is BindingElement {
|
||||
return node.kind === SyntaxKind.BindingElement;
|
||||
}
|
||||
|
||||
function isObjectLiteralElementKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.PropertyAssignment
|
||||
|| kind === SyntaxKind.ShorthandPropertyAssignment
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor
|
||||
|| kind === SyntaxKind.MissingDeclaration;
|
||||
}
|
||||
|
||||
export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
|
||||
return isObjectLiteralElementKind(node.kind);
|
||||
}
|
||||
|
||||
function isTemplateKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.TemplateExpression
|
||||
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
|
||||
}
|
||||
|
||||
export function isTemplate(node: Node): node is Template {
|
||||
return isTemplateKind(node.kind);
|
||||
}
|
||||
|
||||
function isTemplateLiteralFragmentKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.TemplateHead
|
||||
|| kind === SyntaxKind.TemplateMiddle
|
||||
|| kind === SyntaxKind.TemplateTail;
|
||||
}
|
||||
|
||||
export function isTemplateLiteralFragment(node: Node): node is TemplateLiteralFragment {
|
||||
return isTemplateLiteralFragmentKind(node.kind);
|
||||
}
|
||||
|
||||
export function isTemplateSpan(node: Node): node is TemplateSpan {
|
||||
return node.kind === SyntaxKind.TemplateSpan;
|
||||
}
|
||||
|
||||
export function isHeritageClause(node: Node): node is HeritageClause {
|
||||
return node.kind === SyntaxKind.HeritageClause;
|
||||
}
|
||||
|
||||
export function isVariableDeclarationList(node: Node): node is VariableDeclarationList {
|
||||
return node.kind === SyntaxKind.VariableDeclarationList;
|
||||
}
|
||||
|
||||
function isForInitializerKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.VariableDeclarationList
|
||||
|| isExpressionKind(kind);
|
||||
}
|
||||
|
||||
export function isForInitializer(node: Node): node is ForInitializer {
|
||||
return isForInitializerKind(node.kind);
|
||||
}
|
||||
|
||||
export function isCaseBlock(node: Node): node is CaseBlock {
|
||||
return node.kind === SyntaxKind.CaseBlock;
|
||||
}
|
||||
|
||||
export function isBlock(node: Node): node is Block {
|
||||
return node.kind === SyntaxKind.Block;
|
||||
}
|
||||
|
||||
export function isCatchClause(node: Node): node is CatchClause {
|
||||
return node.kind === SyntaxKind.CatchClause;
|
||||
}
|
||||
|
||||
export function isVariableDeclaration(node: Node): node is VariableDeclaration {
|
||||
return node.kind === SyntaxKind.VariableDeclaration;
|
||||
}
|
||||
|
||||
export function isEnumMember(node: Node): node is EnumMember {
|
||||
return node.kind === SyntaxKind.EnumMember;
|
||||
}
|
||||
|
||||
function isModuleNameKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| kind === SyntaxKind.StringLiteral;
|
||||
}
|
||||
|
||||
export function isModuleName(node: Node): node is ModuleName {
|
||||
return isModuleNameKind(node.kind);
|
||||
}
|
||||
|
||||
function isCaseOrDefaultClauseKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.CaseClause
|
||||
|| kind === SyntaxKind.DefaultClause;
|
||||
}
|
||||
|
||||
export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause {
|
||||
return isCaseOrDefaultClauseKind(node.kind);
|
||||
}
|
||||
|
||||
function isModuleReferenceKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.ExternalModuleReference
|
||||
|| isEntityNameKind(kind);
|
||||
}
|
||||
// Module references
|
||||
|
||||
export function isModuleReference(node: Node): node is ModuleReference {
|
||||
return isModuleReferenceKind(node.kind);
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ExternalModuleReference
|
||||
|| kind === SyntaxKind.QualifiedName
|
||||
|| kind === SyntaxKind.Identifier;
|
||||
}
|
||||
|
||||
export function isImportClause(node: Node): node is ImportClause {
|
||||
return node.kind === SyntaxKind.ImportClause;
|
||||
}
|
||||
|
||||
function isNamedImportBindingsKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.NamedImports
|
||||
|| kind === SyntaxKind.NamespaceImport;
|
||||
}
|
||||
|
||||
export function isNamedImportBindings(node: Node): node is NamedImportBindings {
|
||||
return isNamedImportBindingsKind(node.kind);
|
||||
}
|
||||
|
||||
export function isImportSpecifier(node: Node): node is ImportSpecifier {
|
||||
return node.kind === SyntaxKind.ImportSpecifier;
|
||||
}
|
||||
|
||||
export function isNamedExports(node: Node): node is NamedExports {
|
||||
return node.kind === SyntaxKind.NamedExports;
|
||||
}
|
||||
|
||||
export function isExportSpecifier(node: Node): node is ExportSpecifier {
|
||||
return node.kind === SyntaxKind.ExportSpecifier;
|
||||
}
|
||||
// JSX
|
||||
|
||||
export function isJsxOpeningElement(node: Node): node is JsxOpeningElement {
|
||||
return node.kind === SyntaxKind.JsxOpeningElement;
|
||||
@@ -3219,59 +3223,56 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.JsxClosingElement;
|
||||
}
|
||||
|
||||
function isJsxChildKind(kind: SyntaxKind) {
|
||||
export function isJsxChild(node: Node): node is JsxChild {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.JsxElement
|
||||
|| kind === SyntaxKind.JsxExpression
|
||||
|| kind === SyntaxKind.JsxSelfClosingElement
|
||||
|| kind === SyntaxKind.JsxText;
|
||||
}
|
||||
|
||||
export function isJsxChild(node: Node): node is JsxChild {
|
||||
return isJsxChildKind(node.kind);
|
||||
}
|
||||
|
||||
function isJsxAttributeLikeKind(kind: SyntaxKind) {
|
||||
export function isJsxAttributeLike(node: Node): node is JsxAttributeLike {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.JsxAttribute
|
||||
|| kind === SyntaxKind.JsxSpreadAttribute;
|
||||
}
|
||||
|
||||
export function isJsxAttributeLike(node: Node): node is JsxAttributeLike {
|
||||
return isJsxAttributeLikeKind(node.kind);
|
||||
// Clauses
|
||||
|
||||
export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.CaseClause
|
||||
|| kind === SyntaxKind.DefaultClause;
|
||||
}
|
||||
|
||||
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
|
||||
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
export function isHeritageClause(node: Node): node is HeritageClause {
|
||||
return node.kind === SyntaxKind.HeritageClause;
|
||||
}
|
||||
|
||||
function isModuleBodyKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.ModuleBlock
|
||||
|| kind === SyntaxKind.ModuleDeclaration;
|
||||
export function isCatchClause(node: Node): node is CatchClause {
|
||||
return node.kind === SyntaxKind.CatchClause;
|
||||
}
|
||||
|
||||
export function isModuleBody(node: Node): node is ModuleBody {
|
||||
return isModuleBodyKind(node.kind);
|
||||
|
||||
// Property assignments
|
||||
|
||||
export function isShortHandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.ShorthandPropertyAssignment;
|
||||
}
|
||||
|
||||
function isBindingNameKind(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.Identifier
|
||||
|| isBindingPatternKind(kind);
|
||||
// Enum
|
||||
|
||||
export function isEnumMember(node: Node): node is EnumMember {
|
||||
return node.kind === SyntaxKind.EnumMember;
|
||||
}
|
||||
|
||||
export function isBindingName(node: Node): node is BindingName {
|
||||
return isBindingNameKind(node.kind);
|
||||
}
|
||||
|
||||
// Synthesized
|
||||
|
||||
export function isNodeArrayNode<T extends Node>(node: Node): node is NodeArrayNode<T> {
|
||||
return node.kind === SyntaxKind.NodeArrayNode;
|
||||
}
|
||||
|
||||
export function isNodeArray<T extends Node>(array: T[]): array is NodeArray<T> {
|
||||
return (<NodeArray<T>>array).arrayKind === ArrayKind.ModifiersArray;
|
||||
}
|
||||
|
||||
export function isModifiersArray(array: Modifier[]): array is ModifiersArray {
|
||||
return (<ModifiersArray>array).arrayKind === ArrayKind.ModifiersArray;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
|
||||
+116
-75
@@ -471,10 +471,10 @@ namespace ts {
|
||||
* @param node The Node to visit.
|
||||
* @param visitor The callback used to visit the Node.
|
||||
* @param test A callback to execute to verify the Node is valid.
|
||||
* @param lift A callback to execute to lift a NodeArrayNode into a valid Node.
|
||||
* @param optional A value indicating whether the Node is optional.
|
||||
* @param optional An optional value indicating whether the Node is itself optional.
|
||||
* @param lift An optional callback to execute to lift a NodeArrayNode into a valid Node.
|
||||
*/
|
||||
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => Node, test?: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T {
|
||||
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => Node, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -502,53 +502,53 @@ namespace ts {
|
||||
* @param nodes The NodeArray to visit.
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
* @param start An optional value indicating the starting offset at which to start visiting.
|
||||
* @param count An optional value indicating the maximum number of nodes to visit.
|
||||
*/
|
||||
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => Node, test?: (node: Node) => boolean, start?: number, count?: number): TArray;
|
||||
export function visitNodes<T extends Node, U extends Node>(nodes: T[], visitor: (node: T) => U): NodeArray<U>;
|
||||
export function visitNodes<T extends Node>(nodes: T[], visitor: (node: Node) => Node, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
|
||||
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => Node, test?: (node: Node) => boolean, start?: number, count?: number): TArray {
|
||||
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => Node, test: (node: Node) => boolean, start?: number, count?: number): TArray {
|
||||
if (nodes === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const len = nodes.length;
|
||||
start = start !== undefined ? Math.max(start, 0) : 0;
|
||||
count = count !== undefined ? Math.min(count, len - start) : len - start;
|
||||
|
||||
let updated: T[];
|
||||
if (start > 0 || count < len) {
|
||||
|
||||
// Ensure start and count have valid values
|
||||
const length = nodes.length;
|
||||
if (start === undefined || start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (count === undefined || count > length - start) {
|
||||
count = length - start;
|
||||
}
|
||||
|
||||
// If we are not visiting all of the original nodes, we must always create a new array.
|
||||
if (start > 0 || count < length) {
|
||||
updated = [];
|
||||
}
|
||||
|
||||
// Visit each original node.
|
||||
for (let i = 0; i < count; i++) {
|
||||
const node = nodes[i + start];
|
||||
if (node === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const visited = <OneOrMore<T>>visitor(node);
|
||||
const visited = node && <OneOrMore<T>>visitor(node);
|
||||
if (updated !== undefined || visited === undefined || visited !== node) {
|
||||
if (updated === undefined) {
|
||||
// Ensure we have a copy of `nodes`, up to the current index.
|
||||
updated = nodes.slice(0, i);
|
||||
}
|
||||
|
||||
if (visited === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (visited !== node) {
|
||||
aggregateTransformFlags(visited);
|
||||
visited.original = node;
|
||||
}
|
||||
|
||||
addNode(updated, visited, test);
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
if (updated !== undefined) {
|
||||
return <TArray>(isModifiersArray(nodes)
|
||||
? createModifiersArray(updated, /*location*/ nodes)
|
||||
: createNodeArray(updated, /*location*/ nodes));
|
||||
? createModifiersArray(updated, nodes)
|
||||
: createNodeArray(updated, nodes));
|
||||
}
|
||||
|
||||
return nodes;
|
||||
@@ -559,36 +559,40 @@ namespace ts {
|
||||
*
|
||||
* @param node The Node whose children will be visited.
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @param environment An optional lexical environment context for the visitor.
|
||||
* @param context A lexical environment context for the visitor.
|
||||
*/
|
||||
export function visitEachChild<T extends Node>(node: T, visitor: (node: Node) => Node, environment?: LexicalEnvironment): T {
|
||||
export function visitEachChild<T extends Node>(node: T, visitor: (node: Node) => Node, context: LexicalEnvironment): T;
|
||||
export function visitEachChild<T extends Node>(node: T & Map<any>, visitor: (node: Node) => Node, context: LexicalEnvironment): T {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const isNewLexicalEnvironment = environment !== undefined && nodeStartsNewLexicalEnvironment(node);
|
||||
let updated: T & Map<any>;
|
||||
|
||||
// If this node starts a new lexical environment, start a new lexical environment on the context.
|
||||
const isNewLexicalEnvironment = nodeStartsNewLexicalEnvironment(node);
|
||||
if (isNewLexicalEnvironment) {
|
||||
environment.startLexicalEnvironment();
|
||||
context.startLexicalEnvironment();
|
||||
}
|
||||
|
||||
let modifiers: NodeFlags;
|
||||
let updated: T & Map<any>;
|
||||
const edgeTraversalPath = nodeEdgeTraversalMap[node.kind];
|
||||
if (edgeTraversalPath) {
|
||||
for (const edge of edgeTraversalPath) {
|
||||
const value = (<Map<any>>node)[edge.name];
|
||||
const value = <Node | NodeArray<Node>>node[edge.name];
|
||||
if (value !== undefined) {
|
||||
const visited = visitEdge(edge, value, visitor);
|
||||
if (updated !== undefined || visited !== value) {
|
||||
if (updated === undefined) {
|
||||
updated = cloneNode(node, /*location*/ undefined, node.flags & ~NodeFlags.Modifier, /*parent*/ undefined, /*original*/ node);
|
||||
updated = cloneNode(node, /*location*/ node, node.flags & ~NodeFlags.Modifier, /*parent*/ undefined, /*original*/ node);
|
||||
}
|
||||
|
||||
updated[edge.name] = visited;
|
||||
}
|
||||
|
||||
if (visited && isArray(visited) && isModifiersArray(visited)) {
|
||||
modifiers = visited.flags;
|
||||
if (visited && isArray(visited) && isModifiersArray(visited)) {
|
||||
updated[edge.name] = visited;
|
||||
updated.flags |= visited.flags;
|
||||
}
|
||||
else {
|
||||
updated[edge.name] = visited;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,14 +601,11 @@ namespace ts {
|
||||
if (updated === undefined) {
|
||||
updated = node;
|
||||
}
|
||||
else if (modifiers) {
|
||||
updated.flags |= modifiers;
|
||||
}
|
||||
|
||||
if (isNewLexicalEnvironment) {
|
||||
const declarations = environment.endLexicalEnvironment();
|
||||
const declarations = context.endLexicalEnvironment();
|
||||
if (declarations !== undefined && declarations.length > 0) {
|
||||
updated = <T>mergeLexicalEnvironment(updated, declarations, /*nodeIsMutable*/ updated !== node);
|
||||
updated = <T>mergeLexicalEnvironment(updated, declarations);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,7 +626,7 @@ namespace ts {
|
||||
*/
|
||||
function visitEdge(edge: NodeEdge, value: Node | NodeArray<Node>, visitor: (node: Node) => Node) {
|
||||
return isArray(value)
|
||||
? visitNodes(<NodeArray<Node>>value, visitor, edge.test)
|
||||
? visitNodes(<NodeArray<Node>>value, visitor, edge.test, /*start*/ undefined, /*count*/ undefined)
|
||||
: visitNode(<Node>value, visitor, edge.test, edge.optional, edge.lift);
|
||||
}
|
||||
|
||||
@@ -665,72 +666,105 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Merge generated declarations of a lexical environment.
|
||||
*
|
||||
* @param node The source node.
|
||||
* @param declarations The generated lexical declarations.
|
||||
*/
|
||||
function mergeLexicalEnvironment(node: Node, declarations: Statement[], nodeIsMutable: boolean) {
|
||||
const mutableNode = nodeIsMutable ? node : cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
|
||||
function mergeLexicalEnvironment(node: Node, declarations: Statement[]): Node {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
mergeSourceFileLexicalEnvironment(<SourceFile>mutableNode, declarations);
|
||||
break;
|
||||
return mergeSourceFileLexicalEnvironment(<SourceFile>node, declarations);
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
mergeModuleDeclarationLexicalEnvironment(<ModuleDeclaration>mutableNode, declarations);
|
||||
break;
|
||||
return mergeModuleDeclarationLexicalEnvironment(<ModuleDeclaration>node, declarations);
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.Constructor:
|
||||
mergeFunctionLikeLexicalEnvironment(<FunctionLikeDeclaration>mutableNode, declarations);
|
||||
break;
|
||||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.Block:
|
||||
mergeBlockLexicalEnvironment(<Block>mutableNode, declarations);
|
||||
break;
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return mergeFunctionLikeLexicalEnvironment(<FunctionLikeDeclaration>node, declarations);
|
||||
}
|
||||
|
||||
return mutableNode;
|
||||
Debug.fail("Node is not a valid lexical environment.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge generated declarations of a lexical environment into a SourceFile.
|
||||
*
|
||||
* @param node The SourceFile node.
|
||||
* @param declarations The generated lexical declarations.
|
||||
*/
|
||||
function mergeSourceFileLexicalEnvironment(node: SourceFile, declarations: Statement[]) {
|
||||
node.statements = mergeStatements(node.statements, declarations);
|
||||
export function mergeSourceFileLexicalEnvironment(node: SourceFile, declarations: Statement[]) {
|
||||
if (declarations !== undefined && declarations.length) {
|
||||
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
|
||||
mutableNode.statements = mergeStatements(mutableNode.statements, declarations);
|
||||
return mutableNode;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge generated declarations of a lexical environment into a ModuleDeclaration.
|
||||
*
|
||||
* @param node The ModuleDeclaration node.
|
||||
* @param declarations The generated lexical declarations.
|
||||
*/
|
||||
function mergeModuleDeclarationLexicalEnvironment(node: ModuleDeclaration, declarations: Statement[]) {
|
||||
export function mergeModuleDeclarationLexicalEnvironment(node: ModuleDeclaration, declarations: Statement[]) {
|
||||
Debug.assert(node.body.kind === SyntaxKind.ModuleBlock);
|
||||
node.body = <ModuleBlock>mergeLexicalEnvironment(node.body, declarations, /*nodeIsMutable*/ false);
|
||||
if (declarations !== undefined && declarations.length) {
|
||||
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
|
||||
mutableNode.body = mergeBlockLexicalEnvironment(<ModuleBlock>node.body, declarations);
|
||||
return mutableNode;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge generated declarations of a lexical environment into a FunctionLikeDeclaration.
|
||||
*
|
||||
* @param node The function-like node.
|
||||
* @param declarations The generated lexical declarations.
|
||||
*/
|
||||
function mergeFunctionLikeLexicalEnvironment(node: FunctionLikeDeclaration, declarations: Statement[]) {
|
||||
Debug.assert(node.body !== undefined);
|
||||
node.body = mergeConciseBodyLexicalEnvironment(node.body, declarations);
|
||||
if (declarations !== undefined && declarations.length) {
|
||||
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
|
||||
mutableNode.body = mergeConciseBodyLexicalEnvironment(mutableNode.body, declarations);
|
||||
return mutableNode;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function mergeFunctionBodyLexicalEnvironment(body: FunctionBody, declarations: Statement[], nodeIsMutable?: boolean): FunctionBody {
|
||||
if (declarations && declarations.length > 0) {
|
||||
return <Block>mergeLexicalEnvironment(body, declarations, nodeIsMutable);
|
||||
/**
|
||||
* Merges generated lexical declarations into the FunctionBody of a non-arrow function-like declaration.
|
||||
*
|
||||
* @param node The ConciseBody of an arrow function.
|
||||
* @param declarations The lexical declarations to merge.
|
||||
*/
|
||||
export function mergeFunctionBodyLexicalEnvironment(body: FunctionBody, declarations: Statement[]) {
|
||||
if (declarations !== undefined && declarations.length > 0) {
|
||||
return mergeBlockLexicalEnvironment(body, declarations);
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
export function mergeConciseBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[], nodeIsMutable?: boolean): ConciseBody {
|
||||
if (declarations && declarations.length > 0) {
|
||||
/**
|
||||
* Merges generated lexical declarations into the ConciseBody of an ArrowFunction.
|
||||
*
|
||||
* @param node The ConciseBody of an arrow function.
|
||||
* @param declarations The lexical declarations to merge.
|
||||
*/
|
||||
export function mergeConciseBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[]) {
|
||||
if (declarations !== undefined && declarations.length > 0) {
|
||||
if (isBlock(body)) {
|
||||
return <Block>mergeLexicalEnvironment(body, declarations, nodeIsMutable);
|
||||
return mergeBlockLexicalEnvironment(body, declarations);
|
||||
}
|
||||
else {
|
||||
return createBlock([
|
||||
@@ -739,20 +773,27 @@ namespace ts {
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return body;
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge generated declarations of a lexical environment into a FunctionBody or ModuleBlock.
|
||||
*
|
||||
* @param node The block into which to merge lexical declarations.
|
||||
* @param declarations The lexical declarations to merge.
|
||||
*/
|
||||
function mergeBlockLexicalEnvironment(node: FunctionBody | ModuleBlock, declarations: Statement[]) {
|
||||
node.statements = mergeStatements(node.statements, declarations);
|
||||
function mergeBlockLexicalEnvironment<T extends Block>(node: T, declarations: Statement[]) {
|
||||
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
|
||||
mutableNode.statements = mergeStatements(node.statements, declarations);
|
||||
return mutableNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge generated declarations of a lexical environment into a NodeArray of Statement.
|
||||
*
|
||||
* @param statements The node array to concatentate with the supplied lexical declarations.
|
||||
* @param declarations The lexical declarations to merge.
|
||||
*/
|
||||
function mergeStatements(statements: NodeArray<Statement>, declarations: Statement[]) {
|
||||
return createNodeArray(concatenate(statements, declarations), /*location*/ statements);
|
||||
|
||||
Reference in New Issue
Block a user