From ecaaef33047b09bb1b4c5fc9e652d652994a799a Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Sun, 29 May 2022 00:50:50 +0200 Subject: [PATCH] more parser --- Makefile | 3 + src/CMakeLists.txt | 2 +- src/core.h | 32 + src/diagnostic_messages.h | 1 + src/node_factory.h | 2635 +++++++++++++++---------- src/node_test.h | 19 +- src/parser2.h | 3904 +++++++++++++++++++------------------ src/scanner.cpp | 1106 +++++++---- src/scanner.h | 41 +- src/tests/test_core.cpp | 18 + src/types.h | 109 +- src/utilities.h | 593 ++++-- 12 files changed, 4906 insertions(+), 3557 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..14eac4c --- /dev/null +++ b/Makefile @@ -0,0 +1,3 @@ + +xcode: + cd xcode && cmake -D CMAKE_C_COMPILER="`xcrun -find cc`" -D CMAKE_CXX_COMPILER="`xcrun -find c++`" .. -GXcode \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7ab2300..a854fc9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,4 +7,4 @@ add_subdirectory(tests) #add_library(typescript parser.cpp scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h parser2.h) add_library(typescript scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h parser2.h types.cpp node_test.h path.h node_factory.h) -#add_library(typescript scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h) \ No newline at end of file +#add_library(typescript scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h) diff --git a/src/core.h b/src/core.h index 0f81634..bde9907 100644 --- a/src/core.h +++ b/src/core.h @@ -33,6 +33,17 @@ namespace ts { return const_hash(s); } + string substr(const string &str, int start, int length) { + if (start < 0) start += str.length(); + if (length < 0) length = str.length() + length - start; + if (length < 0) return ""; + return str.substr(start, length); + } + + string substr(const string &str, int start) { + return substr(str, start, str.length()); + } + /** * shared_ptr has optional semantic already built-in, so we use it instead of std::optional, * but instead of using shared_ptr directly, we use opt to make it clear that it can be empty. @@ -64,12 +75,22 @@ namespace ts { return array.back(); } + template + T defaultTo(optional v, T def) { + if (v) return *v; + return def; + } + vector charToStringVector(vector chars) { vector s; for (auto c: chars) s.push_back(c); return s; } + bool startsWith(const string &str, const string &suffix) { + return str.find(suffix) == 0; + } + bool endsWith(const string &str, const string &suffix) { auto expectedPos = str.size() - suffix.size(); return expectedPos >= 0 && str.find(suffix, expectedPos) == expectedPos; @@ -235,6 +256,17 @@ namespace ts { return res; } + template + unordered_map reverse( + const unordered_map &map1 + ) { + unordered_map res; + for (auto &i: map1) { + res[i.second] = i.first; + } + return res; + } + template static optional get(unordered_map &m, K key) { auto v = m.find(key); diff --git a/src/diagnostic_messages.h b/src/diagnostic_messages.h index 591a7f7..ba5694a 100644 --- a/src/diagnostic_messages.h +++ b/src/diagnostic_messages.h @@ -123,6 +123,7 @@ namespace ts { static inline const auto String_literal_expected = diag(1141, DiagnosticCategory::Error, "String_literal_expected_1141", "String literal expected."); static inline const auto Line_break_not_permitted_here = diag(1142, DiagnosticCategory::Error, "Line_break_not_permitted_here_1142", "Line break not permitted here."); static inline const auto or_expected = diag(1144, DiagnosticCategory::Error, "or_expected_1144", "'{' or ';' expected."); + static inline const auto or_JSX_element_expected = diag(1145, DiagnosticCategory::Error, "or_JSX_element_expected_1145", "{' or JSX element expected."); static inline const auto Declaration_expected = diag(1146, DiagnosticCategory::Error, "Declaration_expected_1146", "Declaration expected."); static inline const auto Import_declarations_in_a_namespace_cannot_reference_a_module = diag(1147, DiagnosticCategory::Error, "Import_declarations_in_a_namespace_cannot_reference_a_module_1147", "Import declarations in a namespace cannot reference a module."); static inline const auto Cannot_use_imports_exports_or_module_augmentations_when_module_is_none = diag(1148, DiagnosticCategory::Error, "Cannot_use_imports_exports_or_module_augmentations_when_module_is_none_1148", "Cannot use imports, exports, or module augmentations when '--module' is 'none'."); diff --git a/src/node_factory.h b/src/node_factory.h index df5d691..d0e2328 100644 --- a/src/node_factory.h +++ b/src/node_factory.h @@ -1,10 +1,579 @@ #pragma once +#include + #include "types.h" #include "utilities.h" #include "scanner.h" #include "node_test.h" +namespace ts::factory { + shared createParenthesizedExpression(shared expression); +} + +namespace ts::parenthesizerRules { + using namespace ts; + using namespace ts::types; + +// +// function getParenthesizeLeftSideOfBinaryForOperator(operatorKind: BinaryOperator) { +// binaryLeftOperandParenthesizerCache ||= new Map(); +// let parenthesizerRule = binaryLeftOperandParenthesizerCache.get(operatorKind); +// if (!parenthesizerRule) { +// parenthesizerRule = node => parenthesizeLeftSideOfBinary(operatorKind, node); +// binaryLeftOperandParenthesizerCache.set(operatorKind, parenthesizerRule); +// } +// return parenthesizerRule; +// } +// +// function getParenthesizeRightSideOfBinaryForOperator(operatorKind: BinaryOperator) { +// binaryRightOperandParenthesizerCache ||= new Map(); +// let parenthesizerRule = binaryRightOperandParenthesizerCache.get(operatorKind); +// if (!parenthesizerRule) { +// parenthesizerRule = node => parenthesizeRightSideOfBinary(operatorKind, /*leftSide*/ undefined, node); +// binaryRightOperandParenthesizerCache.set(operatorKind, parenthesizerRule); +// } +// return parenthesizerRule; +// } +// +// /** +// * 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, leftOperand: Expression | undefined) { +// // 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` +// auto binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind::BinaryExpression, binaryOperator); +// auto binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind::BinaryExpression, binaryOperator); +// auto emittedOperand = skipPartiallyEmittedExpressions(operand); +// if (!isLeftSideOfBinary && operand.kind === SyntaxKind::ArrowFunction && binaryOperatorPrecedence > OperatorPrecedence.Assignment) { +// // We need to parenthesize arrow functions on the right side to avoid it being +// // parsed as parenthesized expression: `a && (() => {})` +// return true; +// } +// auto operandPrecedence = getExpressionPrecedence(emittedOperand); +// switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) { +// case Comparison.LessThan: +// // If the operand is the right side of a right-associative binary operation +// // and is a yield expression, then we do not need parentheses. +// if (!isLeftSideOfBinary +// && binaryOperatorAssociativity === Associativity.Right +// && operand.kind === SyntaxKind::YieldExpression) { +// return false; +// } +// +// return true; +// +// 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 +// return binaryOperatorAssociativity === Associativity.Right; +// } +// else { +// if (isBinaryExpression(emittedOperand) +// && emittedOperand.operatorToken.kind === binaryOperator) { +// // 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 (operatorHasAssociativeProperty(binaryOperator)) { +// return false; +// } +// +// // No need to parenthesize the right operand when the binary operator +// // is plus (+) if both the left and right operands consist solely of either +// // literals of the same kind or binary plus (+) expressions for literals of +// // the same kind (recursively). +// // "a"+(1+2) => "a"+(1+2) +// // "a"+("b"+"c") => "a"+"b"+"c" +// if (binaryOperator === SyntaxKind::PlusToken) { +// auto leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : SyntaxKind::Unknown; +// if (isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { +// 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) +// auto operandAssociativity = getExpressionAssociativity(emittedOperand); +// return operandAssociativity === Associativity.Left; +// } +// } +// } +// +// /** +// * Determines whether a binary operator is mathematically associative. +// * +// * @param binaryOperator The binary operator. +// */ +// function operatorHasAssociativeProperty(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; +// } +// +// /** +// * This function determines whether an expression consists of a homogeneous set of +// * literal expressions or binary plus expressions that all share the same literal kind. +// * It is used to determine whether the right-hand operand of a binary plus expression can be +// * emitted without parentheses. +// */ +// function getLiteralKindOfBinaryPlusOperand(node: Expression): SyntaxKind { +// node = skipPartiallyEmittedExpressions(node); +// +// if (isLiteralKind(node.kind)) { +// return node.kind; +// } +// +// if (node.kind === SyntaxKind::BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind::PlusToken) { +// if ((node as BinaryPlusExpression).cachedLiteralKind !== undefined) { +// return (node as BinaryPlusExpression).cachedLiteralKind; +// } +// +// auto leftKind = getLiteralKindOfBinaryPlusOperand((node as BinaryExpression).left); +// auto literalKind = isLiteralKind(leftKind) +// && leftKind === getLiteralKindOfBinaryPlusOperand((node as BinaryExpression).right) +// ? leftKind +// : SyntaxKind::Unknown; +// +// (node as BinaryPlusExpression).cachedLiteralKind = literalKind; +// return literalKind; +// } +// +// return SyntaxKind::Unknown; +// } +// +// /** +// * 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, leftOperand?: Expression) { +// auto skipped = skipPartiallyEmittedExpressions(operand); +// +// // If the resulting expression is already parenthesized, we do not need to do any further processing. +// if (skipped.kind === SyntaxKind::ParenthesizedExpression) { +// return operand; +// } +// +// return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand) +// ? factory::createParenthesizedExpression(operand) +// : operand; +// } +// +// +// function parenthesizeLeftSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression): Expression { +// return parenthesizeBinaryOperand(binaryOperator, leftSide, /*isLeftSideOfBinary*/ true); +// } +// +// function parenthesizeRightSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression | undefined, rightSide: Expression): Expression { +// return parenthesizeBinaryOperand(binaryOperator, rightSide, /*isLeftSideOfBinary*/ false, leftSide); +// } + + shared parenthesizeExpressionOfComputedPropertyName(shared expression) { + return isCommaSequence(expression) ? factory::createParenthesizedExpression(expression) : expression; + } +// +// function parenthesizeConditionOfConditionalExpression(condition: Expression): Expression { +// auto conditionalPrecedence = getOperatorPrecedence(SyntaxKind::ConditionalExpression, SyntaxKind::QuestionToken); +// auto emittedCondition = skipPartiallyEmittedExpressions(condition); +// auto conditionPrecedence = getExpressionPrecedence(emittedCondition); +// if (compareValues(conditionPrecedence, conditionalPrecedence) !== Comparison.GreaterThan) { +// return factory::createParenthesizedExpression(condition); +// } +// return condition; +// } +// +// function parenthesizeBranchOfConditionalExpression(branch: Expression): Expression { +// // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions +// // so in case when comma expression is introduced as a part of previous transformations +// // if should be wrapped in parens since comma operator has the lowest precedence +// auto emittedExpression = skipPartiallyEmittedExpressions(branch); +// return isCommaSequence(emittedExpression) +// ? factory::createParenthesizedExpression(branch) +// : branch; +// } +// +// /** +// * [Per the spec](https://tc39.github.io/ecma262/#prod-ExportDeclaration), `export default` accepts _AssigmentExpression_ but +// * has a lookahead restriction for `function`, `async function`, and `class`. +// * +// * Basically, that means we need to parenthesize in the following cases: +// * +// * - BinaryExpression of CommaToken +// * - CommaList (synthetic list of multiple comma expressions) +// * - FunctionExpression +// * - ClassExpression +// */ +// function parenthesizeExpressionOfExportDefault(expression: Expression): Expression { +// auto check = skipPartiallyEmittedExpressions(expression); +// let needsParens = isCommaSequence(check); +// if (!needsParens) { +// switch (getLeftmostExpression(check, /*stopAtCallExpression*/ false).kind) { +// case SyntaxKind::ClassExpression: +// case SyntaxKind::FunctionExpression: +// needsParens = true; +// } +// } +// return needsParens ? factory::createParenthesizedExpression(expression) : expression; +// } +// +// /** +// * Wraps an expression in parentheses if it is needed in order to use the expression +// * as the expression of a `NewExpression` node. +// */ +// function parenthesizeExpressionOfNew(expression: Expression): LeftHandSideExpression { +// auto leftmostExpr = getLeftmostExpression(expression, /*stopAtCallExpressions*/ true); +// switch (leftmostExpr.kind) { +// case SyntaxKind::CallExpression: +// return factory::createParenthesizedExpression(expression); +// +// case SyntaxKind::NewExpression: +// return !(leftmostExpr as NewExpression).arguments +// ? factory::createParenthesizedExpression(expression) +// : expression as LeftHandSideExpression; // TODO(rbuckton): Verify this assertion holds +// } +// +// return parenthesizeLeftSideOfAccess(expression); +// } +// +// /** +// * Wraps an expression in parentheses if it is needed in order to use the expression for +// * property or element access. +// */ + shared parenthesizeLeftSideOfAccess(shared expression) { + // isLeftHandSideExpression is almost the correct criterion for when it is not necessary + // to parenthesize the expression before a dot. The known exception is: + // + // NewExpression: + // new C.x -> not the same as (new C).x + // + auto emittedExpression = skipPartiallyEmittedExpressions(expression); + if (isLeftHandSideExpression(emittedExpression) + && (emittedExpression->kind != SyntaxKind::NewExpression || emittedExpression->to().arguments)) { + // TODO(rbuckton): Verify whether this assertion holds. + return dynamic_pointer_cast(expression); + } + + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return setTextRange(factory::createParenthesizedExpression(expression), expression); + } +// +// function parenthesizeOperandOfPostfixUnary(operand: Expression): LeftHandSideExpression { +// // TODO(rbuckton): Verifiy whether `setTextRange` is needed. +// return isLeftHandSideExpression(operand) ? operand : setTextRange(factory::createParenthesizedExpression(operand), operand); +// } + + shared parenthesizeOperandOfPrefixUnary(shared operand) { + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return isUnaryExpression(operand) ? operand : setTextRange(factory::createParenthesizedExpression(operand), operand); + } + +// function parenthesizeExpressionsOfCommaDelimitedList(elements: NodeArray): NodeArray { +// auto result = sameMap(elements, parenthesizeExpressionForDisallowedComma); +// return setTextRange(factory::createNodeArray(result, elements.hasTrailingComma), elements); +// } + + shared parenthesizeExpressionForDisallowedComma(shared expression) { + auto emittedExpression = skipPartiallyEmittedExpressions(expression); + auto expressionPrecedence = getExpressionPrecedence(emittedExpression); + auto commaPrecedence = getOperatorPrecedence(SyntaxKind::BinaryExpression, SyntaxKind::CommaToken); + // TODO(rbuckton): Verifiy whether `setTextRange` is needed. + return expressionPrecedence > commaPrecedence ? expression : setTextRange(factory::createParenthesizedExpression(expression), expression); + } + +// function parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression { +// auto emittedExpression = skipPartiallyEmittedExpressions(expression); +// if (isCallExpression(emittedExpression)) { +// auto callee = emittedExpression.expression; +// auto kind = skipPartiallyEmittedExpressions(callee).kind; +// if (kind === SyntaxKind::FunctionExpression || kind === SyntaxKind::ArrowFunction) { +// // TODO(rbuckton): Verifiy whether `setTextRange` is needed. +// auto updated = factory::updateCallExpression( +// emittedExpression, +// setTextRange(factory::createParenthesizedExpression(callee), callee), +// emittedExpression.typeArguments, +// emittedExpression.arguments +// ); +// return factory::restoreOuterExpressions(expression, updated, OuterExpressionKinds.PartiallyEmittedExpressions); +// } +// } +// +// auto leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; +// if (leftmostExpressionKind === SyntaxKind::ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind::FunctionExpression) { +// // TODO(rbuckton): Verifiy whether `setTextRange` is needed. +// return setTextRange(factory::createParenthesizedExpression(expression), expression); +// } +// +// return expression; +// } +// +// function parenthesizeConciseBodyOfArrowFunction(body: Expression): Expression; +// function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody; +// function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody { +// if (!isBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind::ObjectLiteralExpression)) { +// // TODO(rbuckton): Verifiy whether `setTextRange` is needed. +// return setTextRange(factory::createParenthesizedExpression(body), body); +// } +// +// return body; +// } +// +// // Type[Extends] : +// // FunctionOrConstructorType +// // ConditionalType[?Extends] +// +// // ConditionalType[Extends] : +// // UnionType[?Extends] +// // [~Extends] UnionType[~Extends] `extends` Type[+Extends] `?` Type[~Extends] `:` Type[~Extends] +// // +// // - The check type (the `UnionType`, above) does not allow function, constructor, or conditional types (they must be parenthesized) +// // - The extends type (the first `Type`, above) does not allow conditional types (they must be parenthesized). Function and constructor types are fine. +// // - The true and false branch types (the second and third `Type` non-terminals, above) allow any type +// function parenthesizeCheckTypeOfConditionalType(checkType: TypeNode): TypeNode { +// switch (checkType.kind) { +// case SyntaxKind::FunctionType: +// case SyntaxKind::ConstructorType: +// case SyntaxKind::ConditionalType: +// return factory::createParenthesizedType(checkType); +// } +// return checkType; +// } +// +// function parenthesizeExtendsTypeOfConditionalType(extendsType: TypeNode): TypeNode { +// switch (extendsType.kind) { +// case SyntaxKind::ConditionalType: +// return factory::createParenthesizedType(extendsType); +// } +// return extendsType; +// } +// +// // UnionType[Extends] : +// // `|`? IntersectionType[?Extends] +// // UnionType[?Extends] `|` IntersectionType[?Extends] +// // +// // - A union type constituent has the same precedence as the check type of a conditional type +// function parenthesizeConstituentTypeOfUnionType(type: TypeNode) { +// switch (type.kind) { +// case SyntaxKind::UnionType: // Not strictly necessary, but a union containing a union should have been flattened +// case SyntaxKind::IntersectionType: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests +// return factory::createParenthesizedType(type); +// } +// return parenthesizeCheckTypeOfConditionalType(type); +// } +// +// function parenthesizeConstituentTypesOfUnionType(members: readonly TypeNode[]): NodeArray { +// return factory::createNodeArray(sameMap(members, parenthesizeConstituentTypeOfUnionType)); +// } +// +// // IntersectionType[Extends] : +// // `&`? TypeOperator[?Extends] +// // IntersectionType[?Extends] `&` TypeOperator[?Extends] +// // +// // - An intersection type constituent does not allow function, constructor, conditional, or union types (they must be parenthesized) +// function parenthesizeConstituentTypeOfIntersectionType(type: TypeNode) { +// switch (type.kind) { +// case SyntaxKind::UnionType: +// case SyntaxKind::IntersectionType: // Not strictly necessary, but an intersection containing an intersection should have been flattened +// return factory::createParenthesizedType(type); +// } +// return parenthesizeConstituentTypeOfUnionType(type); +// } +// +// function parenthesizeConstituentTypesOfIntersectionType(members: readonly TypeNode[]): NodeArray { +// return factory::createNodeArray(sameMap(members, parenthesizeConstituentTypeOfIntersectionType)); +// } +// +// // TypeOperator[Extends] : +// // PostfixType +// // InferType[?Extends] +// // `keyof` TypeOperator[?Extends] +// // `unique` TypeOperator[?Extends] +// // `readonly` TypeOperator[?Extends] +// // +// function parenthesizeOperandOfTypeOperator(type: TypeNode) { +// switch (type.kind) { +// case SyntaxKind::IntersectionType: +// return factory::createParenthesizedType(type); +// } +// return parenthesizeConstituentTypeOfIntersectionType(type); +// } +// +// function parenthesizeOperandOfReadonlyTypeOperator(type: TypeNode) { +// switch (type.kind) { +// case SyntaxKind::TypeOperator: +// return factory::createParenthesizedType(type); +// } +// return parenthesizeOperandOfTypeOperator(type); +// } +// +// // PostfixType : +// // NonArrayType +// // NonArrayType [no LineTerminator here] `!` // JSDoc +// // NonArrayType [no LineTerminator here] `?` // JSDoc +// // IndexedAccessType +// // ArrayType +// // +// // IndexedAccessType : +// // NonArrayType `[` Type[~Extends] `]` +// // +// // ArrayType : +// // NonArrayType `[` `]` +// // +// function parenthesizeNonArrayTypeOfPostfixType(type: TypeNode) { +// switch (type.kind) { +// case SyntaxKind::InferType: +// case SyntaxKind::TypeOperator: +// case SyntaxKind::TypeQuery: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests +// return factory::createParenthesizedType(type); +// } +// return parenthesizeOperandOfTypeOperator(type); +// } +// +// // TupleType : +// // `[` Elision? `]` +// // `[` NamedTupleElementTypes `]` +// // `[` NamedTupleElementTypes `,` Elision? `]` +// // `[` TupleElementTypes `]` +// // `[` TupleElementTypes `,` Elision? `]` +// // +// // NamedTupleElementTypes : +// // Elision? NamedTupleMember +// // NamedTupleElementTypes `,` Elision? NamedTupleMember +// // +// // NamedTupleMember : +// // Identifier `?`? `:` Type[~Extends] +// // `...` Identifier `:` Type[~Extends] +// // +// // TupleElementTypes : +// // Elision? TupleElementType +// // TupleElementTypes `,` Elision? TupleElementType +// // +// // TupleElementType : +// // Type[~Extends] // NOTE: Needs cover grammar to disallow JSDoc postfix-optional +// // OptionalType +// // RestType +// // +// // OptionalType : +// // Type[~Extends] `?` // NOTE: Needs cover grammar to disallow JSDoc postfix-optional +// // +// // RestType : +// // `...` Type[~Extends] +// // +// function parenthesizeElementTypesOfTupleType(types: readonly (TypeNode | NamedTupleMember)[]): NodeArray { +// return factory::createNodeArray(sameMap(types, parenthesizeElementTypeOfTupleType)); +// } +// +// function parenthesizeElementTypeOfTupleType(type: TypeNode | NamedTupleMember): TypeNode { +// if (hasJSDocPostfixQuestion(type)) return factory::createParenthesizedType(type); +// return type; +// } +// +// function hasJSDocPostfixQuestion(type: TypeNode | NamedTupleMember): boolean { +// if (isJSDocNullableType(type)) return type.postfix; +// if (isNamedTupleMember(type)) return hasJSDocPostfixQuestion(type.type); +// if (isFunctionTypeNode(type) || isConstructorTypeNode(type) || isTypeOperatorNode(type)) return hasJSDocPostfixQuestion(type.type); +// if (isConditionalTypeNode(type)) return hasJSDocPostfixQuestion(type.falseType); +// if (isUnionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types)); +// if (isIntersectionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types)); +// if (isInferTypeNode(type)) return !!type.typeParameter.constraint && hasJSDocPostfixQuestion(type.typeParameter.constraint); +// return false; +// } +// +// function parenthesizeTypeOfOptionalType(type: TypeNode): TypeNode { +// if (hasJSDocPostfixQuestion(type)) return factory::createParenthesizedType(type); +// return parenthesizeNonArrayTypeOfPostfixType(type); +// } +// +// // function parenthesizeMemberOfElementType(member: TypeNode): TypeNode { +// // switch (member.kind) { +// // case SyntaxKind::UnionType: +// // case SyntaxKind::IntersectionType: +// // case SyntaxKind::FunctionType: +// // case SyntaxKind::ConstructorType: +// // return factory::createParenthesizedType(member); +// // } +// // return parenthesizeMemberOfConditionalType(member); +// // } +// +// // function parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode { +// // switch (member.kind) { +// // case SyntaxKind::TypeQuery: +// // case SyntaxKind::TypeOperator: +// // case SyntaxKind::InferType: +// // return factory::createParenthesizedType(member); +// // } +// // return parenthesizeMemberOfElementType(member); +// // } +// +// function parenthesizeLeadingTypeArgument(node: TypeNode) { +// return isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory::createParenthesizedType(node) : node; +// } +// +// function parenthesizeOrdinalTypeArgument(node: TypeNode, i: number) { +// return i === 0 ? parenthesizeLeadingTypeArgument(node) : node; +// } +// +// function parenthesizeTypeArguments(typeArguments: NodeArray | undefined): NodeArray | undefined { +// if (some(typeArguments)) { +// return factory::createNodeArray(sameMap(typeArguments, parenthesizeOrdinalTypeArgument)); +// } +// } +} + namespace ts::factory { int nextAutoGenerateId = 0; @@ -15,9 +584,9 @@ namespace ts::factory { /* @internal */ enum class NodeFactoryFlags { None = 0, - // Disables the parenthesizer rules for the factory. + // Disables the parenthesizer rules for the factory:: NoParenthesizerRules = 1 << 0, - // Disables the node converters for the factory. + // Disables the node converters for the factory:: NoNodeConverters = 1 << 1, // Ensures new `PropertyAccessExpression` nodes are created with the `NoIndentation` emit flag set. NoIndentationOnFreshPropertyAccess = 1 << 2, @@ -25,7 +594,7 @@ namespace ts::factory { NoOriginalNode = 1 << 3, }; - int propagatePropertyNameFlagsOfChild(auto shared &node, int transformFlags) { + int propagatePropertyNameFlagsOfChild(shared &node, int transformFlags) { return transformFlags | (node->transformFlags & (int) TransformFlags::PropertyNamePropagatingFlags); } @@ -37,9 +606,9 @@ namespace ts::factory { return name ? propagatePropertyNameFlagsOfChild(name, childFlags) : childFlags; } - int propagateIdentifierNameFlags(shared node) { + int propagateIdentifierNameFlags(shared node) { // An IdentifierName is allowed to be `await` - return propagateChildFlags(node) & ~ (int) TransformFlags::ContainsPossibleTopLevelAwait; + return propagateChildFlags(std::move(node)) & ~ (int) TransformFlags::ContainsPossibleTopLevelAwait; } int propagateChildrenFlags(optional children) { @@ -54,23 +623,7 @@ namespace ts::factory { children.transformFlags = subtreeFlags; } - // @api - NodeArray createNodeArray(auto vector> &elements, bool hasTrailingComma = false) { - // Since the element list of a node array is typically created by starting with an empty array and - // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for - // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. -// auto length = elements.length; - NodeArray array; - for (auto node: elements) array.list.push_back(node); -// auto array = (length >= 1 && length <= 4 ? elements.slice() : elements) as MutableNodeArray; - setTextRangePosEnd(array, - 1, - 1); - array.hasTrailingComma = hasTrailingComma; - aggregateChildrenFlags(array); -// Debug.attachNodeArrayDebugInfo(array); - return array; - } - - NodeArray createNodeArray(NodeArray &elements, optional hasTrailingComma = {}) { + NodeArray createNodeArray(NodeArray elements, optional hasTrailingComma = {}) { if (! hasTrailingComma || elements.hasTrailingComma == hasTrailingComma) { // Ensure the transform flags have been aggregated for this NodeArray if (elements.transformFlags == (int) types::TransformFlags::None) { @@ -86,12 +639,50 @@ namespace ts::factory { NodeArray array = elements; array.pos = elements.pos; array.end = elements.end; - array.hasTrailingComma = hasTrailingComma ? *hasTrailingComma : false; + array.hasTrailingComma = *hasTrailingComma; array.transformFlags = elements.transformFlags; // Debug.attachNodeArrayDebugInfo(array); return array; } + optional asNodeArray(optional array) { + return array; + } + + template + NodeArray asNodeArray(vector> array) { + NodeArray nodeArray; + for (auto node: array) nodeArray.list.push_back(node); + return nodeArray; + } + + template + optional asNodeArray(optional>> array) { + if (! array) return nullopt; + + return asNodeArray(*array); + } + + shared createIdentifier(string text, optional typeArguments = {}, optional originalKeywordKind = {}); + + shared asName(variant> name = {}) { + if (holds_alternative(name)) return createIdentifier(get(name)); + return get>(name); + } + + sharedOpt asName(optional>> name = {}) { + if (! name) return nullptr; + return asName(*name); + } + + // @api + NodeArray createNodeArray(vector> elements, optional hasTrailingComma = {}) { + // Since the element list of a node array is typically created by starting with an empty array and + // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for + // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. + return createNodeArray(asNodeArray(elements), hasTrailingComma); + } + template shared createBaseNode() { auto node = make_shared(); @@ -112,66 +703,68 @@ namespace ts::factory { } // function createBaseNode(kind: T["kind"]) { -// return baseFactory.createBaseNode(kind) as Mutable; -// } -// -// function createBaseDeclaration( -// kind: T["kind"], -// decorators: readonly Decorator[] | undefined, -// modifiers: readonly Modifier[] | undefined -// ) { -// auto node = createBaseNode(kind); -// node.decorators = asNodeArray(decorators); -// node.modifiers = asNodeArray(modifiers); -// node.transformFlags |= -// propagateChildrenFlags(node.decorators) | -// propagateChildrenFlags(node.modifiers); -// // NOTE: The following properties are commonly set by the binder and are added here to -// // ensure declarations have a stable shape. -// node.symbol = undefined!; // initialized by binder -// node.localSymbol = undefined; // initialized by binder -// node.locals = undefined; // initialized by binder -// node.nextContainer = undefined; // initialized by binder -// return node; -// } -// -// function createBaseNamedDeclaration( -// kind: T["kind"], -// decorators: readonly Decorator[] | undefined, -// modifiers: readonly Modifier[] | undefined, -// name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined -// ) { -// auto node = createBaseDeclaration( -// kind, -// decorators, -// modifiers -// ); -// name = asName(name); -// node.name = name; -// -// // The PropertyName of a member is allowed to be `await`. -// // We don't need to exclude `await` for type signatures since types -// // don't propagate child flags. -// if (name) { -// switch (node.kind) { -// case SyntaxKind::MethodDeclaration: -// case SyntaxKind::GetAccessor: -// case SyntaxKind::SetAccessor: -// case SyntaxKind::PropertyDeclaration: -// case SyntaxKind::PropertyAssignment: -// if (isIdentifier(name)) { -// node.transformFlags |= propagateIdentifierNameFlags(name); -// break; -// } -// // fall through -// default: -// node.transformFlags |= propagateChildFlags(name); -// break; -// } -// } -// return node; +// return basefactory::createBaseNode(kind) as Mutable; // } // + template + shared createBaseDeclaration( + SyntaxKind kind, + optional>> decorators = {}, + optional>> modifiers = {} + ) { + auto node = createBaseNode(kind); + node->decorators = asNodeArray(decorators); + node->modifiers = asNodeArray(modifiers); + node->transformFlags |= + propagateChildrenFlags(node->decorators) | + propagateChildrenFlags(node->modifiers); + // NOTE: The following properties are commonly set by the binder and are added here to + // ensure declarations have a stable shape. +// node->symbol = undefined!; // initialized by binder +// node->localSymbol = undefined; // initialized by binder +// node->locals = undefined; // initialized by binder +// node->nextContainer = undefined; // initialized by binder + return node; + } + + template + shared createBaseNamedDeclaration( + SyntaxKind kind, + optional>> decorators = {}, + optional>> modifiers = {}, + optional>> _name = {} + ) { + auto node = createBaseDeclaration( + kind, + decorators, + modifiers + ); + auto name = asName(_name); + node->name = name; + + // The PropertyName of a member is allowed to be `await`. + // We don't need to exclude `await` for type signatures since types + // don't propagate child flags. + if (name) { + switch (node->kind) { + case SyntaxKind::MethodDeclaration: + case SyntaxKind::GetAccessor: + case SyntaxKind::SetAccessor: + case SyntaxKind::PropertyDeclaration: + case SyntaxKind::PropertyAssignment: + if (isIdentifier(name)) { + node->transformFlags |= propagateIdentifierNameFlags(name); + break; + } + // fall through + default: + node->transformFlags |= propagateChildFlags(name); + break; + } + } + return node; + } + // function createBaseGenericNamedDeclaration }>( // kind: T["kind"], // decorators: readonly Decorator[] | undefined, @@ -185,8 +778,8 @@ namespace ts::factory { // modifiers, // name // ); -// node.typeParameters = asNodeArray(typeParameters); -// node.transformFlags |= propagateChildrenFlags(node.typeParameters); +// node->typeParameters = asNodeArray(typeParameters); +// node->transformFlags |= propagateChildrenFlags(node.typeParameters); // if (typeParameters) node.transformFlags |= TransformFlags::ContainsTypeScript; // return node; // } @@ -207,9 +800,9 @@ namespace ts::factory { // name, // typeParameters // ); -// node.parameters = createNodeArray(parameters); -// node.type = type; -// node.transformFlags |= +// node->parameters = createNodeArray(parameters); +// node->type = type; +// node->transformFlags |= // propagateChildrenFlags(node.parameters) | // propagateChildFlags(node.type); // if (type) node.transformFlags |= TransformFlags::ContainsTypeScript; @@ -241,8 +834,8 @@ namespace ts::factory { // parameters, // type // ); -// node.body = body; -// node.transformFlags |= propagateChildFlags(node.body) & ~TransformFlags::ContainsPossibleTopLevelAwait; +// node->body = body; +// node->transformFlags |= propagateChildFlags(node.body) & ~TransformFlags::ContainsPossibleTopLevelAwait; // if (!body) node.transformFlags |= TransformFlags::ContainsTypeScript; // return node; // } @@ -269,8 +862,8 @@ namespace ts::factory { // name, // typeParameters // ); -// node.heritageClauses = asNodeArray(heritageClauses); -// node.transformFlags |= propagateChildrenFlags(node.heritageClauses); +// node->heritageClauses = asNodeArray(heritageClauses); +// node->transformFlags |= propagateChildrenFlags(node.heritageClauses); // return node; // } // @@ -291,29 +884,30 @@ namespace ts::factory { // typeParameters, // heritageClauses // ); -// node.members = createNodeArray(members); -// node.transformFlags |= propagateChildrenFlags(node.members); +// node->members = createNodeArray(members); +// node->transformFlags |= propagateChildrenFlags(node.members); // return node; // } -// -// function createBaseBindingLikeDeclaration( -// kind: T["kind"], -// decorators: readonly Decorator[] | undefined, -// modifiers: readonly Modifier[] | undefined, -// name: string | T["name"] | undefined, -// initializer: Expression | undefined -// ) { -// auto node = createBaseNamedDeclaration( -// kind, -// decorators, -// modifiers, -// name -// ); -// node.initializer = initializer; -// node.transformFlags |= propagateChildFlags(node.initializer); -// return node; -// } -// + + template + shared createBaseBindingLikeDeclaration( + SyntaxKind kind, + optional>> decorators = {}, + optional>> modifiers = {}, + optional>> name = {}, + sharedOpt initializer = {} + ) { + auto node = createBaseNamedDeclaration( + kind, + decorators, + modifiers, + name + ); + node->initializer = initializer; + node->transformFlags |= propagateChildFlags(node->initializer); + return node; + } + // function createBaseVariableLikeDeclaration( // kind: T["kind"], // decorators: readonly Decorator[] | undefined, @@ -329,80 +923,112 @@ namespace ts::factory { // name, // initializer // ); -// node.type = type; -// node.transformFlags |= propagateChildFlags(type); +// node->type = type; +// node->transformFlags |= propagateChildFlags(type); // if (type) node.transformFlags |= TransformFlags::ContainsTypeScript; // return node; // } -// -// // -// // Literals -// // -// -// function createBaseLiteral( -// kind: T["kind"], -// text: string -// ) { -// auto node = createBaseToken(kind); -// node.text = text; -// return node; -// } -// -// // @api -// function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { -// auto node = createBaseLiteral(SyntaxKind::NumericLiteral, typeof value == "number" ? value + "" : value); -// node.numericLiteralFlags = numericLiteralFlags; -// if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= TransformFlags::ContainsES2015; -// return node; -// } -// -// // @api -// function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral { -// auto node = createBaseLiteral(SyntaxKind::BigIntLiteral, typeof value == "string" ? value : pseudoBigIntToString(value) + "n"); -// node.transformFlags |= TransformFlags::ContainsESNext; -// return node; -// } -// -// function createBaseStringLiteral(text: string, isSingleQuote?: boolean) { -// auto node = createBaseLiteral(SyntaxKind::StringLiteral, text); -// node.singleQuote = isSingleQuote; -// return node; -// } -// -// // @api -// function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral { -// auto node = createBaseStringLiteral(text, isSingleQuote); -// node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; -// if (hasExtendedUnicodeEscape) node.transformFlags |= TransformFlags::ContainsES2015; -// return node; -// } -// + + // + // Literals + // + + template + shared createBaseLiteral(SyntaxKind kind, string text) { + auto node = createBaseToken(kind); + node->text = text; + return node; + } + + // @api + shared createNumericLiteral(string value, int numericLiteralFlags = (int) types::TokenFlags::None) { + auto node = createBaseLiteral(SyntaxKind::NumericLiteral, std::move(value)); + node->numericLiteralFlags = numericLiteralFlags; + if (numericLiteralFlags & TokenFlags::BinaryOrOctalSpecifier) node->transformFlags |= (int) TransformFlags::ContainsES2015; + return node; + } + + shared createNumericLiteral(double value, types::TokenFlags numericLiteralFlags = types::TokenFlags::None) { + return createNumericLiteral(std::to_string(value), numericLiteralFlags); + } + + // @api + shared createBigIntLiteral(variant value) { + string v = holds_alternative(value) ? get(value) : pseudoBigIntToString(get(value)) + "n"; + auto node = createBaseLiteral(SyntaxKind::BigIntLiteral, v); + node->transformFlags |= (int) TransformFlags::ContainsESNext; + return node; + } + + shared createBaseStringLiteral(string text, optional isSingleQuote = {}) { + auto node = createBaseLiteral(SyntaxKind::StringLiteral, std::move(text)); + node->singleQuote = isSingleQuote; + return node; + } + + // @api + shared createStringLiteral(string text, optional isSingleQuote = {}, optional hasExtendedUnicodeEscape = {}) { + auto node = createBaseStringLiteral(std::move(text), isSingleQuote); + node->hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; + if (hasExtendedUnicodeEscape) node->transformFlags |= (int) TransformFlags::ContainsES2015; + return node; + } + // // @api // function createStringLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { // auto node = createBaseStringLiteral(getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined); -// node.textSourceNode = sourceNode; -// return node; -// } -// -// // @api -// function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { -// auto node = createBaseLiteral(SyntaxKind::RegularExpressionLiteral, text); +// node->textSourceNode = sourceNode; // return node; // } // -// // @api -// function createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind::JsxTextAllWhiteSpaces, text: string): LiteralToken { -// switch (kind) { -// case SyntaxKind::NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0); -// case SyntaxKind::BigIntLiteral: return createBigIntLiteral(text); -// case SyntaxKind::StringLiteral: return createStringLiteral(text, /*isSingleQuote*/ undefined); -// case SyntaxKind::JsxText: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ false); -// case SyntaxKind::JsxTextAllWhiteSpaces: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ true); -// case SyntaxKind::RegularExpressionLiteral: return createRegularExpressionLiteral(text); -// case SyntaxKind::NoSubstitutionTemplateLiteral: return createTemplateLiteralLikeNode(kind, text, /*rawText*/ undefined, /*templateFlags*/ 0) as NoSubstitutionTemplateLiteral; -// } -// } -// + // @api + shared createRegularExpressionLiteral(string text) { + auto node = createBaseLiteral(SyntaxKind::RegularExpressionLiteral, text); + return node; + } + + // @api + shared createJsxText(string text, optional containsOnlyTriviaWhiteSpaces = {}) { + auto node = createBaseNode(SyntaxKind::JsxText); + node->text = text; + node->containsOnlyTriviaWhiteSpaces = containsOnlyTriviaWhiteSpaces ? *containsOnlyTriviaWhiteSpaces : false; + node->transformFlags |= (int) TransformFlags::ContainsJsx; + return node; + } + + // @api + shared createTemplateLiteralLikeNode(SyntaxKind kind, string text, optional rawText = {}, optional templateFlags = {}) { + auto node = createBaseToken(kind); + node->text = std::move(text); + node->rawText = std::move(rawText); + node->templateFlags = (templateFlags ? *templateFlags : 0) & (int) TokenFlags::TemplateLiteralLikeFlags; + node->transformFlags |= (int) TransformFlags::ContainsES2015; + if (node->templateFlags) { + node->transformFlags |= (int) TransformFlags::ContainsES2018; + } + return node; + } + + // @api + shared createLiteralLikeNode(SyntaxKind kind, string text) { + switch (kind) { + case SyntaxKind::NumericLiteral: + return createNumericLiteral(text, /*numericLiteralFlags*/ 0); + case SyntaxKind::BigIntLiteral: + return createBigIntLiteral(text); + case SyntaxKind::StringLiteral: + return createStringLiteral(text, /*isSingleQuote*/ {}); + case SyntaxKind::JsxText: + return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ false); + case SyntaxKind::JsxTextAllWhiteSpaces: + return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ true); + case SyntaxKind::RegularExpressionLiteral: + return createRegularExpressionLiteral(text); + case SyntaxKind::NoSubstitutionTemplateLiteral: + return createTemplateLiteralLikeNode(kind, text, /*rawText*/ {}, /*templateFlags*/ 0); + } + } + // // // // Identifiers // // @@ -422,15 +1048,15 @@ namespace ts::factory { shared createBaseGeneratedIdentifier(string text, GeneratedIdentifierFlags autoGenerateFlags) { auto node = createBaseIdentifier(text, /*originalKeywordKind*/ {}); - node->autoGenerateFlags = autoGenerateFlags; + node->autoGenerateFlags = (int) autoGenerateFlags; node->autoGenerateId = nextAutoGenerateId; nextAutoGenerateId ++; return node; } // @api - shared createIdentifier(string &text, optional typeArguments, optional originalKeywordKind) { - auto node = createBaseIdentifier(text, originalKeywordKind); + shared createIdentifier(string text, optional typeArguments, optional originalKeywordKind) { + auto node = createBaseIdentifier(std::move(text), originalKeywordKind); if (typeArguments) { // NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations node->typeArguments = createNodeArray(*typeArguments); @@ -484,15 +1110,15 @@ namespace ts::factory { // return name; // } // -// // @api -// function createPrivateIdentifier(text: string): PrivateIdentifier { -// if (!startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text); -// auto node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind::PrivateIdentifier) as Mutable; -// node.escapedText = escapeLeadingUnderscores(text); -// node.transformFlags |= TransformFlags::ContainsClassFields; -// return node; -// } -// + // @api + shared createPrivateIdentifier(string text) { + if (! startsWith(text, "#")) throw runtime_error("First character of private identifier must be #: " + text); + auto node = createBaseNode(SyntaxKind::PrivateIdentifier); + node->escapedText = escapeLeadingUnderscores(text); + node->transformFlags |= (int) TransformFlags::ContainsClassFields; + return node; + } + // // // // Punctuation // // @@ -562,7 +1188,7 @@ namespace ts::factory { } return node; } -// + // // // // Reserved words // // @@ -628,9 +1254,9 @@ namespace ts::factory { // // @api // function createQualifiedName(left: EntityName, right: string | Identifier) { // auto node = createBaseNode(SyntaxKind::QualifiedName); -// node.left = left; -// node.right = asName(right); -// node.transformFlags |= +// node->left = left; +// node->right = asName(right); +// node->transformFlags |= // propagateChildFlags(node.left) | // propagateIdentifierNameFlags(node.right); // return node; @@ -644,17 +1270,17 @@ namespace ts::factory { // : node; // } // -// // @api -// function createComputedPropertyName(expression: Expression) { -// auto node = createBaseNode(SyntaxKind::ComputedPropertyName); -// node.expression = parenthesizerRules().parenthesizeExpressionOfComputedPropertyName(expression); -// node.transformFlags |= -// propagateChildFlags(node.expression) | -// TransformFlags::ContainsES2015 | -// TransformFlags::ContainsComputedPropertyName; -// return node; -// } -// + // @api + shared createComputedPropertyName(shared expression) { + auto node = createBaseNode(SyntaxKind::ComputedPropertyName); + node->expression = parenthesizerRules::parenthesizeExpressionOfComputedPropertyName(expression); + node->transformFlags |= + propagateChildFlags(node->expression) | + (int) TransformFlags::ContainsES2015 | + (int) TransformFlags::ContainsComputedPropertyName; + return node; + } + // // @api // function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) { // return node.expression != expression @@ -690,9 +1316,9 @@ namespace ts::factory { // modifiers, // name // ); -// node.constraint = constraint; -// node.default = defaultType; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->constraint = constraint; +// node->default = defaultType; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -738,15 +1364,15 @@ namespace ts::factory { // modifiers, // name, // type, -// initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) +// initializer && parenthesizerRules::parenthesizeExpressionForDisallowedComma(initializer) // ); -// node.dotDotDotToken = dotDotDotToken; -// node.questionToken = questionToken; +// node->dotDotDotToken = dotDotDotToken; +// node->questionToken = questionToken; // if (isThisIdentifier(node.name)) { -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // } // else { -// node.transformFlags |= +// node->transformFlags |= // propagateChildFlags(node.dotDotDotToken) | // propagateChildFlags(node.questionToken); // if (questionToken) node.transformFlags |= TransformFlags::ContainsTypeScript; @@ -781,8 +1407,8 @@ namespace ts::factory { // // @api // function createDecorator(expression: Expression) { // auto node = createBaseNode(SyntaxKind::Decorator); -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsTypeScript | // TransformFlags::ContainsTypeScriptClassSyntax; @@ -813,9 +1439,9 @@ namespace ts::factory { // modifiers, // name // ); -// node.type = type; -// node.questionToken = questionToken; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->type = type; +// node->questionToken = questionToken; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -852,17 +1478,17 @@ namespace ts::factory { // type, // initializer // ); -// node.questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; -// node.exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; -// node.transformFlags |= +// node->questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; +// node->exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; +// node->transformFlags |= // propagateChildFlags(node.questionToken) | // propagateChildFlags(node.exclamationToken) | // TransformFlags::ContainsClassFields; // if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { -// node.transformFlags |= TransformFlags::ContainsTypeScriptClassSyntax; +// node->transformFlags |= TransformFlags::ContainsTypeScriptClassSyntax; // } // if (questionOrExclamationToken || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // return node; // } @@ -906,8 +1532,8 @@ namespace ts::factory { // parameters, // type // ); -// node.questionToken = questionToken; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->questionToken = questionToken; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -953,25 +1579,25 @@ namespace ts::factory { // type, // body // ); -// node.asteriskToken = asteriskToken; -// node.questionToken = questionToken; -// node.transformFlags |= +// node->asteriskToken = asteriskToken; +// node->questionToken = questionToken; +// node->transformFlags |= // propagateChildFlags(node.asteriskToken) | // propagateChildFlags(node.questionToken) | // TransformFlags::ContainsES2015; // if (questionToken) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { // if (asteriskToken) { -// node.transformFlags |= TransformFlags::ContainsES2018; +// node->transformFlags |= TransformFlags::ContainsES2018; // } // else { -// node.transformFlags |= TransformFlags::ContainsES2017; +// node->transformFlags |= TransformFlags::ContainsES2017; // } // } // else if (asteriskToken) { -// node.transformFlags |= TransformFlags::ContainsGenerator; +// node->transformFlags |= TransformFlags::ContainsGenerator; // } // return node; // } @@ -1015,8 +1641,8 @@ namespace ts::factory { // /*name*/ undefined, // /*typeParameters*/ undefined // ); -// node.body = body; -// node.transformFlags = propagateChildFlags(body) | TransformFlags::ContainsClassFields; +// node->body = body; +// node->transformFlags = propagateChildFlags(body) | TransformFlags::ContainsClassFields; // return node; // } // @@ -1051,7 +1677,7 @@ namespace ts::factory { // /*type*/ undefined, // body // ); -// node.transformFlags |= TransformFlags::ContainsES2015; +// node->transformFlags |= TransformFlags::ContainsES2015; // return node; // } // @@ -1165,7 +1791,7 @@ namespace ts::factory { // parameters, // type // ); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1198,7 +1824,7 @@ namespace ts::factory { // parameters, // type // ); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1232,7 +1858,7 @@ namespace ts::factory { // parameters, // type // ); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1255,9 +1881,9 @@ namespace ts::factory { // // @api // function createTemplateLiteralTypeSpan(type: TypeNode, literal: TemplateMiddle | TemplateTail) { // auto node = createBaseNode(SyntaxKind::TemplateLiteralTypeSpan); -// node.type = type; -// node.literal = literal; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->type = type; +// node->literal = literal; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1281,10 +1907,10 @@ namespace ts::factory { // // @api // function createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) { // auto node = createBaseNode(SyntaxKind::TypePredicate); -// node.assertsModifier = assertsModifier; -// node.parameterName = asName(parameterName); -// node.type = type; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->assertsModifier = assertsModifier; +// node->parameterName = asName(parameterName); +// node->type = type; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1300,9 +1926,9 @@ namespace ts::factory { // // @api // function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) { // auto node = createBaseNode(SyntaxKind::TypeReference); -// node.typeName = asName(typeName); -// node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments)); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->typeName = asName(typeName); +// node->typeArguments = typeArguments && parenthesizerRules::parenthesizeTypeArguments(createNodeArray(typeArguments)); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1329,7 +1955,7 @@ namespace ts::factory { // parameters, // type // ); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1369,7 +1995,7 @@ namespace ts::factory { // parameters, // type // ); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1417,9 +2043,9 @@ namespace ts::factory { // // @api // function createTypeQueryNode(exprName: EntityName, typeArguments?: readonly TypeNode[]) { // auto node = createBaseNode(SyntaxKind::TypeQuery); -// node.exprName = exprName; -// node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->exprName = exprName; +// node->typeArguments = typeArguments && parenthesizerRules::parenthesizeTypeArguments(typeArguments); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1434,8 +2060,8 @@ namespace ts::factory { // // @api // function createTypeLiteralNode(members: readonly TypeElement[] | undefined) { // auto node = createBaseNode(SyntaxKind::TypeLiteral); -// node.members = createNodeArray(members); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->members = createNodeArray(members); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1449,8 +2075,8 @@ namespace ts::factory { // // @api // function createArrayTypeNode(elementType: TypeNode) { // auto node = createBaseNode(SyntaxKind::ArrayType); -// node.elementType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(elementType); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->elementType = parenthesizerRules::parenthesizeNonArrayTypeOfPostfixType(elementType); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1464,8 +2090,8 @@ namespace ts::factory { // // @api // function createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]) { // auto node = createBaseNode(SyntaxKind::TupleType); -// node.elements = createNodeArray(parenthesizerRules().parenthesizeElementTypesOfTupleType(elements)); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->elements = createNodeArray(parenthesizerRules::parenthesizeElementTypesOfTupleType(elements)); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1479,11 +2105,11 @@ namespace ts::factory { // // @api // function createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) { // auto node = createBaseNode(SyntaxKind::NamedTupleMember); -// node.dotDotDotToken = dotDotDotToken; -// node.name = name; -// node.questionToken = questionToken; -// node.type = type; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->dotDotDotToken = dotDotDotToken; +// node->name = name; +// node->questionToken = questionToken; +// node->type = type; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1500,8 +2126,8 @@ namespace ts::factory { // // @api // function createOptionalTypeNode(type: TypeNode) { // auto node = createBaseNode(SyntaxKind::OptionalType); -// node.type = parenthesizerRules().parenthesizeTypeOfOptionalType(type); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->type = parenthesizerRules::parenthesizeTypeOfOptionalType(type); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1515,8 +2141,8 @@ namespace ts::factory { // // @api // function createRestTypeNode(type: TypeNode) { // auto node = createBaseNode(SyntaxKind::RestType); -// node.type = type; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->type = type; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1529,8 +2155,8 @@ namespace ts::factory { // // function createUnionOrIntersectionTypeNode(kind: SyntaxKind::UnionType | SyntaxKind::IntersectionType, types: readonly TypeNode[], parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]) { // auto node = createBaseNode(kind); -// node.types = factory.createNodeArray(parenthesize(types)); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->types = factory::createNodeArray(parenthesize(types)); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1542,32 +2168,32 @@ namespace ts::factory { // // // @api // function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode { -// return createUnionOrIntersectionTypeNode(SyntaxKind::UnionType, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType) as UnionTypeNode; +// return createUnionOrIntersectionTypeNode(SyntaxKind::UnionType, types, parenthesizerRules::parenthesizeConstituentTypesOfUnionType) as UnionTypeNode; // } // // // @api // function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray) { -// return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType); +// return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules::parenthesizeConstituentTypesOfUnionType); // } // // // @api // function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode { -// return createUnionOrIntersectionTypeNode(SyntaxKind::IntersectionType, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType) as IntersectionTypeNode; +// return createUnionOrIntersectionTypeNode(SyntaxKind::IntersectionType, types, parenthesizerRules::parenthesizeConstituentTypesOfIntersectionType) as IntersectionTypeNode; // } // // // @api // function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray) { -// return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType); +// return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules::parenthesizeConstituentTypesOfIntersectionType); // } // // // @api // function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { // auto node = createBaseNode(SyntaxKind::ConditionalType); -// node.checkType = parenthesizerRules().parenthesizeCheckTypeOfConditionalType(checkType); -// node.extendsType = parenthesizerRules().parenthesizeExtendsTypeOfConditionalType(extendsType); -// node.trueType = trueType; -// node.falseType = falseType; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->checkType = parenthesizerRules::parenthesizeCheckTypeOfConditionalType(checkType); +// node->extendsType = parenthesizerRules::parenthesizeExtendsTypeOfConditionalType(extendsType); +// node->trueType = trueType; +// node->falseType = falseType; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1584,8 +2210,8 @@ namespace ts::factory { // // @api // function createInferTypeNode(typeParameter: TypeParameterDeclaration) { // auto node = createBaseNode(SyntaxKind::InferType); -// node.typeParameter = typeParameter; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->typeParameter = typeParameter; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1599,9 +2225,9 @@ namespace ts::factory { // // @api // function createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) { // auto node = createBaseNode(SyntaxKind::TemplateLiteralType); -// node.head = head; -// node.templateSpans = createNodeArray(templateSpans); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->head = head; +// node->templateSpans = createNodeArray(templateSpans); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1630,12 +2256,12 @@ namespace ts::factory { // isTypeOf = typeof isTypeOfOrTypeArguments == "boolean" ? isTypeOfOrTypeArguments : typeof isTypeOf == "boolean" ? isTypeOf : false; // // auto node = createBaseNode(SyntaxKind::ImportType); -// node.argument = argument; -// node.assertions = assertion; -// node.qualifier = qualifier; -// node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments); -// node.isTypeOf = isTypeOf; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->argument = argument; +// node->assertions = assertion; +// node->qualifier = qualifier; +// node->typeArguments = typeArguments && parenthesizerRules::parenthesizeTypeArguments(typeArguments); +// node->isTypeOf = isTypeOf; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1668,8 +2294,8 @@ namespace ts::factory { // // @api // function createParenthesizedType(type: TypeNode) { // auto node = createBaseNode(SyntaxKind::ParenthesizedType); -// node.type = type; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->type = type; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1683,18 +2309,18 @@ namespace ts::factory { // // @api // function createThisTypeNode() { // auto node = createBaseNode(SyntaxKind::ThisType); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // // // @api // function createTypeOperatorNode(operator: SyntaxKind::KeyOfKeyword | SyntaxKind::UniqueKeyword | SyntaxKind::ReadonlyKeyword, type: TypeNode): TypeOperatorNode { // auto node = createBaseNode(SyntaxKind::TypeOperator); -// node.operator = operator; -// node.type = operator == SyntaxKind::ReadonlyKeyword ? -// parenthesizerRules().parenthesizeOperandOfReadonlyTypeOperator(type) : -// parenthesizerRules().parenthesizeOperandOfTypeOperator(type); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->operator = operator; +// node->type = operator == SyntaxKind::ReadonlyKeyword ? +// parenthesizerRules::parenthesizeOperandOfReadonlyTypeOperator(type) : +// parenthesizerRules::parenthesizeOperandOfTypeOperator(type); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1708,9 +2334,9 @@ namespace ts::factory { // // @api // function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) { // auto node = createBaseNode(SyntaxKind::IndexedAccessType); -// node.objectType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(objectType); -// node.indexType = indexType; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->objectType = parenthesizerRules::parenthesizeNonArrayTypeOfPostfixType(objectType); +// node->indexType = indexType; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1725,13 +2351,13 @@ namespace ts::factory { // // @api // function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode { // auto node = createBaseNode(SyntaxKind::MappedType); -// node.readonlyToken = readonlyToken; -// node.typeParameter = typeParameter; -// node.nameType = nameType; -// node.questionToken = questionToken; -// node.type = type; -// node.members = members && createNodeArray(members); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->readonlyToken = readonlyToken; +// node->typeParameter = typeParameter; +// node->nameType = nameType; +// node->questionToken = questionToken; +// node->type = type; +// node->members = members && createNodeArray(members); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1750,8 +2376,8 @@ namespace ts::factory { // // @api // function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) { // auto node = createBaseNode(SyntaxKind::LiteralType); -// node.literal = literal; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->literal = literal; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -1766,21 +2392,21 @@ namespace ts::factory { // // Binding Patterns // // // -// // @api -// function createObjectBindingPattern(elements: readonly BindingElement[]) { -// auto node = createBaseNode(SyntaxKind::ObjectBindingPattern); -// node.elements = createNodeArray(elements); -// node.transformFlags |= -// propagateChildrenFlags(node.elements) | -// TransformFlags::ContainsES2015 | -// TransformFlags::ContainsBindingPattern; -// if (node.transformFlags & TransformFlags::ContainsRestOrSpread) { -// node.transformFlags |= -// TransformFlags::ContainsES2018 | -// TransformFlags::ContainsObjectRestOrSpread; -// } -// return node; -// } + // @api + shared createObjectBindingPattern(NodeArray elements) { + auto node = createBaseNode(SyntaxKind::ObjectBindingPattern); + node->elements = createNodeArray(elements); + node->transformFlags |= + propagateChildrenFlags(node->elements) | + (int) TransformFlags::ContainsES2015 | + (int) TransformFlags::ContainsBindingPattern; + if (node->transformFlags & (int) TransformFlags::ContainsRestOrSpread) { + node->transformFlags |= + (int) TransformFlags::ContainsES2018 | + (int) TransformFlags::ContainsObjectRestOrSpread; + } + return node; + } // // // @api // function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) { @@ -1789,17 +2415,17 @@ namespace ts::factory { // : node; // } // -// // @api -// function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) { -// auto node = createBaseNode(SyntaxKind::ArrayBindingPattern); -// node.elements = createNodeArray(elements); -// node.transformFlags |= -// propagateChildrenFlags(node.elements) | -// TransformFlags::ContainsES2015 | -// TransformFlags::ContainsBindingPattern; -// return node; -// } -// + // @api + shared createArrayBindingPattern(NodeArray elements) { + auto node = createBaseNode(SyntaxKind::ArrayBindingPattern); + node->elements = createNodeArray(elements); + node->transformFlags |= + propagateChildrenFlags(node->elements) | + (int) TransformFlags::ContainsES2015 | + (int) TransformFlags::ContainsBindingPattern; + return node; + } + // // @api // function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) { // return node.elements != elements @@ -1807,29 +2433,32 @@ namespace ts::factory { // : node; // } // -// // @api -// function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) { -// auto node = createBaseBindingLikeDeclaration( -// SyntaxKind::BindingElement, -// /*decorators*/ undefined, -// /*modifiers*/ undefined, -// name, -// initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) -// ); -// node.propertyName = asName(propertyName); -// node.dotDotDotToken = dotDotDotToken; -// node.transformFlags |= -// propagateChildFlags(node.dotDotDotToken) | -// TransformFlags::ContainsES2015; -// if (node.propertyName) { -// node.transformFlags |= isIdentifier(node.propertyName) ? -// propagateIdentifierNameFlags(node.propertyName) : -// propagateChildFlags(node.propertyName); -// } -// if (dotDotDotToken) node.transformFlags |= TransformFlags::ContainsRestOrSpread; -// return node; -// } -// + // @api + shared createBindingElement( + sharedOpt dotDotDotToken, + optional>> propertyName = {}, + variant> name = "", + sharedOpt initializer = {} + ) { + auto node = createBaseBindingLikeDeclaration( + SyntaxKind::BindingElement, + /*decorators*/ {}, + /*modifiers*/ {}, + name, + initializer ? parenthesizerRules::parenthesizeExpressionForDisallowedComma(initializer) : nullptr + ); + node->propertyName = asName(*propertyName); + node->dotDotDotToken = dotDotDotToken; + node->transformFlags |= propagateChildFlags(node->dotDotDotToken) | (int) TransformFlags::ContainsES2015; + if (node->propertyName) { + node->transformFlags |= isIdentifier(node->propertyName) ? + propagateIdentifierNameFlags(node->propertyName) : + propagateChildFlags(node->propertyName); + } + if (dotDotDotToken) node->transformFlags |= (int) TransformFlags::ContainsRestOrSpread; + return node; + } + // // @api // function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) { // return node.propertyName != propertyName @@ -1859,9 +2488,9 @@ namespace ts::factory { // // a trailing comma. // auto lastElement = elements && lastOrUndefined(elements); // auto elementsArray = createNodeArray(elements, lastElement && isOmittedExpression(lastElement) ? true : undefined); -// node.elements = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(elementsArray); -// node.multiLine = multiLine; -// node.transformFlags |= propagateChildrenFlags(node.elements); +// node->elements = parenthesizerRules::parenthesizeExpressionsOfCommaDelimitedList(elementsArray); +// node->multiLine = multiLine; +// node->transformFlags |= propagateChildrenFlags(node.elements); // return node; // } // @@ -1875,9 +2504,9 @@ namespace ts::factory { // // @api // function createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) { // auto node = createBaseExpression(SyntaxKind::ObjectLiteralExpression); -// node.properties = createNodeArray(properties); -// node.multiLine = multiLine; -// node.transformFlags |= propagateChildrenFlags(node.properties); +// node->properties = createNodeArray(properties); +// node->multiLine = multiLine; +// node->transformFlags |= propagateChildrenFlags(node.properties); // return node; // } // @@ -1888,26 +2517,26 @@ namespace ts::factory { // : node; // } // -// // @api -// function createPropertyAccessExpression(expression: Expression, name: string | Identifier | PrivateIdentifier) { -// auto node = createBaseExpression(SyntaxKind::PropertyAccessExpression); -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.name = asName(name); -// node.transformFlags = -// propagateChildFlags(node.expression) | -// (isIdentifier(node.name) ? -// propagateIdentifierNameFlags(node.name) : -// propagateChildFlags(node.name)); -// if (isSuperKeyword(expression)) { -// // super method calls require a lexical 'this' -// // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators -// node.transformFlags |= -// TransformFlags::ContainsES2017 | -// TransformFlags::ContainsES2018; -// } -// return node; -// } -// + // @api + shared createPropertyAccessExpression(shared expression, variant> _name) { + auto node = createBaseExpression(SyntaxKind::PropertyAccessExpression); + node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); + node->name = asName(_name); + node->transformFlags = + propagateChildFlags(node->expression) | + (isIdentifier(node->name) ? + propagateIdentifierNameFlags(node->name) : + propagateChildFlags(node->name)); + if (isSuperKeyword(expression)) { + // super method calls require a lexical 'this' + // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators + node->transformFlags |= + (int) TransformFlags::ContainsES2017 | + (int) TransformFlags::ContainsES2018; + } + return node; + } + // // @api // function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateIdentifier) { // if (isPropertyAccessChain(node)) { @@ -1922,11 +2551,11 @@ namespace ts::factory { // // @api // function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier | PrivateIdentifier) { // auto node = createBaseExpression(SyntaxKind::PropertyAccessExpression); -// node.flags |= NodeFlags.OptionalChain; -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.questionDotToken = questionDotToken; -// node.name = asName(name); -// node.transformFlags |= +// node->flags |= NodeFlags.OptionalChain; +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->questionDotToken = questionDotToken; +// node->name = asName(name); +// node->transformFlags |= // TransformFlags::ContainsES2020 | // propagateChildFlags(node.expression) | // propagateChildFlags(node.questionDotToken) | @@ -1951,15 +2580,15 @@ namespace ts::factory { // // @api // function createElementAccessExpression(expression: Expression, index: number | Expression) { // auto node = createBaseExpression(SyntaxKind::ElementAccessExpression); -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.argumentExpression = asExpression(index); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->argumentExpression = asExpression(index); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.argumentExpression); // if (isSuperKeyword(expression)) { // // super method calls require a lexical 'this' // // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators -// node.transformFlags |= +// node->transformFlags |= // TransformFlags::ContainsES2017 | // TransformFlags::ContainsES2018; // } @@ -1980,11 +2609,11 @@ namespace ts::factory { // // @api // function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) { // auto node = createBaseExpression(SyntaxKind::ElementAccessExpression); -// node.flags |= NodeFlags.OptionalChain; -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.questionDotToken = questionDotToken; -// node.argumentExpression = asExpression(index); -// node.transformFlags |= +// node->flags |= NodeFlags.OptionalChain; +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->questionDotToken = questionDotToken; +// node->argumentExpression = asExpression(index); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.questionDotToken) | // propagateChildFlags(node.argumentExpression) | @@ -2007,21 +2636,21 @@ namespace ts::factory { // // @api // function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { // auto node = createBaseExpression(SyntaxKind::CallExpression); -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.typeArguments = asNodeArray(typeArguments); -// node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->typeArguments = asNodeArray(typeArguments); +// node->arguments = parenthesizerRules::parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildrenFlags(node.typeArguments) | // propagateChildrenFlags(node.arguments); // if (node.typeArguments) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // if (isImportKeyword(node.expression)) { -// node.transformFlags |= TransformFlags::ContainsDynamicImport; +// node->transformFlags |= TransformFlags::ContainsDynamicImport; // } // else if (isSuperProperty(node.expression)) { -// node.transformFlags |= TransformFlags::ContainsLexicalThis; +// node->transformFlags |= TransformFlags::ContainsLexicalThis; // } // return node; // } @@ -2041,22 +2670,22 @@ namespace ts::factory { // // @api // function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { // auto node = createBaseExpression(SyntaxKind::CallExpression); -// node.flags |= NodeFlags.OptionalChain; -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.questionDotToken = questionDotToken; -// node.typeArguments = asNodeArray(typeArguments); -// node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); -// node.transformFlags |= +// node->flags |= NodeFlags.OptionalChain; +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->questionDotToken = questionDotToken; +// node->typeArguments = asNodeArray(typeArguments); +// node->arguments = parenthesizerRules::parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.questionDotToken) | // propagateChildrenFlags(node.typeArguments) | // propagateChildrenFlags(node.arguments) | // TransformFlags::ContainsES2020; // if (node.typeArguments) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // if (isSuperProperty(node.expression)) { -// node.transformFlags |= TransformFlags::ContainsLexicalThis; +// node->transformFlags |= TransformFlags::ContainsLexicalThis; // } // return node; // } @@ -2075,16 +2704,16 @@ namespace ts::factory { // // @api // function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { // auto node = createBaseExpression(SyntaxKind::NewExpression); -// node.expression = parenthesizerRules().parenthesizeExpressionOfNew(expression); -// node.typeArguments = asNodeArray(typeArguments); -// node.arguments = argumentsArray ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined; -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeExpressionOfNew(expression); +// node->typeArguments = asNodeArray(typeArguments); +// node->arguments = argumentsArray ? parenthesizerRules::parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined; +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildrenFlags(node.typeArguments) | // propagateChildrenFlags(node.arguments) | // TransformFlags::ContainsES2020; // if (node.typeArguments) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // return node; // } @@ -2101,19 +2730,19 @@ namespace ts::factory { // // @api // function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { // auto node = createBaseExpression(SyntaxKind::TaggedTemplateExpression); -// node.tag = parenthesizerRules().parenthesizeLeftSideOfAccess(tag); -// node.typeArguments = asNodeArray(typeArguments); -// node.template = template; -// node.transformFlags |= +// node->tag = parenthesizerRules::parenthesizeLeftSideOfAccess(tag); +// node->typeArguments = asNodeArray(typeArguments); +// node->template = template; +// node->transformFlags |= // propagateChildFlags(node.tag) | // propagateChildrenFlags(node.typeArguments) | // propagateChildFlags(node.template) | // TransformFlags::ContainsES2015; // if (node.typeArguments) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // if (hasInvalidEscape(node.template)) { -// node.transformFlags |= TransformFlags::ContainsES2018; +// node->transformFlags |= TransformFlags::ContainsES2018; // } // return node; // } @@ -2130,9 +2759,9 @@ namespace ts::factory { // // @api // function createTypeAssertion(type: TypeNode, expression: Expression) { // auto node = createBaseExpression(SyntaxKind::TypeAssertionExpression); -// node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); -// node.type = type; -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeOperandOfPrefixUnary(expression); +// node->type = type; +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.type) | // TransformFlags::ContainsTypeScript; @@ -2147,14 +2776,14 @@ namespace ts::factory { // : node; // } // -// // @api -// function createParenthesizedExpression(expression: Expression) { -// auto node = createBaseExpression(SyntaxKind::ParenthesizedExpression); -// node.expression = expression; -// node.transformFlags = propagateChildFlags(node.expression); -// return node; -// } -// + // @api + shared createParenthesizedExpression(shared expression) { + auto node = createBaseExpression(SyntaxKind::ParenthesizedExpression); + node->expression = expression; + node->transformFlags = propagateChildFlags(node->expression); + return node; + } + // // @api // function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression) { // return node.expression != expression @@ -2182,21 +2811,21 @@ namespace ts::factory { // type, // body // ); -// node.asteriskToken = asteriskToken; -// node.transformFlags |= propagateChildFlags(node.asteriskToken); +// node->asteriskToken = asteriskToken; +// node->transformFlags |= propagateChildFlags(node.asteriskToken); // if (node.typeParameters) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { // if (node.asteriskToken) { -// node.transformFlags |= TransformFlags::ContainsES2018; +// node->transformFlags |= TransformFlags::ContainsES2018; // } // else { -// node.transformFlags |= TransformFlags::ContainsES2017; +// node->transformFlags |= TransformFlags::ContainsES2017; // } // } // else if (node.asteriskToken) { -// node.transformFlags |= TransformFlags::ContainsGenerator; +// node->transformFlags |= TransformFlags::ContainsGenerator; // } // return node; // } @@ -2240,14 +2869,14 @@ namespace ts::factory { // typeParameters, // parameters, // type, -// parenthesizerRules().parenthesizeConciseBodyOfArrowFunction(body) +// parenthesizerRules::parenthesizeConciseBodyOfArrowFunction(body) // ); -// node.equalsGreaterThanToken = equalsGreaterThanToken ?? createToken(SyntaxKind::EqualsGreaterThanToken); -// node.transformFlags |= +// node->equalsGreaterThanToken = equalsGreaterThanToken ?? createToken(SyntaxKind::EqualsGreaterThanToken); +// node->transformFlags |= // propagateChildFlags(node.equalsGreaterThanToken) | // TransformFlags::ContainsES2015; // if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { -// node.transformFlags |= TransformFlags::ContainsES2017 | TransformFlags::ContainsLexicalThis; +// node->transformFlags |= TransformFlags::ContainsES2017 | TransformFlags::ContainsLexicalThis; // } // return node; // } @@ -2275,8 +2904,8 @@ namespace ts::factory { // // @api // function createDeleteExpression(expression: Expression) { // auto node = createBaseExpression(SyntaxKind::DeleteExpression); -// node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); -// node.transformFlags |= propagateChildFlags(node.expression); +// node->expression = parenthesizerRules::parenthesizeOperandOfPrefixUnary(expression); +// node->transformFlags |= propagateChildFlags(node.expression); // return node; // } // @@ -2290,8 +2919,8 @@ namespace ts::factory { // // @api // function createTypeOfExpression(expression: Expression) { // auto node = createBaseExpression(SyntaxKind::TypeOfExpression); -// node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); -// node.transformFlags |= propagateChildFlags(node.expression); +// node->expression = parenthesizerRules::parenthesizeOperandOfPrefixUnary(expression); +// node->transformFlags |= propagateChildFlags(node.expression); // return node; // } // @@ -2305,8 +2934,8 @@ namespace ts::factory { // // @api // function createVoidExpression(expression: Expression) { // auto node = createBaseExpression(SyntaxKind::VoidExpression); -// node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); -// node.transformFlags |= propagateChildFlags(node.expression); +// node->expression = parenthesizerRules::parenthesizeOperandOfPrefixUnary(expression); +// node->transformFlags |= propagateChildFlags(node.expression); // return node; // } // @@ -2320,8 +2949,8 @@ namespace ts::factory { // // @api // function createAwaitExpression(expression: Expression) { // auto node = createBaseExpression(SyntaxKind::AwaitExpression); -// node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeOperandOfPrefixUnary(expression); +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsES2017 | // TransformFlags::ContainsES2018 | @@ -2336,23 +2965,23 @@ namespace ts::factory { // : node; // } // -// // @api -// function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) { -// auto node = createBaseExpression(SyntaxKind::PrefixUnaryExpression); -// node.operator = operator; -// node.operand = parenthesizerRules().parenthesizeOperandOfPrefixUnary(operand); -// node.transformFlags |= propagateChildFlags(node.operand); -// // Only set this flag for non-generated identifiers and non-"local" names. See the -// // comment in `visitPreOrPostfixUnaryExpression` in module.ts -// if ((operator == SyntaxKind::PlusPlusToken || operator == SyntaxKind::MinusMinusToken) && -// isIdentifier(node.operand) && -// !isGeneratedIdentifier(node.operand) && -// !isLocalName(node.operand)) { -// node.transformFlags |= TransformFlags::ContainsUpdateExpressionForIdentifier; -// } -// return node; -// } -// + // @api + shared createPrefixUnaryExpression(SyntaxKind operatorKind, shared operand) { + auto node = createBaseExpression(SyntaxKind::PrefixUnaryExpression); + node->operatorKind = operatorKind; + node->operand = parenthesizerRules::parenthesizeOperandOfPrefixUnary(operand); + node->transformFlags |= propagateChildFlags(node->operand); + // Only set this flag for non-generated identifiers and non-"local" names. See the + // comment in `visitPreOrPostfixUnaryExpression` in module.ts + if ((operatorKind == SyntaxKind::PlusPlusToken || operatorKind == SyntaxKind::MinusMinusToken) && + isIdentifier(node->operand) && + ! isGeneratedIdentifier(node->operand)) { + //!isLocalName(node->operand)) { //<- this is always false as its set by transformer/emit stuff + node->transformFlags |= (int) TransformFlags::ContainsUpdateExpressionForIdentifier; + } + return node; + } + // // @api // function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression) { // return node.operand != operand @@ -2363,15 +2992,15 @@ namespace ts::factory { // // @api // function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) { // auto node = createBaseExpression(SyntaxKind::PostfixUnaryExpression); -// node.operator = operator; -// node.operand = parenthesizerRules().parenthesizeOperandOfPostfixUnary(operand); -// node.transformFlags |= propagateChildFlags(node.operand); +// node->operator = operator; +// node->operand = parenthesizerRules::parenthesizeOperandOfPostfixUnary(operand); +// node->transformFlags |= propagateChildFlags(node.operand); // // Only set this flag for non-generated identifiers and non-"local" names. See the // // comment in `visitPreOrPostfixUnaryExpression` in module.ts // if (isIdentifier(node.operand) && // !isGeneratedIdentifier(node.operand) && // !isLocalName(node.operand)) { -// node.transformFlags |= TransformFlags::ContainsUpdateExpressionForIdentifier; +// node->transformFlags |= TransformFlags::ContainsUpdateExpressionForIdentifier; // } // return node; // } @@ -2388,36 +3017,36 @@ namespace ts::factory { auto node = createBaseExpression(SyntaxKind::BinaryExpression); // auto operatorToken = asToken(operatorNode); // auto operatorKind = operatorToken.kind; -// node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left); -// node.operatorToken = operatorToken; -// node.right = parenthesizerRules().parenthesizeRightSideOfBinary(operatorKind, node.left, right); -// node.transformFlags |= +// node->left = parenthesizerRules::parenthesizeLeftSideOfBinary(operatorKind, left); +// node->operatorToken = operatorToken; +// node->right = parenthesizerRules::parenthesizeRightSideOfBinary(operatorKind, node.left, right); +// node->transformFlags |= // propagateChildFlags(node.left) | // propagateChildFlags(node.operatorToken) | // propagateChildFlags(node.right); // if (operatorKind == SyntaxKind::QuestionQuestionToken) { -// node.transformFlags |= TransformFlags::ContainsES2020; +// node->transformFlags |= TransformFlags::ContainsES2020; // } // else if (operatorKind == SyntaxKind::EqualsToken) { // if (isObjectLiteralExpression(node.left)) { -// node.transformFlags |= +// node->transformFlags |= // TransformFlags::ContainsES2015 | // TransformFlags::ContainsES2018 | // TransformFlags::ContainsDestructuringAssignment | // propagateAssignmentPatternFlags(node.left); // } // else if (isArrayLiteralExpression(node.left)) { -// node.transformFlags |= +// node->transformFlags |= // TransformFlags::ContainsES2015 | // TransformFlags::ContainsDestructuringAssignment | // propagateAssignmentPatternFlags(node.left); // } // } // else if (operatorKind == SyntaxKind::AsteriskAsteriskToken || operatorKind == SyntaxKind::AsteriskAsteriskEqualsToken) { -// node.transformFlags |= TransformFlags::ContainsES2016; +// node->transformFlags |= TransformFlags::ContainsES2016; // } // else if (isLogicalOrCoalescingAssignmentOperator(operatorKind)) { -// node.transformFlags |= TransformFlags::ContainsES2021; +// node->transformFlags |= TransformFlags::ContainsES2021; // } return node; } @@ -2455,12 +3084,12 @@ namespace ts::factory { // // @api // function createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression) { // auto node = createBaseExpression(SyntaxKind::ConditionalExpression); -// node.condition = parenthesizerRules().parenthesizeConditionOfConditionalExpression(condition); -// node.questionToken = questionToken ?? createToken(SyntaxKind::QuestionToken); -// node.whenTrue = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenTrue); -// node.colonToken = colonToken ?? createToken(SyntaxKind::ColonToken); -// node.whenFalse = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenFalse); -// node.transformFlags |= +// node->condition = parenthesizerRules::parenthesizeConditionOfConditionalExpression(condition); +// node->questionToken = questionToken ?? createToken(SyntaxKind::QuestionToken); +// node->whenTrue = parenthesizerRules::parenthesizeBranchOfConditionalExpression(whenTrue); +// node->colonToken = colonToken ?? createToken(SyntaxKind::ColonToken); +// node->whenFalse = parenthesizerRules::parenthesizeBranchOfConditionalExpression(whenFalse); +// node->transformFlags |= // propagateChildFlags(node.condition) | // propagateChildFlags(node.questionToken) | // propagateChildFlags(node.whenTrue) | @@ -2490,9 +3119,9 @@ namespace ts::factory { // // @api // function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) { // auto node = createBaseExpression(SyntaxKind::TemplateExpression); -// node.head = head; -// node.templateSpans = createNodeArray(templateSpans); -// node.transformFlags |= +// node->head = head; +// node->templateSpans = createNodeArray(templateSpans); +// node->transformFlags |= // propagateChildFlags(node.head) | // propagateChildrenFlags(node.templateSpans) | // TransformFlags::ContainsES2015; @@ -2507,8 +3136,8 @@ namespace ts::factory { // : node; // } // -// function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags.None) { -// Debug.assert(!(templateFlags & ~TokenFlags.TemplateLiteralLikeFlags), "Unsupported template flags."); +// function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags::None) { +// Debug.assert(!(templateFlags & ~TokenFlags::TemplateLiteralLikeFlags), "Unsupported template flags."); // // NOTE: without the assignment to `undefined`, we don't narrow the initial type of `cooked`. // // eslint-disable-next-line no-undef-init // let cooked: string | object | undefined = undefined; @@ -2531,19 +3160,6 @@ namespace ts::factory { // } // // // @api -// function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { -// auto node = createBaseToken(kind); -// node.text = text; -// node.rawText = rawText; -// node.templateFlags = templateFlags! & TokenFlags.TemplateLiteralLikeFlags; -// node.transformFlags |= TransformFlags::ContainsES2015; -// if (node.templateFlags) { -// node.transformFlags |= TransformFlags::ContainsES2018; -// } -// return node; -// } -// -// // @api // function createTemplateHead(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { // return createTemplateLiteralLikeNodeChecked(SyntaxKind::TemplateHead, text, rawText, templateFlags) as TemplateHead; // } @@ -2567,9 +3183,9 @@ namespace ts::factory { // function createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression { // Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression."); // auto node = createBaseExpression(SyntaxKind::YieldExpression); -// node.expression = expression && parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); -// node.asteriskToken = asteriskToken; -// node.transformFlags |= +// node->expression = expression && parenthesizerRules::parenthesizeExpressionForDisallowedComma(expression); +// node->asteriskToken = asteriskToken; +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.asteriskToken) | // TransformFlags::ContainsES2015 | @@ -2589,8 +3205,8 @@ namespace ts::factory { // // @api // function createSpreadElement(expression: Expression) { // auto node = createBaseExpression(SyntaxKind::SpreadElement); -// node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeExpressionForDisallowedComma(expression); +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsES2015 | // TransformFlags::ContainsRestOrSpread; @@ -2622,7 +3238,7 @@ namespace ts::factory { // heritageClauses, // members // ); -// node.transformFlags |= TransformFlags::ContainsES2015; +// node->transformFlags |= TransformFlags::ContainsES2015; // return node; // } // @@ -2646,17 +3262,17 @@ namespace ts::factory { // : node; // } // -// // @api -// function createOmittedExpression() { -// return createBaseExpression(SyntaxKind::OmittedExpression); -// } -// + // @api + shared createOmittedExpression() { + return createBaseExpression(SyntaxKind::OmittedExpression); + } + // // @api // function createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined) { // auto node = createBaseNode(SyntaxKind::ExpressionWithTypeArguments); -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->typeArguments = typeArguments && parenthesizerRules::parenthesizeTypeArguments(typeArguments); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildrenFlags(node.typeArguments) | // TransformFlags::ContainsES2015; @@ -2674,9 +3290,9 @@ namespace ts::factory { // // @api // function createAsExpression(expression: Expression, type: TypeNode) { // auto node = createBaseExpression(SyntaxKind::AsExpression); -// node.expression = expression; -// node.type = type; -// node.transformFlags |= +// node->expression = expression; +// node->type = type; +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.type) | // TransformFlags::ContainsTypeScript; @@ -2694,8 +3310,8 @@ namespace ts::factory { // // @api // function createNonNullExpression(expression: Expression) { // auto node = createBaseExpression(SyntaxKind::NonNullExpression); -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsTypeScript; // return node; @@ -2714,9 +3330,9 @@ namespace ts::factory { // // @api // function createNonNullChain(expression: Expression) { // auto node = createBaseExpression(SyntaxKind::NonNullExpression); -// node.flags |= NodeFlags.OptionalChain; -// node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); -// node.transformFlags |= +// node->flags |= NodeFlags.OptionalChain; +// node->expression = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsTypeScript; // return node; @@ -2733,15 +3349,15 @@ namespace ts::factory { // // @api // function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) { // auto node = createBaseExpression(SyntaxKind::MetaProperty); -// node.keywordToken = keywordToken; -// node.name = name; -// node.transformFlags |= propagateChildFlags(node.name); +// node->keywordToken = keywordToken; +// node->name = name; +// node->transformFlags |= propagateChildFlags(node.name); // switch (keywordToken) { // case SyntaxKind::NewKeyword: -// node.transformFlags |= TransformFlags::ContainsES2015; +// node->transformFlags |= TransformFlags::ContainsES2015; // break; // case SyntaxKind::ImportKeyword: -// node.transformFlags |= TransformFlags::ContainsESNext; +// node->transformFlags |= TransformFlags::ContainsESNext; // break; // default: // return Debug.assertNever(keywordToken); @@ -2763,9 +3379,9 @@ namespace ts::factory { // // @api // function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) { // auto node = createBaseNode(SyntaxKind::TemplateSpan); -// node.expression = expression; -// node.literal = literal; -// node.transformFlags |= +// node->expression = expression; +// node->literal = literal; +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.literal) | // TransformFlags::ContainsES2015; @@ -2783,7 +3399,7 @@ namespace ts::factory { // // @api // function createSemicolonClassElement() { // auto node = createBaseNode(SyntaxKind::SemicolonClassElement); -// node.transformFlags |= TransformFlags::ContainsES2015; +// node->transformFlags |= TransformFlags::ContainsES2015; // return node; // } // @@ -2794,9 +3410,9 @@ namespace ts::factory { // // @api // function createBlock(statements: readonly Statement[], multiLine?: boolean): Block { // auto node = createBaseNode(SyntaxKind::Block); -// node.statements = createNodeArray(statements); -// node.multiLine = multiLine; -// node.transformFlags |= propagateChildrenFlags(node.statements); +// node->statements = createNodeArray(statements); +// node->multiLine = multiLine; +// node->transformFlags |= propagateChildrenFlags(node.statements); // return node; // } // @@ -2810,11 +3426,11 @@ namespace ts::factory { // // @api // function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { // auto node = createBaseDeclaration(SyntaxKind::VariableStatement, /*decorators*/ undefined, modifiers); -// node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; -// node.transformFlags |= +// node->declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; +// node->transformFlags |= // propagateChildFlags(node.declarationList); // if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // } // return node; // } @@ -2835,8 +3451,8 @@ namespace ts::factory { // // @api // function createExpressionStatement(expression: Expression): ExpressionStatement { // auto node = createBaseNode(SyntaxKind::ExpressionStatement); -// node.expression = parenthesizerRules().parenthesizeExpressionOfExpressionStatement(expression); -// node.transformFlags |= propagateChildFlags(node.expression); +// node->expression = parenthesizerRules::parenthesizeExpressionOfExpressionStatement(expression); +// node->transformFlags |= propagateChildFlags(node.expression); // return node; // } // @@ -2850,10 +3466,10 @@ namespace ts::factory { // // @api // function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement) { // auto node = createBaseNode(SyntaxKind::IfStatement); -// node.expression = expression; -// node.thenStatement = asEmbeddedStatement(thenStatement); -// node.elseStatement = asEmbeddedStatement(elseStatement); -// node.transformFlags |= +// node->expression = expression; +// node->thenStatement = asEmbeddedStatement(thenStatement); +// node->elseStatement = asEmbeddedStatement(elseStatement); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.thenStatement) | // propagateChildFlags(node.elseStatement); @@ -2872,9 +3488,9 @@ namespace ts::factory { // // @api // function createDoStatement(statement: Statement, expression: Expression) { // auto node = createBaseNode(SyntaxKind::DoStatement); -// node.statement = asEmbeddedStatement(statement); -// node.expression = expression; -// node.transformFlags |= +// node->statement = asEmbeddedStatement(statement); +// node->expression = expression; +// node->transformFlags |= // propagateChildFlags(node.statement) | // propagateChildFlags(node.expression); // return node; @@ -2891,9 +3507,9 @@ namespace ts::factory { // // @api // function createWhileStatement(expression: Expression, statement: Statement) { // auto node = createBaseNode(SyntaxKind::WhileStatement); -// node.expression = expression; -// node.statement = asEmbeddedStatement(statement); -// node.transformFlags |= +// node->expression = expression; +// node->statement = asEmbeddedStatement(statement); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.statement); // return node; @@ -2910,11 +3526,11 @@ namespace ts::factory { // // @api // function createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { // auto node = createBaseNode(SyntaxKind::ForStatement); -// node.initializer = initializer; -// node.condition = condition; -// node.incrementor = incrementor; -// node.statement = asEmbeddedStatement(statement); -// node.transformFlags |= +// node->initializer = initializer; +// node->condition = condition; +// node->incrementor = incrementor; +// node->statement = asEmbeddedStatement(statement); +// node->transformFlags |= // propagateChildFlags(node.initializer) | // propagateChildFlags(node.condition) | // propagateChildFlags(node.incrementor) | @@ -2935,10 +3551,10 @@ namespace ts::factory { // // @api // function createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement) { // auto node = createBaseNode(SyntaxKind::ForInStatement); -// node.initializer = initializer; -// node.expression = expression; -// node.statement = asEmbeddedStatement(statement); -// node.transformFlags |= +// node->initializer = initializer; +// node->expression = expression; +// node->statement = asEmbeddedStatement(statement); +// node->transformFlags |= // propagateChildFlags(node.initializer) | // propagateChildFlags(node.expression) | // propagateChildFlags(node.statement); @@ -2957,11 +3573,11 @@ namespace ts::factory { // // @api // function createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { // auto node = createBaseNode(SyntaxKind::ForOfStatement); -// node.awaitModifier = awaitModifier; -// node.initializer = initializer; -// node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); -// node.statement = asEmbeddedStatement(statement); -// node.transformFlags |= +// node->awaitModifier = awaitModifier; +// node->initializer = initializer; +// node->expression = parenthesizerRules::parenthesizeExpressionForDisallowedComma(expression); +// node->statement = asEmbeddedStatement(statement); +// node->transformFlags |= // propagateChildFlags(node.awaitModifier) | // propagateChildFlags(node.initializer) | // propagateChildFlags(node.expression) | @@ -2984,8 +3600,8 @@ namespace ts::factory { // // @api // function createContinueStatement(label?: string | Identifier): ContinueStatement { // auto node = createBaseNode(SyntaxKind::ContinueStatement); -// node.label = asName(label); -// node.transformFlags |= +// node->label = asName(label); +// node->transformFlags |= // propagateChildFlags(node.label) | // TransformFlags::ContainsHoistedDeclarationOrCompletion; // return node; @@ -3001,8 +3617,8 @@ namespace ts::factory { // // @api // function createBreakStatement(label?: string | Identifier): BreakStatement { // auto node = createBaseNode(SyntaxKind::BreakStatement); -// node.label = asName(label); -// node.transformFlags |= +// node->label = asName(label); +// node->transformFlags |= // propagateChildFlags(node.label) | // TransformFlags::ContainsHoistedDeclarationOrCompletion; // return node; @@ -3018,9 +3634,9 @@ namespace ts::factory { // // @api // function createReturnStatement(expression?: Expression): ReturnStatement { // auto node = createBaseNode(SyntaxKind::ReturnStatement); -// node.expression = expression; +// node->expression = expression; // // return in an ES2018 async generator must be awaited -// node.transformFlags |= +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsES2018 | // TransformFlags::ContainsHoistedDeclarationOrCompletion; @@ -3037,9 +3653,9 @@ namespace ts::factory { // // @api // function createWithStatement(expression: Expression, statement: Statement) { // auto node = createBaseNode(SyntaxKind::WithStatement); -// node.expression = expression; -// node.statement = asEmbeddedStatement(statement); -// node.transformFlags |= +// node->expression = expression; +// node->statement = asEmbeddedStatement(statement); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.statement); // return node; @@ -3056,9 +3672,9 @@ namespace ts::factory { // // @api // function createSwitchStatement(expression: Expression, caseBlock: CaseBlock): SwitchStatement { // auto node = createBaseNode(SyntaxKind::SwitchStatement); -// node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); -// node.caseBlock = caseBlock; -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeExpressionForDisallowedComma(expression); +// node->caseBlock = caseBlock; +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.caseBlock); // return node; @@ -3075,9 +3691,9 @@ namespace ts::factory { // // @api // function createLabeledStatement(label: string | Identifier, statement: Statement) { // auto node = createBaseNode(SyntaxKind::LabeledStatement); -// node.label = asName(label); -// node.statement = asEmbeddedStatement(statement); -// node.transformFlags |= +// node->label = asName(label); +// node->statement = asEmbeddedStatement(statement); +// node->transformFlags |= // propagateChildFlags(node.label) | // propagateChildFlags(node.statement); // return node; @@ -3094,8 +3710,8 @@ namespace ts::factory { // // @api // function createThrowStatement(expression: Expression) { // auto node = createBaseNode(SyntaxKind::ThrowStatement); -// node.expression = expression; -// node.transformFlags |= propagateChildFlags(node.expression); +// node->expression = expression; +// node->transformFlags |= propagateChildFlags(node.expression); // return node; // } // @@ -3109,10 +3725,10 @@ namespace ts::factory { // // @api // function createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { // auto node = createBaseNode(SyntaxKind::TryStatement); -// node.tryBlock = tryBlock; -// node.catchClause = catchClause; -// node.finallyBlock = finallyBlock; -// node.transformFlags |= +// node->tryBlock = tryBlock; +// node->catchClause = catchClause; +// node->finallyBlock = finallyBlock; +// node->transformFlags |= // propagateChildFlags(node.tryBlock) | // propagateChildFlags(node.catchClause) | // propagateChildFlags(node.finallyBlock); @@ -3141,12 +3757,12 @@ namespace ts::factory { // /*modifiers*/ undefined, // name, // type, -// initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) +// initializer && parenthesizerRules::parenthesizeExpressionForDisallowedComma(initializer) // ); -// node.exclamationToken = exclamationToken; -// node.transformFlags |= propagateChildFlags(node.exclamationToken); +// node->exclamationToken = exclamationToken; +// node->transformFlags |= propagateChildFlags(node.exclamationToken); // if (exclamationToken) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // return node; // } @@ -3164,13 +3780,13 @@ namespace ts::factory { // // @api // function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) { // auto node = createBaseNode(SyntaxKind::VariableDeclarationList); -// node.flags |= flags & NodeFlags.BlockScoped; -// node.declarations = createNodeArray(declarations); -// node.transformFlags |= +// node->flags |= flags & NodeFlags.BlockScoped; +// node->declarations = createNodeArray(declarations); +// node->transformFlags |= // propagateChildrenFlags(node.declarations) | // TransformFlags::ContainsHoistedDeclarationOrCompletion; // if (flags & NodeFlags.BlockScoped) { -// node.transformFlags |= +// node->transformFlags |= // TransformFlags::ContainsES2015 | // TransformFlags::ContainsBlockScopedBinding; // } @@ -3205,24 +3821,24 @@ namespace ts::factory { // type, // body // ); -// node.asteriskToken = asteriskToken; +// node->asteriskToken = asteriskToken; // if (!node.body || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // } // else { -// node.transformFlags |= +// node->transformFlags |= // propagateChildFlags(node.asteriskToken) | // TransformFlags::ContainsHoistedDeclarationOrCompletion; // if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { // if (node.asteriskToken) { -// node.transformFlags |= TransformFlags::ContainsES2018; +// node->transformFlags |= TransformFlags::ContainsES2018; // } // else { -// node.transformFlags |= TransformFlags::ContainsES2017; +// node->transformFlags |= TransformFlags::ContainsES2017; // } // } // else if (node.asteriskToken) { -// node.transformFlags |= TransformFlags::ContainsGenerator; +// node->transformFlags |= TransformFlags::ContainsGenerator; // } // } // return node; @@ -3271,12 +3887,12 @@ namespace ts::factory { // members // ); // if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // } // else { -// node.transformFlags |= TransformFlags::ContainsES2015; +// node->transformFlags |= TransformFlags::ContainsES2015; // if (node.transformFlags & TransformFlags::ContainsTypeScriptClassSyntax) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } // } // return node; @@ -3319,8 +3935,8 @@ namespace ts::factory { // typeParameters, // heritageClauses // ); -// node.members = createNodeArray(members); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->members = createNodeArray(members); +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -3359,8 +3975,8 @@ namespace ts::factory { // name, // typeParameters // ); -// node.type = type; -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->type = type; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -3395,11 +4011,11 @@ namespace ts::factory { // modifiers, // name // ); -// node.members = createNodeArray(members); -// node.transformFlags |= +// node->members = createNodeArray(members); +// node->transformFlags |= // propagateChildrenFlags(node.members) | // TransformFlags::ContainsTypeScript; -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await` +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await` // return node; // } // @@ -3431,19 +4047,19 @@ namespace ts::factory { // decorators, // modifiers // ); -// node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); -// node.name = name; -// node.body = body; +// node->flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); +// node->name = name; +// node->body = body; // if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // } // else { -// node.transformFlags |= +// node->transformFlags |= // propagateChildFlags(node.name) | // propagateChildFlags(node.body) | // TransformFlags::ContainsTypeScript; // } -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`. +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`. // return node; // } // @@ -3466,8 +4082,8 @@ namespace ts::factory { // // @api // function createModuleBlock(statements: readonly Statement[]) { // auto node = createBaseNode(SyntaxKind::ModuleBlock); -// node.statements = createNodeArray(statements); -// node.transformFlags |= propagateChildrenFlags(node.statements); +// node->statements = createNodeArray(statements); +// node->transformFlags |= propagateChildrenFlags(node.statements); // return node; // } // @@ -3481,8 +4097,8 @@ namespace ts::factory { // // @api // function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock { // auto node = createBaseNode(SyntaxKind::CaseBlock); -// node.clauses = createNodeArray(clauses); -// node.transformFlags |= propagateChildrenFlags(node.clauses); +// node->clauses = createNodeArray(clauses); +// node->transformFlags |= propagateChildrenFlags(node.clauses); // return node; // } // @@ -3501,7 +4117,7 @@ namespace ts::factory { // /*modifiers*/ undefined, // name // ); -// node.transformFlags = TransformFlags::ContainsTypeScript; +// node->transformFlags = TransformFlags::ContainsTypeScript; // return node; // } // @@ -3526,11 +4142,11 @@ namespace ts::factory { // modifiers, // name // ); -// node.isTypeOnly = isTypeOnly; -// node.moduleReference = moduleReference; -// node.transformFlags |= propagateChildFlags(node.moduleReference); +// node->isTypeOnly = isTypeOnly; +// node->moduleReference = moduleReference; +// node->transformFlags |= propagateChildFlags(node.moduleReference); // if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags::ContainsTypeScript; -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context // return node; // } // @@ -3565,13 +4181,13 @@ namespace ts::factory { // decorators, // modifiers // ); -// node.importClause = importClause; -// node.moduleSpecifier = moduleSpecifier; -// node.assertClause = assertClause; -// node.transformFlags |= +// node->importClause = importClause; +// node->moduleSpecifier = moduleSpecifier; +// node->assertClause = assertClause; +// node->transformFlags |= // propagateChildFlags(node.importClause) | // propagateChildFlags(node.moduleSpecifier); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3596,16 +4212,16 @@ namespace ts::factory { // // @api // function createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause { // auto node = createBaseNode(SyntaxKind::ImportClause); -// node.isTypeOnly = isTypeOnly; -// node.name = name; -// node.namedBindings = namedBindings; -// node.transformFlags |= +// node->isTypeOnly = isTypeOnly; +// node->name = name; +// node->namedBindings = namedBindings; +// node->transformFlags |= // propagateChildFlags(node.name) | // propagateChildFlags(node.namedBindings); // if (isTypeOnly) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // } -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3621,9 +4237,9 @@ namespace ts::factory { // // @api // function createAssertClause(elements: readonly AssertEntry[], multiLine?: boolean): AssertClause { // auto node = createBaseNode(SyntaxKind::AssertClause); -// node.elements = createNodeArray(elements); -// node.multiLine = multiLine; -// node.transformFlags |= TransformFlags::ContainsESNext; +// node->elements = createNodeArray(elements); +// node->multiLine = multiLine; +// node->transformFlags |= TransformFlags::ContainsESNext; // return node; // } // @@ -3638,9 +4254,9 @@ namespace ts::factory { // // @api // function createAssertEntry(name: AssertionKey, value: Expression): AssertEntry { // auto node = createBaseNode(SyntaxKind::AssertEntry); -// node.name = name; -// node.value = value; -// node.transformFlags |= TransformFlags::ContainsESNext; +// node->name = name; +// node->value = value; +// node->transformFlags |= TransformFlags::ContainsESNext; // return node; // } // @@ -3655,8 +4271,8 @@ namespace ts::factory { // // @api // function createImportTypeAssertionContainer(clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer { // auto node = createBaseNode(SyntaxKind::ImportTypeAssertionContainer); -// node.assertClause = clause; -// node.multiLine = multiLine; +// node->assertClause = clause; +// node->multiLine = multiLine; // return node; // } // @@ -3671,9 +4287,9 @@ namespace ts::factory { // // @api // function createNamespaceImport(name: Identifier): NamespaceImport { // auto node = createBaseNode(SyntaxKind::NamespaceImport); -// node.name = name; -// node.transformFlags |= propagateChildFlags(node.name); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->name = name; +// node->transformFlags |= propagateChildFlags(node.name); +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3687,11 +4303,11 @@ namespace ts::factory { // // @api // function createNamespaceExport(name: Identifier): NamespaceExport { // auto node = createBaseNode(SyntaxKind::NamespaceExport); -// node.name = name; -// node.transformFlags |= +// node->name = name; +// node->transformFlags |= // propagateChildFlags(node.name) | // TransformFlags::ContainsESNext; -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3705,9 +4321,9 @@ namespace ts::factory { // // @api // function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports { // auto node = createBaseNode(SyntaxKind::NamedImports); -// node.elements = createNodeArray(elements); -// node.transformFlags |= propagateChildrenFlags(node.elements); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->elements = createNodeArray(elements); +// node->transformFlags |= propagateChildrenFlags(node.elements); +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3721,13 +4337,13 @@ namespace ts::factory { // // @api // function createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) { // auto node = createBaseNode(SyntaxKind::ImportSpecifier); -// node.isTypeOnly = isTypeOnly; -// node.propertyName = propertyName; -// node.name = name; -// node.transformFlags |= +// node->isTypeOnly = isTypeOnly; +// node->propertyName = propertyName; +// node->name = name; +// node->transformFlags |= // propagateChildFlags(node.propertyName) | // propagateChildFlags(node.name); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3752,12 +4368,12 @@ namespace ts::factory { // decorators, // modifiers // ); -// node.isExportEquals = isExportEquals; -// node.expression = isExportEquals -// ? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind::EqualsToken, /*leftSide*/ undefined, expression) -// : parenthesizerRules().parenthesizeExpressionOfExportDefault(expression); -// node.transformFlags |= propagateChildFlags(node.expression); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->isExportEquals = isExportEquals; +// node->expression = isExportEquals +// ? parenthesizerRules::parenthesizeRightSideOfBinary(SyntaxKind::EqualsToken, /*leftSide*/ undefined, expression) +// : parenthesizerRules::parenthesizeExpressionOfExportDefault(expression); +// node->transformFlags |= propagateChildFlags(node.expression); +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3789,14 +4405,14 @@ namespace ts::factory { // decorators, // modifiers // ); -// node.isTypeOnly = isTypeOnly; -// node.exportClause = exportClause; -// node.moduleSpecifier = moduleSpecifier; -// node.assertClause = assertClause; -// node.transformFlags |= +// node->isTypeOnly = isTypeOnly; +// node->exportClause = exportClause; +// node->moduleSpecifier = moduleSpecifier; +// node->assertClause = assertClause; +// node->transformFlags |= // propagateChildFlags(node.exportClause) | // propagateChildFlags(node.moduleSpecifier); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3823,9 +4439,9 @@ namespace ts::factory { // // @api // function createNamedExports(elements: readonly ExportSpecifier[]) { // auto node = createBaseNode(SyntaxKind::NamedExports); -// node.elements = createNodeArray(elements); -// node.transformFlags |= propagateChildrenFlags(node.elements); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->elements = createNodeArray(elements); +// node->transformFlags |= propagateChildrenFlags(node.elements); +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3839,13 +4455,13 @@ namespace ts::factory { // // @api // function createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier) { // auto node = createBaseNode(SyntaxKind::ExportSpecifier); -// node.isTypeOnly = isTypeOnly; -// node.propertyName = asName(propertyName); -// node.name = asName(name); -// node.transformFlags |= +// node->isTypeOnly = isTypeOnly; +// node->propertyName = asName(propertyName); +// node->name = asName(name); +// node->transformFlags |= // propagateChildFlags(node.propertyName) | // propagateChildFlags(node.name); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3858,16 +4474,16 @@ namespace ts::factory { // : node; // } // -// // @api -// function createMissingDeclaration() { -// auto node = createBaseDeclaration( -// SyntaxKind::MissingDeclaration, -// /*decorators*/ undefined, -// /*modifiers*/ undefined -// ); -// return node; -// } -// + // @api + shared createMissingDeclaration() { + auto node = createBaseDeclaration( + SyntaxKind::MissingDeclaration, + /*decorators*/ {}, + /*modifiers*/ {} + ); + return node; + } + // // // // Module references // // @@ -3875,9 +4491,9 @@ namespace ts::factory { // // @api // function createExternalModuleReference(expression: Expression) { // auto node = createBaseNode(SyntaxKind::ExternalModuleReference); -// node.expression = expression; -// node.transformFlags |= propagateChildFlags(node.expression); -// node.transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context +// node->expression = expression; +// node->transformFlags |= propagateChildFlags(node.expression); +// node->transformFlags &= ~TransformFlags::ContainsPossibleTopLevelAwait; // always parsed in an Await context // return node; // } // @@ -3905,9 +4521,9 @@ namespace ts::factory { // function createJSDocPrePostfixUnaryTypeWorker(kind: T["kind"], type: T["type"], postfix = false): T { // auto node = createJSDocUnaryTypeWorker( // kind, -// postfix ? type && parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(type) : type +// postfix ? type && parenthesizerRules::parenthesizeNonArrayTypeOfPostfixType(type) : type // ) as Mutable; -// node.postfix = postfix; +// node->postfix = postfix; // return node; // } // @@ -3917,7 +4533,7 @@ namespace ts::factory { // // createJSDocNamepathType // function createJSDocUnaryTypeWorker(kind: T["kind"], type: T["type"]): T { // auto node = createBaseNode(kind); -// node.type = type; +// node->type = type; // return node; // } // @@ -3965,8 +4581,8 @@ namespace ts::factory { // // @api // function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType = false): JSDocTypeLiteral { // auto node = createBaseNode(SyntaxKind::JSDocTypeLiteral); -// node.jsDocPropertyTags = asNodeArray(propertyTags); -// node.isArrayType = isArrayType; +// node->jsDocPropertyTags = asNodeArray(propertyTags); +// node->isArrayType = isArrayType; // return node; // } // @@ -3981,7 +4597,7 @@ namespace ts::factory { // // @api // function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression { // auto node = createBaseNode(SyntaxKind::JSDocTypeExpression); -// node.type = type; +// node->type = type; // return node; // } // @@ -3995,9 +4611,9 @@ namespace ts::factory { // // @api // function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature { // auto node = createBaseNode(SyntaxKind::JSDocSignature); -// node.typeParameters = asNodeArray(typeParameters); -// node.parameters = createNodeArray(parameters); -// node.type = type; +// node->typeParameters = asNodeArray(typeParameters); +// node->parameters = createNodeArray(parameters); +// node->type = type; // return node; // } // @@ -4020,16 +4636,16 @@ namespace ts::factory { // // @api // function createBaseJSDocTag(kind: T["kind"], tagName: Identifier, comment: string | NodeArray | undefined) { // auto node = createBaseNode(kind); -// node.tagName = tagName; -// node.comment = comment; +// node->tagName = tagName; +// node->comment = comment; // return node; // } // // // @api // function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray): JSDocTemplateTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocTemplateTag, tagName ?? createIdentifier("template"), comment); -// node.constraint = constraint; -// node.typeParameters = createNodeArray(typeParameters); +// node->constraint = constraint; +// node->typeParameters = createNodeArray(typeParameters); // return node; // } // @@ -4046,9 +4662,9 @@ namespace ts::factory { // // @api // function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocTypedefTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment); -// node.typeExpression = typeExpression; -// node.fullName = fullName; -// node.name = getJSDocTypeAliasName(fullName); +// node->typeExpression = typeExpression; +// node->fullName = fullName; +// node->name = getJSDocTypeAliasName(fullName); // return node; // } // @@ -4065,10 +4681,10 @@ namespace ts::factory { // // @api // function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocParameterTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocParameterTag, tagName ?? createIdentifier("param"), comment); -// node.typeExpression = typeExpression; -// node.name = name; -// node.isNameFirst = !!isNameFirst; -// node.isBracketed = isBracketed; +// node->typeExpression = typeExpression; +// node->name = name; +// node->isNameFirst = !!isNameFirst; +// node->isBracketed = isBracketed; // return node; // } // @@ -4087,10 +4703,10 @@ namespace ts::factory { // // @api // function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocPropertyTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment); -// node.typeExpression = typeExpression; -// node.name = name; -// node.isNameFirst = !!isNameFirst; -// node.isBracketed = isBracketed; +// node->typeExpression = typeExpression; +// node->name = name; +// node->isNameFirst = !!isNameFirst; +// node->isBracketed = isBracketed; // return node; // } // @@ -4109,9 +4725,9 @@ namespace ts::factory { // // @api // function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment); -// node.typeExpression = typeExpression; -// node.fullName = fullName; -// node.name = getJSDocTypeAliasName(fullName); +// node->typeExpression = typeExpression; +// node->fullName = fullName; +// node->name = getJSDocTypeAliasName(fullName); // return node; // } // @@ -4128,7 +4744,7 @@ namespace ts::factory { // // @api // function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment); -// node.class = className; +// node->class = className; // return node; // } // @@ -4144,14 +4760,14 @@ namespace ts::factory { // // @api // function createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocImplementsTag, tagName ?? createIdentifier("implements"), comment); -// node.class = className; +// node->class = className; // return node; // } // // // @api // function createJSDocSeeTag(tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag { // auto node = createBaseJSDocTag(SyntaxKind::JSDocSeeTag, tagName ?? createIdentifier("see"), comment); -// node.name = name; +// node->name = name; // return node; // } // @@ -4167,7 +4783,7 @@ namespace ts::factory { // // @api // function createJSDocNameReference(name: EntityName | JSDocMemberName): JSDocNameReference { // auto node = createBaseNode(SyntaxKind::JSDocNameReference); -// node.name = name; +// node->name = name; // return node; // } // @@ -4181,9 +4797,9 @@ namespace ts::factory { // // @api // function createJSDocMemberName(left: EntityName | JSDocMemberName, right: Identifier) { // auto node = createBaseNode(SyntaxKind::JSDocMemberName); -// node.left = left; -// node.right = right; -// node.transformFlags |= +// node->left = left; +// node->right = right; +// node->transformFlags |= // propagateChildFlags(node.left) | // propagateChildFlags(node.right); // return node; @@ -4200,8 +4816,8 @@ namespace ts::factory { // // @api // function createJSDocLink(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink { // auto node = createBaseNode(SyntaxKind::JSDocLink); -// node.name = name; -// node.text = text; +// node->name = name; +// node->text = text; // return node; // } // @@ -4215,8 +4831,8 @@ namespace ts::factory { // // @api // function createJSDocLinkCode(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode { // auto node = createBaseNode(SyntaxKind::JSDocLinkCode); -// node.name = name; -// node.text = text; +// node->name = name; +// node->text = text; // return node; // } // @@ -4230,8 +4846,8 @@ namespace ts::factory { // // @api // function createJSDocLinkPlain(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain { // auto node = createBaseNode(SyntaxKind::JSDocLinkPlain); -// node.name = name; -// node.text = text; +// node->name = name; +// node->text = text; // return node; // } // @@ -4286,7 +4902,7 @@ namespace ts::factory { // // createJSDocEnumTag // function createJSDocTypeLikeTagWorker(kind: T["kind"], tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string | NodeArray) { // auto node = createBaseJSDocTag(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment); -// node.typeExpression = typeExpression; +// node->typeExpression = typeExpression; // return node; // } // @@ -4320,7 +4936,7 @@ namespace ts::factory { // // @api // function createJSDocText(text: string): JSDocText { // auto node = createBaseNode(SyntaxKind::JSDocText); -// node.text = text; +// node->text = text; // return node; // } // @@ -4334,8 +4950,8 @@ namespace ts::factory { // // @api // function createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined) { // auto node = createBaseNode(SyntaxKind::JSDoc); -// node.comment = comment; -// node.tags = asNodeArray(tags); +// node->comment = comment; +// node->tags = asNodeArray(tags); // return node; // } // @@ -4351,20 +4967,20 @@ namespace ts::factory { // // JSX // // // -// // @api -// function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { -// auto node = createBaseNode(SyntaxKind::JsxElement); -// node.openingElement = openingElement; -// node.children = createNodeArray(children); -// node.closingElement = closingElement; -// node.transformFlags |= -// propagateChildFlags(node.openingElement) | -// propagateChildrenFlags(node.children) | -// propagateChildFlags(node.closingElement) | -// TransformFlags::ContainsJsx; -// return node; -// } -// + // @api + shared createJsxElement(shared openingElement, NodeArray children, shared closingElement) { + auto node = createBaseNode(SyntaxKind::JsxElement); + node->openingElement = openingElement; + node->children = createNodeArray(children); + node->closingElement = closingElement; + node->transformFlags |= + propagateChildFlags(node->openingElement) | + propagateChildrenFlags(node->children) | + propagateChildFlags(node->closingElement) | + (int) TransformFlags::ContainsJsx; + return node; + } + // // @api // function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { // return node.openingElement != openingElement @@ -4373,23 +4989,23 @@ namespace ts::factory { // ? update(createJsxElement(openingElement, children, closingElement), node) // : node; // } -// -// // @api -// function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { -// auto node = createBaseNode(SyntaxKind::JsxSelfClosingElement); -// node.tagName = tagName; -// node.typeArguments = asNodeArray(typeArguments); -// node.attributes = attributes; -// node.transformFlags |= -// propagateChildFlags(node.tagName) | -// propagateChildrenFlags(node.typeArguments) | -// propagateChildFlags(node.attributes) | -// TransformFlags::ContainsJsx; -// if (node.typeArguments) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; -// } -// return node; -// } + + // @api + shared createJsxSelfClosingElement(shared tagName, optional typeArguments, shared attributes) { + auto node = createBaseNode(SyntaxKind::JsxSelfClosingElement); + node->tagName = tagName; + node->typeArguments = asNodeArray(typeArguments); + node->attributes = attributes; + node->transformFlags |= + propagateChildFlags(node->tagName) | + propagateChildrenFlags(node->typeArguments) | + propagateChildFlags(node->attributes) | + (int)TransformFlags::ContainsJsx; + if (node->typeArguments) { + node->transformFlags |= (int)TransformFlags::ContainsTypeScript; + } + return node; + } // // // @api // function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { @@ -4400,22 +5016,22 @@ namespace ts::factory { // : node; // } // -// // @api -// function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { -// auto node = createBaseNode(SyntaxKind::JsxOpeningElement); -// node.tagName = tagName; -// node.typeArguments = asNodeArray(typeArguments); -// node.attributes = attributes; -// node.transformFlags |= -// propagateChildFlags(node.tagName) | -// propagateChildrenFlags(node.typeArguments) | -// propagateChildFlags(node.attributes) | -// TransformFlags::ContainsJsx; -// if (typeArguments) { -// node.transformFlags |= TransformFlags::ContainsTypeScript; -// } -// return node; -// } + // @api + shared createJsxOpeningElement(shared tagName, optional typeArguments, shared attributes) { + auto node = createBaseNode(SyntaxKind::JsxOpeningElement); + node->tagName = tagName; + node->typeArguments = asNodeArray(typeArguments); + node->attributes = attributes; + node->transformFlags |= + propagateChildFlags(node->tagName) | + propagateChildrenFlags(node->typeArguments) | + propagateChildFlags(node->attributes) | + (int) TransformFlags::ContainsJsx; + if (typeArguments) { + node->transformFlags |= (int) TransformFlags::ContainsTypeScript; + } + return node; + } // // // @api // function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { @@ -4426,37 +5042,37 @@ namespace ts::factory { // : node; // } // -// // @api -// function createJsxClosingElement(tagName: JsxTagNameExpression) { -// auto node = createBaseNode(SyntaxKind::JsxClosingElement); -// node.tagName = tagName; -// node.transformFlags |= -// propagateChildFlags(node.tagName) | -// TransformFlags::ContainsJsx; -// return node; -// } -// + // @api + shared createJsxClosingElement(shared tagName) { + auto node = createBaseNode(SyntaxKind::JsxClosingElement); + node->tagName = tagName; + node->transformFlags |= + propagateChildFlags(node->tagName) | + (int) TransformFlags::ContainsJsx; + return node; + } + // // @api // function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) { // return node.tagName != tagName // ? update(createJsxClosingElement(tagName), node) // : node; // } -// -// // @api -// function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { -// auto node = createBaseNode(SyntaxKind::JsxFragment); -// node.openingFragment = openingFragment; -// node.children = createNodeArray(children); -// node.closingFragment = closingFragment; -// node.transformFlags |= -// propagateChildFlags(node.openingFragment) | -// propagateChildrenFlags(node.children) | -// propagateChildFlags(node.closingFragment) | -// TransformFlags::ContainsJsx; -// return node; -// } -// + + // @api + shared createJsxFragment(shared openingFragment, NodeArray children, shared closingFragment) { + auto node = createBaseNode(SyntaxKind::JsxFragment); + node->openingFragment = openingFragment; + node->children = createNodeArray(children); + node->closingFragment = closingFragment; + node->transformFlags |= + propagateChildFlags(node->openingFragment) | + propagateChildrenFlags(node->children) | + propagateChildFlags(node->closingFragment) | + (int) TransformFlags::ContainsJsx; + return node; + } + // // @api // function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { // return node.openingFragment != openingFragment @@ -4466,14 +5082,6 @@ namespace ts::factory { // : node; // } // -// // @api -// function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) { -// auto node = createBaseNode(SyntaxKind::JsxText); -// node.text = text; -// node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; -// node.transformFlags |= TransformFlags::ContainsJsx; -// return node; -// } // // // @api // function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { @@ -4483,32 +5091,32 @@ namespace ts::factory { // : node; // } // -// // @api -// function createJsxOpeningFragment() { -// auto node = createBaseNode(SyntaxKind::JsxOpeningFragment); -// node.transformFlags |= TransformFlags::ContainsJsx; -// return node; -// } -// -// // @api -// function createJsxJsxClosingFragment() { -// auto node = createBaseNode(SyntaxKind::JsxClosingFragment); -// node.transformFlags |= TransformFlags::ContainsJsx; -// return node; -// } -// -// // @api -// function createJsxAttribute(name: Identifier, initializer: JsxAttributeValue | undefined) { -// auto node = createBaseNode(SyntaxKind::JsxAttribute); -// node.name = name; -// node.initializer = initializer; -// node.transformFlags |= -// propagateChildFlags(node.name) | -// propagateChildFlags(node.initializer) | -// TransformFlags::ContainsJsx; -// return node; -// } -// + // @api + shared createJsxOpeningFragment() { + auto node = createBaseNode(SyntaxKind::JsxOpeningFragment); + node->transformFlags |= (int) TransformFlags::ContainsJsx; + return node; + } + + // @api + shared createJsxJsxClosingFragment() { + auto node = createBaseNode(SyntaxKind::JsxClosingFragment); + node->transformFlags |= (int) TransformFlags::ContainsJsx; + return node; + } + + // @api + shared createJsxAttribute(shared name, sharedOpt initializer = {}) { + auto node = createBaseNode(SyntaxKind::JsxAttribute); + node->name = name; + node->initializer = initializer; + node->transformFlags |= + propagateChildFlags(node->name) | + propagateChildFlags(node->initializer) | + (int) TransformFlags::ContainsJsx; + return node; + } + // // @api // function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: JsxAttributeValue | undefined) { // return node.name != name @@ -4517,15 +5125,15 @@ namespace ts::factory { // : node; // } // -// // @api -// function createJsxAttributes(properties: readonly JsxAttributeLike[]) { -// auto node = createBaseNode(SyntaxKind::JsxAttributes); -// node.properties = createNodeArray(properties); -// node.transformFlags |= -// propagateChildrenFlags(node.properties) | -// TransformFlags::ContainsJsx; -// return node; -// } + // @api + shared createJsxAttributes(NodeArray properties) { + auto node = createBaseNode(SyntaxKind::JsxAttributes); + node->properties = createNodeArray(properties); + node->transformFlags |= + propagateChildrenFlags(node->properties) | + (int) TransformFlags::ContainsJsx; + return node; + } // // // @api // function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) { @@ -4533,17 +5141,17 @@ namespace ts::factory { // ? update(createJsxAttributes(properties), node) // : node; // } -// -// // @api -// function createJsxSpreadAttribute(expression: Expression) { -// auto node = createBaseNode(SyntaxKind::JsxSpreadAttribute); -// node.expression = expression; -// node.transformFlags |= -// propagateChildFlags(node.expression) | -// TransformFlags::ContainsJsx; -// return node; -// } -// + + // @api + shared createJsxSpreadAttribute(shared expression) { + auto node = createBaseNode(SyntaxKind::JsxSpreadAttribute); + node->expression = expression; + node->transformFlags |= + propagateChildFlags(node->expression) | + (int) TransformFlags::ContainsJsx; + return node; + } + // // @api // function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) { // return node.expression != expression @@ -4551,18 +5159,18 @@ namespace ts::factory { // : node; // } // -// // @api -// function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) { -// auto node = createBaseNode(SyntaxKind::JsxExpression); -// node.dotDotDotToken = dotDotDotToken; -// node.expression = expression; -// node.transformFlags |= -// propagateChildFlags(node.dotDotDotToken) | -// propagateChildFlags(node.expression) | -// TransformFlags::ContainsJsx; -// return node; -// } -// + // @api + shared createJsxExpression(sharedOpt dotDotDotToken, sharedOpt expression) { + auto node = createBaseNode(SyntaxKind::JsxExpression); + node->dotDotDotToken = dotDotDotToken; + node->expression = expression; + node->transformFlags |= + propagateChildFlags(node->dotDotDotToken) | + propagateChildFlags(node->expression) | + (int) TransformFlags::ContainsJsx; + return node; + } + // // @api // function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) { // return node.expression != expression @@ -4577,9 +5185,9 @@ namespace ts::factory { // // @api // function createCaseClause(expression: Expression, statements: readonly Statement[]) { // auto node = createBaseNode(SyntaxKind::CaseClause); -// node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); -// node.statements = createNodeArray(statements); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeExpressionForDisallowedComma(expression); +// node->statements = createNodeArray(statements); +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildrenFlags(node.statements); // return node; @@ -4596,8 +5204,8 @@ namespace ts::factory { // // @api // function createDefaultClause(statements: readonly Statement[]) { // auto node = createBaseNode(SyntaxKind::DefaultClause); -// node.statements = createNodeArray(statements); -// node.transformFlags = propagateChildrenFlags(node.statements); +// node->statements = createNodeArray(statements); +// node->transformFlags = propagateChildrenFlags(node.statements); // return node; // } // @@ -4611,15 +5219,15 @@ namespace ts::factory { // // @api // function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]) { // auto node = createBaseNode(SyntaxKind::HeritageClause); -// node.token = token; -// node.types = createNodeArray(types); -// node.transformFlags |= propagateChildrenFlags(node.types); +// node->token = token; +// node->types = createNodeArray(types); +// node->transformFlags |= propagateChildrenFlags(node.types); // switch (token) { // case SyntaxKind::ExtendsKeyword: -// node.transformFlags |= TransformFlags::ContainsES2015; +// node->transformFlags |= TransformFlags::ContainsES2015; // break; // case SyntaxKind::ImplementsKeyword: -// node.transformFlags |= TransformFlags::ContainsTypeScript; +// node->transformFlags |= TransformFlags::ContainsTypeScript; // break; // default: // return Debug.assertNever(token); @@ -4645,9 +5253,9 @@ namespace ts::factory { // /*initializer*/ undefined // ); // } -// node.variableDeclaration = variableDeclaration; -// node.block = block; -// node.transformFlags |= +// node->variableDeclaration = variableDeclaration; +// node->block = block; +// node->transformFlags |= // propagateChildFlags(node.variableDeclaration) | // propagateChildFlags(node.block); // if (!variableDeclaration) node.transformFlags |= TransformFlags::ContainsES2019; @@ -4674,8 +5282,8 @@ namespace ts::factory { // /*modifiers*/ undefined, // name // ); -// node.initializer = parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer); -// node.transformFlags |= +// node->initializer = parenthesizerRules::parenthesizeExpressionForDisallowedComma(initializer); +// node->transformFlags |= // propagateChildFlags(node.name) | // propagateChildFlags(node.initializer); // return node; @@ -4706,8 +5314,8 @@ namespace ts::factory { // /*modifiers*/ undefined, // name // ); -// node.objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer); -// node.transformFlags |= +// node->objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules::parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer); +// node->transformFlags |= // propagateChildFlags(node.objectAssignmentInitializer) | // TransformFlags::ContainsES2015; // return node; @@ -4734,8 +5342,8 @@ namespace ts::factory { // // @api // function createSpreadAssignment(expression: Expression) { // auto node = createBaseNode(SyntaxKind::SpreadAssignment); -// node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); -// node.transformFlags |= +// node->expression = parenthesizerRules::parenthesizeExpressionForDisallowedComma(expression); +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsES2018 | // TransformFlags::ContainsObjectRestOrSpread; @@ -4756,9 +5364,9 @@ namespace ts::factory { // // @api // function createEnumMember(name: string | PropertyName, initializer?: Expression) { // auto node = createBaseNode(SyntaxKind::EnumMember); -// node.name = asName(name); -// node.initializer = initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer); -// node.transformFlags |= +// node->name = asName(name); +// node->initializer = initializer && parenthesizerRules::parenthesizeExpressionForDisallowedComma(initializer); +// node->transformFlags |= // propagateChildFlags(node.name) | // propagateChildFlags(node.initializer) | // TransformFlags::ContainsTypeScript; @@ -4783,18 +5391,18 @@ namespace ts::factory { // endOfFileToken: EndOfFileToken, // flags: NodeFlags // ) { -// auto node = baseFactory.createBaseSourceFileNode(SyntaxKind::SourceFile) as Mutable; -// node.statements = createNodeArray(statements); -// node.endOfFileToken = endOfFileToken; -// node.flags |= flags; -// node.fileName = ""; -// node.text = ""; -// node.languageVersion = 0; -// node.languageVariant = 0; -// node.scriptKind = 0; -// node.isDeclarationFile = false; -// node.hasNoDefaultLib = false; -// node.transformFlags |= +// auto node = basefactory::createBaseSourceFileNode(SyntaxKind::SourceFile) as Mutable; +// node->statements = createNodeArray(statements); +// node->endOfFileToken = endOfFileToken; +// node->flags |= flags; +// node->fileName = ""; +// node->text = ""; +// node->languageVersion = 0; +// node->languageVariant = 0; +// node->scriptKind = 0; +// node->isDeclarationFile = false; +// node->hasNoDefaultLib = false; +// node->transformFlags |= // propagateChildrenFlags(node.statements) | // propagateChildFlags(node.endOfFileToken); // return node; @@ -4809,23 +5417,23 @@ namespace ts::factory { // hasNoDefaultLib: boolean, // libReferences: readonly FileReference[] // ) { -// auto node = (source.redirectInfo ? Object.create(source.redirectInfo.redirectTarget) : baseFactory.createBaseSourceFileNode(SyntaxKind::SourceFile)) as Mutable; +// auto node = (source.redirectInfo ? Object.create(source.redirectInfo.redirectTarget) : basefactory::createBaseSourceFileNode(SyntaxKind::SourceFile)) as Mutable; // for (auto p in source) { // if (p == "emitNode" || hasProperty(node, p) || !hasProperty(source, p)) continue; // (node as any)[p] = (source as any)[p]; // } -// node.flags |= source.flags; -// node.statements = createNodeArray(statements); -// node.endOfFileToken = source.endOfFileToken; -// node.isDeclarationFile = isDeclarationFile; -// node.referencedFiles = referencedFiles; -// node.typeReferenceDirectives = typeReferences; -// node.hasNoDefaultLib = hasNoDefaultLib; -// node.libReferenceDirectives = libReferences; -// node.transformFlags = +// node->flags |= source.flags; +// node->statements = createNodeArray(statements); +// node->endOfFileToken = source.endOfFileToken; +// node->isDeclarationFile = isDeclarationFile; +// node->referencedFiles = referencedFiles; +// node->typeReferenceDirectives = typeReferences; +// node->hasNoDefaultLib = hasNoDefaultLib; +// node->libReferenceDirectives = libReferences; +// node->transformFlags = // propagateChildrenFlags(node.statements) | // propagateChildFlags(node.endOfFileToken); -// node.impliedNodeFormat = source.impliedNodeFormat; +// node->impliedNodeFormat = source.impliedNodeFormat; // return node; // } // @@ -4852,8 +5460,8 @@ namespace ts::factory { // // @api // function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { // auto node = createBaseNode(SyntaxKind::Bundle); -// node.prepends = prepends; -// node.sourceFiles = sourceFiles; +// node->prepends = prepends; +// node->sourceFiles = sourceFiles; // return node; // } // @@ -4868,20 +5476,20 @@ namespace ts::factory { // // @api // function createUnparsedSource(prologues: readonly UnparsedPrologue[], syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, texts: readonly UnparsedSourceText[]) { // auto node = createBaseNode(SyntaxKind::UnparsedSource); -// node.prologues = prologues; -// node.syntheticReferences = syntheticReferences; -// node.texts = texts; -// node.fileName = ""; -// node.text = ""; -// node.referencedFiles = emptyArray; -// node.libReferenceDirectives = emptyArray; -// node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos); +// node->prologues = prologues; +// node->syntheticReferences = syntheticReferences; +// node->texts = texts; +// node->fileName = ""; +// node->text = ""; +// node->referencedFiles = emptyArray; +// node->libReferenceDirectives = emptyArray; +// node->getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos); // return node; // } // // function createBaseUnparsedNode(kind: T["kind"], data?: string) { // auto node = createBaseNode(kind); -// node.data = data; +// node->data = data; // return node; // } // @@ -4893,7 +5501,7 @@ namespace ts::factory { // // @api // function createUnparsedPrepend(data: string | undefined, texts: readonly UnparsedTextLike[]): UnparsedPrepend { // auto node = createBaseUnparsedNode(SyntaxKind::UnparsedPrepend, data); -// node.texts = texts; +// node->texts = texts; // return node; // } // @@ -4905,16 +5513,16 @@ namespace ts::factory { // // @api // function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference): UnparsedSyntheticReference { // auto node = createBaseNode(SyntaxKind::UnparsedSyntheticReference); -// node.data = section.data; -// node.section = section; +// node->data = section.data; +// node->section = section; // return node; // } // // // @api // function createInputFiles(): InputFiles { // auto node = createBaseNode(SyntaxKind::InputFiles); -// node.javascriptText = ""; -// node.declarationText = ""; +// node->javascriptText = ""; +// node->declarationText = ""; // return node; // } // @@ -4925,16 +5533,16 @@ namespace ts::factory { // // @api // function createSyntheticExpression(type: Type, isSpread = false, tupleNameSource?: ParameterDeclaration | NamedTupleMember) { // auto node = createBaseNode(SyntaxKind::SyntheticExpression); -// node.type = type; -// node.isSpread = isSpread; -// node.tupleNameSource = tupleNameSource; +// node->type = type; +// node->isSpread = isSpread; +// node->tupleNameSource = tupleNameSource; // return node; // } // // // @api // function createSyntaxList(children: Node[]) { // auto node = createBaseNode(SyntaxKind::SyntaxList); -// node._children = children; +// node->_children = children; // return node; // } // @@ -4951,7 +5559,7 @@ namespace ts::factory { // // @api // function createNotEmittedStatement(original: Node) { // auto node = createBaseNode(SyntaxKind::NotEmittedStatement); -// node.original = original; +// node->original = original; // setTextRange(node, original); // return node; // } @@ -4966,9 +5574,9 @@ namespace ts::factory { // // @api // function createPartiallyEmittedExpression(expression: Expression, original?: Node) { // auto node = createBaseNode(SyntaxKind::PartiallyEmittedExpression); -// node.expression = expression; -// node.original = original; -// node.transformFlags |= +// node->expression = expression; +// node->original = original; +// node->transformFlags |= // propagateChildFlags(node.expression) | // TransformFlags::ContainsTypeScript; // setTextRange(node, original); @@ -4997,8 +5605,8 @@ namespace ts::factory { // // @api // function createCommaListExpression(elements: readonly Expression[]) { // auto node = createBaseNode(SyntaxKind::CommaListExpression); -// node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements)); -// node.transformFlags |= propagateChildrenFlags(node.elements); +// node->elements = createNodeArray(sameFlatMap(elements, flattenCommaElements)); +// node->transformFlags |= propagateChildrenFlags(node.elements); // return node; // } // @@ -5016,8 +5624,8 @@ namespace ts::factory { // // @api // function createEndOfDeclarationMarker(original: Node) { // auto node = createBaseNode(SyntaxKind::EndOfDeclarationMarker); -// node.emitNode = {} as EmitNode; -// node.original = original; +// node->emitNode = {} as EmitNode; +// node->original = original; // return node; // } // @@ -5028,17 +5636,17 @@ namespace ts::factory { // // @api // function createMergeDeclarationMarker(original: Node) { // auto node = createBaseNode(SyntaxKind::MergeDeclarationMarker); -// node.emitNode = {} as EmitNode; -// node.original = original; +// node->emitNode = {} as EmitNode; +// node->original = original; // return node; // } // // // @api // function createSyntheticReferenceExpression(expression: Expression, thisArg: Expression) { // auto node = createBaseNode(SyntaxKind::SyntheticReferenceExpression); -// node.expression = expression; -// node.thisArg = thisArg; -// node.transformFlags |= +// node->expression = expression; +// node->thisArg = thisArg; +// node->transformFlags |= // propagateChildFlags(node.expression) | // propagateChildFlags(node.thisArg); // return node; @@ -5063,11 +5671,11 @@ namespace ts::factory { // } // // auto clone = -// isSourceFile(node) ? baseFactory.createBaseSourceFileNode(SyntaxKind::SourceFile) as T : -// isIdentifier(node) ? baseFactory.createBaseIdentifierNode(SyntaxKind::Identifier) as T : -// isPrivateIdentifier(node) ? baseFactory.createBasePrivateIdentifierNode(SyntaxKind::PrivateIdentifier) as T : -// !isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T : -// baseFactory.createBaseNode(node.kind) as T; +// isSourceFile(node) ? basefactory::createBaseSourceFileNode(SyntaxKind::SourceFile) as T : +// isIdentifier(node) ? basefactory::createBaseIdentifierNode(SyntaxKind::Identifier) as T : +// isPrivateIdentifier(node) ? basefactory::createBasePrivateIdentifierNode(SyntaxKind::PrivateIdentifier) as T : +// !isNodeKind(node.kind) ? basefactory::createBaseTokenNode(node.kind) as T : +// basefactory::createBaseNode(node.kind) as T; // // (clone as Mutable).flags |= (node.flags & ~NodeFlags.Synthesized); // (clone as Mutable).transformFlags = node.transformFlags; @@ -5149,8 +5757,8 @@ namespace ts::factory { // // function createTypeCheck(value: Expression, tag: TypeOfTag) { // return tag == "undefined" -// ? factory.createStrictEquality(value, createVoidZero()) -// : factory.createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag)); +// ? factory::createStrictEquality(value, createVoidZero()) +// : factory::createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag)); // } // // function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) { @@ -5328,7 +5936,7 @@ namespace ts::factory { // } // else if (getEmitFlags(callee) & EmitFlags.HelperName) { // thisArg = createVoidZero(); -// target = parenthesizerRules().parenthesizeLeftSideOfAccess(callee); +// target = parenthesizerRules::parenthesizeLeftSideOfAccess(callee); // } // else if (isPropertyAccessExpression(callee)) { // if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { @@ -5336,7 +5944,7 @@ namespace ts::factory { // thisArg = createTempVariable(recordTempVariable); // target = createPropertyAccessExpression( // setTextRange( -// factory.createAssignment( +// factory::createAssignment( // thisArg, // callee.expression // ), @@ -5357,7 +5965,7 @@ namespace ts::factory { // thisArg = createTempVariable(recordTempVariable); // target = createElementAccessExpression( // setTextRange( -// factory.createAssignment( +// factory::createAssignment( // thisArg, // callee.expression // ), @@ -5375,7 +5983,7 @@ namespace ts::factory { // else { // // for `a()` target is `a` and thisArg is `void 0` // thisArg = createVoidZero(); -// target = parenthesizerRules().parenthesizeLeftSideOfAccess(expression); +// target = parenthesizerRules::parenthesizeLeftSideOfAccess(expression); // } // // return { target, thisArg }; @@ -5414,7 +6022,7 @@ namespace ts::factory { // // stack size exceeded" errors. // return expressions.length > 10 // ? createCommaListExpression(expressions) -// : reduceLeft(expressions, factory.createComma)!; +// : reduceLeft(expressions, factory::createComma)!; // } // // function getName(node: Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) { @@ -5764,11 +6372,6 @@ namespace ts::factory { // return array ? createNodeArray(array) : undefined; // } // -// function asName(name: string | T): T | Identifier { -// return typeof name == "string" ? createIdentifier(name) : -// name; -// } -// // function asExpression(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral { // return typeof value == "string" ? createStringLiteral(value) : // typeof value == "number" ? createNumericLiteral(value) : @@ -5963,11 +6566,11 @@ namespace ts::factory { // } // // auto syntheticFactory: BaseNodeFactory = { -// createBaseSourceFileNode: kind => makeSynthetic(baseFactory.createBaseSourceFileNode(kind)), -// createBaseIdentifierNode: kind => makeSynthetic(baseFactory.createBaseIdentifierNode(kind)), -// createBasePrivateIdentifierNode: kind => makeSynthetic(baseFactory.createBasePrivateIdentifierNode(kind)), -// createBaseTokenNode: kind => makeSynthetic(baseFactory.createBaseTokenNode(kind)), -// createBaseNode: kind => makeSynthetic(baseFactory.createBaseNode(kind)), +// createBaseSourceFileNode: kind => makeSynthetic(basefactory::createBaseSourceFileNode(kind)), +// createBaseIdentifierNode: kind => makeSynthetic(basefactory::createBaseIdentifierNode(kind)), +// createBasePrivateIdentifierNode: kind => makeSynthetic(basefactory::createBasePrivateIdentifierNode(kind)), +// createBaseTokenNode: kind => makeSynthetic(basefactory::createBaseTokenNode(kind)), +// createBaseNode: kind => makeSynthetic(basefactory::createBaseNode(kind)), // }; // // export auto factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, syntheticFactory); @@ -6011,17 +6614,17 @@ namespace ts::factory { // auto node = oldFileOfCurrentEmit ? // parseOldFileOfCurrentEmit(Debug.checkDefined(bundleFileInfo)) : // parseUnparsedSourceFile(bundleFileInfo, stripInternal, length); -// node.fileName = fileName; -// node.sourceMapPath = sourceMapPath; -// node.oldFileOfCurrentEmit = oldFileOfCurrentEmit; +// node->fileName = fileName; +// node->sourceMapPath = sourceMapPath; +// node->oldFileOfCurrentEmit = oldFileOfCurrentEmit; // if (getText && getSourceMapText) { // Object.defineProperty(node, "text", { get: getText }); // Object.defineProperty(node, "sourceMapText", { get: getSourceMapText }); // } // else { // Debug.assert(!oldFileOfCurrentEmit); -// node.text = text ?? ""; -// node.sourceMapText = sourceMapText; +// node->text = text ?? ""; +// node->sourceMapText = sourceMapText; // } // // return node; @@ -6040,7 +6643,7 @@ namespace ts::factory { // for (auto section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) { // switch (section.kind) { // case BundleFileSectionKind.Prologue: -// prologues = append(prologues, setTextRange(factory.createUnparsedPrologue(section.data), section)); +// prologues = append(prologues, setTextRange(factory::createUnparsedPrologue(section.data), section)); // break; // case BundleFileSectionKind.EmitHelpers: // helpers = append(helpers, getAllUnscopedEmitHelpers().get(section.data)!); @@ -6067,11 +6670,11 @@ namespace ts::factory { // let prependTexts: UnparsedTextLike[] | undefined; // for (auto text of section.texts) { // if (!stripInternal || text.kind != BundleFileSectionKind.Internal) { -// prependTexts = append(prependTexts, setTextRange(factory.createUnparsedTextLike(text.data, text.kind == BundleFileSectionKind.Internal), text)); +// prependTexts = append(prependTexts, setTextRange(factory::createUnparsedTextLike(text.data, text.kind == BundleFileSectionKind.Internal), text)); // } // } // prependChildren = addRange(prependChildren, prependTexts); -// texts = append(texts, factory.createUnparsedPrepend(section.data, prependTexts ?? emptyArray)); +// texts = append(texts, factory::createUnparsedPrepend(section.data, prependTexts ?? emptyArray)); // break; // case BundleFileSectionKind.Internal: // if (stripInternal) { @@ -6081,7 +6684,7 @@ namespace ts::factory { // // falls through // // case BundleFileSectionKind.Text: -// texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind == BundleFileSectionKind.Internal), section)); +// texts = append(texts, setTextRange(factory::createUnparsedTextLike(section.data, section.kind == BundleFileSectionKind.Internal), section)); // break; // default: // Debug.assertNever(section); @@ -6089,20 +6692,20 @@ namespace ts::factory { // } // // if (!texts) { -// auto textNode = factory.createUnparsedTextLike(/*data*/ undefined, /*internal*/ false); +// auto textNode = factory::createUnparsedTextLike(/*data*/ undefined, /*internal*/ false); // setTextRangePosWidth(textNode, 0, typeof length == "function" ? length() : length); // texts = [textNode]; // } // -// auto node = parseNodeFactory.createUnparsedSource(prologues ?? emptyArray, /*syntheticReferences*/ undefined, texts); +// auto node = parseNodefactory::createUnparsedSource(prologues ?? emptyArray, /*syntheticReferences*/ undefined, texts); // setEachParent(prologues, node); // setEachParent(texts, node); // setEachParent(prependChildren, node); -// node.hasNoDefaultLib = hasNoDefaultLib; -// node.helpers = helpers; -// node.referencedFiles = referencedFiles || emptyArray; -// node.typeReferenceDirectives = typeReferenceDirectives; -// node.libReferenceDirectives = libReferenceDirectives || emptyArray; +// node->hasNoDefaultLib = hasNoDefaultLib; +// node->helpers = helpers; +// node->referencedFiles = referencedFiles || emptyArray; +// node->typeReferenceDirectives = typeReferenceDirectives; +// node->libReferenceDirectives = libReferenceDirectives || emptyArray; // return node; // } // @@ -6113,7 +6716,7 @@ namespace ts::factory { // switch (section.kind) { // case BundleFileSectionKind.Internal: // case BundleFileSectionKind.Text: -// texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind == BundleFileSectionKind.Internal), section)); +// texts = append(texts, setTextRange(factory::createUnparsedTextLike(section.data, section.kind == BundleFileSectionKind.Internal), section)); // break; // // case BundleFileSectionKind.NoDefaultLib: @@ -6122,7 +6725,7 @@ namespace ts::factory { // case BundleFileSectionKind.TypeResolutionModeImport: // case BundleFileSectionKind.TypeResolutionModeRequire: // case BundleFileSectionKind.Lib: -// syntheticReferences = append(syntheticReferences, setTextRange(factory.createUnparsedSyntheticReference(section), section)); +// syntheticReferences = append(syntheticReferences, setTextRange(factory::createUnparsedSyntheticReference(section), section)); // break; // // // Ignore @@ -6136,10 +6739,10 @@ namespace ts::factory { // } // } // -// auto node = factory.createUnparsedSource(emptyArray, syntheticReferences, texts ?? emptyArray); +// auto node = factory::createUnparsedSource(emptyArray, syntheticReferences, texts ?? emptyArray); // setEachParent(syntheticReferences, node); // setEachParent(texts, node); -// node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!); +// node->helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!); // return node; // } // @@ -6191,7 +6794,7 @@ namespace ts::factory { // buildInfo?: BuildInfo, // oldFileOfCurrentEmit?: boolean // ): InputFiles { -// auto node = parseNodeFactory.createInputFiles(); +// auto node = parseNodefactory::createInputFiles(); // if (!isString(javascriptTextOrReadFileText)) { // auto cache = new Map(); // auto textGetter = (path: string | undefined) => { @@ -6215,11 +6818,11 @@ namespace ts::factory { // } // return buildInfo || undefined; // }; -// node.javascriptPath = declarationTextOrJavascriptPath; -// node.javascriptMapPath = javascriptMapPath; -// node.declarationPath = Debug.checkDefined(javascriptMapTextOrDeclarationPath); -// node.declarationMapPath = declarationMapPath; -// node.buildInfoPath = declarationMapTextOrBuildInfoPath; +// node->javascriptPath = declarationTextOrJavascriptPath; +// node->javascriptMapPath = javascriptMapPath; +// node->declarationPath = Debug.checkDefined(javascriptMapTextOrDeclarationPath); +// node->declarationMapPath = declarationMapPath; +// node->buildInfoPath = declarationMapTextOrBuildInfoPath; // Object.defineProperties(node, { // javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } }, // javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that @@ -6229,17 +6832,17 @@ namespace ts::factory { // }); // } // else { -// node.javascriptText = javascriptTextOrReadFileText; -// node.javascriptMapPath = javascriptMapPath; -// node.javascriptMapText = javascriptMapTextOrDeclarationPath; -// node.declarationText = declarationTextOrJavascriptPath; -// node.declarationMapPath = declarationMapPath; -// node.declarationMapText = declarationMapTextOrBuildInfoPath; -// node.javascriptPath = javascriptPath; -// node.declarationPath = declarationPath; -// node.buildInfoPath = buildInfoPath; -// node.buildInfo = buildInfo; -// node.oldFileOfCurrentEmit = oldFileOfCurrentEmit; +// node->javascriptText = javascriptTextOrReadFileText; +// node->javascriptMapPath = javascriptMapPath; +// node->javascriptMapText = javascriptMapTextOrDeclarationPath; +// node->declarationText = declarationTextOrJavascriptPath; +// node->declarationMapPath = declarationMapPath; +// node->declarationMapText = declarationMapTextOrBuildInfoPath; +// node->javascriptPath = javascriptPath; +// node->declarationPath = declarationPath; +// node->buildInfoPath = buildInfoPath; +// node->buildInfo = buildInfo; +// node->oldFileOfCurrentEmit = oldFileOfCurrentEmit; // } // return node; // } @@ -6257,7 +6860,7 @@ namespace ts::factory { // // Utilities // // export function setOriginalNode(node: T, original: Node | undefined): T { -// node.original = original; +// node->original = original; // if (original) { // auto emitNode = original.emitNode; // if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode); @@ -6302,4 +6905,4 @@ namespace ts::factory { // } // return destRanges; // } -} \ No newline at end of file +} diff --git a/src/node_test.h b/src/node_test.h index dabe773..e259d23 100644 --- a/src/node_test.h +++ b/src/node_test.h @@ -1,6 +1,6 @@ #pragma once -#include "types.h"; +#include "types.h" namespace ts { // Literals @@ -19,6 +19,23 @@ namespace ts { throw runtime_error(format("resolveNamToNode with kind %d no valid name property", (int) node->kind)); } + shared getTagName(shared node) { + switch (node->kind) { + case SyntaxKind::JsxClosingElement: return node->to().tagName; + case SyntaxKind::JsxOpeningElement: return node->to().tagName; + default: throw runtime_error(format("node %d has no tagName", node->kind)); + } + } + + string &getEscapedName(const shared &node) { + switch (node->kind) { + case SyntaxKind::Identifier: return dynamic_pointer_cast(node)->escapedText; + case SyntaxKind::PrivateIdentifier: return dynamic_pointer_cast(node)->escapedText; + } + + throw runtime_error(format("getEscapedName with kind %d no valid", (int) node->kind)); + } + sharedOpt getName(const shared &node) { //[x] Check all with `name` //[x] Check child of NamedDeclaration diff --git a/src/parser2.h b/src/parser2.h index 8757a02..76d4a68 100644 --- a/src/parser2.h +++ b/src/parser2.h @@ -75,11 +75,11 @@ namespace ts { }; -//// let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; -//// let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; -//// let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; -//// let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; -//// let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +//// auto NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +//// auto TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +//// auto IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +//// auto PrivateIdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +//// auto SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; // // /** // * NOTE: You should not use this, it is only exported to support `createNode` in `~/src/deprecatedCompat/deprecations.ts`. @@ -771,7 +771,7 @@ namespace ts { shared parseSourceFile(string fileName, string sourceText, ScriptTarget languageVersion, bool setParentNodes = false, optional scriptKind = {}, optional)>> setExternalModuleIndicatorOverride = {}); }; - shared createSourceFile(string fileName, string sourceText, variant languageVersionOrOptions, bool setParentNodes = false, optional scriptKind = {}) { + shared createSourceFile(string fileName, string sourceText, variant languageVersionOrOptions, bool setParentNodes = false, optional scriptKind = {}) { // tracing?.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true); // performance.mark("beforeParse"); shared_ptr result = make_shared(); @@ -870,22 +870,25 @@ namespace ts { // Share a single scanner across all calls to parse a source file. This helps speed things // up by avoiding the cost of creating/compiling scanners over and over again. Scanner scanner{ScriptTarget::Latest, /*skipTrivia*/ true}; + shared parseType(); + + shared createIdentifier(bool isIdentifier, optional diagnosticMessage = {}, optional privateIdentifierDiagnosticMessage = {}); // auto disallowInAndDecoratorContext = NodeFlags::DisallowInContext | NodeFlags::DecoratorContext; // // // capture constructors in 'initializeState' to avoid null checks // // tslint:disable variable-name -// let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; -// let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; -// let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; -// let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; -// let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; +// auto NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; +// auto TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; +// auto IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; +// auto PrivateIdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; +// auto SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; // // tslint:enable variable-name int nodeCount = 0; shared countNode(const shared &node) { - nodeCount++; + nodeCount ++; return node; } @@ -909,16 +912,17 @@ namespace ts { LanguageVariant languageVariant; vector parseDiagnostics; vector jsDocDiagnostics; -// let syntaxCursor: IncrementalParser.SyntaxCursor | undefined; +// auto syntaxCursor: IncrementalParser.SyntaxCursor | undefined; SyntaxKind currentToken; unordered_map identifiers; -// let privateIdentifiers: ESMap; + unordered_map privateIdentifiers; +// auto privateIdentifiers: ESMap; int identifierCount = 0; /*ParsingContext*/ int parsingContext = 0; -// let notParenthesizedArrow: Set | undefined; +// auto notParenthesizedArrow: Set | undefined; // Flags that dictate what parsing context we're in. For example: // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is @@ -1019,22 +1023,22 @@ namespace ts { return currentToken = scanner.scan(); } - optional parseErrorAtPosition(int start, int length, const DiagnosticMessage &message) { + optional parseErrorAtPosition(int start, int length, const DiagnosticMessage &message, optional arg = {}) { // Mark that we've encountered an error. We'll set an appropriate bit on the next // node we finish so that it can't be reused incrementally. parseErrorBeforeNextFinishedNode = true; // Don't report another error if it would just be at the same position as the last error. if (! parseDiagnostics.empty() || start != parseDiagnostics.back().start) { - auto d = createDetachedDiagnostic(fileName, start, length, message); + auto d = createDetachedDiagnostic(fileName, start, length, message, arg); parseDiagnostics.push_back(d); return d; } return nullopt; } - optional parseErrorAt(int start, int end, const DiagnosticMessage &message) { - return parseErrorAtPosition(start, end - start, message); + optional parseErrorAt(int start, int end, const DiagnosticMessage &message, optional arg = {}) { + return parseErrorAtPosition(start, end - start, message, arg); } void scanError(const DiagnosticMessage &message, int length) { @@ -1130,7 +1134,7 @@ namespace ts { // return hasJSDoc ? addJSDocComment(node) : node; // } // -// let hasDeprecatedTag = false; +// auto hasDeprecatedTag = false; // function addJSDocComment(node: T): T { // Debug.assert(!node.jsDoc); // Should only be called once per node // auto jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); @@ -1152,8 +1156,8 @@ namespace ts { // // parseDiagnostics = []; // -// let pos = 0; -// let start = findNextStatementWithAwait(sourceFile.statements, 0); +// auto pos = 0; +// auto start = findNextStatementWithAwait(sourceFile.statements, 0); // while (start != -1) { // // append all statements between pos and start // auto prevStatement = sourceFile.statements[pos]; @@ -1270,7 +1274,7 @@ namespace ts { // setExternalModuleIndicator: (sourceFile: SourceFile) => void): SourceFile { // // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // // this is quite rare comparing to other nodes and createNode should be as fast as possible -// let sourceFile = factory::createSourceFile(statements, endOfFileToken, flags); +// auto sourceFile = factory::createSourceFile(statements, endOfFileToken, flags); // setTextRangePosWidth(sourceFile, 0, sourceText.length); // setFields(sourceFile); // @@ -1297,13 +1301,16 @@ namespace ts { // } // } - void setContextFlag(bool val, NodeFlags flag) { + void setContextFlag(bool val, int flag) { if (val) { - contextFlags |= (int) flag; + contextFlags |= flag; } else { - contextFlags &= ~ (int) flag; + contextFlags &= ~ flag; } } + void setContextFlag(bool val, NodeFlags flag) { + return setContextFlag(val, (int)flag); + } void setDisallowInContext(bool val) { setContextFlag(val, NodeFlags::DisallowInContext); @@ -1320,121 +1327,15 @@ namespace ts { void setAwaitContext(bool val) { setContextFlag(val, NodeFlags::AwaitContext); } -// -// function doOutsideOfContext(context: NodeFlags, func: () => T): T { -// // contextFlagsToClear will contain only the context flags that are -// // currently set that we need to temporarily clear -// // We don't just blindly reset to the previous flags to ensure -// // that we do not mutate cached flags for the incremental -// // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and -// // HasAggregatedChildData). -// auto contextFlagsToClear = context & contextFlags; -// if (contextFlagsToClear) { -// // clear the requested context flags -// setContextFlag(/*val*/ false, contextFlagsToClear); -// auto result = func(); -// // restore the context flags we just cleared -// setContextFlag(/*val*/ true, contextFlagsToClear); -// return result; -// } -// -// // no need to do anything special as we are not in any of the requested contexts -// return func(); -// } -// -// function doInsideOfContext(context: NodeFlags, func: () => T): T { -// // contextFlagsToSet will contain only the context flags that -// // are not currently set that we need to temporarily enable. -// // We don't just blindly reset to the previous flags to ensure -// // that we do not mutate cached flags for the incremental -// // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and -// // HasAggregatedChildData). -// auto contextFlagsToSet = context & ~contextFlags; -// if (contextFlagsToSet) { -// // set the requested context flags -// setContextFlag(/*val*/ true, contextFlagsToSet); -// auto result = func(); -// // reset the context flags we just set -// setContextFlag(/*val*/ false, contextFlagsToSet); -// return result; -// } -// -// // no need to do anything special as we are already in all of the requested contexts -// return func(); -// } -// -// function allowInAnd(func: () => T): T { -// return doOutsideOfContext(NodeFlags::DisallowInContext, func); -// } -// -// function disallowInAnd(func: () => T): T { -// return doInsideOfContext(NodeFlags::DisallowInContext, func); -// } -// -// function allowConditionalTypesAnd(func: () => T): T { -// return doOutsideOfContext(NodeFlags::DisallowConditionalTypesContext, func); -// } -// -// function disallowConditionalTypesAnd(func: () => T): T { -// return doInsideOfContext(NodeFlags::DisallowConditionalTypesContext, func); -// } -// -// function doInYieldContext(func: () => T): T { -// return doInsideOfContext(NodeFlags::YieldContext, func); -// } -// -// function doInDecoratorContext(func: () => T): T { -// return doInsideOfContext(NodeFlags::DecoratorContext, func); -// } -// -// function doInAwaitContext(func: () => T): T { -// return doInsideOfContext(NodeFlags::AwaitContext, func); -// } -// -// function doOutsideOfAwaitContext(func: () => T): T { -// return doOutsideOfContext(NodeFlags::AwaitContext, func); -// } -// -// function doInYieldAndAwaitContext(func: () => T): T { -// return doInsideOfContext(NodeFlags::YieldContext | NodeFlags::AwaitContext, func); -// } -// -// function doOutsideOfYieldAndAwaitContext(func: () => T): T { -// return doOutsideOfContext(NodeFlags::YieldContext | NodeFlags::AwaitContext, func); -// } -// - bool inContext(NodeFlags flags) { - return (contextFlags & (int) flags) != 0; - } - - bool inYieldContext() { - return inContext(NodeFlags::YieldContext); - } - - bool inDisallowInContext() { - return inContext(NodeFlags::DisallowInContext); - } - - bool inDisallowConditionalTypesContext() { - return inContext(NodeFlags::DisallowConditionalTypesContext); - } - bool inDecoratorContext() { - return inContext(NodeFlags::DecoratorContext); - } - - bool inAwaitContext() { - return inContext(NodeFlags::AwaitContext); - } - - optional parseErrorAtCurrentToken(DiagnosticMessage message){ - return parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), message); + optional parseErrorAtCurrentToken(DiagnosticMessage message, optional arg = {}) { + return parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), message, arg); } // // function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined { // // Don't report another error if it would just be at the same position as the last error. // auto lastError = lastOrUndefined(parseDiagnostics); -// let result: DiagnosticWithDetachedLocation | undefined; +// auto result: DiagnosticWithDetachedLocation | undefined; // if (!lastError || start != lastError.start) { // result = createDetachedDiagnostic(fileName, start, length, message, arg0); // parseDiagnostics.push(result); @@ -1445,18 +1346,14 @@ namespace ts { // parseErrorBeforeNextFinishedNode = true; // return result; // } -// -// function parseErrorAt(start: number, end: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined { -// return parseErrorAtPosition(start, end - start, message, arg0); -// } -// -// function parseErrorAtRange(range: TextRange, message: DiagnosticMessage, arg0?: any): void { -// parseErrorAt(range.pos, range.end, message, arg0); -// } -// bool hasPrecedingJSDocComment() { -// return scanner.hasPrecedingJSDocComment(); -// } + void parseErrorAtRange(shared range, DiagnosticMessage message, optional arg = {}) { + parseErrorAt(range->pos, range->end, message, arg); + } + + bool hasPrecedingJSDocComment() { + return scanner.hasPrecedingJSDocComment(); + } // function nextTokenJSDoc(): JSDocSyntaxKind { // return currentToken = scanner.scanJsDocToken(); @@ -1485,19 +1382,14 @@ namespace ts { // function reScanHashToken(): SyntaxKind { // return currentToken = scanner.reScanHashToken(); // } -// -// function scanJsxIdentifier(): SyntaxKind { -// return currentToken = scanner.scanJsxIdentifier(); -// } -// -// function scanJsxText(): SyntaxKind { -// return currentToken = scanner.scanJsxToken(); -// } -// -// function scanJsxAttributeValue(): SyntaxKind { -// return currentToken = scanner.scanJsxAttributeValue(); -// } -// + + SyntaxKind scanJsxIdentifier() { + return currentToken = scanner.scanJsxIdentifier(); + } + + SyntaxKind scanJsxText() { + return currentToken = scanner.scanJsxToken(); + } template T speculationHelper(const function &callback, SpeculationKind speculationKind) { // Keep track of the state we'll need to rollback to if lookahead fails (or if the @@ -1515,15 +1407,15 @@ namespace ts { // If we're only looking ahead, then tell the scanner to only lookahead as well. // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the // same. - auto result = speculationKind != SpeculationKind::TryParse - ? scanner.lookAhead(callback) - : scanner.tryScan(callback); + T result = speculationKind != SpeculationKind::TryParse + ? scanner.lookAhead(callback) + : scanner.tryScan(callback); assert(saveContextFlags == contextFlags); // If our callback returned something 'falsy' or we're just looking ahead, // then unconditionally restore us to where we were. - if (! result || speculationKind != SpeculationKind::TryParse) { + if (!result || (speculationKind != SpeculationKind::TryParse)) { currentToken = saveToken; if (speculationKind != SpeculationKind::Reparse) { parseDiagnostics.resize(saveParseDiagnosticsLength); @@ -1540,7 +1432,19 @@ namespace ts { */ template T lookAhead(const function &callback) { - return speculationHelper(callback, SpeculationKind::Lookahead); + return speculationHelper(callback, SpeculationKind::Lookahead); + } + + bool inContext(NodeFlags flags) { + return (contextFlags & (int) flags) != 0; + } + + bool inYieldContext() { + return inContext(NodeFlags::YieldContext); + } + + bool inAwaitContext() { + return inContext(NodeFlags::AwaitContext); } // Ignore strict mode flag because we will report an error in type checker instead. @@ -1563,25 +1467,6 @@ namespace ts { return token() > SyntaxKind::LastReservedWord; } -// -// function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean { -// if (token() == kind) { -// if (shouldAdvance) { -// nextToken(); -// } -// return true; -// } -// -// // Report specific message if provided with one. Otherwise, report generic fallback message. -// if (diagnosticMessage) { -// parseErrorAtCurrentToken(diagnosticMessage); -// } -// else { -// parseErrorAtCurrentToken(Diagnostics::_0_expected, tokenToString(kind)); -// } -// return false; -// } -// // auto viableKeywordSuggestions = Object.keys(textToKeywordObj).filter(keyword => keyword.length > 2); // // /** @@ -1760,23 +1645,25 @@ namespace ts { // flag so that we don't mark any subsequent nodes. if (parseErrorBeforeNextFinishedNode) { parseErrorBeforeNextFinishedNode = false; - node->flags |= (int)NodeFlags::ThisNodeHasError; + node->flags |= (int) NodeFlags::ThisNodeHasError; } return node; } - shared parseTokenNode() { + template + shared parseTokenNode() { auto pos = getNodePos(); auto kind = token(); nextToken(); - return finishNode(factory::createToken(kind), pos); + return finishNode(factory::createToken(kind), pos); } // function parseOptionalToken(t: TKind): Token; - sharedOpt parseOptionalToken(SyntaxKind t){ + template + sharedOpt parseOptionalToken(SyntaxKind t) { if (token() == t) { - return parseTokenNode(); + return parseTokenNode(); } return nullptr; } @@ -1834,37 +1721,37 @@ namespace ts { // function parseSemicolon(): boolean { // return tryParseSemicolon() || parseExpected(SyntaxKind::SemicolonToken); // } -// -// function createNodeArray(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): NodeArray { -// auto array = factory::createNodeArray(elements, hasTrailingComma); -// setTextRangePosEnd(array, pos, end ?? scanner.getStartPos()); -// return array; -// } + + NodeArray createNodeArray(vector> elements, int pos, optional end = {}, optional hasTrailingComma = {}) { + auto array = factory::createNodeArray(elements, hasTrailingComma); + setTextRangePosEnd(array, pos, end ? *end : scanner.getStartPos()); + return array; + } // function createMissingNode(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, arg0?: any): T; // function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T; - shared createMissingNode(SyntaxKind kind, bool reportAtCurrentPosition, DiagnosticMessage diagnosticMessage) { - if (reportAtCurrentPosition) { - parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage); + template + shared createMissingNode(SyntaxKind kind, bool reportAtCurrentPosition, optional diagnosticMessage = {}) { + if (reportAtCurrentPosition && diagnosticMessage) { + parseErrorAtPosition(scanner.getStartPos(), 0, *diagnosticMessage); + } else if (diagnosticMessage) { + parseErrorAtCurrentToken(*diagnosticMessage); } -// else if (diagnosticMessage) { - parseErrorAtCurrentToken(diagnosticMessage); -// } auto pos = getNodePos(); auto result = - kind == SyntaxKind::Identifier ? factory::createIdentifier("", /*typeArguments*/ {}, /*originalKeywordKind*/ {}) : - isTemplateLiteralKind(kind) ? factory::createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ {}) : - kind == SyntaxKind::NumericLiteral ? factory::createNumericLiteral("", /*numericLiteralFlags*/ {}) : - kind == SyntaxKind::StringLiteral ? factory::createStringLiteral("", /*isSingleQuote*/ {}) : - kind == SyntaxKind::MissingDeclaration ? factory::createMissingDeclaration() : - factory::createToken(kind); - return finishNode(result, pos) as T; + kind == SyntaxKind::Identifier ? factory::createIdentifier("", /*typeArguments*/ {}, /*originalKeywordKind*/ {}) : + isTemplateLiteralKind(kind) ? factory::createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ {}) : + kind == SyntaxKind::NumericLiteral ? factory::createNumericLiteral("", /*numericLiteralFlags*/ {}) : + kind == SyntaxKind::StringLiteral ? factory::createStringLiteral("", /*isSingleQuote*/ {}) : + kind == SyntaxKind::MissingDeclaration ? factory::createMissingDeclaration() : + factory::createToken(kind); + auto a = finishNode(result, pos); } string internIdentifier(string text) { auto identifier = get(identifiers, text); - if (!identifier) { + if (! identifier) { identifier = text; set(identifiers, text, *identifier); } @@ -1879,67 +1766,18 @@ namespace ts { // `let await`/`let yield` in [Yield] or [Await] are allowed here and disallowed in the binder. return token() > SyntaxKind::LastReservedWord; } - -// function parseBindingIdentifier(privateIdentifierDiagnosticMessage?: DiagnosticMessage) { -// return createIdentifier(isBindingIdentifier(), /*diagnosticMessage*/ undefined, privateIdentifierDiagnosticMessage); -// } -// function parseIdentifierName(diagnosticMessage?: DiagnosticMessage): Identifier { -// return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage); -// } -// -// function isAssertionKey(): boolean { -// return tokenIsIdentifierOrKeyword(token()) || -// token() == SyntaxKind::StringLiteral; -// } -// -// function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { -// if (token() == SyntaxKind::StringLiteral || token() == SyntaxKind::NumericLiteral) { -// auto node = parseLiteralNode() as StringLiteral | NumericLiteral; -// node.text = internIdentifier(node.text); -// return node; -// } -// if (allowComputedPropertyNames && token() == SyntaxKind::OpenBracketToken) { -// return parseComputedPropertyName(); -// } -// if (token() == SyntaxKind::PrivateIdentifier) { -// return parsePrivateIdentifier(); -// } -// return parseIdentifierName(); -// } -// -// function parsePropertyName(): PropertyName { -// return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); -// } -// -// function parseComputedPropertyName(): ComputedPropertyName { -// // PropertyName [Yield]: -// // LiteralPropertyName -// // ComputedPropertyName[?Yield] -// auto pos = getNodePos(); -// parseExpected(SyntaxKind::OpenBracketToken); -// // We parse any expression (including a comma expression). But the grammar -// // says that only an assignment expression is allowed, so the grammar checker -// // will error if it sees a comma expression. -// auto expression = allowInAnd(parseExpression); -// parseExpected(SyntaxKind::CloseBracketToken); -// return finishNode(factory::createComputedPropertyName(expression), pos); -// } -// -// function internPrivateIdentifier(text: string): string { -// let privateIdentifier = privateIdentifiers.get(text); -// if (privateIdentifier == undefined) { -// privateIdentifiers.set(text, privateIdentifier = text); -// } -// return privateIdentifier; -// } -// -// function parsePrivateIdentifier(): PrivateIdentifier { -// auto pos = getNodePos(); -// auto node = factory::createPrivateIdentifier(internPrivateIdentifier(scanner.getTokenText())); -// nextToken(); -// return finishNode(node, pos); -// } -// + + shared parseBindingIdentifier(optional privateIdentifierDiagnosticMessage = {}) { + return createIdentifier(isBindingIdentifier(), /*diagnosticMessage*/ {}, privateIdentifierDiagnosticMessage); + } + + shared parseIdentifierName(optional diagnosticMessage = {}) { + return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage); + } + + bool isAssertionKey() { + return tokenIsIdentifierOrKeyword(token()) || token() == SyntaxKind::StringLiteral; + } /** Invokes the provided callback. If the callback returns something falsy, then it restores * the parser to the state it was in immediately prior to invoking the callback. If the @@ -1953,20 +1791,20 @@ namespace ts { bool nextTokenIsClassKeywordOnSameLine() { nextToken(); - return token() == SyntaxKind::ClassKeyword && !scanner.hasPrecedingLineBreak(); + return token() == SyntaxKind::ClassKeyword && ! scanner.hasPrecedingLineBreak(); } bool nextTokenIsFunctionKeywordOnSameLine() { nextToken(); - return token() == SyntaxKind::FunctionKeyword && !scanner.hasPrecedingLineBreak(); + return token() == SyntaxKind::FunctionKeyword && ! scanner.hasPrecedingLineBreak(); } - bool nextTokenCanFollowDefaultKeyword(){ + bool nextTokenCanFollowDefaultKeyword() { nextToken(); return token() == SyntaxKind::ClassKeyword || token() == SyntaxKind::FunctionKeyword || - token() == SyntaxKind::InterfaceKeyword || - (token() == SyntaxKind::AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) || - (token() == SyntaxKind::AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + token() == SyntaxKind::InterfaceKeyword || + (token() == SyntaxKind::AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) || + (token() == SyntaxKind::AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); } bool isLiteralPropertyName() { @@ -1985,9 +1823,9 @@ namespace ts { bool canFollowExportModifier() { return token() != SyntaxKind::AsteriskToken - && token() != SyntaxKind::AsKeyword - && token() != SyntaxKind::OpenBraceToken - && canFollowModifier(); + && token() != SyntaxKind::AsKeyword + && token() != SyntaxKind::OpenBraceToken + && canFollowModifier(); } bool nextTokenCanFollowExportModifier() { @@ -2033,7 +1871,6 @@ namespace ts { return token() == t && tryParse(nextTokenCanFollowModifier); } - bool nextTokenIsOpenParenOrLessThanOrDot() { switch (nextToken()) { case SyntaxKind::OpenParenToken: @@ -2074,12 +1911,16 @@ namespace ts { } } + bool inDisallowInContext() { + return inContext(NodeFlags::DisallowInContext); + } + bool isBinaryOperator() { if (inDisallowInContext() && token() == SyntaxKind::InKeyword) { return false; } - return (int)getBinaryOperatorPrecedence(token()) > 0; + return getBinaryOperatorPrecedence(token()) > 0; } bool isStartOfExpression() { @@ -2121,10 +1962,10 @@ namespace ts { bool isStartOfExpressionStatement() { // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement. return token() != SyntaxKind::OpenBraceToken && - token() != SyntaxKind::FunctionKeyword && - token() != SyntaxKind::ClassKeyword && - token() != SyntaxKind::AtToken && - isStartOfExpression(); + token() != SyntaxKind::FunctionKeyword && + token() != SyntaxKind::ClassKeyword && + token() != SyntaxKind::AtToken && + isStartOfExpression(); } bool nextTokenIsNumericOrBigIntLiteral() { @@ -2134,21 +1975,21 @@ namespace ts { bool isBindingIdentifierOrPrivateIdentifierOrPattern() { return token() == SyntaxKind::OpenBraceToken - || token() == SyntaxKind::OpenBracketToken - || token() == SyntaxKind::PrivateIdentifier - || isBindingIdentifier(); + || token() == SyntaxKind::OpenBracketToken + || token() == SyntaxKind::PrivateIdentifier + || isBindingIdentifier(); } bool isStartOfType(bool inStartOfParameter = false); bool isStartOfParameter(bool isJSDocParameter) { return token() == SyntaxKind::DotDotDotToken || - isBindingIdentifierOrPrivateIdentifierOrPattern() || - isModifierKind(token()) || - token() == SyntaxKind::AtToken || - isStartOfType(/*inStartOfParameter*/ !isJSDocParameter); + isBindingIdentifierOrPrivateIdentifierOrPattern() || + isModifierKind(token()) || + token() == SyntaxKind::AtToken || + isStartOfType(/*inStartOfParameter*/ ! isJSDocParameter); } - + bool isStartOfParenthesizedOrFunctionType() { nextToken(); return token() == SyntaxKind::CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType(); @@ -2194,169 +2035,495 @@ namespace ts { case SyntaxKind::TemplateHead: return true; case SyntaxKind::FunctionKeyword: - return !inStartOfParameter; + return ! inStartOfParameter; case SyntaxKind::MinusToken: - return !inStartOfParameter && lookAhead(nextTokenIsNumericOrBigIntLiteral); + return ! inStartOfParameter && lookAhead(nextTokenIsNumericOrBigIntLiteral); case SyntaxKind::OpenParenToken: // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, // or something that starts a type. We don't want to consider things like '(1)' a type. - return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType); + return ! inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType); default: return isIdentifier(); } } -// // True if positioned at the start of a list element -// function isListElement(parsingContext: ParsingContext, inErrorRecovery: boolean): boolean { -// auto node = currentNode(parsingContext); -// if (node) { -// return true; + sharedOpt currentNode(ParsingContext parsingContext) { + // If we don't have a cursor or the parsing context isn't reusable, there's nothing to reuse. + // + // If there is an outstanding parse error that we've encountered, but not attached to + // some node, then we cannot get a node from the old source tree. This is because we + // want to mark the next node we encounter as being unusable. + // + // Note: This may be too conservative. Perhaps we could reuse the node and set the bit + // on it (or its leftmost child) as having the error. For now though, being conservative + // is nice and likely won't ever affect perf. +// if (!syntaxCursor || !isReusableParsingContext(parsingContext) || parseErrorBeforeNextFinishedNode) { +// return undefined; // } + + //I hope we do not need to reimplement syntaxCursor too + return nullptr; + +// auto node = syntaxCursor.currentNode(scanner.getStartPos()); // -// switch (parsingContext) { -// case ParsingContext::SourceElements: -// case ParsingContext::BlockStatements: -// case ParsingContext::SwitchClauseStatements: -// // If we're in error recovery, then we don't want to treat ';' as an empty statement. -// // The problem is that ';' can show up in far too many contexts, and if we see one -// // and assume it's a statement, then we may bail out inappropriately from whatever -// // we're parsing. For example, if we have a semicolon in the middle of a class, then -// // we really don't want to assume the class is over and we're on a statement in the -// // outer module. We just want to consume and move on. -// return !(token() == SyntaxKind::SemicolonToken && inErrorRecovery) && isStartOfStatement(); -// case ParsingContext::SwitchClauses: -// return token() == SyntaxKind::CaseKeyword || token() == SyntaxKind::DefaultKeyword; -// case ParsingContext::TypeMembers: -// return lookAhead(isTypeMemberStart); -// case ParsingContext::ClassMembers: -// // We allow semicolons as class elements (as specified by ES6) as long as we're -// // not in error recovery. If we're in error recovery, we don't want an errant -// // semicolon to be treated as a class member (since they're almost always used -// // for statements. -// return lookAhead(isClassMemberStart) || (token() == SyntaxKind::SemicolonToken && !inErrorRecovery); -// case ParsingContext::EnumMembers: -// // Include open bracket computed properties. This technically also lets in indexers, -// // which would be a candidate for improved error reporting. -// return token() == SyntaxKind::OpenBracketToken || isLiteralPropertyName(); -// case ParsingContext::ObjectLiteralMembers: -// switch (token()) { -// case SyntaxKind::OpenBracketToken: -// case SyntaxKind::AsteriskToken: -// case SyntaxKind::DotDotDotToken: -// case SyntaxKind::DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`) -// return true; -// default: -// return isLiteralPropertyName(); -// } -// case ParsingContext::RestProperties: -// return isLiteralPropertyName(); -// case ParsingContext::ObjectBindingElements: -// return token() == SyntaxKind::OpenBracketToken || token() == SyntaxKind::DotDotDotToken || isLiteralPropertyName(); -// case ParsingContext::AssertEntries: -// return isAssertionKey(); -// case ParsingContext::HeritageClauseElement: -// // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{` -// // That way we won't consume the body of a class in its heritage clause. -// if (token() == SyntaxKind::OpenBraceToken) { -// return lookAhead(isValidHeritageClauseObjectLiteral); -// } -// -// if (!inErrorRecovery) { -// return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); -// } -// else { -// // If we're in error recovery we tighten up what we're willing to match. -// // That way we don't treat something like "this" as a valid heritage clause -// // element during recovery. -// return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); -// } -// case ParsingContext::VariableDeclarations: -// return isBindingIdentifierOrPrivateIdentifierOrPattern(); -// case ParsingContext::ArrayBindingElements: -// return token() == SyntaxKind::CommaToken || token() == SyntaxKind::DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern(); -// case ParsingContext::TypeParameters: -// return token() == SyntaxKind::InKeyword || isIdentifier(); -// case ParsingContext::ArrayLiteralMembers: -// switch (token()) { -// case SyntaxKind::CommaToken: -// case SyntaxKind::DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`) -// return true; -// } -// // falls through -// case ParsingContext::ArgumentExpressions: -// return token() == SyntaxKind::DotDotDotToken || isStartOfExpression(); -// case ParsingContext::Parameters: -// return isStartOfParameter(/*isJSDocParameter*/ false); -// case ParsingContext::JSDocParameters: -// return isStartOfParameter(/*isJSDocParameter*/ true); -// case ParsingContext::TypeArguments: -// case ParsingContext::TupleElementTypes: -// return token() == SyntaxKind::CommaToken || isStartOfType(); -// case ParsingContext::HeritageClauses: -// return isHeritageClause(); -// case ParsingContext::ImportOrExportSpecifiers: -// return tokenIsIdentifierOrKeyword(token()); -// case ParsingContext::JsxAttributes: -// return tokenIsIdentifierOrKeyword(token()) || token() == SyntaxKind::OpenBraceToken; -// case ParsingContext::JsxChildren: -// return true; +// // Can't reuse a missing node. +// // Can't reuse a node that intersected the change range. +// // Can't reuse a node that contains a parse error. This is necessary so that we +// // produce the same set of errors again. +// if (nodeIsMissing(node) || node.intersectsChange || containsParseError(node)) { +// return undefined; // } // -// return Debug.fail("Non-exhaustive case in 'isListElement'."); -// } +// // We can only reuse a node if it was parsed under the same strict mode that we're +// // currently in. i.e. if we originally parsed a node in non-strict mode, but then +// // the user added 'using strict' at the top of the file, then we can't use that node +// // again as the presence of strict mode may cause us to parse the tokens in the file +// // differently. +// // +// // Note: we *can* reuse tokens when the strict mode changes. That's because tokens +// // are unaffected by strict mode. It's just the parser will decide what to do with it +// // differently depending on what mode it is in. +// // +// // This also applies to all our other context flags as well. +// auto nodeContextFlags = node.flags & NodeFlags::ContextFlags; +// if (nodeContextFlags != contextFlags) { +// return undefined; +// } // -// function isValidHeritageClauseObjectLiteral() { -// Debug.assert(token() == SyntaxKind::OpenBraceToken); -// if (nextToken() == SyntaxKind::CloseBraceToken) { -// // if we see "extends {}" then only treat the {} as what we're extending (and not -// // the class body) if we have: -// // -// // extends {} { -// // extends {}, -// // extends {} extends -// // extends {} implements +// // Ok, we have a node that looks like it could be reused. Now verify that it is valid +// // in the current list parsing context that we're currently at. +// if (!canReuseNode(node, parsingContext)) { +// return undefined; +// } // -// auto next = nextToken(); -// return next == SyntaxKind::CommaToken || next == SyntaxKind::OpenBraceToken || next == SyntaxKind::ExtendsKeyword || next == SyntaxKind::ImplementsKeyword; +// if (reinterpret_cast(node).jsDocCache) { +// // jsDocCache may include tags from parent nodes, which might have been modified. +// reinterpret_cast(node).jsDocCache = undefined; // } // -// return true; -// } +// return node; + } - bool nextTokenIsIdentifier() { - nextToken(); - return isIdentifier(); + bool isHeritageClause() { + return token() == SyntaxKind::ExtendsKeyword || token() == SyntaxKind::ImplementsKeyword; } - bool nextTokenIsIdentifierOrKeyword() { - nextToken(); - return tokenIsIdentifierOrKeyword(token()); + bool isTypeMemberStart() { + // Return true if we have the start of a signature member + if (token() == SyntaxKind::OpenParenToken || + token() == SyntaxKind::LessThanToken || + token() == SyntaxKind::GetKeyword || + token() == SyntaxKind::SetKeyword) { + return true; + } + auto idToken = false; + // Eat up all modifiers, but hold on to the last one in case it is actually an identifier + while (isModifierKind(token())) { + idToken = true; + nextToken(); + } + // Index signatures and computed property names are type members + if (token() == SyntaxKind::OpenBracketToken) { + return true; + } + // Try to get the first property-like token following all modifiers + if (isLiteralPropertyName()) { + idToken = true; + nextToken(); + } + // If we were able to get any potential identifier, check that it is + // the start of a member declaration + if (idToken) { + return token() == SyntaxKind::OpenParenToken || + token() == SyntaxKind::LessThanToken || + token() == SyntaxKind::QuestionToken || + token() == SyntaxKind::ColonToken || + token() == SyntaxKind::CommaToken || + canParseSemicolon(); + } + return false; } - bool nextTokenIsIdentifierOrKeywordOrGreaterThan() { + bool nextTokenIsIdentifierOnSameLine() { nextToken(); - return tokenIsIdentifierOrKeywordOrGreaterThan(token()); + return ! scanner.hasPrecedingLineBreak() && isIdentifier(); } - bool nextTokenIsStartOfExpression() { + bool nextTokenIsIdentifierOrStringLiteralOnSameLine() { nextToken(); - return isStartOfExpression(); + return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() == SyntaxKind::StringLiteral); } - bool isHeritageClauseExtendsOrImplementsKeyword() { - if (token() == SyntaxKind::ImplementsKeyword || - token() == SyntaxKind::ExtendsKeyword) { - - return lookAhead(nextTokenIsStartOfExpression); - } + bool isDeclaration() { + while (true) { + switch (token()) { + case SyntaxKind::VarKeyword: + case SyntaxKind::LetKeyword: + case SyntaxKind::ConstKeyword: + case SyntaxKind::FunctionKeyword: + case SyntaxKind::ClassKeyword: + case SyntaxKind::EnumKeyword: + return true; - return false; - } + // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers; + // however, an identifier cannot be followed by another identifier on the same line. This is what we + // count on to parse out the respective declarations. For instance, we exploit this to say that + // + // namespace n + // + // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees + // + // namespace + // n + // + // as the identifier 'namespace' on one line followed by the identifier 'n' on another. + // We need to look one token ahead to see if it permissible to try parsing a declaration. + // + // *Note*: 'interface' is actually a strict mode reserved word. So while + // + // "use strict" + // interface + // I {} + // + // could be legal, it would add complexity for very little gain. + case SyntaxKind::InterfaceKeyword: + case SyntaxKind::TypeKeyword: + return nextTokenIsIdentifierOnSameLine(); + case SyntaxKind::ModuleKeyword: + case SyntaxKind::NamespaceKeyword: + return nextTokenIsIdentifierOrStringLiteralOnSameLine(); + case SyntaxKind::AbstractKeyword: + case SyntaxKind::AsyncKeyword: + case SyntaxKind::DeclareKeyword: + case SyntaxKind::PrivateKeyword: + case SyntaxKind::ProtectedKeyword: + case SyntaxKind::PublicKeyword: + case SyntaxKind::ReadonlyKeyword: + nextToken(); + // ASI takes effect for this modifier. + if (scanner.hasPrecedingLineBreak()) { + return false; + } + continue; - bool nextTokenIsStartOfType() { - nextToken(); - return isStartOfType(); - } + case SyntaxKind::GlobalKeyword: + nextToken(); + return token() == SyntaxKind::OpenBraceToken || token() == SyntaxKind::Identifier || token() == SyntaxKind::ExportKeyword; + + case SyntaxKind::ImportKeyword: + nextToken(); + return token() == SyntaxKind::StringLiteral || token() == SyntaxKind::AsteriskToken || + token() == SyntaxKind::OpenBraceToken || tokenIsIdentifierOrKeyword(token()); + case SyntaxKind::ExportKeyword: { + auto currentToken = nextToken(); + if (currentToken == SyntaxKind::TypeKeyword) { + currentToken = lookAhead(nextToken); + } + if (currentToken == SyntaxKind::EqualsToken || currentToken == SyntaxKind::AsteriskToken || + currentToken == SyntaxKind::OpenBraceToken || currentToken == SyntaxKind::DefaultKeyword || + currentToken == SyntaxKind::AsKeyword) { + return true; + } + continue; + } + case SyntaxKind::StaticKeyword: + nextToken(); + continue; + default: + return false; + } + } + } + + bool isStartOfDeclaration() { + return lookAhead(isDeclaration); + } + + bool nextTokenIsIdentifierOrKeywordOnSameLine() { + nextToken(); + return tokenIsIdentifierOrKeyword(token()) && ! scanner.hasPrecedingLineBreak(); + } + + bool isStartOfStatement() { + switch (token()) { + case SyntaxKind::AtToken: + case SyntaxKind::SemicolonToken: + case SyntaxKind::OpenBraceToken: + case SyntaxKind::VarKeyword: + case SyntaxKind::LetKeyword: + case SyntaxKind::FunctionKeyword: + case SyntaxKind::ClassKeyword: + case SyntaxKind::EnumKeyword: + case SyntaxKind::IfKeyword: + case SyntaxKind::DoKeyword: + case SyntaxKind::WhileKeyword: + case SyntaxKind::ForKeyword: + case SyntaxKind::ContinueKeyword: + case SyntaxKind::BreakKeyword: + case SyntaxKind::ReturnKeyword: + case SyntaxKind::WithKeyword: + case SyntaxKind::SwitchKeyword: + case SyntaxKind::ThrowKeyword: + case SyntaxKind::TryKeyword: + case SyntaxKind::DebuggerKeyword: + // 'catch' and 'finally' do not actually indicate that the code is part of a statement, + // however, we say they are here so that we may gracefully parse them and error later. + // falls through + case SyntaxKind::CatchKeyword: + case SyntaxKind::FinallyKeyword: + return true; + + case SyntaxKind::ImportKeyword: + return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot); + + case SyntaxKind::ConstKeyword: + case SyntaxKind::ExportKeyword: + return isStartOfDeclaration(); + + case SyntaxKind::AsyncKeyword: + case SyntaxKind::DeclareKeyword: + case SyntaxKind::InterfaceKeyword: + case SyntaxKind::ModuleKeyword: + case SyntaxKind::NamespaceKeyword: + case SyntaxKind::TypeKeyword: + case SyntaxKind::GlobalKeyword: + // When these don't start a declaration, they're an identifier in an expression statement + return true; + + case SyntaxKind::PublicKeyword: + case SyntaxKind::PrivateKeyword: + case SyntaxKind::ProtectedKeyword: + case SyntaxKind::StaticKeyword: + case SyntaxKind::ReadonlyKeyword: + // When these don't start a declaration, they may be the start of a class member if an identifier + // immediately follows. Otherwise they're an identifier in an expression statement. + return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); + + default: + return isStartOfExpression(); + } + } + + bool isClassMemberStart() { + SyntaxKind idToken = SyntaxKind::Unknown; + + if (token() == SyntaxKind::AtToken) { + return true; + } + + // Eat up all modifiers, but hold on to the last one in case it is actually an identifier. + while (isModifierKind(token())) { + idToken = token(); + // If the idToken is a class modifier (protected, private, public, and static), it is + // certain that we are starting to parse class member. This allows better error recovery + // Example: + // public foo() ... // true + // public @dec blah ... // true; we will then report an error later + // export public ... // true; we will then report an error later + if (isClassMemberModifier(idToken)) { + return true; + } + + nextToken(); + } + + if (token() == SyntaxKind::AsteriskToken) { + return true; + } + + // Try to get the first property-like token following all modifiers. + // This can either be an identifier or the 'get' or 'set' keywords. + if (isLiteralPropertyName()) { + idToken = token(); + nextToken(); + } + + // Index signatures and computed properties are class members; we can parse. + if (token() == SyntaxKind::OpenBracketToken) { + return true; + } + + // If we were able to get any potential identifier... + if (idToken != SyntaxKind::Unknown) { + // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse. + if (!isKeyword(idToken) || idToken == SyntaxKind::SetKeyword || idToken == SyntaxKind::GetKeyword) { + return true; + } + + // If it *is* a keyword, but not an accessor, check a little farther along + // to see if it should actually be parsed as a class member. + switch (token()) { + case SyntaxKind::OpenParenToken: // Method declaration + case SyntaxKind::LessThanToken: // Generic Method declaration + case SyntaxKind::ExclamationToken: // Non-null assertion on property name + case SyntaxKind::ColonToken: // Type Annotation for declaration + case SyntaxKind::EqualsToken: // Initializer for declaration + case SyntaxKind::QuestionToken: // Not valid, but permitted so that it gets caught later on. + return true; + default: + // Covers + // - Semicolons (declaration termination) + // - Closing braces (end-of-class, must be declaration) + // - End-of-files (not valid, but permitted so that it gets caught later on) + // - Line-breaks (enabling *automatic semicolon insertion*) + return canParseSemicolon(); + } + } + + return false; + } + + bool isValidHeritageClauseObjectLiteral() { + assert(token() == SyntaxKind::OpenBraceToken); + if (nextToken() == SyntaxKind::CloseBraceToken) { + // if we see "extends {}" then only treat the {} as what we're extending (and not + // the class body) if we have: + // + // extends {} { + // extends {}, + // extends {} extends + // extends {} implements + + auto next = nextToken(); + return next == SyntaxKind::CommaToken || next == SyntaxKind::OpenBraceToken || next == SyntaxKind::ExtendsKeyword || next == SyntaxKind::ImplementsKeyword; + } + + return true; + } + + bool nextTokenIsStartOfExpression() { + nextToken(); + return isStartOfExpression(); + } + + bool isHeritageClauseExtendsOrImplementsKeyword() { + if (token() == SyntaxKind::ImplementsKeyword || + token() == SyntaxKind::ExtendsKeyword) { + + return lookAhead(nextTokenIsStartOfExpression); + } + + return false; + } + + // True if positioned at the start of a list element + bool isListElement(ParsingContext parsingContext, bool inErrorRecovery) { + auto node = currentNode(parsingContext); + if (node) { + return true; + } + + switch (parsingContext) { + case ParsingContext::SourceElements: + case ParsingContext::BlockStatements: + case ParsingContext::SwitchClauseStatements: + // If we're in error recovery, then we don't want to treat ';' as an empty statement. + // The problem is that ';' can show up in far too many contexts, and if we see one + // and assume it's a statement, then we may bail out inappropriately from whatever + // we're parsing. For example, if we have a semicolon in the middle of a class, then + // we really don't want to assume the class is over and we're on a statement in the + // outer module. We just want to consume and move on. + return !(token() == SyntaxKind::SemicolonToken && inErrorRecovery) && isStartOfStatement(); + case ParsingContext::SwitchClauses: + return token() == SyntaxKind::CaseKeyword || token() == SyntaxKind::DefaultKeyword; + case ParsingContext::TypeMembers: + return lookAhead(isTypeMemberStart); + case ParsingContext::ClassMembers: + // We allow semicolons as class elements (as specified by ES6) as long as we're + // not in error recovery. If we're in error recovery, we don't want an errant + // semicolon to be treated as a class member (since they're almost always used + // for statements. + return lookAhead(isClassMemberStart) || (token() == SyntaxKind::SemicolonToken && !inErrorRecovery); + case ParsingContext::EnumMembers: + // Include open bracket computed properties. This technically also lets in indexers, + // which would be a candidate for improved error reporting. + return token() == SyntaxKind::OpenBracketToken || isLiteralPropertyName(); + case ParsingContext::ObjectLiteralMembers: + switch (token()) { + case SyntaxKind::OpenBracketToken: + case SyntaxKind::AsteriskToken: + case SyntaxKind::DotDotDotToken: + case SyntaxKind::DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`) + return true; + default: + return isLiteralPropertyName(); + } + case ParsingContext::RestProperties: + return isLiteralPropertyName(); + case ParsingContext::ObjectBindingElements: + return token() == SyntaxKind::OpenBracketToken || token() == SyntaxKind::DotDotDotToken || isLiteralPropertyName(); + case ParsingContext::AssertEntries: + return isAssertionKey(); + case ParsingContext::HeritageClauseElement: + // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{` + // That way we won't consume the body of a class in its heritage clause. + if (token() == SyntaxKind::OpenBraceToken) { + return lookAhead(isValidHeritageClauseObjectLiteral); + } + + if (!inErrorRecovery) { + return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword(); + } + else { + // If we're in error recovery we tighten up what we're willing to match. + // That way we don't treat something like "this" as a valid heritage clause + // element during recovery. + return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword(); + } + case ParsingContext::VariableDeclarations: + return isBindingIdentifierOrPrivateIdentifierOrPattern(); + case ParsingContext::ArrayBindingElements: + return token() == SyntaxKind::CommaToken || token() == SyntaxKind::DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern(); + case ParsingContext::TypeParameters: + return token() == SyntaxKind::InKeyword || isIdentifier(); + case ParsingContext::ArrayLiteralMembers: + switch (token()) { + case SyntaxKind::CommaToken: + case SyntaxKind::DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`) + return true; + } + // falls through + case ParsingContext::ArgumentExpressions: + return token() == SyntaxKind::DotDotDotToken || isStartOfExpression(); + case ParsingContext::Parameters: + return isStartOfParameter(/*isJSDocParameter*/ false); + case ParsingContext::JSDocParameters: + return isStartOfParameter(/*isJSDocParameter*/ true); + case ParsingContext::TypeArguments: + case ParsingContext::TupleElementTypes: + return token() == SyntaxKind::CommaToken || isStartOfType(); + case ParsingContext::HeritageClauses: + return isHeritageClause(); + case ParsingContext::ImportOrExportSpecifiers: + return tokenIsIdentifierOrKeyword(token()); + case ParsingContext::JsxAttributes: + return tokenIsIdentifierOrKeyword(token()) || token() == SyntaxKind::OpenBraceToken; + case ParsingContext::JsxChildren: + return true; + } + + throw runtime_error("Non-exhaustive case in 'isListElement'."); + } + + bool nextTokenIsIdentifier() { + nextToken(); + return isIdentifier(); + } + + bool nextTokenIsIdentifierOrKeyword() { + nextToken(); + return tokenIsIdentifierOrKeyword(token()); + } + + bool nextTokenIsIdentifierOrKeywordOrGreaterThan() { + nextToken(); + return tokenIsIdentifierOrKeywordOrGreaterThan(token()); + } + + bool nextTokenIsStartOfType() { + nextToken(); + return isStartOfType(); + } bool isInOrOfKeyword(SyntaxKind t) { return t == SyntaxKind::InKeyword || t == SyntaxKind::OfKeyword; @@ -2456,89 +2623,13 @@ namespace ts { } } -// // True if positioned at element or terminator of the current list or any enclosing list -// function isInSomeParsingContext(): boolean { -// for (let kind = 0; kind < ParsingContext::Count; kind++) { -// if (parsingContext & (1 << kind)) { -// if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) { -// return true; -// } -// } -// } -// -// return false; -// } -// -// function parseListElement(parsingContext: ParsingContext, parseElement: () => T): T { -// auto node = currentNode(parsingContext); -// if (node) { -// return consumeNode(node) as T; -// } -// -// return parseElement(); -// } -// -// function currentNode(parsingContext: ParsingContext): Node | undefined { -// // If we don't have a cursor or the parsing context isn't reusable, there's nothing to reuse. -// // -// // If there is an outstanding parse error that we've encountered, but not attached to -// // some node, then we cannot get a node from the old source tree. This is because we -// // want to mark the next node we encounter as being unusable. -// // -// // Note: This may be too conservative. Perhaps we could reuse the node and set the bit -// // on it (or its leftmost child) as having the error. For now though, being conservative -// // is nice and likely won't ever affect perf. -// if (!syntaxCursor || !isReusableParsingContext(parsingContext) || parseErrorBeforeNextFinishedNode) { -// return undefined; -// } -// -// auto node = syntaxCursor.currentNode(scanner.getStartPos()); -// -// // Can't reuse a missing node. -// // Can't reuse a node that intersected the change range. -// // Can't reuse a node that contains a parse error. This is necessary so that we -// // produce the same set of errors again. -// if (nodeIsMissing(node) || node.intersectsChange || containsParseError(node)) { -// return undefined; -// } -// -// // We can only reuse a node if it was parsed under the same strict mode that we're -// // currently in. i.e. if we originally parsed a node in non-strict mode, but then -// // the user added 'using strict' at the top of the file, then we can't use that node -// // again as the presence of strict mode may cause us to parse the tokens in the file -// // differently. -// // -// // Note: we *can* reuse tokens when the strict mode changes. That's because tokens -// // are unaffected by strict mode. It's just the parser will decide what to do with it -// // differently depending on what mode it is in. -// // -// // This also applies to all our other context flags as well. -// auto nodeContextFlags = node.flags & NodeFlags::ContextFlags; -// if (nodeContextFlags != contextFlags) { -// return undefined; -// } -// -// // Ok, we have a node that looks like it could be reused. Now verify that it is valid -// // in the current list parsing context that we're currently at. -// if (!canReuseNode(node, parsingContext)) { -// return undefined; -// } -// -// if (reinterpret_cast(node).jsDocCache) { -// // jsDocCache may include tags from parent nodes, which might have been modified. -// reinterpret_cast(node).jsDocCache = undefined; -// } -// -// return node; -// } -// -// function consumeNode(node: Node) { -// // Move the scanner so it is after the node we just consumed. -// scanner.setTextPos(node.end); -// nextToken(); -// return node; -// } -// + shared consumeNode(shared node) { + // Move the scanner so it is after the node we just consumed. + scanner.setTextPos(node->end); + nextToken(); + return node; + } + // function isReusableParsingContext(parsingContext: ParsingContext): boolean { // switch (parsingContext) { // case ParsingContext::ClassMembers: @@ -2737,12 +2828,12 @@ namespace ts { // // // Very subtle incremental parsing bug. Consider the following code: // // -// // let v = new List < A, B +// // auto v = new List < A, B // // // // This is actually legal code. It's a list of variable declarators "v = new List() +// // auto v = new List < A, B >() // // // // then we have a problem. "v = new List(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray; -// function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined; -// function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined { -// auto saveParsingContext = parsingContext; -// parsingContext |= 1 << kind; -// auto list = []; -// auto listPos = getNodePos(); -// -// let commaStart = -1; // Meaning the previous token was not a comma -// while (true) { -// if (isListElement(kind, /*inErrorRecovery*/ false)) { -// auto startPos = scanner.getStartPos(); -// auto result = parseListElement(kind, parseElement); -// if (!result) { -// parsingContext = saveParsingContext; -// return undefined; -// } -// list.push(result as NonNullable); -// commaStart = scanner.getTokenPos(); -// -// if (parseOptional(SyntaxKind::CommaToken)) { -// // No need to check for a zero length node since we know we parsed a comma -// continue; -// } -// -// commaStart = -1; // Back to the state where the last token was not a comma -// if (isListTerminator(kind)) { -// break; -// } -// -// // We didn't get a comma, and the list wasn't terminated, explicitly parse -// // out a comma so we give a good error message. -// parseExpected(SyntaxKind::CommaToken, getExpectedCommaDiagnostic(kind)); -// -// // If the token was a semicolon, and the caller allows that, then skip it and -// // continue. This ensures we get back on track and don't result in tons of -// // parse errors. For example, this can happen when people do things like use -// // a semicolon to delimit object literal members. Note: we'll have already -// // reported an error when we called parseExpected above. -// if (considerSemicolonAsDelimiter && token() == SyntaxKind::SemicolonToken && !scanner.hasPrecedingLineBreak()) { -// nextToken(); -// } -// if (startPos == scanner.getStartPos()) { -// // What we're parsing isn't actually remotely recognizable as a element and we've consumed no tokens whatsoever -// // Consume a token to advance the parser in some way and avoid an infinite loop -// // This can happen when we're speculatively parsing parenthesized expressions which we think may be arrow functions, -// // or when a modifier keyword which is disallowed as a parameter name (ie, `static` in strict mode) is supplied -// nextToken(); -// } -// continue; -// } -// -// if (isListTerminator(kind)) { -// break; -// } -// -// if (abortParsingListOrMoveToNextToken(kind)) { -// break; -// } -// } -// -// parsingContext = saveParsingContext; -// // Recording the trailing comma is deliberately done after the previous -// // loop, and not just if we see a list terminator. This is because the list -// // may have ended incorrectly, but it is still important to know if there -// // was a trailing comma. -// // Check if the last token was a comma. -// // Always preserve a trailing comma by marking it on the NodeArray -// return createNodeArray(list, listPos, /*end*/ undefined, commaStart >= 0); -// } -// -// function getExpectedCommaDiagnostic(kind: ParsingContext) { -// return kind == ParsingContext::EnumMembers ? Diagnostics::An_enum_member_name_must_be_followed_by_a_or : undefined; -// } -// + optional getExpectedCommaDiagnostic(ParsingContext kind) { + if (kind == ParsingContext::EnumMembers) return Diagnostics::An_enum_member_name_must_be_followed_by_a_or; + return nullopt; + } + + bool parseExpected(SyntaxKind kind, optional diagnosticMessage = {}, bool shouldAdvance = true) { + if (token() == kind) { + if (shouldAdvance) { + nextToken(); + } + return true; + } + + // Report specific message if provided with one. Otherwise, report generic fallback message. + if (diagnosticMessage) { + parseErrorAtCurrentToken(*diagnosticMessage); + } else { + parseErrorAtCurrentToken(Diagnostics::_0_expected, tokenToString(kind)); + } + return false; + } + + optional parsingContextErrors(ParsingContext context) { + switch (context) { + case ParsingContext::SourceElements: + return token() == SyntaxKind::DefaultKeyword + ? parseErrorAtCurrentToken(Diagnostics::_0_expected, tokenToString(SyntaxKind::ExportKeyword)) + : parseErrorAtCurrentToken(Diagnostics::Declaration_or_statement_expected); + case ParsingContext::BlockStatements: return parseErrorAtCurrentToken(Diagnostics::Declaration_or_statement_expected); + case ParsingContext::SwitchClauses: return parseErrorAtCurrentToken(Diagnostics::case_or_default_expected); + case ParsingContext::SwitchClauseStatements: return parseErrorAtCurrentToken(Diagnostics::Statement_expected); + case ParsingContext::RestProperties: // fallthrough + case ParsingContext::TypeMembers: return parseErrorAtCurrentToken(Diagnostics::Property_or_signature_expected); + case ParsingContext::ClassMembers: return parseErrorAtCurrentToken(Diagnostics::Unexpected_token_A_constructor_method_accessor_or_property_was_expected); + case ParsingContext::EnumMembers: return parseErrorAtCurrentToken(Diagnostics::Enum_member_expected); + case ParsingContext::HeritageClauseElement: return parseErrorAtCurrentToken(Diagnostics::Expression_expected); + case ParsingContext::VariableDeclarations: + return isKeyword(token()) + ? parseErrorAtCurrentToken(Diagnostics::_0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token())) + : parseErrorAtCurrentToken(Diagnostics::Variable_declaration_expected); + case ParsingContext::ObjectBindingElements: return parseErrorAtCurrentToken(Diagnostics::Property_destructuring_pattern_expected); + case ParsingContext::ArrayBindingElements: return parseErrorAtCurrentToken(Diagnostics::Array_element_destructuring_pattern_expected); + case ParsingContext::ArgumentExpressions: return parseErrorAtCurrentToken(Diagnostics::Argument_expression_expected); + case ParsingContext::ObjectLiteralMembers: return parseErrorAtCurrentToken(Diagnostics::Property_assignment_expected); + case ParsingContext::ArrayLiteralMembers: return parseErrorAtCurrentToken(Diagnostics::Expression_or_comma_expected); + case ParsingContext::JSDocParameters: return parseErrorAtCurrentToken(Diagnostics::Parameter_declaration_expected); + case ParsingContext::Parameters: + return isKeyword(token()) + ? parseErrorAtCurrentToken(Diagnostics::_0_is_not_allowed_as_a_parameter_name, tokenToString(token())) + : parseErrorAtCurrentToken(Diagnostics::Parameter_declaration_expected); + case ParsingContext::TypeParameters: return parseErrorAtCurrentToken(Diagnostics::Type_parameter_declaration_expected); + case ParsingContext::TypeArguments: return parseErrorAtCurrentToken(Diagnostics::Type_argument_expected); + case ParsingContext::TupleElementTypes: return parseErrorAtCurrentToken(Diagnostics::Type_expected); + case ParsingContext::HeritageClauses: return parseErrorAtCurrentToken(Diagnostics::Unexpected_token_expected); + case ParsingContext::ImportOrExportSpecifiers: return parseErrorAtCurrentToken(Diagnostics::Identifier_expected); + case ParsingContext::JsxAttributes: return parseErrorAtCurrentToken(Diagnostics::Identifier_expected); + case ParsingContext::JsxChildren: return parseErrorAtCurrentToken(Diagnostics::Identifier_expected); + default: return nullopt; // TODO: GH#18217 `default: Debug.assertNever(context);` + } + } + bool isListElement(ParsingContext parsingContext, bool inErrorRecovery); + bool isListTerminator(ParsingContext kind); + + // True if positioned at element or terminator of the current list or any enclosing list + bool isInSomeParsingContext() { + for (int kind = 0; kind < (int)ParsingContext::Count; kind++) { + if (parsingContext & (1 << kind)) { + if (isListElement((ParsingContext)kind, /*inErrorRecovery*/ true) || isListTerminator((ParsingContext)kind)) { + return true; + } + } + } + + return false; + } + + // Returns true if we should abort parsing. + bool abortParsingListOrMoveToNextToken(ParsingContext kind) { + parsingContextErrors(kind); + if (isInSomeParsingContext()) { + return true; + } + + nextToken(); + return false; + } + + template + sharedOpt parseListElement(ParsingContext parsingContext, function()> parseElement) { + auto node = currentNode(parsingContext); + if (node) { + return consumeNode(node); + } + + return parseElement(); + } + + // Parses a list of elements + NodeArray parseList(ParsingContext kind, function()> parseElement) { + auto saveParsingContext = parsingContext; + parsingContext |= 1 << (int) kind; + vector> list; + + auto listPos = getNodePos(); + + while (! isListTerminator(kind)) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { + list.push_back(parseListElement(kind, parseElement)); + + continue; + } + + if (abortParsingListOrMoveToNextToken(kind)) { + break; + } + } + + parsingContext = saveParsingContext; + return createNodeArray(list, listPos); + } + +// // Parses a comma-delimited list of elements +// function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray; +// function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined; + optional parseDelimitedList(ParsingContext kind, function()> parseElement, optional considerSemicolonAsDelimiter = {}) { + auto saveParsingContext = parsingContext; + parsingContext |= 1 << (int)kind; + vector> list; + auto listPos = getNodePos(); + + int commaStart = -1; // Meaning the previous token was not a comma + while (true) { + if (isListElement(kind, /*inErrorRecovery*/ false)) { + auto startPos = scanner.getStartPos(); + auto result = parseListElement(kind, parseElement); + if (!result) { + parsingContext = saveParsingContext; + return nullopt; + } + list.push_back(result); + commaStart = scanner.getTokenPos(); + + if (parseOptional(SyntaxKind::CommaToken)) { + // No need to check for a zero length node since we know we parsed a comma + continue; + } + + commaStart = -1; // Back to the state where the last token was not a comma + if (isListTerminator(kind)) { + break; + } + + // We didn't get a comma, and the list wasn't terminated, explicitly parse + // out a comma so we give a good error message. + parseExpected(SyntaxKind::CommaToken, getExpectedCommaDiagnostic(kind)); + + // If the token was a semicolon, and the caller allows that, then skip it and + // continue. This ensures we get back on track and don't result in tons of + // parse errors. For example, this can happen when people do things like use + // a semicolon to delimit object literal members. Note: we'll have already + // reported an error when we called parseExpected above. + if (considerSemicolonAsDelimiter && token() == SyntaxKind::SemicolonToken && !scanner.hasPrecedingLineBreak()) { + nextToken(); + } + if (startPos == scanner.getStartPos()) { + // What we're parsing isn't actually remotely recognizable as a element and we've consumed no tokens whatsoever + // Consume a token to advance the parser in some way and avoid an infinite loop + // This can happen when we're speculatively parsing parenthesized expressions which we think may be arrow functions, + // or when a modifier keyword which is disallowed as a parameter name (ie, `static` in strict mode) is supplied + nextToken(); + } + continue; + } + + if (isListTerminator(kind)) { + break; + } + + if (abortParsingListOrMoveToNextToken(kind)) { + break; + } + } + + parsingContext = saveParsingContext; + // Recording the trailing comma is deliberately done after the previous + // loop, and not just if we see a list terminator. This is because the list + // may have ended incorrectly, but it is still important to know if there + // was a trailing comma. + // Check if the last token was a comma. + // Always preserve a trailing comma by marking it on the NodeArray + return createNodeArray(list, listPos, /*end*/ {}, commaStart >= 0); + } + // interface MissingList extends NodeArray { // isMissingList: true; // } -// -// function createMissingList(): MissingList { -// auto list = createNodeArray([], getNodePos()) as MissingList; -// list.isMissingList = true; -// return list; -// } -// -// function isMissingList(arr: NodeArray): boolean { -// return !!(arr as MissingList).isMissingList; -// } -// -// function parseBracketedList(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray { -// if (parseExpected(open)) { -// auto result = parseDelimitedList(kind, parseElement); -// parseExpected(close); -// return result; -// } -// -// return createMissingList(); -// } + NodeArray createMissingList() { + auto list = createNodeArray({}, getNodePos()); + list.isMissingList = true; + return list; + } + + bool isMissingList(NodeArray &arr) { + return arr.isMissingList; + } // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for // each identifier in order to reduce memory consumption. - shared createIdentifier(bool isIdentifier, optional diagnosticMessage = {}, optional privateIdentifierDiagnosticMessage = {}) { + shared createIdentifier(bool isIdentifier, optional diagnosticMessage, optional privateIdentifierDiagnosticMessage) { if (isIdentifier) { - identifierCount++; + identifierCount ++; auto pos = getNodePos(); // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker auto originalKeywordKind = token(); @@ -2933,12 +3080,12 @@ namespace ts { return createIdentifier(/*isIdentifier*/ true); } - if (token() == SyntaxKind::Unknown && scanner.tryScan([](){ return scanner.reScanInvalidIdentifier() == SyntaxKind::Identifier; })) { + if (token() == SyntaxKind::Unknown && scanner.tryScan([]() { return scanner.reScanInvalidIdentifier() == SyntaxKind::Identifier; })) { // Scanner has already recorded an 'Invalid character' error, so no need to add another from the parser. return createIdentifier(/*isIdentifier*/ true); } - identifierCount++; + identifierCount ++; // Only for end of file because the error gets reported incorrectly on embedded script tags. auto reportAtCurrentPosition = token() == SyntaxKind::EndOfFileToken; @@ -2946,10 +3093,10 @@ namespace ts { auto msgArg = scanner.getTokenText(); auto defaultMessage = isReservedWord ? - Diagnostics::Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here : - Diagnostics::Identifier_expected; + Diagnostics::Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here : + Diagnostics::Identifier_expected; - return createMissingNode(SyntaxKind::Identifier, reportAtCurrentPosition, diagnosticMessage ? diagnosticMessage : defaultMessage, msgArg); + return createMissingNode(SyntaxKind::Identifier, reportAtCurrentPosition, diagnosticMessage ? *diagnosticMessage : defaultMessage); } shared parseIdentifier(optional diagnosticMessage = {}, optional privateIdentifierDiagnosticMessage = {}) { @@ -2958,8 +3105,8 @@ namespace ts { // function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { // auto pos = getNodePos(); -// let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); -// let dotPos = getNodePos(); +// auto entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); +// auto dotPos = getNodePos(); // while (parseOptional(SyntaxKind::DotToken)) { // if (token() == SyntaxKind::LessThanToken) { // // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting @@ -2982,49 +3129,10 @@ namespace ts { // return finishNode(factory::createQualifiedName(entity, name), entity.pos); // } // -// function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean): Identifier | PrivateIdentifier { -// // Technically a keyword is valid here as all identifiers and keywords are identifier names. -// // However, often we'll encounter this in error situations when the identifier or keyword -// // is actually starting another valid construct. -// // -// // So, we check for the following specific case: -// // -// // name. -// // identifierOrKeyword identifierNameOrKeyword -// // -// // Note: the newlines are important here. For example, if that above code -// // were rewritten into: -// // -// // name.identifierOrKeyword -// // identifierNameOrKeyword -// // -// // Then we would consider it valid. That's because ASI would take effect and -// // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". -// // In the first case though, ASI will not take effect because there is not a -// // line terminator after the identifier or keyword. -// if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token())) { -// auto matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); -// -// if (matchesPattern) { -// // Report that we need an identifier. However, report it right after the dot, -// // and not on the next token. This is because the next token might actually -// // be an identifier and the error would be quite confusing. -// return createMissingNode(SyntaxKind::Identifier, /*reportAtCurrentPosition*/ true, Diagnostics::Identifier_expected); -// } -// } -// -// if (token() == SyntaxKind::PrivateIdentifier) { -// auto node = parsePrivateIdentifier(); -// return allowPrivateIdentifiers ? node : createMissingNode(SyntaxKind::Identifier, /*reportAtCurrentPosition*/ true, Diagnostics::Identifier_expected); -// } -// -// return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); -// } -// // function parseTemplateSpans(isTaggedTemplate: boolean) { // auto pos = getNodePos(); // auto list = []; -// let node: TemplateSpan; +// auto node: TemplateSpan; // do { // node = parseTemplateSpan(isTaggedTemplate); // list.push(node); @@ -3058,7 +3166,7 @@ namespace ts { // function parseTemplateTypeSpans() { // auto pos = getNodePos(); // auto list = []; -// let node: TemplateLiteralTypeSpan; +// auto node: TemplateLiteralTypeSpan; // do { // node = parseTemplateTypeSpan(); // list.push(node); @@ -3100,10 +3208,6 @@ namespace ts { // ); // } // -// function parseLiteralNode(): LiteralExpression { -// return parseLiteralLikeNode(token()) as LiteralExpression; -// } -// // function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead { // if (isTaggedTemplate) { // reScanTemplateHeadOrNoSubstitutionTemplate(); @@ -3119,39 +3223,6 @@ namespace ts { // return fragment as TemplateMiddle | TemplateTail; // } // -// function getTemplateLiteralRawText(kind: TemplateLiteralToken["kind"]) { -// auto isLast = kind == SyntaxKind::NoSubstitutionTemplateLiteral || kind == SyntaxKind::TemplateTail; -// auto tokenText = scanner.getTokenText(); -// return tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2)); -// } -// -// function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode { -// auto pos = getNodePos(); -// auto node = -// isTemplateLiteralKind(kind) ? factory::createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags) : -// // Octal literals are not allowed in strict mode or ES5 -// // Note that theoretically the following condition would hold true literals like 009, -// // which is not octal. But because of how the scanner separates the tokens, we would -// // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. -// // We also do not need to check for negatives because any prefix operator would be part of a -// // parent unary expression. -// kind == SyntaxKind::NumericLiteral ? factory::createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : -// kind == SyntaxKind::StringLiteral ? factory::createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) : -// isLiteralKind(kind) ? factory::createLiteralLikeNode(kind, scanner.getTokenValue()) : -// Debug.fail(); -// -// if (scanner.hasExtendedUnicodeEscape()) { -// node.hasExtendedUnicodeEscape = true; -// } -// -// if (scanner.isUnterminated()) { -// node.isUnterminated = true; -// } -// -// nextToken(); -// return finishNode(node, pos); -// } -// // // TYPES // // function parseEntityNameOfTypeReference() { @@ -3257,7 +3328,7 @@ namespace ts { // // function parseJSDocParameter(): ParameterDeclaration { // auto pos = getNodePos(); -// let name: Identifier | undefined; +// auto name: Identifier | undefined; // if (token() == SyntaxKind::ThisKeyword || token() == SyntaxKind::NewKeyword) { // name = parseIdentifierName(); // parseExpected(SyntaxKind::ColonToken); @@ -3300,7 +3371,7 @@ namespace ts { // } // // auto hasDotDotDot = parseOptional(SyntaxKind::DotDotDotToken); -// let type = parseTypeOrTypePredicate(); +// auto type = parseTypeOrTypePredicate(); // scanner.setInJSDocType(false); // if (hasDotDotDot) { // type = finishNode(factory::createJSDocVariadicType(type), pos); @@ -3366,18 +3437,15 @@ namespace ts { if (token() == SyntaxKind::ConstKeyword && permitInvalidConstAsModifier) { // We need to ensure that any subsequent modifiers appear on the same line // so that when 'const' is a standalone declaration, we don't issue an error. - if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { + if (! tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { return nullptr; } - } - else if (stopOnStartOfClassStaticBlock && token() == SyntaxKind::StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { + } else if (stopOnStartOfClassStaticBlock && token() == SyntaxKind::StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { return nullptr; - } - else if (hasSeenStaticModifier && token() == SyntaxKind::StaticKeyword) { + } else if (hasSeenStaticModifier && token() == SyntaxKind::StaticKeyword) { return nullptr; - } - else { - if (!parseAnyContextualModifier()) { + } else { + if (! parseAnyContextualModifier()) { return nullptr; } } @@ -3401,7 +3469,7 @@ namespace ts { if (modifier->kind == SyntaxKind::StaticKeyword) hasSeenStatic = true; list = append(list, modifier); } - if (!list.empty()) return factory::createNodeArray(list, pos); + if (! list.empty()) return createNodeArray(list, pos); return nullopt; } @@ -3555,50 +3623,987 @@ namespace ts { // parseSemicolon(); // } - shared parseTypeParameter() { + shared> parseIdentifierOrPattern(optional privateIdentifierDiagnosticMessage = {}); + shared parseAssignmentExpressionOrHigher(); + + sharedOpt parseInitializer() { + return parseOptional(SyntaxKind::EqualsToken) ? parseAssignmentExpressionOrHigher() : nullptr; + } + + shared parseArrayBindingElement() { auto pos = getNodePos(); - auto modifiers = parseModifiers(); - auto name = parseIdentifier(); - let constraint: TypeNode | undefined; - let expression: Expression | undefined; - if (parseOptional(SyntaxKind::ExtendsKeyword)) { - // It's not uncommon for people to write improper constraints to a generic. If the - // user writes a constraint that is an expression and not an actual type, then parse - // it out as an expression (so we can recover well), but report that a type is needed - // instead. - if (isStartOfType() || !isStartOfExpression()) { - constraint = parseType(); - } else { - // It was not a type, and it looked like an expression. Parse out an expression - // here so we recover well. Note: it is important that we call parseUnaryExpression - // and not parseExpression here. If the user has: - // - // - // - // We do *not* want to consume the `>` as we're consuming the expression for "". - expression = parseUnaryExpressionOrHigher(); - } + if (token() == SyntaxKind::CommaToken) { + return finishNode(factory::createOmittedExpression(), pos); } + auto dotDotDotToken = parseOptionalToken(SyntaxKind::DotDotDotToken); + auto name = parseIdentifierOrPattern(); + auto initializer = parseInitializer(); + return finishNode(factory::createBindingElement(dotDotDotToken, /*propertyName*/ {}, name, initializer), pos); + } - auto defaultType = parseOptional(SyntaxKind::EqualsToken) ? parseType() : undefined; - auto node = factory::createTypeParameterDeclaration(modifiers, name, constraint, defaultType); - node.expression = expression; + shared parseArrayBindingPattern() { + auto pos = getNodePos(); + parseExpected(SyntaxKind::OpenBracketToken); + auto elements = parseDelimitedList(ParsingContext::ArrayBindingElements, parseArrayBindingElement); + parseExpected(SyntaxKind::CloseBracketToken); + return finishNode(factory::createArrayBindingPattern(*elements), pos); + } + + string getTemplateLiteralRawText(SyntaxKind kind) { + auto isLast = kind == SyntaxKind::NoSubstitutionTemplateLiteral || kind == SyntaxKind::TemplateTail; + auto tokenText = scanner.getTokenText(); + return tokenText.substr(1, tokenText.size() - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2)); + } + + shared parseLiteralLikeNode(SyntaxKind kind) { + auto pos = getNodePos(); + shared node = + isTemplateLiteralKind(kind) ? factory::createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & (int)TokenFlags::TemplateLiteralLikeFlags) : + // Octal literals are not allowed in strict mode or ES5 + // Note that theoretically the following condition would hold true literals like 009, + // which is not octal. But because of how the scanner separates the tokens, we would + // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. + kind == SyntaxKind::NumericLiteral ? factory::createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : + kind == SyntaxKind::StringLiteral ? factory::createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ {}, scanner.hasExtendedUnicodeEscape()) : + isLiteralKind(kind) ? factory::createLiteralLikeNode(kind, scanner.getTokenValue()) : + throw runtime_error("Nope"); + + if (scanner.hasExtendedUnicodeEscape()) { + node->hasExtendedUnicodeEscape = true; + } + + if (scanner.isUnterminated()) { + node->isUnterminated = true; + } + + nextToken(); + return finishNode(node, pos); + } + + shared parseLiteralNode() { + return parseLiteralLikeNode(token()); + } + + shared parseExpression(); + + template + T doOutsideOfContext(int context, function func) { + // contextFlagsToClear will contain only the context flags that are + // currently set that we need to temporarily clear + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). + auto contextFlagsToClear = context & contextFlags; + if (contextFlagsToClear) { + // clear the requested context flags + setContextFlag(/*val*/ false, contextFlagsToClear); + auto result = func(); + // restore the context flags we just cleared + setContextFlag(/*val*/ true, contextFlagsToClear); + return result; + } + + // no need to do anything special as we are not in any of the requested contexts + return func(); + } + + template + T doOutsideOfContext(NodeFlags context, function func) { + return doOutsideOfContext((int)context, func); + } + + template + T doInsideOfContext(/*NodeFlags*/int context, function &func) { + // contextFlagsToSet will contain only the context flags that + // are not currently set that we need to temporarily enable. + // We don't just blindly reset to the previous flags to ensure + // that we do not mutate cached flags for the incremental + // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and + // HasAggregatedChildData). + auto contextFlagsToSet = context & ~contextFlags; + if (contextFlagsToSet) { + // set the requested context flags + setContextFlag(/*val*/ true, contextFlagsToSet); + auto result = func(); + // reset the context flags we just set + setContextFlag(/*val*/ false, contextFlagsToSet); + return result; + } + + // no need to do anything special as we are already in all of the requested contexts + return func(); + } + + template + T allowInAnd(const function &func) { + return doOutsideOfContext(NodeFlags::DisallowInContext, func); + } + + template + T disallowInAnd(const function &func) { + return doInsideOfContext(NodeFlags::DisallowInContext, func); + } + + template + T allowConditionalTypesAnd(const function &func) { + return doOutsideOfContext(NodeFlags::DisallowConditionalTypesContext, func); + } + template + T disallowConditionalTypesAnd(const function &func) { + return doInsideOfContext(NodeFlags::DisallowConditionalTypesContext, func); + } + template + T doInYieldContext(const function &func) { + return doInsideOfContext(NodeFlags::YieldContext, func); + } + template + T doInDecoratorContext(const function &func) { + return doInsideOfContext(NodeFlags::DecoratorContext, func); + } + template + T doInAwaitContext(const function &func) { + return doInsideOfContext(NodeFlags::AwaitContext, func); + } + template + T doOutsideOfAwaitContext(const function &func) { + return doOutsideOfContext(NodeFlags::AwaitContext, func); + } + template + T doInYieldAndAwaitContext(const function &func) { + return doInsideOfContext((int)NodeFlags::YieldContext | (int)NodeFlags::AwaitContext, func); + } + template + T doOutsideOfYieldAndAwaitContext(const function &func) { + return doOutsideOfContext((int)NodeFlags::YieldContext | (int)NodeFlags::AwaitContext, func); + } + + bool inDisallowConditionalTypesContext() { + return inContext(NodeFlags::DisallowConditionalTypesContext); + } + + bool inDecoratorContext() { + return inContext(NodeFlags::DecoratorContext); + } + + shared parseComputedPropertyName() { + // PropertyName [Yield]: + // LiteralPropertyName + // ComputedPropertyName[?Yield] + auto pos = getNodePos(); + parseExpected(SyntaxKind::OpenBracketToken); + // We parse any expression (including a comma expression). But the grammar + // says that only an assignment expression is allowed, so the grammar checker + // will error if it sees a comma expression. + auto expression = allowInAnd>(parseExpression); + parseExpected(SyntaxKind::CloseBracketToken); + return finishNode(factory::createComputedPropertyName(expression), pos); + } + + string internPrivateIdentifier(string text) { + auto privateIdentifier = get(privateIdentifiers, text); + if (!privateIdentifier) { + privateIdentifier = text; + set(privateIdentifiers, text, *privateIdentifier); + } + return *privateIdentifier; + } + + shared parsePrivateIdentifier() { + auto pos = getNodePos(); + auto node = factory::createPrivateIdentifier(internPrivateIdentifier(scanner.getTokenText())); + nextToken(); return finishNode(node, pos); } + shared parsePropertyNameWorker(bool allowComputedPropertyNames) { + if (token() == SyntaxKind::StringLiteral || token() == SyntaxKind::NumericLiteral) { + auto node = parseLiteralNode(); + node->text = internIdentifier(node->text); + return node; + } + if (allowComputedPropertyNames && token() == SyntaxKind::OpenBracketToken) { + return parseComputedPropertyName(); + } + if (token() == SyntaxKind::PrivateIdentifier) { + return parsePrivateIdentifier(); + } + return parseIdentifierName(); + } + + shared parsePropertyName() { + return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); + } - optional parseTypeParameters() { - if (token() == SyntaxKind::LessThanToken) { - return parseBracketedList(ParsingContext::TypeParameters, parseTypeParameter, SyntaxKind::LessThanToken, SyntaxKind::GreaterThanToken); + shared parseObjectBindingElement() { + auto pos = getNodePos(); + auto dotDotDotToken = parseOptionalToken(SyntaxKind::DotDotDotToken); + auto tokenIsIdentifier = isBindingIdentifier(); + sharedOpt propertyName = parsePropertyName(); + sharedOpt name; + if (tokenIsIdentifier && token() != SyntaxKind::ColonToken) { + name = propertyName; + propertyName = nullptr; } - return nullopt; + else { + parseExpected(SyntaxKind::ColonToken); + name = parseIdentifierOrPattern(); + } + auto initializer = parseInitializer(); + return finishNode(factory::createBindingElement(dotDotDotToken, propertyName, name, initializer), pos); } -// function parseSignatureMember(kind: SyntaxKind::CallSignature | SyntaxKind::ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration { -// auto pos = getNodePos(); -// auto hasJSDoc = hasPrecedingJSDocComment(); -// if (kind == SyntaxKind::ConstructSignature) { -// parseExpected(SyntaxKind::NewKeyword); + shared parseObjectBindingPattern() { + auto pos = getNodePos(); + parseExpected(SyntaxKind::OpenBraceToken); + auto elements = parseDelimitedList(ParsingContext::ObjectBindingElements, parseObjectBindingElement); + parseExpected(SyntaxKind::CloseBraceToken); + return finishNode(factory::createObjectBindingPattern(*elements), pos); + } + + shared> parseIdentifierOrPattern(optional privateIdentifierDiagnosticMessage) { + if (token() == SyntaxKind::OpenBracketToken) { + return parseArrayBindingPattern(); + } + if (token() == SyntaxKind::OpenBraceToken) { + return parseObjectBindingPattern(); + } + return parseBindingIdentifier(privateIdentifierDiagnosticMessage); + } + + + bool skipParameterStart() { + if (isModifierKind(token())) { + // Skip modifiers + parseModifiers(); + } + if (isIdentifier() || token() == SyntaxKind::ThisKeyword) { + nextToken(); + return true; + } + if (token() == SyntaxKind::OpenBracketToken || token() == SyntaxKind::OpenBraceToken) { + // Return true if we can parse an array or object binding pattern with no errors + auto previousErrorCount = parseDiagnostics.size(); + parseIdentifierOrPattern(); + return previousErrorCount == parseDiagnostics.size(); + } + return false; + } + + bool isUnambiguouslyStartOfFunctionType() { + nextToken(); + if (token() == SyntaxKind::CloseParenToken || token() == SyntaxKind::DotDotDotToken) { + // ( ) + // ( ... + return true; + } + if (skipParameterStart()) { + // We successfully skipped modifiers (if any) and an identifier or binding pattern, + // now see if we have something that indicates a parameter declaration + if (token() == SyntaxKind::ColonToken || token() == SyntaxKind::CommaToken || + token() == SyntaxKind::QuestionToken || token() == SyntaxKind::EqualsToken) { + // ( xxx : + // ( xxx , + // ( xxx ? + // ( xxx = + return true; + } + if (token() == SyntaxKind::CloseParenToken) { + nextToken(); + if (token() == SyntaxKind::EqualsGreaterThanToken) { + // ( xxx ) => + return true; + } + } + } + return false; + } + + bool nextTokenIsNewKeyword() { + nextToken(); + return token() == SyntaxKind::NewKeyword; + } + + bool isStartOfFunctionTypeOrConstructorType() { + if (token() == SyntaxKind::LessThanToken) { + return true; + } + if (token() == SyntaxKind::OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) { + return true; + } + return token() == SyntaxKind::NewKeyword || (token() == SyntaxKind::AbstractKeyword && lookAhead(nextTokenIsNewKeyword)); + } + + optional parseModifiersForConstructorType() { + optional modifiers; + if (token() == SyntaxKind::AbstractKeyword) { + auto pos = getNodePos(); + nextToken(); + auto modifier = finishNode(factory::createToken(SyntaxKind::AbstractKeyword), pos); + modifiers = createNodeArray({modifier}, pos); + } + return modifiers; + } + + /** + * Check if the current token can possibly be an ES7 increment expression. + * + * ES7 UpdateExpression: + * LeftHandSideExpression[?Yield] + * LeftHandSideExpression[?Yield][no LineTerminator here]++ + * LeftHandSideExpression[?Yield][no LineTerminator here]-- + * ++LeftHandSideExpression[?Yield] + * --LeftHandSideExpression[?Yield] + */ + bool isUpdateExpression() { + // This function is called inside parseUnaryExpression to decide + // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly + switch (token()) { + case SyntaxKind::PlusToken: + case SyntaxKind::MinusToken: + case SyntaxKind::TildeToken: + case SyntaxKind::ExclamationToken: + case SyntaxKind::DeleteKeyword: + case SyntaxKind::TypeOfKeyword: + case SyntaxKind::VoidKeyword: + case SyntaxKind::AwaitKeyword: + return false; + case SyntaxKind::LessThanToken: + // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression + if (languageVariant != LanguageVariant::JSX) { + return false; + } + // We are in JSX context and the token is part of JSXElement. + // falls through + default: + return true; + } + } + + shared parseRightSideOfDot(bool allowIdentifierNames, bool allowPrivateIdentifiers) { + // Technically a keyword is valid here as all identifiers and keywords are identifier names. + // However, often we'll encounter this in error situations when the identifier or keyword + // is actually starting another valid construct. + // + // So, we check for the following specific case: + // + // name. + // identifierOrKeyword identifierNameOrKeyword + // + // Note: the newlines are important here. For example, if that above code + // were rewritten into: + // + // name.identifierOrKeyword + // identifierNameOrKeyword + // + // Then we would consider it valid. That's because ASI would take effect and + // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". + // In the first case though, ASI will not take effect because there is not a + // line terminator after the identifier or keyword. + if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token())) { + auto matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); + + if (matchesPattern) { + // Report that we need an identifier. However, report it right after the dot, + // and not on the next token. This is because the next token might actually + // be an identifier and the error would be quite confusing. + return createMissingNode(SyntaxKind::Identifier, /*reportAtCurrentPosition*/ true, Diagnostics::Identifier_expected); + } + } + + if (token() == SyntaxKind::PrivateIdentifier) { + auto node = parsePrivateIdentifier(); + return allowPrivateIdentifiers ? (shared)node : createMissingNode(SyntaxKind::Identifier, /*reportAtCurrentPosition*/ true, Diagnostics::Identifier_expected); + } + + return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); + } + + + shared parseJsxElementName() { + auto pos = getNodePos(); + scanJsxIdentifier(); + // JsxElement can have name in the form of + // propertyAccessExpression + // primaryExpression in the form of an identifier and "this" keyword + // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword + // We only want to consider "this" as a primaryExpression + shared expression = token() == SyntaxKind::ThisKeyword ? (shared)parseTokenNode() : parseIdentifierName(); + while (parseOptional(SyntaxKind::DotToken)) { + expression = finishNode(factory::createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos); + } + return expression; + } + + NodeArray parseBracketedList(ParsingContext kind, function()> parseElement, SyntaxKind open, SyntaxKind close) { + if (parseExpected(open)) { + auto result = parseDelimitedList(kind, parseElement); + parseExpected(close); + return *result; + } + + return createMissingList(); + } + + optional tryParseTypeArguments() { + if (token() == SyntaxKind::LessThanToken) return parseBracketedList(ParsingContext::TypeArguments, parseType, SyntaxKind::LessThanToken, SyntaxKind::GreaterThanToken); + return nullopt; + } + + SyntaxKind scanJsxAttributeValue() { + return currentToken = scanner.scanJsxAttributeValue(); + } + + sharedOpt parseJsxExpression(bool inExpressionContext) { + auto pos = getNodePos(); + if (!parseExpected(SyntaxKind::OpenBraceToken)) { + return nullptr; + } + + sharedOpt dotDotDotToken; + sharedOpt expression; + if (token() != SyntaxKind::CloseBraceToken) { + dotDotDotToken = parseOptionalToken(SyntaxKind::DotDotDotToken); + // Only an AssignmentExpression is valid here per the JSX spec, + // but we can unambiguously parse a comma sequence and provide + // a better error message in grammar checking. + expression = parseExpression(); + } + if (inExpressionContext) { + parseExpected(SyntaxKind::CloseBraceToken); + } + else { + if (parseExpected(SyntaxKind::CloseBraceToken, /*message*/ {}, /*shouldAdvance*/ false)) { + scanJsxText(); + } + } + + return finishNode(factory::createJsxExpression(dotDotDotToken, expression), pos); + } + + shared parseJsxOpeningOrSelfClosingElementOrOpeningFragment(bool inExpressionContext); + + shared parseJsxText() { + auto pos = getNodePos(); + auto node = factory::createJsxText(scanner.getTokenValue(), currentToken == SyntaxKind::JsxTextAllWhiteSpaces); + currentToken = scanner.scanJsxToken(); + return finishNode(node, pos); + } + + shared + parseJsxElementOrSelfClosingElementOrFragment(bool inExpressionContext, optional topInvalidNodePosition = {}, sharedOpt openingTag = {}); + + sharedOpt parseJsxChild(shared openingTag, SyntaxKind token) { + switch (token) { + case SyntaxKind::EndOfFileToken: + // If we hit EOF, issue the error at the tag that lacks the closing element + // rather than at the end of the file (which is useless) + if (isJsxOpeningFragment(openingTag)) { + parseErrorAtRange(openingTag, Diagnostics::JSX_fragment_has_no_corresponding_closing_tag); + } + else { + // We want the error span to cover only 'Foo.Bar' in < Foo.Bar > + // or to cover only 'Foo' in < Foo > + auto tag = getTagName(openingTag); + auto start = skipTrivia(sourceText, tag->pos); + parseErrorAt(start, tag->end, Diagnostics::JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, tag)); + } + return nullptr; + case SyntaxKind::LessThanSlashToken: + case SyntaxKind::ConflictMarkerTrivia: + return nullptr; + case SyntaxKind::JsxText: + case SyntaxKind::JsxTextAllWhiteSpaces: + return parseJsxText(); + case SyntaxKind::OpenBraceToken: + return parseJsxExpression(/*inExpressionContext*/ false); + case SyntaxKind::LessThanToken: + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false, /*topInvalidNodePosition*/ {}, openingTag); + default: + throw runtime_error(format("Should not reach %d", token)); +// return Debug.assertNever(token); + } + } + + /** @internal */ + bool tagNamesAreEquivalent(shared lhs, shared rhs) { + if (lhs->kind != rhs->kind) { + return false; + } + + if (lhs->kind == SyntaxKind::Identifier) { + if (rhs->kind == SyntaxKind::Identifier) return lhs->to().escapedText == rhs->to().escapedText; + return false; + } + + if (lhs->kind == SyntaxKind::ThisKeyword) { + return true; + } + + // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only + // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression + // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element + if (lhs->kind == SyntaxKind::PropertyAccessExpression && rhs->kind == SyntaxKind::PropertyAccessExpression) { + auto l = lhs->to(); + auto r = rhs->to(); + return getEscapedName(l.name) == getEscapedName(r.name) && tagNamesAreEquivalent(l.expression, r.expression); + } + return false; + } + + NodeArray parseJsxChildren(shared openingTag) { + vector> list; + auto listPos = getNodePos(); + auto saveParsingContext = parsingContext; + parsingContext |= 1 << (int)ParsingContext::JsxChildren; + + while (true) { + auto child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken()); + if (!child) break; + list.push_back(child); + if (isJsxOpeningElement(openingTag) + && (child && child->kind == SyntaxKind::JsxElement) + && !tagNamesAreEquivalent(getTagName(child->to().openingElement), getTagName(child->to().closingElement)) + && tagNamesAreEquivalent(getTagName(openingTag), getTagName(child->to().closingElement))) { + // stop after parsing a mismatched child like
...(
) in order to reattach the higher + break; + } + } + + parsingContext = saveParsingContext; + return createNodeArray(list, listPos); + } + + shared parseJsxClosingElement(shared open, bool inExpressionContext) { + auto pos = getNodePos(); + parseExpected(SyntaxKind::LessThanSlashToken); + auto tagName = parseJsxElementName(); + if (parseExpected(SyntaxKind::GreaterThanToken, /*diagnostic*/ {}, /*shouldAdvance*/ false)) { + // manually advance the scanner in order to look for jsx text inside jsx + if (inExpressionContext || !tagNamesAreEquivalent(open->tagName, tagName)) { + nextToken(); + } + else { + scanJsxText(); + } + } + return finishNode(factory::createJsxClosingElement(tagName), pos); + } + + shared parseJsxClosingFragment(bool inExpressionContext) { + auto pos = getNodePos(); + parseExpected(SyntaxKind::LessThanSlashToken); + if (tokenIsIdentifierOrKeyword(token())) { + parseErrorAtRange(parseJsxElementName(), Diagnostics::Expected_corresponding_closing_tag_for_JSX_fragment); + } + if (parseExpected(SyntaxKind::GreaterThanToken, /*diagnostic*/ {}, /*shouldAdvance*/ false)) { + // manually advance the scanner in order to look for jsx text inside jsx + if (inExpressionContext) { + nextToken(); + } + else { + scanJsxText(); + } + } + return finishNode(factory::createJsxJsxClosingFragment(), pos); + } + + shared + parseJsxElementOrSelfClosingElementOrFragment(bool inExpressionContext, optional topInvalidNodePosition, sharedOpt openingTag) { + auto pos = getNodePos(); + auto _opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); + sharedOpt result; //JsxElement | JsxSelfClosingElement | JsxFragment + if (_opening->kind == SyntaxKind::JsxOpeningElement) { + auto opening = dynamic_pointer_cast(_opening); + auto children = parseJsxChildren(opening); + sharedOpt closingElement; // JsxClosingElement; + + auto lastChild = children.list[children.length() - 1]; + if (lastChild && lastChild->kind == SyntaxKind::JsxElement + && !tagNamesAreEquivalent(getTagName(lastChild->to().openingElement), getTagName(lastChild->to().closingElement)) + && tagNamesAreEquivalent(getTagName(opening), getTagName(lastChild->to().closingElement))) { + // when an unclosed JsxOpeningElement incorrectly parses its parent's JsxClosingElement, + // restructure (
(......
)) --> (
(......)
) + // (no need to error; the parent will error) + auto jsxElement = lastChild->to(); + auto end = jsxElement.children.end; + auto newLast = finishNode(factory::createJsxElement( + jsxElement.openingElement, + jsxElement.children, + finishNode(factory::createJsxClosingElement(finishNode(factory::createIdentifier(""), end, end)), end, end)), + jsxElement.openingElement->pos, + end); + + auto c = children.slice(0, children.length() - 1); + c.push_back(newLast); + children = createNodeArray(c, children.pos, end); + closingElement = jsxElement.closingElement; + } + else { + closingElement = parseJsxClosingElement(opening, inExpressionContext); + if (!tagNamesAreEquivalent(getTagName(opening), getTagName(closingElement))) { + if (openingTag && isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(getTagName(closingElement), getTagName(openingTag))) { + // opening incorrectly matched with its parent's closing -- put error on opening + parseErrorAtRange(getTagName(opening), Diagnostics::JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, getTagName(opening))); + } + else { + // other opening/closing mismatches -- put error on closing + parseErrorAtRange(getTagName(closingElement), Diagnostics::Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, getTagName(opening))); + } + } + } + result = finishNode(factory::createJsxElement(opening, children, closingElement), pos); + } + else if (_opening->kind == SyntaxKind::JsxOpeningFragment) { + auto opening = dynamic_pointer_cast(_opening); + result = finishNode(factory::createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos); + } + else { + assert(_opening->kind == SyntaxKind::JsxSelfClosingElement); + // Nothing else to do for self-closing elements + result = _opening; + } + + // If the user writes the invalid code '
' in an expression context (i.e. not wrapped in + // an enclosing tag), we'll naively try to parse ^ this as a 'less than' operator and the remainder of the tag + // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX + // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter + // does less damage and we can report a better error. + // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios + // of one sort or another. + if (inExpressionContext && token() == SyntaxKind::LessThanToken) { +// auto topBadPos = typeof topInvalidNodePosition == "undefined" ? result.pos : topInvalidNodePosition; +// auto invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, topBadPos)); +// if (invalidElement) { +// auto operatorToken = createMissingNode(SyntaxKind::CommaToken, /*reportAtCurrentPosition*/ false); +// setTextRangePosWidth(operatorToken, invalidElement.pos, 0); +// parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics::JSX_expressions_must_have_one_parent_element); +// return finishNode(factory::createBinaryExpression(result, operatorToken as Token, invalidElement), pos) as Node as JsxElement; +// } + } + + return result; + } + + sharedOpt parseJsxAttributeValue() { + if (token() == SyntaxKind::EqualsToken) { + if (scanJsxAttributeValue() == SyntaxKind::StringLiteral) { + return parseLiteralNode(); + } + if (token() == SyntaxKind::OpenBraceToken) { + return parseJsxExpression(/*inExpressionContext*/ true); + } + if (token() == SyntaxKind::LessThanToken) { + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); + } + parseErrorAtCurrentToken(Diagnostics::or_JSX_element_expected); + } + return nullptr; + } + + shared parseJsxSpreadAttribute() { + auto pos = getNodePos(); + parseExpected(SyntaxKind::OpenBraceToken); + parseExpected(SyntaxKind::DotDotDotToken); + auto expression = parseExpression(); + parseExpected(SyntaxKind::CloseBraceToken); + return finishNode(factory::createJsxSpreadAttribute(expression), pos); + } + + shared parseJsxAttribute() { + if (token() == SyntaxKind::OpenBraceToken) { + return parseJsxSpreadAttribute(); + } + + scanJsxIdentifier(); + auto pos = getNodePos(); + return finishNode(factory::createJsxAttribute(parseIdentifierName(), parseJsxAttributeValue()), pos); + } + + shared parseJsxAttributes() { + auto pos = getNodePos(); + return finishNode(factory::createJsxAttributes(parseList(ParsingContext::JsxAttributes, parseJsxAttribute)), pos); + } + + shared parseJsxOpeningOrSelfClosingElementOrOpeningFragment(bool inExpressionContext) { + auto pos = getNodePos(); + + parseExpected(SyntaxKind::LessThanToken); + + if (token() == SyntaxKind::GreaterThanToken) { + // See below for explanation of scanJsxText + scanJsxText(); + return finishNode(factory::createJsxOpeningFragment(), pos); + } + auto tagName = parseJsxElementName(); + optional typeArguments = (contextFlags & (int)NodeFlags::JavaScriptFile) == 0 ? tryParseTypeArguments() : nullopt; + auto attributes = parseJsxAttributes(); + + sharedOpt node; + + if (token() == SyntaxKind::GreaterThanToken) { + // Closing tag, so scan the immediately-following text with the JSX scanning instead + // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate + // scanning errors + scanJsxText(); + node = factory::createJsxOpeningElement(tagName, typeArguments, attributes); + } + else { + parseExpected(SyntaxKind::SlashToken); + if (parseExpected(SyntaxKind::GreaterThanToken, /*diagnostic*/ {}, /*shouldAdvance*/ false)) { + // manually advance the scanner in order to look for jsx text inside jsx + if (inExpressionContext) { + nextToken(); + } + else { + scanJsxText(); + } + } + node = factory::createJsxSelfClosingElement(tagName, typeArguments, attributes); + } + + return finishNode(node, pos); + } + + shared parseLeftHandSideExpressionOrHigher() { + // Original Ecma: + // LeftHandSideExpression: See 11.2 + // NewExpression + // CallExpression + // + // Our simplification: + // + // LeftHandSideExpression: See 11.2 + // MemberExpression + // CallExpression + // + // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with + // MemberExpression to make our lives easier. + // + // to best understand the below code, it's important to see how CallExpression expands + // out into its own productions: + // + // CallExpression: + // MemberExpression Arguments + // CallExpression Arguments + // CallExpression[Expression] + // CallExpression.IdentifierName + // import (AssignmentExpression) + // super Arguments + // super.IdentifierName + // + // Because of the recursion in these calls, we need to bottom out first. There are three + // bottom out states we can run into: 1) We see 'super' which must start either of + // the last two CallExpression productions. 2) We see 'import' which must start import call. + // 3)we have a MemberExpression which either completes the LeftHandSideExpression, + // or starts the beginning of the first four CallExpression productions. + auto pos = getNodePos(); + sharedOpt expression; + if (token() == SyntaxKind::ImportKeyword) { + if (lookAhead(nextTokenIsOpenParenOrLessThan)) { + // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" + // For example: + // var foo3 = require("subfolder + // import * as foo1 from "module-from-node + // We want this import to be a statement rather than import call expression + sourceFlags |= (int)NodeFlags::PossiblyContainsDynamicImport; + expression = parseTokenNode(); + } + else if (lookAhead(nextTokenIsDot)) { + // This is an 'import.*' metaproperty (i.e. 'import.meta') + nextToken(); // advance past the 'import' + nextToken(); // advance past the dot + expression = finishNode(factory::createMetaProperty(SyntaxKind::ImportKeyword, parseIdentifierName()), pos); + sourceFlags |= (int)NodeFlags::PossiblyContainsImportMeta; + } + else { + expression = parseMemberExpressionOrHigher(); + } + } + else { + expression = token() == SyntaxKind::SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher(); + } + + // Now, we *may* be complete. However, we might have consumed the start of a + // CallExpression or OptionalExpression. As such, we need to consume the rest + // of it here to be complete. + return parseCallExpressionRest(pos, expression); + } + + + /** + * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression. + * + * ES7 UpdateExpression[yield]: + * 1) LeftHandSideExpression[?yield] + * 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++ + * 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]-- + * 4) ++LeftHandSideExpression[?yield] + * 5) --LeftHandSideExpression[?yield] + * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression + */ + shared parseUpdateExpression() { + if (token() == SyntaxKind::PlusPlusToken || token() == SyntaxKind::MinusMinusToken) { + auto pos = getNodePos(); + return finishNode(factory::createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); + } + else if (languageVariant == LanguageVariant::JSX && token() == SyntaxKind::LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + // JSXElement is part of primaryExpression + return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); + } + + auto expression = parseLeftHandSideExpressionOrHigher(); + + assert(isLeftHandSideExpression(expression)); + if ((token() == SyntaxKind::PlusPlusToken || token() == SyntaxKind::MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { + auto operatorToken = token(); + nextToken(); + return finishNode(factory::createPostfixUnaryExpression(expression, operatorToken), expression->pos); + } + + return expression; + } + + + /** + * Parse ES7 exponential expression and await expression + * + * ES7 ExponentiationExpression: + * 1) UnaryExpression[?Yield] + * 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield] + * + */ + shared parseUnaryExpressionOrHigher() { + /** + * ES7 UpdateExpression: + * 1) LeftHandSideExpression[?Yield] + * 2) LeftHandSideExpression[?Yield][no LineTerminator here]++ + * 3) LeftHandSideExpression[?Yield][no LineTerminator here]-- + * 4) ++UnaryExpression[?Yield] + * 5) --UnaryExpression[?Yield] + */ + if (isUpdateExpression()) { + auto pos = getNodePos(); + auto updateExpression = parseUpdateExpression(); + return token() == SyntaxKind::AsteriskAsteriskToken ? + parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) as BinaryExpression : + updateExpression; + } + + /** + * ES7 UnaryExpression: + * 1) UpdateExpression[?yield] + * 2) delete UpdateExpression[?yield] + * 3) void UpdateExpression[?yield] + * 4) typeof UpdateExpression[?yield] + * 5) + UpdateExpression[?yield] + * 6) - UpdateExpression[?yield] + * 7) ~ UpdateExpression[?yield] + * 8) ! UpdateExpression[?yield] + */ + auto unaryOperator = token(); + auto simpleUnaryExpression = parseSimpleUnaryExpression(); + if (token() == SyntaxKind::AsteriskAsteriskToken) { + auto pos = skipTrivia(sourceText, simpleUnaryExpression.pos); + auto { end } = simpleUnaryExpression; + if (simpleUnaryExpression.kind == SyntaxKind::TypeAssertionExpression) { + parseErrorAt(pos, end, Diagnostics::A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); + } + else { + parseErrorAt(pos, end, Diagnostics::An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator)); + } + } + return simpleUnaryExpression; + } + + shared parseTypeParameter() { + auto pos = getNodePos(); + auto modifiers = parseModifiers(); + auto name = parseIdentifier(); + + sharedOpt constraint; + sharedOpt expression; + + if (parseOptional(SyntaxKind::ExtendsKeyword)) { + // It's not uncommon for people to write improper constraints to a generic. If the + // user writes a constraint that is an expression and not an actual type, then parse + // it out as an expression (so we can recover well), but report that a type is needed + // instead. + if (isStartOfType() || ! isStartOfExpression()) { + constraint = parseType(); + } else { + // It was not a type, and it looked like an expression. Parse out an expression + // here so we recover well. Note: it is important that we call parseUnaryExpression + // and not parseExpression here. If the user has: + // + // + // + // We do *not* want to consume the `>` as we're consuming the expression for "". + expression = parseUnaryExpressionOrHigher(); + } + } + + auto defaultType = parseOptional(SyntaxKind::EqualsToken) ? parseType() : undefined; + auto node = factory::createTypeParameterDeclaration(modifiers, name, constraint, defaultType); + node.expression = expression; + return finishNode(node, pos); + } + + optional parseTypeParameters() { + if (token() == SyntaxKind::LessThanToken) { + return parseBracketedList(ParsingContext::TypeParameters, parseTypeParameter, SyntaxKind::LessThanToken, SyntaxKind::GreaterThanToken); + } + return nullopt; + } + + shared parseFunctionOrConstructorType() { + auto pos = getNodePos(); + auto hasJSDoc = hasPrecedingJSDocComment(); + auto modifiers = parseModifiersForConstructorType(); + auto isConstructorType = parseOptional(SyntaxKind::NewKeyword); + auto typeParameters = parseTypeParameters(); + auto parameters = parseParameters(SignatureFlags::Type); + auto type = parseReturnType(SyntaxKind::EqualsGreaterThanToken, /*isType*/ false); + auto node = isConstructorType + ? factory::createConstructorTypeNode(modifiers, typeParameters, parameters, type) + : factory::createFunctionTypeNode(typeParameters, parameters, type); + if (!isConstructorType) reinterpret_cast&>(node).modifiers = modifiers; + return withJSDoc(finishNode(node, pos), hasJSDoc); + } + + shared parseType() { + if (contextFlags & (int)NodeFlags::TypeExcludesFlags) { + return doOutsideOfContext>(NodeFlags::TypeExcludesFlags, parseType); + } + + if (isStartOfFunctionTypeOrConstructorType()) { + return parseFunctionOrConstructorType(); + } + auto pos = getNodePos(); + auto type = parseUnionTypeOrHigher(); + if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind::ExtendsKeyword)) { + // The type following 'extends' is not permitted to be another conditional type + auto extendsType = disallowConditionalTypesAnd(parseType); + parseExpected(SyntaxKind::QuestionToken); + auto trueType = allowConditionalTypesAnd(parseType); + parseExpected(SyntaxKind::ColonToken); + auto falseType = allowConditionalTypesAnd(parseType); + return finishNode(factory::createConditionalTypeNode(type, extendsType, trueType, falseType), pos); + } + return type; + } + + sharedOpt parseTypeAnnotation() { + return parseOptional(SyntaxKind::ColonToken) ? parseType() : nullptr; + } + +// function parseSignatureMember(kind: SyntaxKind::CallSignature | SyntaxKind::ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration { +// auto pos = getNodePos(); +// auto hasJSDoc = hasPrecedingJSDocComment(); +// if (kind == SyntaxKind::ConstructSignature) { +// parseExpected(SyntaxKind::NewKeyword); // } // // auto typeParameters = parseTypeParameters(); @@ -3681,7 +4686,7 @@ namespace ts { // function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): PropertySignature | MethodSignature { // auto name = parsePropertyName(); // auto questionToken = parseOptionalToken(SyntaxKind::QuestionToken); -// let node: PropertySignature | MethodSignature; +// auto node: PropertySignature | MethodSignature; // if (token() == SyntaxKind::OpenParenToken || token() == SyntaxKind::LessThanToken) { // // Method signatures don't exist in expression contexts. So they have neither // // [Yield] nor [Await] @@ -3702,42 +4707,6 @@ namespace ts { // return withJSDoc(finishNode(node, pos), hasJSDoc); // } // -// function isTypeMemberStart(): boolean { -// // Return true if we have the start of a signature member -// if (token() == SyntaxKind::OpenParenToken || -// token() == SyntaxKind::LessThanToken || -// token() == SyntaxKind::GetKeyword || -// token() == SyntaxKind::SetKeyword) { -// return true; -// } -// let idToken = false; -// // Eat up all modifiers, but hold on to the last one in case it is actually an identifier -// while (isModifierKind(token())) { -// idToken = true; -// nextToken(); -// } -// // Index signatures and computed property names are type members -// if (token() == SyntaxKind::OpenBracketToken) { -// return true; -// } -// // Try to get the first property-like token following all modifiers -// if (isLiteralPropertyName()) { -// idToken = true; -// nextToken(); -// } -// // If we were able to get any potential identifier, check that it is -// // the start of a member declaration -// if (idToken) { -// return token() == SyntaxKind::OpenParenToken || -// token() == SyntaxKind::LessThanToken || -// token() == SyntaxKind::QuestionToken || -// token() == SyntaxKind::ColonToken || -// token() == SyntaxKind::CommaToken || -// canParseSemicolon(); -// } -// return false; -// } -// // function parseTypeMember(): TypeElement { // if (token() == SyntaxKind::OpenParenToken || token() == SyntaxKind::LessThanToken) { // return parseSignatureMember(SyntaxKind::CallSignature); @@ -3777,7 +4746,7 @@ namespace ts { // } // // function parseObjectTypeMembers(): NodeArray { -// let members: NodeArray; +// auto members: NodeArray; // if (parseExpected(SyntaxKind::OpenBraceToken)) { // members = parseList(ParsingContext::TypeMembers, parseTypeMember); // parseExpected(SyntaxKind::CloseBraceToken); @@ -3811,7 +4780,7 @@ namespace ts { // function parseMappedType() { // auto pos = getNodePos(); // parseExpected(SyntaxKind::OpenBraceToken); -// let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined; +// auto readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined; // if (token() == SyntaxKind::ReadonlyKeyword || token() == SyntaxKind::PlusToken || token() == SyntaxKind::MinusToken) { // readonlyToken = parseTokenNode(); // if (readonlyToken.kind != SyntaxKind::ReadonlyKeyword) { @@ -3822,7 +4791,7 @@ namespace ts { // auto typeParameter = parseMappedTypeParameter(); // auto nameType = parseOptional(SyntaxKind::AsKeyword) ? parseType() : undefined; // parseExpected(SyntaxKind::CloseBracketToken); -// let questionToken: QuestionToken | PlusToken | MinusToken | undefined; +// auto questionToken: QuestionToken | PlusToken | MinusToken | undefined; // if (token() == SyntaxKind::QuestionToken || token() == SyntaxKind::PlusToken || token() == SyntaxKind::MinusToken) { // questionToken = parseTokenNode(); // if (questionToken.kind != SyntaxKind::QuestionToken) { @@ -3883,42 +4852,16 @@ namespace ts { // factory::createTupleTypeNode( // parseBracketedList(ParsingContext::TupleElementTypes, parseTupleElementNameOrTupleElementType, SyntaxKind::OpenBracketToken, SyntaxKind::CloseBracketToken) // ), -// pos -// ); -// } -// -// function parseParenthesizedType(): TypeNode { -// auto pos = getNodePos(); -// parseExpected(SyntaxKind::OpenParenToken); -// auto type = parseType(); -// parseExpected(SyntaxKind::CloseParenToken); -// return finishNode(factory::createParenthesizedType(type), pos); -// } -// -// function parseModifiersForConstructorType(): NodeArray | undefined { -// let modifiers: NodeArray | undefined; -// if (token() == SyntaxKind::AbstractKeyword) { -// auto pos = getNodePos(); -// nextToken(); -// auto modifier = finishNode(factory::createToken(SyntaxKind::AbstractKeyword), pos); -// modifiers = createNodeArray([modifier], pos); -// } -// return modifiers; +// pos +// ); // } // -// function parseFunctionOrConstructorType(): TypeNode { +// function parseParenthesizedType(): TypeNode { // auto pos = getNodePos(); -// auto hasJSDoc = hasPrecedingJSDocComment(); -// auto modifiers = parseModifiersForConstructorType(); -// auto isConstructorType = parseOptional(SyntaxKind::NewKeyword); -// auto typeParameters = parseTypeParameters(); -// auto parameters = parseParameters(SignatureFlags::Type); -// auto type = parseReturnType(SyntaxKind::EqualsGreaterThanToken, /*isType*/ false); -// auto node = isConstructorType -// ? factory::createConstructorTypeNode(modifiers, typeParameters, parameters, type) -// : factory::createFunctionTypeNode(typeParameters, parameters, type); -// if (!isConstructorType) reinterpret_cast&>(node).modifiers = modifiers; -// return withJSDoc(finishNode(node, pos), hasJSDoc); +// parseExpected(SyntaxKind::OpenParenToken); +// auto type = parseType(); +// parseExpected(SyntaxKind::CloseParenToken); +// return finishNode(factory::createParenthesizedType(type), pos); // } // // function parseKeywordAndNoDot(): TypeNode | undefined { @@ -3931,7 +4874,7 @@ namespace ts { // if (negative) { // nextToken(); // } -// let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression = +// auto expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression = // token() == SyntaxKind::TrueKeyword || token() == SyntaxKind::FalseKeyword || token() == SyntaxKind::NullKeyword ? // parseTokenNode() : // parseLiteralLikeNode(token()) as LiteralExpression; @@ -3973,7 +4916,7 @@ namespace ts { // parseExpected(SyntaxKind::ImportKeyword); // parseExpected(SyntaxKind::OpenParenToken); // auto type = parseType(); -// let assertions: ImportTypeAssertionContainer | undefined; +// auto assertions: ImportTypeAssertionContainer | undefined; // if (parseOptional(SyntaxKind::CommaToken)) { // assertions = parseImportTypeAssertions(); // } @@ -4107,7 +5050,7 @@ namespace ts { // // function parsePostfixTypeOrHigher(): TypeNode { // auto pos = getNodePos(); -// let type = parseNonArrayType(); +// auto type = parseNonArrayType(); // while (!scanner.hasPrecedingLineBreak()) { // switch (token()) { // case SyntaxKind::ExclamationToken: @@ -4191,7 +5134,7 @@ namespace ts { // // try to parse them gracefully and issue a helpful message. // if (isStartOfFunctionTypeOrConstructorType()) { // auto type = parseFunctionOrConstructorType(); -// let diagnostic: DiagnosticMessage; +// auto diagnostic: DiagnosticMessage; // if (isFunctionTypeNode(type)) { // diagnostic = isInUnionType // ? Diagnostics::Function_type_notation_must_be_parenthesized_when_used_in_a_union_type @@ -4217,7 +5160,7 @@ namespace ts { // auto pos = getNodePos(); // auto isUnionType = operator == SyntaxKind::BarToken; // auto hasLeadingOperator = parseOptional(operator); -// let type = hasLeadingOperator && parseFunctionOrConstructorTypeToError(isUnionType) +// auto type = hasLeadingOperator && parseFunctionOrConstructorTypeToError(isUnionType) // || parseConstituentType(); // if (token() == operator || hasLeadingOperator) { // auto types = [type]; @@ -4237,69 +5180,6 @@ namespace ts { // return parseUnionOrIntersectionType(SyntaxKind::BarToken, parseIntersectionTypeOrHigher, factory::createUnionTypeNode); // } // -// function nextTokenIsNewKeyword(): boolean { -// nextToken(); -// return token() == SyntaxKind::NewKeyword; -// } -// -// function isStartOfFunctionTypeOrConstructorType(): boolean { -// if (token() == SyntaxKind::LessThanToken) { -// return true; -// } -// if (token() == SyntaxKind::OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) { -// return true; -// } -// return token() == SyntaxKind::NewKeyword || -// token() == SyntaxKind::AbstractKeyword && lookAhead(nextTokenIsNewKeyword); -// } -// -// function skipParameterStart(): boolean { -// if (isModifierKind(token())) { -// // Skip modifiers -// parseModifiers(); -// } -// if (isIdentifier() || token() == SyntaxKind::ThisKeyword) { -// nextToken(); -// return true; -// } -// if (token() == SyntaxKind::OpenBracketToken || token() == SyntaxKind::OpenBraceToken) { -// // Return true if we can parse an array or object binding pattern with no errors -// auto previousErrorCount = parseDiagnostics.length; -// parseIdentifierOrPattern(); -// return previousErrorCount == parseDiagnostics.length; -// } -// return false; -// } -// -// function isUnambiguouslyStartOfFunctionType() { -// nextToken(); -// if (token() == SyntaxKind::CloseParenToken || token() == SyntaxKind::DotDotDotToken) { -// // ( ) -// // ( ... -// return true; -// } -// if (skipParameterStart()) { -// // We successfully skipped modifiers (if any) and an identifier or binding pattern, -// // now see if we have something that indicates a parameter declaration -// if (token() == SyntaxKind::ColonToken || token() == SyntaxKind::CommaToken || -// token() == SyntaxKind::QuestionToken || token() == SyntaxKind::EqualsToken) { -// // ( xxx : -// // ( xxx , -// // ( xxx ? -// // ( xxx = -// return true; -// } -// if (token() == SyntaxKind::CloseParenToken) { -// nextToken(); -// if (token() == SyntaxKind::EqualsGreaterThanToken) { -// // ( xxx ) => -// return true; -// } -// } -// } -// return false; -// } -// // function parseTypeOrTypePredicate(): TypeNode { // auto pos = getNodePos(); // auto typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); @@ -4327,37 +5207,9 @@ namespace ts { // auto type = parseOptional(SyntaxKind::IsKeyword) ? parseType() : undefined; // return finishNode(factory::createTypePredicateNode(assertsModifier, parameterName, type), pos); // } -// -// function parseType(): TypeNode { -// if (contextFlags & NodeFlags::TypeExcludesFlags) { -// return doOutsideOfContext(NodeFlags::TypeExcludesFlags, parseType); -// } -// -// if (isStartOfFunctionTypeOrConstructorType()) { -// return parseFunctionOrConstructorType(); -// } -// auto pos = getNodePos(); -// auto type = parseUnionTypeOrHigher(); -// if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind::ExtendsKeyword)) { -// // The type following 'extends' is not permitted to be another conditional type -// auto extendsType = disallowConditionalTypesAnd(parseType); -// parseExpected(SyntaxKind::QuestionToken); -// auto trueType = allowConditionalTypesAnd(parseType); -// parseExpected(SyntaxKind::ColonToken); -// auto falseType = allowConditionalTypesAnd(parseType); -// return finishNode(factory::createConditionalTypeNode(type, extendsType, trueType, falseType), pos); -// } -// return type; -// } -// -// function parseTypeAnnotation(): TypeNode | undefined { -// return parseOptional(SyntaxKind::ColonToken) ? parseType() : undefined; -// } -// shared parseAssignmentExpressionOrHigher(); - shared makeBinaryExpression(shared left, shared operatorNode, shared right, int pos) { auto n = factory::createBinaryExpression(left, operatorNode, right); return finishNode(n, pos); @@ -4387,15 +5239,9 @@ namespace ts { return expr; } - shared parseAssignmentExpressionOrHigher(); - - sharedOpt parseInitializer() { - return parseOptional(SyntaxKind::EqualsToken) ? parseAssignmentExpressionOrHigher() : nullptr; - } - bool nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() { nextToken(); - return (tokenIsIdentifierOrKeyword(token()) || token() == SyntaxKind::NumericLiteral || token() == SyntaxKind::BigIntLiteral || token() == SyntaxKind::StringLiteral) && !scanner.hasPrecedingLineBreak(); + return (tokenIsIdentifierOrKeyword(token()) || token() == SyntaxKind::NumericLiteral || token() == SyntaxKind::BigIntLiteral || token() == SyntaxKind::StringLiteral) && ! scanner.hasPrecedingLineBreak(); } bool isYieldExpression() { @@ -4435,7 +5281,7 @@ namespace ts { // yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield] nextToken(); - if (!scanner.hasPrecedingLineBreak() && + if (! scanner.hasPrecedingLineBreak() && (token() == SyntaxKind::AsteriskToken || isStartOfExpression())) { return finishNode( factory::createYieldExpression( @@ -4512,7 +5358,7 @@ namespace ts { // If we had "(" followed by something that's not an identifier, // then this definitely doesn't look like a lambda. "this" is not // valid, but we want to parse it and then give a semantic error. - if (!isIdentifier() && second != SyntaxKind::ThisKeyword) { + if (! isIdentifier() && second != SyntaxKind::ThisKeyword) { return Tristate::False; } @@ -4537,13 +5383,12 @@ namespace ts { } // It is definitely not an arrow function return Tristate::False; - } - else { + } else { assert(first == SyntaxKind::LessThanToken); // If we have "<" not followed by an identifier, // then this definitely is not an arrow function. - if (!isIdentifier()) { + if (! isIdentifier()) { return Tristate::False; } @@ -4560,8 +5405,7 @@ namespace ts { default: return true; } - } - else if (third == SyntaxKind::CommaToken || third == SyntaxKind::EqualsToken) { + } else if (third == SyntaxKind::CommaToken || third == SyntaxKind::EqualsToken) { return true; } return false; @@ -4579,7 +5423,6 @@ namespace ts { } } - // True -> We definitely expect a parenthesized arrow function here. // False -> There *cannot* be a parenthesized arrow function here. // Unknown -> There *might* be a parenthesized arrow function here. @@ -4603,7 +5446,7 @@ namespace ts { if (token() == SyntaxKind::AsyncKeyword) { auto pos = getNodePos(); nextToken(); - auto modifier = finishNode(factory::createToken(SyntaxKind::AsyncKeyword), pos); + auto modifier = finishNode(factory::createToken(SyntaxKind::AsyncKeyword), pos); return factory::createNodeArray({modifier}, pos); } return nullopt; @@ -4624,30 +5467,28 @@ namespace ts { auto typeParameters = parseTypeParameters(); NodeArray parameters; - if (!parseExpected(SyntaxKind::OpenParenToken)) { - if (!allowAmbiguity) { + if (! parseExpected(SyntaxKind::OpenParenToken)) { + if (! allowAmbiguity) { return undefined; } parameters = createMissingList(); - } - else { - if (!allowAmbiguity) { + } else { + if (! allowAmbiguity) { auto maybeParameters = parseParametersWorker(isAsync, allowAmbiguity); - if (!maybeParameters) { + if (! maybeParameters) { return undefined; } parameters = maybeParameters; - } - else { + } else { parameters = parseParametersWorker(isAsync, allowAmbiguity); } - if (!parseExpected(SyntaxKind::CloseParenToken) && !allowAmbiguity) { + if (! parseExpected(SyntaxKind::CloseParenToken) && ! allowAmbiguity) { return undefined; } } auto type = parseReturnType(SyntaxKind::ColonToken, /*isType*/ false); - if (type && !allowAmbiguity && typeHasArrowFunctionBlockingParseError(type)) { + if (type && ! allowAmbiguity && typeHasArrowFunctionBlockingParseError(type)) { return undefined; } @@ -4662,15 +5503,17 @@ namespace ts { // // So we need just a bit of lookahead to ensure that it can only be a signature. - let unwrappedType = type; - while (unwrappedType?.kind == SyntaxKind::ParenthesizedType) { - unwrappedType = (unwrappedType as ParenthesizedTypeNode).type; // Skip parens if need be + auto unwrappedType = type; + while (unwrappedType ?.kind == SyntaxKind::ParenthesizedType) { + unwrappedType = (unwrappedType + as + ParenthesizedTypeNode).type; // Skip parens if need be } auto hasJSDocFunctionType = unwrappedType && isJSDocFunctionType(unwrappedType); - if (!allowAmbiguity && token() != SyntaxKind::EqualsGreaterThanToken && (hasJSDocFunctionType || token() != SyntaxKind::OpenBraceToken)) { + if (! allowAmbiguity && token() != SyntaxKind::EqualsGreaterThanToken && (hasJSDocFunctionType || token() != SyntaxKind::OpenBraceToken)) { // Returning undefined here will cause our caller to rewind to where we started from. - return undefined; + return undefined; } // If we have an arrow, then try to parse the body. Even if not, try to parse if we @@ -4678,14 +5521,13 @@ namespace ts { auto lastToken = token(); auto equalsGreaterThanToken = parseExpectedToken(SyntaxKind::EqualsGreaterThanToken); auto body = (lastToken == SyntaxKind::EqualsGreaterThanToken || lastToken == SyntaxKind::OpenBraceToken) - ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier)) - : parseIdentifier(); + ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier)) + : parseIdentifier(); auto node = factory::createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body); return withJSDoc(finishNode(node, pos), hasJSDoc); } - sharedOpt tryParseParenthesizedArrowFunctionExpression() { auto triState = isParenthesizedArrowFunctionExpression(); if (triState == Tristate::False) { @@ -4698,11 +5540,10 @@ namespace ts { // it out, but don't allow any ambiguity, and return 'undefined' if this could be an // expression instead. return triState == Tristate::True ? - parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ true) : - tryParse(parsePossibleParenthesizedArrowFunctionExpression); + parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ true) : + tryParse(parsePossibleParenthesizedArrowFunctionExpression); } - shared parseAssignmentExpressionOrHigher() { // AssignmentExpression[in,yield]: // 1) ConditionalExpression[?in,?yield] @@ -4752,7 +5593,9 @@ namespace ts { // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single // identifier and the current token is an arrow. if (expr.kind == SyntaxKind::Identifier && token() == SyntaxKind::EqualsGreaterThanToken) { - return parseSimpleArrowFunctionExpression(pos, expr as Identifier, /*asyncModifier*/ {}); + return parseSimpleArrowFunctionExpression(pos, expr + as + Identifier, /*asyncModifier*/ {}); } // Now see if we might be in cases '2' or '3'. @@ -4769,11 +5612,6 @@ namespace ts { return parseConditionalExpressionRest(expr, pos); } - bool nextTokenIsIdentifierOnSameLine() { - nextToken(); - return !scanner.hasPrecedingLineBreak() && isIdentifier(); - } - // function parseSimpleArrowFunctionExpression(pos: number, identifier: Identifier, asyncModifier?: NodeArray | undefined): ArrowFunction { // Debug.assert(token() == SyntaxKind::EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); // auto parameter = factory::createParameterDeclaration( @@ -4859,7 +5697,7 @@ namespace ts { // // user meant to supply a block. For example, if the user wrote: // // // // a => -// // let v = 0; +// // auto v = 0; // // } // // // // they may be missing an open brace. Check to see if that's the case so we can @@ -4888,7 +5726,7 @@ namespace ts { // // // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and // // we do not that for the 'whenFalse' part. -// let colonToken; +// auto colonToken; // return finishNode( // factory::createConditionalExpression( // leftOperand, @@ -5015,57 +5853,6 @@ namespace ts { // } // // /** -// * Parse ES7 exponential expression and await expression -// * -// * ES7 ExponentiationExpression: -// * 1) UnaryExpression[?Yield] -// * 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield] -// * -// */ -// function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression { -// /** -// * ES7 UpdateExpression: -// * 1) LeftHandSideExpression[?Yield] -// * 2) LeftHandSideExpression[?Yield][no LineTerminator here]++ -// * 3) LeftHandSideExpression[?Yield][no LineTerminator here]-- -// * 4) ++UnaryExpression[?Yield] -// * 5) --UnaryExpression[?Yield] -// */ -// if (isUpdateExpression()) { -// auto pos = getNodePos(); -// auto updateExpression = parseUpdateExpression(); -// return token() == SyntaxKind::AsteriskAsteriskToken ? -// parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) as BinaryExpression : -// updateExpression; -// } -// -// /** -// * ES7 UnaryExpression: -// * 1) UpdateExpression[?yield] -// * 2) delete UpdateExpression[?yield] -// * 3) void UpdateExpression[?yield] -// * 4) typeof UpdateExpression[?yield] -// * 5) + UpdateExpression[?yield] -// * 6) - UpdateExpression[?yield] -// * 7) ~ UpdateExpression[?yield] -// * 8) ! UpdateExpression[?yield] -// */ -// auto unaryOperator = token(); -// auto simpleUnaryExpression = parseSimpleUnaryExpression(); -// if (token() == SyntaxKind::AsteriskAsteriskToken) { -// auto pos = skipTrivia(sourceText, simpleUnaryExpression.pos); -// auto { end } = simpleUnaryExpression; -// if (simpleUnaryExpression.kind == SyntaxKind::TypeAssertionExpression) { -// parseErrorAt(pos, end, Diagnostics::A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); -// } -// else { -// parseErrorAt(pos, end, Diagnostics::An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator)); -// } -// } -// return simpleUnaryExpression; -// } -// -// /** // * Parse ES7 simple-unary expression or higher: // * // * ES7 UnaryExpression: @@ -5107,139 +5894,6 @@ namespace ts { // } // } // -// /** -// * Check if the current token can possibly be an ES7 increment expression. -// * -// * ES7 UpdateExpression: -// * LeftHandSideExpression[?Yield] -// * LeftHandSideExpression[?Yield][no LineTerminator here]++ -// * LeftHandSideExpression[?Yield][no LineTerminator here]-- -// * ++LeftHandSideExpression[?Yield] -// * --LeftHandSideExpression[?Yield] -// */ -// function isUpdateExpression(): boolean { -// // This function is called inside parseUnaryExpression to decide -// // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly -// switch (token()) { -// case SyntaxKind::PlusToken: -// case SyntaxKind::MinusToken: -// case SyntaxKind::TildeToken: -// case SyntaxKind::ExclamationToken: -// case SyntaxKind::DeleteKeyword: -// case SyntaxKind::TypeOfKeyword: -// case SyntaxKind::VoidKeyword: -// case SyntaxKind::AwaitKeyword: -// return false; -// case SyntaxKind::LessThanToken: -// // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression -// if (languageVariant != LanguageVariant::JSX) { -// return false; -// } -// // We are in JSX context and the token is part of JSXElement. -// // falls through -// default: -// return true; -// } -// } -// -// /** -// * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression. -// * -// * ES7 UpdateExpression[yield]: -// * 1) LeftHandSideExpression[?yield] -// * 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++ -// * 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]-- -// * 4) ++LeftHandSideExpression[?yield] -// * 5) --LeftHandSideExpression[?yield] -// * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression -// */ -// function parseUpdateExpression(): UpdateExpression { -// if (token() == SyntaxKind::PlusPlusToken || token() == SyntaxKind::MinusMinusToken) { -// auto pos = getNodePos(); -// return finishNode(factory::createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); -// } -// else if (languageVariant == LanguageVariant::JSX && token() == SyntaxKind::LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { -// // JSXElement is part of primaryExpression -// return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); -// } -// -// auto expression = parseLeftHandSideExpressionOrHigher(); -// -// Debug.assert(isLeftHandSideExpression(expression)); -// if ((token() == SyntaxKind::PlusPlusToken || token() == SyntaxKind::MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { -// auto operator = token() as PostfixUnaryOperator; -// nextToken(); -// return finishNode(factory::createPostfixUnaryExpression(expression, operator), expression.pos); -// } -// -// return expression; -// } -// -// function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression { -// // Original Ecma: -// // LeftHandSideExpression: See 11.2 -// // NewExpression -// // CallExpression -// // -// // Our simplification: -// // -// // LeftHandSideExpression: See 11.2 -// // MemberExpression -// // CallExpression -// // -// // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with -// // MemberExpression to make our lives easier. -// // -// // to best understand the below code, it's important to see how CallExpression expands -// // out into its own productions: -// // -// // CallExpression: -// // MemberExpression Arguments -// // CallExpression Arguments -// // CallExpression[Expression] -// // CallExpression.IdentifierName -// // import (AssignmentExpression) -// // super Arguments -// // super.IdentifierName -// // -// // Because of the recursion in these calls, we need to bottom out first. There are three -// // bottom out states we can run into: 1) We see 'super' which must start either of -// // the last two CallExpression productions. 2) We see 'import' which must start import call. -// // 3)we have a MemberExpression which either completes the LeftHandSideExpression, -// // or starts the beginning of the first four CallExpression productions. -// auto pos = getNodePos(); -// let expression: MemberExpression; -// if (token() == SyntaxKind::ImportKeyword) { -// if (lookAhead(nextTokenIsOpenParenOrLessThan)) { -// // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" -// // For example: -// // var foo3 = require("subfolder -// // import * as foo1 from "module-from-node -// // We want this import to be a statement rather than import call expression -// sourceFlags |= NodeFlags::PossiblyContainsDynamicImport; -// expression = parseTokenNode(); -// } -// else if (lookAhead(nextTokenIsDot)) { -// // This is an 'import.*' metaproperty (i.e. 'import.meta') -// nextToken(); // advance past the 'import' -// nextToken(); // advance past the dot -// expression = finishNode(factory::createMetaProperty(SyntaxKind::ImportKeyword, parseIdentifierName()), pos); -// sourceFlags |= NodeFlags::PossiblyContainsImportMeta; -// } -// else { -// expression = parseMemberExpressionOrHigher(); -// } -// } -// else { -// expression = token() == SyntaxKind::SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher(); -// } -// -// // Now, we *may* be complete. However, we might have consumed the start of a -// // CallExpression or OptionalExpression. As such, we need to consume the rest -// // of it here to be complete. -// return parseCallExpressionRest(pos, expression); -// } -// // function parseMemberExpressionOrHigher(): MemberExpression { // // Note: to make our lives simpler, we decompose the NewExpression productions and // // place ObjectCreationExpression and FunctionExpression into PrimaryExpression. @@ -5285,323 +5939,34 @@ namespace ts { // // Because there are no other places in the grammar now that refer to FunctionExpression // // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression // // production. -// // -// // Because CallExpression and MemberExpression are left recursive, we need to bottom out -// // of the recursion immediately. So we parse out a primary expression to start with. -// auto pos = getNodePos(); -// auto expression = parsePrimaryExpression(); -// return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); -// } -// -// function parseSuperExpression(): MemberExpression { -// auto pos = getNodePos(); -// auto expression = parseTokenNode(); -// if (token() == SyntaxKind::LessThanToken) { -// auto startPos = getNodePos(); -// auto typeArguments = tryParse(parseTypeArgumentsInExpression); -// if (typeArguments != undefined) { -// parseErrorAt(startPos, getNodePos(), Diagnostics::super_may_not_use_type_arguments); -// } -// } -// -// if (token() == SyntaxKind::OpenParenToken || token() == SyntaxKind::DotToken || token() == SyntaxKind::OpenBracketToken) { -// return expression; -// } -// -// // If we have seen "super" it must be followed by '(' or '.'. -// // If it wasn't then just try to parse out a '.' and report an error. -// parseExpectedToken(SyntaxKind::DotToken, Diagnostics::super_must_be_followed_by_an_argument_list_or_member_access); -// // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic -// return finishNode(factory::createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true)), pos); -// } -// -// function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number, openingTag?: JsxOpeningElement | JsxOpeningFragment): JsxElement | JsxSelfClosingElement | JsxFragment { -// auto pos = getNodePos(); -// auto opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); -// let result: JsxElement | JsxSelfClosingElement | JsxFragment; -// if (opening.kind == SyntaxKind::JsxOpeningElement) { -// let children = parseJsxChildren(opening); -// let closingElement: JsxClosingElement; -// -// auto lastChild: JsxChild | undefined = children[children.length - 1]; -// if (lastChild?.kind == SyntaxKind::JsxElement -// && !tagNamesAreEquivalent(lastChild.openingElement.tagName, lastChild.closingElement.tagName) -// && tagNamesAreEquivalent(opening.tagName, lastChild.closingElement.tagName)) { -// // when an unclosed JsxOpeningElement incorrectly parses its parent's JsxClosingElement, -// // restructure (
(......
)) --> (
(......)
) -// // (no need to error; the parent will error) -// auto end = lastChild.children.end; -// auto newLast = finishNode(factory::createJsxElement( -// lastChild.openingElement, -// lastChild.children, -// finishNode(factory::createJsxClosingElement(finishNode(factory::createIdentifier(""), end, end)), end, end)), -// lastChild.openingElement.pos, -// end); -// -// children = createNodeArray([...children.slice(0, children.length - 1), newLast], children.pos, end); -// closingElement = lastChild.closingElement; -// } -// else { -// closingElement = parseJsxClosingElement(opening, inExpressionContext); -// if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) { -// if (openingTag && isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName)) { -// // opening incorrectly matched with its parent's closing -- put error on opening -// parseErrorAtRange(opening.tagName, Diagnostics::JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.tagName)); -// } -// else { -// // other opening/closing mismatches -- put error on closing -// parseErrorAtRange(closingElement.tagName, Diagnostics::Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName)); -// } -// } -// } -// result = finishNode(factory::createJsxElement(opening, children, closingElement), pos); -// } -// else if (opening.kind == SyntaxKind::JsxOpeningFragment) { -// result = finishNode(factory::createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos); -// } -// else { -// Debug.assert(opening.kind == SyntaxKind::JsxSelfClosingElement); -// // Nothing else to do for self-closing elements -// result = opening; -// } -// -// // If the user writes the invalid code '
' in an expression context (i.e. not wrapped in -// // an enclosing tag), we'll naively try to parse ^ this as a 'less than' operator and the remainder of the tag -// // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX -// // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter -// // does less damage and we can report a better error. -// // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios -// // of one sort or another. -// if (inExpressionContext && token() == SyntaxKind::LessThanToken) { -// auto topBadPos = typeof topInvalidNodePosition == "undefined" ? result.pos : topInvalidNodePosition; -// auto invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, topBadPos)); -// if (invalidElement) { -// auto operatorToken = createMissingNode(SyntaxKind::CommaToken, /*reportAtCurrentPosition*/ false); -// setTextRangePosWidth(operatorToken, invalidElement.pos, 0); -// parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics::JSX_expressions_must_have_one_parent_element); -// return finishNode(factory::createBinaryExpression(result, operatorToken as Token, invalidElement), pos) as Node as JsxElement; -// } -// } -// -// return result; -// } -// -// function parseJsxText(): JsxText { -// auto pos = getNodePos(); -// auto node = factory::createJsxText(scanner.getTokenValue(), currentToken == SyntaxKind::JsxTextAllWhiteSpaces); -// currentToken = scanner.scanJsxToken(); -// return finishNode(node, pos); -// } -// -// function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined { -// switch (token) { -// case SyntaxKind::EndOfFileToken: -// // If we hit EOF, issue the error at the tag that lacks the closing element -// // rather than at the end of the file (which is useless) -// if (isJsxOpeningFragment(openingTag)) { -// parseErrorAtRange(openingTag, Diagnostics::JSX_fragment_has_no_corresponding_closing_tag); -// } -// else { -// // We want the error span to cover only 'Foo.Bar' in < Foo.Bar > -// // or to cover only 'Foo' in < Foo > -// auto tag = openingTag.tagName; -// auto start = skipTrivia(sourceText, tag.pos); -// parseErrorAt(start, tag.end, Diagnostics::JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName)); -// } -// return undefined; -// case SyntaxKind::LessThanSlashToken: -// case SyntaxKind::ConflictMarkerTrivia: -// return undefined; -// case SyntaxKind::JsxText: -// case SyntaxKind::JsxTextAllWhiteSpaces: -// return parseJsxText(); -// case SyntaxKind::OpenBraceToken: -// return parseJsxExpression(/*inExpressionContext*/ false); -// case SyntaxKind::LessThanToken: -// return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false, /*topInvalidNodePosition*/ undefined, openingTag); -// default: -// return Debug.assertNever(token); -// } -// } -// -// function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray { -// auto list = []; -// auto listPos = getNodePos(); -// auto saveParsingContext = parsingContext; -// parsingContext |= 1 << ParsingContext::JsxChildren; -// -// while (true) { -// auto child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken()); -// if (!child) break; -// list.push(child); -// if (isJsxOpeningElement(openingTag) -// && child?.kind == SyntaxKind::JsxElement -// && !tagNamesAreEquivalent(child.openingElement.tagName, child.closingElement.tagName) -// && tagNamesAreEquivalent(openingTag.tagName, child.closingElement.tagName)) { -// // stop after parsing a mismatched child like
...(
) in order to reattach the higher -// break; -// } -// } -// -// parsingContext = saveParsingContext; -// return createNodeArray(list, listPos); -// } -// -// function parseJsxAttributes(): JsxAttributes { -// auto pos = getNodePos(); -// return finishNode(factory::createJsxAttributes(parseList(ParsingContext::JsxAttributes, parseJsxAttribute)), pos); -// } -// -// function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment { -// auto pos = getNodePos(); -// -// parseExpected(SyntaxKind::LessThanToken); -// -// if (token() == SyntaxKind::GreaterThanToken) { -// // See below for explanation of scanJsxText -// scanJsxText(); -// return finishNode(factory::createJsxOpeningFragment(), pos); -// } -// auto tagName = parseJsxElementName(); -// auto typeArguments = (contextFlags & NodeFlags::JavaScriptFile) == 0 ? tryParseTypeArguments() : undefined; -// auto attributes = parseJsxAttributes(); -// -// let node: JsxOpeningLikeElement; -// -// if (token() == SyntaxKind::GreaterThanToken) { -// // Closing tag, so scan the immediately-following text with the JSX scanning instead -// // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate -// // scanning errors -// scanJsxText(); -// node = factory::createJsxOpeningElement(tagName, typeArguments, attributes); -// } -// else { -// parseExpected(SyntaxKind::SlashToken); -// if (parseExpected(SyntaxKind::GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { -// // manually advance the scanner in order to look for jsx text inside jsx -// if (inExpressionContext) { -// nextToken(); -// } -// else { -// scanJsxText(); -// } -// } -// node = factory::createJsxSelfClosingElement(tagName, typeArguments, attributes); -// } -// -// return finishNode(node, pos); -// } -// -// function parseJsxElementName(): JsxTagNameExpression { -// auto pos = getNodePos(); -// scanJsxIdentifier(); -// // JsxElement can have name in the form of -// // propertyAccessExpression -// // primaryExpression in the form of an identifier and "this" keyword -// // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword -// // We only want to consider "this" as a primaryExpression -// let expression: JsxTagNameExpression = token() == SyntaxKind::ThisKeyword ? -// parseTokenNode() : parseIdentifierName(); -// while (parseOptional(SyntaxKind::DotToken)) { -// expression = finishNode(factory::createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos) as JsxTagNamePropertyAccess; -// } -// return expression; -// } -// -// function parseJsxExpression(inExpressionContext: boolean): JsxExpression | undefined { +// // +// // Because CallExpression and MemberExpression are left recursive, we need to bottom out +// // of the recursion immediately. So we parse out a primary expression to start with. // auto pos = getNodePos(); -// if (!parseExpected(SyntaxKind::OpenBraceToken)) { -// return undefined; -// } -// -// let dotDotDotToken: DotDotDotToken | undefined; -// let expression: Expression | undefined; -// if (token() != SyntaxKind::CloseBraceToken) { -// dotDotDotToken = parseOptionalToken(SyntaxKind::DotDotDotToken); -// // Only an AssignmentExpression is valid here per the JSX spec, -// // but we can unambiguously parse a comma sequence and provide -// // a better error message in grammar checking. -// expression = parseExpression(); -// } -// if (inExpressionContext) { -// parseExpected(SyntaxKind::CloseBraceToken); -// } -// else { -// if (parseExpected(SyntaxKind::CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false)) { -// scanJsxText(); -// } -// } -// -// return finishNode(factory::createJsxExpression(dotDotDotToken, expression), pos); +// auto expression = parsePrimaryExpression(); +// return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); // } // -// function parseJsxAttribute(): JsxAttribute | JsxSpreadAttribute { -// if (token() == SyntaxKind::OpenBraceToken) { -// return parseJsxSpreadAttribute(); -// } -// -// scanJsxIdentifier(); +// function parseSuperExpression(): MemberExpression { // auto pos = getNodePos(); -// return finishNode(factory::createJsxAttribute(parseIdentifierName(), parseJsxAttributeValue()), pos); -// } -// -// function parseJsxAttributeValue(): JsxAttributeValue | undefined { -// if (token() == SyntaxKind::EqualsToken) { -// if (scanJsxAttributeValue() == SyntaxKind::StringLiteral) { -// return parseLiteralNode() as StringLiteral; -// } -// if (token() == SyntaxKind::OpenBraceToken) { -// return parseJsxExpression(/*inExpressionContext*/ true); -// } -// if (token() == SyntaxKind::LessThanToken) { -// return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); +// auto expression = parseTokenNode(); +// if (token() == SyntaxKind::LessThanToken) { +// auto startPos = getNodePos(); +// auto typeArguments = tryParse(parseTypeArgumentsInExpression); +// if (typeArguments != undefined) { +// parseErrorAt(startPos, getNodePos(), Diagnostics::super_may_not_use_type_arguments); // } -// parseErrorAtCurrentToken(Diagnostics::or_JSX_element_expected); // } -// return undefined; -// } -// -// function parseJsxSpreadAttribute(): JsxSpreadAttribute { -// auto pos = getNodePos(); -// parseExpected(SyntaxKind::OpenBraceToken); -// parseExpected(SyntaxKind::DotDotDotToken); -// auto expression = parseExpression(); -// parseExpected(SyntaxKind::CloseBraceToken); -// return finishNode(factory::createJsxSpreadAttribute(expression), pos); -// } // -// function parseJsxClosingElement(open: JsxOpeningElement, inExpressionContext: boolean): JsxClosingElement { -// auto pos = getNodePos(); -// parseExpected(SyntaxKind::LessThanSlashToken); -// auto tagName = parseJsxElementName(); -// if (parseExpected(SyntaxKind::GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { -// // manually advance the scanner in order to look for jsx text inside jsx -// if (inExpressionContext || !tagNamesAreEquivalent(open.tagName, tagName)) { -// nextToken(); -// } -// else { -// scanJsxText(); -// } +// if (token() == SyntaxKind::OpenParenToken || token() == SyntaxKind::DotToken || token() == SyntaxKind::OpenBracketToken) { +// return expression; // } -// return finishNode(factory::createJsxClosingElement(tagName), pos); -// } // -// function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment { -// auto pos = getNodePos(); -// parseExpected(SyntaxKind::LessThanSlashToken); -// if (tokenIsIdentifierOrKeyword(token())) { -// parseErrorAtRange(parseJsxElementName(), Diagnostics::Expected_corresponding_closing_tag_for_JSX_fragment); -// } -// if (parseExpected(SyntaxKind::GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { -// // manually advance the scanner in order to look for jsx text inside jsx -// if (inExpressionContext) { -// nextToken(); -// } -// else { -// scanJsxText(); -// } -// } -// return finishNode(factory::createJsxJsxClosingFragment(), pos); +// // If we have seen "super" it must be followed by '(' or '.'. +// // If it wasn't then just try to parse out a '.' and report an error. +// parseExpectedToken(SyntaxKind::DotToken, Diagnostics::super_must_be_followed_by_an_argument_list_or_member_access); +// // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic +// return finishNode(factory::createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true)), pos); // } // // function parseTypeAssertion(): TypeAssertion { @@ -5631,7 +5996,7 @@ namespace ts { // } // // check for an optional chain in a non-null expression // if (isNonNullExpression(node)) { -// let expr = node.expression; +// auto expr = node.expression; // while (isNonNullExpression(expr) && !(expr.flags & NodeFlags::OptionalChain)) { // expr = expr.expression; // } @@ -5660,7 +6025,7 @@ namespace ts { // } // // function parseElementAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { -// let argumentExpression: Expression; +// auto argumentExpression: Expression; // if (token() == SyntaxKind::CloseBracketToken) { // argumentExpression = createMissingNode(SyntaxKind::Identifier, /*reportAtCurrentPosition*/ true, Diagnostics::An_element_access_expression_should_take_an_argument); // } @@ -5682,8 +6047,8 @@ namespace ts { // // function parseMemberExpressionRest(pos: number, expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression { // while (true) { -// let questionDotToken: QuestionDotToken | undefined; -// let isPropertyAccess = false; +// auto questionDotToken: QuestionDotToken | undefined; +// auto isPropertyAccess = false; // if (allowOptionalChain && isStartOfOptionalPropertyOrElementAccessChain()) { // questionDotToken = parseExpectedToken(SyntaxKind::QuestionDotToken); // isPropertyAccess = tokenIsIdentifierOrKeyword(token()); @@ -5750,7 +6115,7 @@ namespace ts { // function parseCallExpressionRest(pos: number, expression: LeftHandSideExpression): LeftHandSideExpression { // while (true) { // expression = parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); -// let typeArguments: NodeArray | undefined; +// auto typeArguments: NodeArray | undefined; // auto questionDotToken = parseOptionalToken(SyntaxKind::QuestionDotToken); // if (questionDotToken) { // typeArguments = tryParse(parseTypeArgumentsInExpression); @@ -5946,7 +6311,7 @@ namespace ts { // // CoverInitializedName[Yield] : // // IdentifierReference[?Yield] Initializer[In, ?Yield] // // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern -// let node: Mutable; +// auto node: Mutable; // auto isShorthandPropertyAssignment = tokenIsIdentifier && (token() != SyntaxKind::ColonToken); // if (isShorthandPropertyAssignment) { // auto equalsToken = parseOptionalToken(SyntaxKind::EqualsToken); @@ -6023,8 +6388,8 @@ namespace ts { // return finishNode(factory::createMetaProperty(SyntaxKind::NewKeyword, name), pos); // } // auto expressionPos = getNodePos(); -// let expression: LeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); -// let typeArguments: NodeArray | undefined; +// auto expression: LeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); +// auto typeArguments: NodeArray | undefined; // // Absorb type arguments into NewExpression when preceding expression is ExpressionWithTypeArguments // if (expression.kind == SyntaxKind::ExpressionWithTypeArguments) { // typeArguments = (expression as ExpressionWithTypeArguments).typeArguments; @@ -6087,14 +6452,14 @@ namespace ts { // // return block; // } -// -// function parseEmptyStatement(): Statement { -// auto pos = getNodePos(); -// auto hasJSDoc = hasPrecedingJSDocComment(); -// parseExpected(SyntaxKind::SemicolonToken); -// return withJSDoc(finishNode(factory::createEmptyStatement(), pos), hasJSDoc); -// } -// + + shared parseEmptyStatement() { + auto pos = getNodePos(); + auto hasJSDoc = hasPrecedingJSDocComment(); + parseExpected(SyntaxKind::SemicolonToken); + return withJSDoc(finishNode(factory::createEmptyStatement(), pos), hasJSDoc); + } + // function parseIfStatement(): IfStatement { // auto pos = getNodePos(); // auto hasJSDoc = hasPrecedingJSDocComment(); @@ -6146,7 +6511,7 @@ namespace ts { // auto awaitToken = parseOptionalToken(SyntaxKind::AwaitKeyword); // parseExpected(SyntaxKind::OpenParenToken); // -// let initializer!: VariableDeclarationList | Expression; +// auto initializer!: VariableDeclarationList | Expression; // if (token() != SyntaxKind::SemicolonToken) { // if (token() == SyntaxKind::VarKeyword || token() == SyntaxKind::LetKeyword || token() == SyntaxKind::ConstKeyword) { // initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); @@ -6156,7 +6521,7 @@ namespace ts { // } // } // -// let node: IterationStatement; +// auto node: IterationStatement; // if (awaitToken ? parseExpected(SyntaxKind::OfKeyword) : parseOptional(SyntaxKind::OfKeyword)) { // auto expression = allowInAnd(parseAssignmentExpressionOrHigher); // parseExpected(SyntaxKind::CloseParenToken); @@ -6272,7 +6637,7 @@ namespace ts { // // directly as that might consume an expression on the following line. // // Instead, we create a "missing" identifier, but don't report an error. The actual error // // will be reported in the grammar walker. -// let expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression); +// auto expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression); // if (expression == undefined) { // identifierCount++; // expression = finishNode(factory::createIdentifier(""), getNodePos()); @@ -6294,7 +6659,7 @@ namespace ts { // // // If we don't have a catch clause, then we must have a finally clause. Try to parse // // one out no matter what. -// let finallyBlock: Block | undefined; +// auto finallyBlock: Block | undefined; // if (!catchClause || token() == SyntaxKind::FinallyKeyword) { // parseExpected(SyntaxKind::FinallyKeyword, Diagnostics::catch_or_finally_expected); // finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); @@ -6307,7 +6672,7 @@ namespace ts { // auto pos = getNodePos(); // parseExpected(SyntaxKind::CatchKeyword); // -// let variableDeclaration; +// auto variableDeclaration; // if (parseOptional(SyntaxKind::OpenParenToken)) { // variableDeclaration = parseVariableDeclaration(); // parseExpected(SyntaxKind::CloseParenToken); @@ -6337,7 +6702,7 @@ namespace ts { // auto hasJSDoc = hasPrecedingJSDocComment(); shared node; auto hasParen = token() == SyntaxKind::OpenParenToken; - auto expression = allowInAnd(parseExpression); + auto expression = allowInAnd>(parseExpression); if (isIdentifier(expression) && parseOptional(SyntaxKind::ColonToken)) { parseStatement(); node = make_shared({ @@ -6358,157 +6723,6 @@ namespace ts { // return withJSDoc(finishNode(node, pos), hasJSDoc); } - bool nextTokenIsIdentifierOrKeywordOnSameLine() { - nextToken(); - return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak(); - } - -// -// function isDeclaration(): boolean { -// while (true) { -// switch (token()) { -// case SyntaxKind::VarKeyword: -// case SyntaxKind::LetKeyword: -// case SyntaxKind::ConstKeyword: -// case SyntaxKind::FunctionKeyword: -// case SyntaxKind::ClassKeyword: -// case SyntaxKind::EnumKeyword: -// return true; -// -// // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers; -// // however, an identifier cannot be followed by another identifier on the same line. This is what we -// // count on to parse out the respective declarations. For instance, we exploit this to say that -// // -// // namespace n -// // -// // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees -// // -// // namespace -// // n -// // -// // as the identifier 'namespace' on one line followed by the identifier 'n' on another. -// // We need to look one token ahead to see if it permissible to try parsing a declaration. -// // -// // *Note*: 'interface' is actually a strict mode reserved word. So while -// // -// // "use strict" -// // interface -// // I {} -// // -// // could be legal, it would add complexity for very little gain. -// case SyntaxKind::InterfaceKeyword: -// case SyntaxKind::TypeKeyword: -// return nextTokenIsIdentifierOnSameLine(); -// case SyntaxKind::ModuleKeyword: -// case SyntaxKind::NamespaceKeyword: -// return nextTokenIsIdentifierOrStringLiteralOnSameLine(); -// case SyntaxKind::AbstractKeyword: -// case SyntaxKind::AsyncKeyword: -// case SyntaxKind::DeclareKeyword: -// case SyntaxKind::PrivateKeyword: -// case SyntaxKind::ProtectedKeyword: -// case SyntaxKind::PublicKeyword: -// case SyntaxKind::ReadonlyKeyword: -// nextToken(); -// // ASI takes effect for this modifier. -// if (scanner.hasPrecedingLineBreak()) { -// return false; -// } -// continue; -// -// case SyntaxKind::GlobalKeyword: -// nextToken(); -// return token() == SyntaxKind::OpenBraceToken || token() == SyntaxKind::Identifier || token() == SyntaxKind::ExportKeyword; -// -// case SyntaxKind::ImportKeyword: -// nextToken(); -// return token() == SyntaxKind::StringLiteral || token() == SyntaxKind::AsteriskToken || -// token() == SyntaxKind::OpenBraceToken || tokenIsIdentifierOrKeyword(token()); -// case SyntaxKind::ExportKeyword: -// let currentToken = nextToken(); -// if (currentToken == SyntaxKind::TypeKeyword) { -// currentToken = lookAhead(nextToken); -// } -// if (currentToken == SyntaxKind::EqualsToken || currentToken == SyntaxKind::AsteriskToken || -// currentToken == SyntaxKind::OpenBraceToken || currentToken == SyntaxKind::DefaultKeyword || -// currentToken == SyntaxKind::AsKeyword) { -// return true; -// } -// continue; -// -// case SyntaxKind::StaticKeyword: -// nextToken(); -// continue; -// default: -// return false; -// } -// } -// } -// -// function isStartOfDeclaration(): boolean { -// return lookAhead(isDeclaration); -// } -// -// function isStartOfStatement(): boolean { -// switch (token()) { -// case SyntaxKind::AtToken: -// case SyntaxKind::SemicolonToken: -// case SyntaxKind::OpenBraceToken: -// case SyntaxKind::VarKeyword: -// case SyntaxKind::LetKeyword: -// case SyntaxKind::FunctionKeyword: -// case SyntaxKind::ClassKeyword: -// case SyntaxKind::EnumKeyword: -// case SyntaxKind::IfKeyword: -// case SyntaxKind::DoKeyword: -// case SyntaxKind::WhileKeyword: -// case SyntaxKind::ForKeyword: -// case SyntaxKind::ContinueKeyword: -// case SyntaxKind::BreakKeyword: -// case SyntaxKind::ReturnKeyword: -// case SyntaxKind::WithKeyword: -// case SyntaxKind::SwitchKeyword: -// case SyntaxKind::ThrowKeyword: -// case SyntaxKind::TryKeyword: -// case SyntaxKind::DebuggerKeyword: -// // 'catch' and 'finally' do not actually indicate that the code is part of a statement, -// // however, we say they are here so that we may gracefully parse them and error later. -// // falls through -// case SyntaxKind::CatchKeyword: -// case SyntaxKind::FinallyKeyword: -// return true; -// -// case SyntaxKind::ImportKeyword: -// return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot); -// -// case SyntaxKind::ConstKeyword: -// case SyntaxKind::ExportKeyword: -// return isStartOfDeclaration(); -// -// case SyntaxKind::AsyncKeyword: -// case SyntaxKind::DeclareKeyword: -// case SyntaxKind::InterfaceKeyword: -// case SyntaxKind::ModuleKeyword: -// case SyntaxKind::NamespaceKeyword: -// case SyntaxKind::TypeKeyword: -// case SyntaxKind::GlobalKeyword: -// // When these don't start a declaration, they're an identifier in an expression statement -// return true; -// -// case SyntaxKind::PublicKeyword: -// case SyntaxKind::PrivateKeyword: -// case SyntaxKind::ProtectedKeyword: -// case SyntaxKind::StaticKeyword: -// case SyntaxKind::ReadonlyKeyword: -// // When these don't start a declaration, they may be the start of a class member if an identifier -// // immediately follows. Otherwise they're an identifier in an expression statement. -// return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); -// -// default: -// return isStartOfExpression(); -// } -// } -// // function nextTokenIsBindingIdentifierOrStartOfDestructuring() { // nextToken(); // return isBindingIdentifier() || token() == SyntaxKind::OpenBraceToken || token() == SyntaxKind::OpenBracketToken; @@ -6592,31 +6806,6 @@ namespace ts { return parseExpressionOrLabeledStatement(); } - // Parses a list of elements -// template - NodeArray parseList(ParsingContext kind, function parseElement) { - auto auto saveParsingContext = parsingContext; - parsingContext |= 1 << (int) kind; - vector> list; - - auto auto listPos = getNodePos(); - - while (! isListTerminator(kind)) { - if (isListElement(kind, /*inErrorRecovery*/ false)) { - list.push(parseListElement(kind, parseElement)); - - continue; - } - - if (abortParsingListOrMoveToNextToken(kind)) { - break; - } - } - - parsingContext = saveParsingContext; - return createNodeArray(list, listPos); - } - shared parseSourceFileWorker(ScriptTarget languageVersion, bool setParentNodes, ScriptKind scriptKind, function)> setExternalModuleIndicator) { auto isDeclarationFile = isDeclarationFileName(fileName); if (isDeclarationFile) { @@ -6748,12 +6937,6 @@ namespace ts { // return undefined!; // TODO: GH#18217 // } // } -// -// function nextTokenIsIdentifierOrStringLiteralOnSameLine() { -// nextToken(); -// return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() == SyntaxKind::StringLiteral); -// } -// // function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined { // if (token() != SyntaxKind::OpenBraceToken && canParseSemicolon()) { // parseSemicolon(); @@ -6765,61 +6948,6 @@ namespace ts { // // // DECLARATIONS // -// function parseArrayBindingElement(): ArrayBindingElement { -// auto pos = getNodePos(); -// if (token() == SyntaxKind::CommaToken) { -// return finishNode(factory::createOmittedExpression(), pos); -// } -// auto dotDotDotToken = parseOptionalToken(SyntaxKind::DotDotDotToken); -// auto name = parseIdentifierOrPattern(); -// auto initializer = parseInitializer(); -// return finishNode(factory::createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), pos); -// } -// -// function parseObjectBindingElement(): BindingElement { -// auto pos = getNodePos(); -// auto dotDotDotToken = parseOptionalToken(SyntaxKind::DotDotDotToken); -// auto tokenIsIdentifier = isBindingIdentifier(); -// let propertyName: PropertyName | undefined = parsePropertyName(); -// let name: BindingName; -// if (tokenIsIdentifier && token() != SyntaxKind::ColonToken) { -// name = propertyName as Identifier; -// propertyName = undefined; -// } -// else { -// parseExpected(SyntaxKind::ColonToken); -// name = parseIdentifierOrPattern(); -// } -// auto initializer = parseInitializer(); -// return finishNode(factory::createBindingElement(dotDotDotToken, propertyName, name, initializer), pos); -// } -// -// function parseObjectBindingPattern(): ObjectBindingPattern { -// auto pos = getNodePos(); -// parseExpected(SyntaxKind::OpenBraceToken); -// auto elements = parseDelimitedList(ParsingContext::ObjectBindingElements, parseObjectBindingElement); -// parseExpected(SyntaxKind::CloseBraceToken); -// return finishNode(factory::createObjectBindingPattern(elements), pos); -// } -// -// function parseArrayBindingPattern(): ArrayBindingPattern { -// auto pos = getNodePos(); -// parseExpected(SyntaxKind::OpenBracketToken); -// auto elements = parseDelimitedList(ParsingContext::ArrayBindingElements, parseArrayBindingElement); -// parseExpected(SyntaxKind::CloseBracketToken); -// return finishNode(factory::createArrayBindingPattern(elements), pos); -// } -// -// function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier | BindingPattern { -// if (token() == SyntaxKind::OpenBracketToken) { -// return parseArrayBindingPattern(); -// } -// if (token() == SyntaxKind::OpenBraceToken) { -// return parseObjectBindingPattern(); -// } -// return parseBindingIdentifier(privateIdentifierDiagnosticMessage); -// } -// // function parseVariableDeclarationAllowExclamation() { // return parseVariableDeclaration(/*allowExclamation*/ true); // } @@ -6828,7 +6956,7 @@ namespace ts { // auto pos = getNodePos(); // auto hasJSDoc = hasPrecedingJSDocComment(); // auto name = parseIdentifierOrPattern(Diagnostics::Private_identifiers_are_not_allowed_in_variable_declarations); -// let exclamationToken: ExclamationToken | undefined; +// auto exclamationToken: ExclamationToken | undefined; // if (allowExclamation && name.kind == SyntaxKind::Identifier && // token() == SyntaxKind::ExclamationToken && !scanner.hasPrecedingLineBreak()) { // exclamationToken = parseTokenNode>(); @@ -6842,7 +6970,7 @@ namespace ts { // function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList { // auto pos = getNodePos(); // -// let flags: NodeFlags = 0; +// auto flags: NodeFlags = 0; // switch (token()) { // case SyntaxKind::VarKeyword: // break; @@ -6867,7 +6995,7 @@ namespace ts { // // So we need to look ahead to determine if 'of' should be treated as a keyword in // // this context. // // The checker will then give an error that there is an empty declaration list. -// let declarations: readonly VariableDeclaration[]; +// auto declarations: readonly VariableDeclaration[]; // if (token() == SyntaxKind::OfKeyword && lookAhead(canFollowContextualOfKeyword)) { // declarations = createMissingList(); // } @@ -7026,75 +7154,6 @@ namespace ts { // return withJSDoc(finishNode(node, pos), hasJSDoc); // } // -// function isClassMemberStart(): boolean { -// let idToken: SyntaxKind | undefined; -// -// if (token() == SyntaxKind::AtToken) { -// return true; -// } -// -// // Eat up all modifiers, but hold on to the last one in case it is actually an identifier. -// while (isModifierKind(token())) { -// idToken = token(); -// // If the idToken is a class modifier (protected, private, public, and static), it is -// // certain that we are starting to parse class member. This allows better error recovery -// // Example: -// // public foo() ... // true -// // public @dec blah ... // true; we will then report an error later -// // export public ... // true; we will then report an error later -// if (isClassMemberModifier(idToken)) { -// return true; -// } -// -// nextToken(); -// } -// -// if (token() == SyntaxKind::AsteriskToken) { -// return true; -// } -// -// // Try to get the first property-like token following all modifiers. -// // This can either be an identifier or the 'get' or 'set' keywords. -// if (isLiteralPropertyName()) { -// idToken = token(); -// nextToken(); -// } -// -// // Index signatures and computed properties are class members; we can parse. -// if (token() == SyntaxKind::OpenBracketToken) { -// return true; -// } -// -// // If we were able to get any potential identifier... -// if (idToken != undefined) { -// // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse. -// if (!isKeyword(idToken) || idToken == SyntaxKind::SetKeyword || idToken == SyntaxKind::GetKeyword) { -// return true; -// } -// -// // If it *is* a keyword, but not an accessor, check a little farther along -// // to see if it should actually be parsed as a class member. -// switch (token()) { -// case SyntaxKind::OpenParenToken: // Method declaration -// case SyntaxKind::LessThanToken: // Generic Method declaration -// case SyntaxKind::ExclamationToken: // Non-null assertion on property name -// case SyntaxKind::ColonToken: // Type Annotation for declaration -// case SyntaxKind::EqualsToken: // Initializer for declaration -// case SyntaxKind::QuestionToken: // Not valid, but permitted so that it gets caught later on. -// return true; -// default: -// // Covers -// // - Semicolons (declaration termination) -// // - Closing braces (end-of-class, must be declaration) -// // - End-of-files (not valid, but permitted so that it gets caught later on) -// // - Line-breaks (enabling *automatic semicolon insertion*) -// return canParseSemicolon(); -// } -// } -// -// return false; -// } -// // function parseClassStaticBlockDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: ModifiersArray | undefined): ClassStaticBlockDeclaration { // parseExpectedToken(SyntaxKind::StaticKeyword); // auto body = parseClassStaticBlockBody(); @@ -7140,7 +7199,7 @@ namespace ts { // // function parseDecorators(): NodeArray | undefined { // auto pos = getNodePos(); -// let list, decorator; +// auto list, decorator; // while (decorator = tryParseDecorator()) { // list = append(list, decorator); // } @@ -7227,7 +7286,7 @@ namespace ts { // if (some(modifiers, isExportModifier)) setAwaitContext(/*value*/ true); // auto heritageClauses = parseHeritageClauses(); // -// let members; +// auto members; // if (parseExpected(SyntaxKind::OpenBraceToken)) { // // ClassTail[Yield,Await] : (Modified) See 14.5 // // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } @@ -7289,15 +7348,6 @@ namespace ts { // return finishNode(factory::createExpressionWithTypeArguments(expression, typeArguments), pos); // } // -// function tryParseTypeArguments(): NodeArray | undefined { -// return token() == SyntaxKind::LessThanToken ? -// parseBracketedList(ParsingContext::TypeArguments, parseType, SyntaxKind::LessThanToken, SyntaxKind::GreaterThanToken) : undefined; -// } -// -// function isHeritageClause(): boolean { -// return token() == SyntaxKind::ExtendsKeyword || token() == SyntaxKind::ImplementsKeyword; -// } -// // function parseClassMembers(): NodeArray { // return parseList(ParsingContext::ClassMembers, parseClassElement); // } @@ -7338,7 +7388,7 @@ namespace ts { // function parseEnumDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): EnumDeclaration { // parseExpected(SyntaxKind::EnumKeyword); // auto name = parseIdentifier(); -// let members; +// auto members; // if (parseExpected(SyntaxKind::OpenBraceToken)) { // members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(ParsingContext::EnumMembers, parseEnumMember)); // parseExpected(SyntaxKind::CloseBraceToken); @@ -7352,7 +7402,7 @@ namespace ts { // // function parseModuleBlock(): ModuleBlock { // auto pos = getNodePos(); -// let statements; +// auto statements; // if (parseExpected(SyntaxKind::OpenBraceToken)) { // statements = parseList(ParsingContext::BlockStatements, parseStatement); // parseExpected(SyntaxKind::CloseBraceToken); @@ -7376,8 +7426,8 @@ namespace ts { // } // // function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ModuleDeclaration { -// let flags: NodeFlags = 0; -// let name; +// auto flags: NodeFlags = 0; +// auto name; // if (token() == SyntaxKind::GlobalKeyword) { // // parse 'global' as name of global scope augmentation // name = parseIdentifier(); @@ -7387,7 +7437,7 @@ namespace ts { // name = parseLiteralNode() as StringLiteral; // name.text = internIdentifier(name.text); // } -// let body: ModuleBlock | undefined; +// auto body: ModuleBlock | undefined; // if (token() == SyntaxKind::OpenBraceToken) { // body = parseModuleBlock(); // } @@ -7399,7 +7449,7 @@ namespace ts { // } // // function parseModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ModuleDeclaration { -// let flags: NodeFlags = 0; +// auto flags: NodeFlags = 0; // if (token() == SyntaxKind::GlobalKeyword) { // // global augmentation // return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers); @@ -7434,12 +7484,12 @@ namespace ts { // auto afterImportPos = scanner.getStartPos(); // // // We don't parse the identifier here in await context, instead we will report a grammar error in the checker. -// let identifier: Identifier | undefined; +// auto identifier: Identifier | undefined; // if (isIdentifier()) { // identifier = parseIdentifier(); // } // -// let isTypeOnly = false; +// auto isTypeOnly = false; // if (token() != SyntaxKind::FromKeyword && // identifier?.escapedText == "type" && // (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration()) @@ -7455,7 +7505,7 @@ namespace ts { // // ImportDeclaration: // // import ImportClause from ModuleSpecifier ; // // import ModuleSpecifier; -// let importClause: ImportClause | undefined; +// auto importClause: ImportClause | undefined; // if (identifier || // import id // token() == SyntaxKind::AsteriskToken || // import * // token() == SyntaxKind::OpenBraceToken // import { @@ -7465,7 +7515,7 @@ namespace ts { // } // auto moduleSpecifier = parseModuleSpecifier(); // -// let assertClause: AssertClause | undefined; +// auto assertClause: AssertClause | undefined; // if (token() == SyntaxKind::AssertKeyword && !scanner.hasPrecedingLineBreak()) { // assertClause = parseAssertClause(); // } @@ -7538,7 +7588,7 @@ namespace ts { // // // If there was no default import or if there is comma token after default import // // parse namespace or named imports -// let namedBindings: NamespaceImport | NamedImports | undefined; +// auto namedBindings: NamespaceImport | NamedImports | undefined; // if (!identifier || // parseOptional(SyntaxKind::CommaToken)) { // namedBindings = token() == SyntaxKind::AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind::NamedImports); @@ -7622,13 +7672,13 @@ namespace ts { // // ExportSpecifier: // // IdentifierName // // IdentifierName as IdentifierName -// let checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier(); -// let checkIdentifierStart = scanner.getTokenPos(); -// let checkIdentifierEnd = scanner.getTextPos(); -// let isTypeOnly = false; -// let propertyName: Identifier | undefined; -// let canParseAsKeyword = true; -// let name = parseIdentifierName(); +// auto checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier(); +// auto checkIdentifierStart = scanner.getTokenPos(); +// auto checkIdentifierEnd = scanner.getTextPos(); +// auto isTypeOnly = false; +// auto propertyName: Identifier | undefined; +// auto canParseAsKeyword = true; +// auto name = parseIdentifierName(); // if (name.escapedText == "type") { // // If the first token of an import specifier is 'type', there are a lot of possibilities, // // especially if we see 'as' afterwards: @@ -7704,9 +7754,9 @@ namespace ts { // function parseExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ExportDeclaration { // auto savedAwaitContext = inAwaitContext(); // setAwaitContext(/*value*/ true); -// let exportClause: NamedExportBindings | undefined; -// let moduleSpecifier: Expression | undefined; -// let assertClause: AssertClause | undefined; +// auto exportClause: NamedExportBindings | undefined; +// auto moduleSpecifier: Expression | undefined; +// auto assertClause: AssertClause | undefined; // auto isTypeOnly = parseOptional(SyntaxKind::TypeKeyword); // auto namespaceExportPos = getNodePos(); // if (parseOptional(SyntaxKind::AsteriskToken)) { @@ -7738,7 +7788,7 @@ namespace ts { // function parseExportAssignment(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ExportAssignment { // auto savedAwaitContext = inAwaitContext(); // setAwaitContext(/*value*/ true); -// let isExportEquals: boolean | undefined; +// auto isExportEquals: boolean | undefined; // if (parseOptional(SyntaxKind::EqualsToken)) { // isExportEquals = true; // } @@ -7794,7 +7844,7 @@ namespace ts { // auto pos = getNodePos(); // auto hasBrace = parseOptional(SyntaxKind::OpenBraceToken); // auto p2 = getNodePos(); -// let entityName: EntityName | JSDocMemberName = parseEntityName(/* allowReservedWords*/ false); +// auto entityName: EntityName | JSDocMemberName = parseEntityName(/* allowReservedWords*/ false); // while (token() == SyntaxKind::PrivateIdentifier) { // reScanHashToken(); // rescan #id as # id // nextTokenJSDoc(); // then skip the # @@ -7867,23 +7917,23 @@ namespace ts { // return undefined; // } // -// let tags: JSDocTag[]; -// let tagsPos: number; -// let tagsEnd: number; -// let linkEnd: number; -// let commentsPos: number | undefined; -// let comments: string[] = []; +// auto tags: JSDocTag[]; +// auto tagsPos: number; +// auto tagsEnd: number; +// auto linkEnd: number; +// auto commentsPos: number | undefined; +// auto comments: string[] = []; // auto parts: JSDocComment[] = []; // // // + 3 for leading /**, - 5 in total for /** */ // return scanner.scanRange(start + 3, length - 5, () => { // // Initially we can parse out a tag. We also have seen a starting asterisk. // // This is so that /** * @type */ doesn't parse. -// let state = JSDocState.SawAsterisk; -// let margin: number | undefined; +// auto state = JSDocState.SawAsterisk; +// auto margin: number | undefined; // // + 4 for leading '/** ' // // + 1 because the last index of \n is always one index before the first character in the line and coincidentally, if there is no \n before start, it is -1, which is also one index before the first character -// let indent = start - (content.lastIndexOf("\n", start) + 1) + 4; +// auto indent = start - (content.lastIndexOf("\n", start) + 1) + 4; // function pushComment(text: string) { // if (!margin) { // margin = indent; @@ -8024,9 +8074,9 @@ namespace ts { // } // } // -// let precedingLineBreak = scanner.hasPrecedingLineBreak(); -// let seenLineBreak = false; -// let indentText = ""; +// auto precedingLineBreak = scanner.hasPrecedingLineBreak(); +// auto seenLineBreak = false; +// auto indentText = ""; // while ((precedingLineBreak && token() == SyntaxKind::AsteriskToken) || token() == SyntaxKind::WhitespaceTrivia || token() == SyntaxKind::NewLineTrivia) { // indentText += scanner.getTokenText(); // if (token() == SyntaxKind::NewLineTrivia) { @@ -8050,7 +8100,7 @@ namespace ts { // auto tagName = parseJSDocIdentifierName(/*message*/ undefined); // auto indentText = skipWhitespaceOrAsterisk(); // -// let tag: JSDocTag | undefined; +// auto tag: JSDocTag | undefined; // switch (tagName.escapedText) { // case "author": // tag = parseAuthorTag(start, tagName, margin, indentText); @@ -8131,12 +8181,12 @@ namespace ts { // // function parseTagComments(indent: number, initialMargin?: string): string | NodeArray | undefined { // auto commentsPos = getNodePos(); -// let comments: string[] = []; +// auto comments: string[] = []; // auto parts: JSDocComment[] = []; -// let linkEnd; -// let state = JSDocState.BeginningOfLine; -// let previousWhitespace = true; -// let margin: number | undefined; +// auto linkEnd; +// auto state = JSDocState.BeginningOfLine; +// auto previousWhitespace = true; +// auto margin: number | undefined; // function pushComment(text: string) { // if (!margin) { // margin = indent; @@ -8151,7 +8201,7 @@ namespace ts { // } // state = JSDocState.SawAsterisk; // } -// let tok = token() as JSDocSyntaxKind; +// auto tok = token() as JSDocSyntaxKind; // loop: while (true) { // switch (tok) { // case SyntaxKind::NewLineTrivia: @@ -8256,7 +8306,7 @@ namespace ts { // skipWhitespace(); // // parseEntityName logs an error for non-identifier, so create a MissingNode ourselves to avoid the error // auto p2 = getNodePos(); -// let name: EntityName | JSDocMemberName | undefined = tokenIsIdentifierOrKeyword(token()) +// auto name: EntityName | JSDocMemberName | undefined = tokenIsIdentifierOrKeyword(token()) // ? parseEntityName(/*allowReservedWords*/ true) // : undefined; // if (name) { @@ -8351,8 +8401,8 @@ namespace ts { // } // // function parseParameterOrPropertyTag(start: number, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag { -// let typeExpression = tryParseTypeExpression(); -// let isNameFirst = !typeExpression; +// auto typeExpression = tryParseTypeExpression(); +// auto isNameFirst = !typeExpression; // skipWhitespaceOrAsterisk(); // // auto { name, isBracketed } = parseBracketNameInPropertyAndParamTag(); @@ -8378,8 +8428,8 @@ namespace ts { // function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) { // if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { // auto pos = getNodePos(); -// let child: JSDocPropertyLikeTag | JSDocTypeTag | false; -// let children: JSDocPropertyLikeTag[] | undefined; +// auto child: JSDocPropertyLikeTag | JSDocTypeTag | false; +// auto children: JSDocPropertyLikeTag[] | undefined; // while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) { // if (child.kind == SyntaxKind::JSDocParameterTag || child.kind == SyntaxKind::JSDocPropertyTag) { // children = append(children, child); @@ -8422,7 +8472,7 @@ namespace ts { // function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag { // auto commentStart = getNodePos(); // auto textOnly = parseAuthorNameAndEmail(); -// let commentEnd = scanner.getStartPos(); +// auto commentEnd = scanner.getStartPos(); // auto comments = parseTrailingTagComments(start, commentEnd, indent, indentText); // if (!comments) { // commentEnd = scanner.getStartPos(); @@ -8435,8 +8485,8 @@ namespace ts { // // function parseAuthorNameAndEmail(): JSDocText { // auto comments: string[] = []; -// let inEmail = false; -// let token = scanner.getToken(); +// auto inEmail = false; +// auto token = scanner.getToken(); // while (token != SyntaxKind::EndOfFileToken && token != SyntaxKind::NewLineTrivia) { // if (token == SyntaxKind::LessThanToken) { // inEmail = true; @@ -8481,7 +8531,7 @@ namespace ts { // // function parsePropertyAccessEntityNameExpression() { // auto pos = getNodePos(); -// let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(); +// auto node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(); // while (parseOptional(SyntaxKind::DotToken)) { // auto name = parseJSDocIdentifierName(); // node = finishNode(factory::createPropertyAccessExpression(node, name), pos) as PropertyAccessEntityNameExpression; @@ -8506,19 +8556,19 @@ namespace ts { // } // // function parseTypedefTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTypedefTag { -// let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression(); +// auto typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression(); // skipWhitespaceOrAsterisk(); // // auto fullName = parseJSDocTypeNameWithNamespace(); // skipWhitespace(); -// let comment = parseTagComments(indent); +// auto comment = parseTagComments(indent); // -// let end: number | undefined; +// auto end: number | undefined; // if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) { -// let child: JSDocTypeTag | JSDocPropertyTag | false; -// let childTypeTag: JSDocTypeTag | undefined; -// let jsDocPropertyTags: JSDocPropertyTag[] | undefined; -// let hasChildren = false; +// auto child: JSDocTypeTag | JSDocPropertyTag | false; +// auto childTypeTag: JSDocTypeTag | undefined; +// auto jsDocPropertyTags: JSDocPropertyTag[] | undefined; +// auto hasChildren = false; // while (child = tryParse(() => parseChildPropertyTag(indent))) { // hasChildren = true; // if (child.kind == SyntaxKind::JSDocTypeTag) { @@ -8587,8 +8637,8 @@ namespace ts { // // function parseCallbackTagParameters(indent: number) { // auto pos = getNodePos(); -// let child: JSDocParameterTag | false; -// let parameters; +// auto child: JSDocParameterTag | false; +// auto parameters; // while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag)) { // parameters = append(parameters, child); // } @@ -8598,7 +8648,7 @@ namespace ts { // function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag { // auto fullName = parseJSDocTypeNameWithNamespace(); // skipWhitespace(); -// let comment = parseTagComments(indent); +// auto comment = parseTagComments(indent); // auto parameters = parseCallbackTagParameters(indent); // auto returnTag = tryParse(() => { // if (parseOptionalJsdoc(SyntaxKind::AtToken)) { @@ -8634,8 +8684,8 @@ namespace ts { // } // // function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false { -// let canParseTag = true; -// let seenAsterisk = false; +// auto canParseTag = true; +// auto seenAsterisk = false; // while (true) { // switch (nextTokenJSDoc()) { // case SyntaxKind::AtToken: @@ -8676,7 +8726,7 @@ namespace ts { // // auto tagName = parseJSDocIdentifierName(); // skipWhitespace(); -// let t: PropertyLikeParse; +// auto t: PropertyLikeParse; // switch (tagName.escapedText) { // case "type": // return target == PropertyLikeParse.Property && parseTypeTag(start, tagName); @@ -8706,7 +8756,7 @@ namespace ts { // } // auto name = parseJSDocIdentifierName(Diagnostics::Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); // -// let defaultType: TypeNode | undefined; +// auto defaultType: TypeNode | undefined; // if (isBracketed) { // skipWhitespace(); // parseExpected(SyntaxKind::EqualsToken); @@ -8760,7 +8810,7 @@ namespace ts { // } // // function parseJSDocEntityName(): EntityName { -// let entity: EntityName = parseJSDocIdentifierName(); +// auto entity: EntityName = parseJSDocIdentifierName(); // if (parseOptional(SyntaxKind::OpenBracketToken)) { // parseExpected(SyntaxKind::CloseBracketToken); // // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking. @@ -8839,7 +8889,7 @@ namespace ts { // // Prime the scanner. // nextToken(); // auto pos = getNodePos(); -// let statements, endOfFileToken; +// auto statements, endOfFileToken; // if (token() == SyntaxKind::EndOfFileToken) { // statements = createNodeArray([], pos, pos); // endOfFileToken = parseTokenNode(); @@ -8847,9 +8897,9 @@ namespace ts { // else { // // Loop and synthesize an ArrayLiteralExpression if there are more than // // one top-level expressions to ensure all input text is consumed. -// let expressions: Expression[] | Expression | undefined; +// auto expressions: Expression[] | Expression | undefined; // while (token() != SyntaxKind::EndOfFileToken) { -// let expression; +// auto expression; // switch (token()) { // case SyntaxKind::OpenBracketToken: // expression = parseArrayLiteralExpression(); @@ -9025,8 +9075,8 @@ namespace ts { // aggressiveChecks: boolean // ): CommentDirective[] | undefined { // if (!oldDirectives) return newDirectives; -// let commentDirectives: CommentDirective[] | undefined; -// let addedNewlyScannedDirectives = false; +// auto commentDirectives: CommentDirective[] | undefined; +// auto addedNewlyScannedDirectives = false; // for (const directive of oldDirectives) { // auto { range, type } = directive; // // Range before the change @@ -9073,7 +9123,7 @@ namespace ts { // return; // // function visitNode(node: IncrementalNode) { -// let text = ""; +// auto text = ""; // if (aggressiveChecks && shouldCheckNode(node)) { // text = oldText.substring(node.pos, node.end); // } @@ -9196,7 +9246,7 @@ namespace ts { // // function checkNodePositions(node: Node, aggressiveChecks: boolean) { // if (aggressiveChecks) { -// let pos = node.pos; +// auto pos = node.pos; // auto visitNode = (child: Node) => { // Debug.assert(child.pos >= pos); // pos = child.end; @@ -9300,7 +9350,7 @@ namespace ts { // // that the prior token sees that change. // auto maxLookahead = 1; // -// let start = changeRange.span.start; +// auto start = changeRange.span.start; // // // the first iteration aligns us with the change start. subsequent iteration move us to // // the left by maxLookahead tokens. We only need to do this as long as we're not at the @@ -9320,8 +9370,8 @@ namespace ts { // } // // function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node { -// let bestResult: Node = sourceFile; -// let lastNodeEntirelyBeforePosition: Node | undefined; +// auto bestResult: Node = sourceFile; +// auto lastNodeEntirelyBeforePosition: Node | undefined; // // forEachChild(sourceFile, visit); // @@ -9444,12 +9494,12 @@ namespace ts { // } // // export function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor { -// let currentArray: NodeArray = sourceFile.statements; -// let currentArrayIndex = 0; +// auto currentArray: NodeArray = sourceFile.statements; +// auto currentArrayIndex = 0; // // Debug.assert(currentArrayIndex < currentArray.length); -// let current = currentArray[currentArrayIndex]; -// let lastQueriedPosition = InvalidPosition.Value; +// auto current = currentArray[currentArrayIndex]; +// auto lastQueriedPosition = InvalidPosition.Value; // // return { // currentNode(position: number) { @@ -9744,7 +9794,7 @@ namespace ts { // // if (range.kind == SyntaxKind::MultiLineCommentTrivia) { // auto multiLinePragmaRegEx = /@(\S+)(\s+.*)?$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating) -// let multiLineMatch: RegExpExecArray | null; +// auto multiLineMatch: RegExpExecArray | null; // while (multiLineMatch = multiLinePragmaRegEx.exec(text)) { // addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch); // } @@ -9783,24 +9833,4 @@ namespace ts { // return argMap; // } // -// /** @internal */ -// export function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagNameExpression): boolean { -// if (lhs.kind != rhs.kind) { -// return false; -// } -// -// if (lhs.kind == SyntaxKind::Identifier) { -// return lhs.escapedText == (rhs as Identifier).escapedText; -// } -// -// if (lhs.kind == SyntaxKind::ThisKeyword) { -// return true; -// } -// -// // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only -// // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression -// // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element -// return (lhs as PropertyAccessExpression).name.escapedText == (rhs as PropertyAccessExpression).name.escapedText && -// tagNamesAreEquivalent((lhs as PropertyAccessExpression).expression as JsxTagNameExpression, (rhs as PropertyAccessExpression).expression as JsxTagNameExpression); -// } } diff --git a/src/scanner.cpp b/src/scanner.cpp index be6cf19..81055c5 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -18,23 +18,6 @@ bool isShebangTrivia(string &text, int pos) { return false; } -bool isWhiteSpaceSingleLine(CharCode ch) { - // Note: nextLine is in the Zs space, and should be considered to be a whitespace. - // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. - return ch.code == CharacterCodes::space || - ch.code == CharacterCodes::tab || - ch.code == CharacterCodes::verticalTab || - ch.code == CharacterCodes::formFeed || - ch.code == CharacterCodes::nonBreakingSpace || - ch.code == CharacterCodes::nextLine || - ch.code == CharacterCodes::ogham || - (ch.code >= CharacterCodes::enQuad && ch.code <= CharacterCodes::zeroWidthSpace) || - ch.code == CharacterCodes::narrowNoBreakSpace || - ch.code == CharacterCodes::mathematicalSpace || - ch.code == CharacterCodes::ideographicSpace || - ch.code == CharacterCodes::byteOrderMark; -} - bool isLineBreak(CharCode ch) { // ES5 7.3: // The ECMAScript line terminator characters are listed in Table 3. @@ -53,37 +36,55 @@ bool isLineBreak(CharCode ch) { ch.code == CharacterCodes::paragraphSeparator; } + +bool isWhiteSpaceSingleLine(CharCode ch) { + // Note: nextLine is in the Zs space, and should be considered to be a whitespace. + // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. + return ch.code == CharacterCodes::space || + ch.code == CharacterCodes::tab || + ch.code == CharacterCodes::verticalTab || + ch.code == CharacterCodes::formFeed || + ch.code == CharacterCodes::nonBreakingSpace || + ch.code == CharacterCodes::nextLine || + ch.code == CharacterCodes::ogham || + (ch.code >= CharacterCodes::enQuad && ch.code <= CharacterCodes::zeroWidthSpace) || + ch.code == CharacterCodes::narrowNoBreakSpace || + ch.code == CharacterCodes::mathematicalSpace || + ch.code == CharacterCodes::ideographicSpace || + ch.code == CharacterCodes::byteOrderMark; +} + string Scanner::scanString(bool jsxAttributeString) { auto quote = charCodeAt(text, pos); - pos++; + pos ++; string result = ""; auto start = pos; while (true) { if (pos >= end) { - result += text.substr(start, pos); + result += substr(text, start, pos); tokenFlags |= TokenFlags::Unterminated; // error(Diagnostics::Unterminated_string_literal); break; } auto ch = charCodeAt(text, pos); if (ch.code == quote.code) { - result += text.substr(start, pos); - pos++; + result += substr(text, start, pos); + pos ++; break; } - if (ch.code == CharacterCodes::backslash && !jsxAttributeString) { - result += text.substr(start, pos); + if (ch.code == CharacterCodes::backslash && ! jsxAttributeString) { + result += substr(text, start, pos); result += scanEscapeSequence(); start = pos; continue; } - if (isLineBreak(ch) && !jsxAttributeString) { - result += text.substr(start, pos); + if (isLineBreak(ch) && ! jsxAttributeString) { + result += substr(text, start, pos); tokenFlags |= TokenFlags::Unterminated; // error(Diagnostics::Unterminated_string_literal); break; } - pos++; + pos ++; } return result; } @@ -118,24 +119,24 @@ string Scanner::scanHexDigits(int minCount, bool scanAsManyAsPossible, bool canH } else { // error(Diagnostics::Numeric_separators_are_not_allowed_here, pos, 1); } - pos++; + pos ++; continue; } allowSeparator = canHaveSeparators; if (ch.code >= CharacterCodes::A && ch.code <= CharacterCodes::F) { ch.code += CharacterCodes::a - CharacterCodes::A; // standardize hex literals to lowercase - } else if (!((ch.code >= CharacterCodes::_0 && ch.code <= CharacterCodes::_9) || - (ch.code >= CharacterCodes::a && ch.code <= CharacterCodes::f) + } else if (! ((ch.code >= CharacterCodes::_0 && ch.code <= CharacterCodes::_9) || + (ch.code >= CharacterCodes::a && ch.code <= CharacterCodes::f) )) { break; } - found++; - result.append(text.substr(pos, ch.length)); - pos++; + found ++; + result.append(substr(text, pos, ch.length)); + pos ++; isPreviousTokenSeparator = false; } -// if (text.charCodeAt(pos - 1) === CharacterCodes::_) { +// if (charCodeAt(text, pos - 1) == CharacterCodes::_) { // error(Diagnostics::Numeric_separators_are_not_allowed_here, pos - 1, 1); // } @@ -146,10 +147,9 @@ bool isCodePoint(CharCode ch) { return ch.code <= 0x10FFFF; } - int Scanner::scanExactNumberOfHexDigits(int count, bool canHaveSeparators) { auto valueString = scanHexDigits(/*minCount*/ count, /*scanAsManyAsPossible*/ false, canHaveSeparators); - return !valueString.empty() ? stoi(valueString, nullptr, 16) : -1; + return ! valueString.empty() ? stoi(valueString, nullptr, 16) : - 1; } string Scanner::scanHexadecimalEscape(int numDigits) { @@ -165,7 +165,7 @@ string Scanner::scanHexadecimalEscape(int numDigits) { string Scanner::scanExtendedUnicodeEscape() { auto escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); - auto escapedValue = !escapedValueString.empty() ? stoi(escapedValueString, nullptr, 16) : -1; + auto escapedValue = ! escapedValueString.empty() ? stoi(escapedValueString, nullptr, 16) : - 1; auto isInvalidExtendedEscape = false; // Validate the value of the digit @@ -182,7 +182,7 @@ string Scanner::scanExtendedUnicodeEscape() { isInvalidExtendedEscape = true; } else if (charCodeAt(text, pos).code == CharacterCodes::closeBrace) { // Only swallow the following character up if it's a '}'. - pos++; + pos ++; } else { // error(Diagnostics::Unterminated_Unicode_escape_sequence); isInvalidExtendedEscape = true; @@ -198,20 +198,20 @@ string Scanner::scanExtendedUnicodeEscape() { string Scanner::scanEscapeSequence(bool isTaggedTemplate) { auto start = pos; - pos++; + pos ++; if (pos >= end) { // error(Diagnostics::Unexpected_end_of_text); return ""; } auto ch = charCodeAt(text, pos); - pos++; + pos ++; switch (ch.code) { case CharacterCodes::_0: // '\01' if (isTaggedTemplate && pos < end && isDigit(charCodeAt(text, pos))) { - pos++; + pos ++; tokenFlags |= TokenFlags::ContainsInvalidEscape; - return text.substr(start, pos); + return substr(text, start, pos); } return "\0"; case CharacterCodes::b: @@ -233,23 +233,23 @@ string Scanner::scanEscapeSequence(bool isTaggedTemplate) { case CharacterCodes::u: if (isTaggedTemplate) { // '\u' or '\u0' or '\u00' or '\u000' - for (auto escapePos = pos; escapePos < pos + 4; escapePos++) { - if (escapePos < end && !isHexDigit(charCodeAt(text, escapePos)) && + for (auto escapePos = pos; escapePos < pos + 4; escapePos ++) { + if (escapePos < end && ! isHexDigit(charCodeAt(text, escapePos)) && charCodeAt(text, escapePos).code != CharacterCodes::openBrace) { pos = escapePos; tokenFlags |= TokenFlags::ContainsInvalidEscape; - return text.substr(start, pos); + return substr(text, start, pos); } } } // '\u{DDDDDDDD}' if (pos < end && charCodeAt(text, pos).code == CharacterCodes::openBrace) { - pos++; + pos ++; // '\u{' - if (isTaggedTemplate && !isHexDigit(charCodeAt(text, pos))) { + if (isTaggedTemplate && ! isHexDigit(charCodeAt(text, pos))) { tokenFlags |= TokenFlags::ContainsInvalidEscape; - return text.substr(start, pos); + return substr(text, start, pos); } if (isTaggedTemplate) { @@ -257,18 +257,18 @@ string Scanner::scanEscapeSequence(bool isTaggedTemplate) { auto escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); try { - auto escapedValue = !escapedValueString.empty() ? stoi(escapedValueString, nullptr, 16) : -1; + auto escapedValue = ! escapedValueString.empty() ? stoi(escapedValueString, nullptr, 16) : - 1; // '\u{Not Code Point' or '\u{CodePoint' if (charCodeAt(text, pos).code != CharacterCodes::closeBrace) { tokenFlags |= TokenFlags::ContainsInvalidEscape; - return text.substr(start, pos); + return substr(text, start, pos); } else { pos = savePos; } } catch (invalid_argument &error) { tokenFlags |= TokenFlags::ContainsInvalidEscape; - return text.substr(start, pos); + return substr(text, start, pos); } } tokenFlags |= TokenFlags::ExtendedUnicodeEscape; @@ -281,13 +281,13 @@ string Scanner::scanEscapeSequence(bool isTaggedTemplate) { case CharacterCodes::x: if (isTaggedTemplate) { - if (!isHexDigit(charCodeAt(text, pos))) { + if (! isHexDigit(charCodeAt(text, pos))) { tokenFlags |= TokenFlags::ContainsInvalidEscape; - return text.substr(start, pos); - } else if (!isHexDigit(charCodeAt(text, pos + 1))) { - pos++; + return substr(text, start, pos); + } else if (! isHexDigit(charCodeAt(text, pos + 1))) { + pos ++; tokenFlags |= TokenFlags::ContainsInvalidEscape; - return text.substr(start, pos); + return substr(text, start, pos); } } // '\xDD' @@ -297,7 +297,7 @@ string Scanner::scanEscapeSequence(bool isTaggedTemplate) { // the line terminator is interpreted to be "the empty code unit sequence". case CharacterCodes::carriageReturn: if (pos < end && charCodeAt(text, pos).code == CharacterCodes::lineFeed) { - pos++; + pos ++; } // falls through case CharacterCodes::lineFeed: @@ -312,14 +312,14 @@ string Scanner::scanEscapeSequence(bool isTaggedTemplate) { SyntaxKind Scanner::scanTemplateAndSetTokenValue(bool isTaggedTemplate) { auto startedWithBacktick = charCodeAt(text, pos).code == CharacterCodes::backtick; - pos++; + pos ++; auto start = pos; string contents; SyntaxKind resultingToken; while (true) { if (pos >= end) { - contents += text.substr(start, pos); + contents += substr(text, start, pos); tokenFlags |= TokenFlags::Unterminated; // error(Diagnostics::Unterminated_template_literal); resultingToken = startedWithBacktick ? SyntaxKind::NoSubstitutionTemplateLiteral : SyntaxKind::TemplateTail; @@ -330,15 +330,15 @@ SyntaxKind Scanner::scanTemplateAndSetTokenValue(bool isTaggedTemplate) { // '`' if (currChar.code == CharacterCodes::backtick) { - contents += text.substr(start, pos); - pos++; + contents += substr(text, start, pos); + pos ++; resultingToken = startedWithBacktick ? SyntaxKind::NoSubstitutionTemplateLiteral : SyntaxKind::TemplateTail; break; } // '${' if (currChar.code == CharacterCodes::$ && pos + 1 < end && charCodeAt(text, pos + 1).code == CharacterCodes::openBrace) { - contents += text.substr(start, pos); + contents += substr(text, start, pos); pos += 2; resultingToken = startedWithBacktick ? SyntaxKind::TemplateHead : SyntaxKind::TemplateMiddle; break; @@ -346,7 +346,7 @@ SyntaxKind Scanner::scanTemplateAndSetTokenValue(bool isTaggedTemplate) { // Escape character if (currChar.code == CharacterCodes::backslash) { - contents += text.substr(start, pos); + contents += substr(text, start, pos); contents += scanEscapeSequence(isTaggedTemplate); start = pos; continue; @@ -355,11 +355,11 @@ SyntaxKind Scanner::scanTemplateAndSetTokenValue(bool isTaggedTemplate) { // Speculated ECMAScript 6 Spec 11.8.6.1: // and LineTerminatorSequences are normalized to for Template Values if (currChar.code == CharacterCodes::carriageReturn) { - contents += text.substr(start, pos); - pos++; + contents += substr(text, start, pos); + pos ++; if (pos < end && charCodeAt(text, pos).code == CharacterCodes::lineFeed) { - pos++; + pos ++; } contents += "\n"; @@ -367,7 +367,7 @@ SyntaxKind Scanner::scanTemplateAndSetTokenValue(bool isTaggedTemplate) { continue; } - pos++; + pos ++; } // Debug.assert(resultingToken !== undefined); @@ -388,20 +388,20 @@ string Scanner::scanNumberFragment() { if (allowSeparator) { allowSeparator = false; isPreviousTokenSeparator = true; - result += text.substr(start, pos); + result += substr(text, start, pos); } else if (isPreviousTokenSeparator) { // error(Diagnostics::Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1); } else { // error(Diagnostics::Numeric_separators_are_not_allowed_here, pos, 1); } - pos++; + pos ++; start = pos; continue; } if (isDigit(ch)) { allowSeparator = true; isPreviousTokenSeparator = false; - pos++; + pos ++; continue; } break; @@ -409,7 +409,7 @@ string Scanner::scanNumberFragment() { if (charCodeAt(text, pos - 1).code == CharacterCodes::_) { // error(Diagnostics::Numeric_separators_are_not_allowed_here, pos - 1, 1); } - return result + text.substr(start, pos); + return result + substr(text, start, pos); } map textToKeyword{ @@ -516,61 +516,61 @@ map textToKeyword{ http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt */ vector unicodeES3IdentifierStart = {170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, - 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, - 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, - 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, - 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, - 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, - 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, - 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, - 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, - 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, - 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, - 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, - 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, - 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, - 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, - 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, - 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, - 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, - 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, - 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, - 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, - 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, - 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, - 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,}; + 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, 1220, 1223, 1224, 1227, 1228, 1232, + 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, + 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, + 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, + 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, + 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, + 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, + 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, + 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, + 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, + 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, + 3805, 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, + 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, + 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, + 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, + 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, + 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, + 8180, 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, + 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, 12445, 12446, 12449, + 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, + 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, + 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, + 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,}; vector unicodeES3IdentifierPart = {170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, - 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, - 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, - 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, - 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, - 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, - 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, - 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, - 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, - 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, - 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, - 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, - 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, - 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, - 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, - 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, - 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, - 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, - 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, - 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, - 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, - 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, - 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, - 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, - 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, - 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, - 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, - 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, - 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, - 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, - 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, - 65479, 65482, 65487, 65490, 65495, 65498, 65500,}; + 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1155, 1158, 1164, 1220, + 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, + 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, + 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, + 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, + 2524, 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, + 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, 2699, 2701, 2701, 2703, 2705, + 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, + 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, + 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, + 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, + 3114, 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, + 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, 3302, 3311, 3330, 3331, + 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3425, 3430, 3439, 3458, 3459, + 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, + 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, + 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, + 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, + 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, + 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, + 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, + 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, + 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, + 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, + 8160, 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, + 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12335, 12337, + 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, + 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, + 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, + 65101, 65103, 65136, 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, + 65479, 65482, 65487, 65490, 65495, 65498, 65500,}; /* As per ECMAScript Language Specification 5th Edition, Section 7.6: ISyntaxToken Names and Identifiers @@ -595,82 +595,81 @@ vector unicodeES3IdentifierPart = {170, 170, 181, 181, 186, 186, 192, 214, http://www.unicode.org/Public/6.2.0/ucd/UnicodeData.txt */ vector unicodeES5IdentifierStart = {170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, 887, 890, 893, 902, - 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, - 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, - 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, - 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, - 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, - 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, - 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, - 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, - 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, - 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, - 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, - 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, - 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, - 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, - 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, - 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, - 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, - 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, - 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, - 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, - 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, - 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, - 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, - 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, - 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, - 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, - 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, - 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, - 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, - 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, - 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, - 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, - 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, - 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,}; + 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, + 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957, + 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2208, 2208, 2210, 2220, + 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, + 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, + 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, + 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, + 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, + 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212, + 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, + 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, + 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, + 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, + 4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, + 4301, 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, + 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, + 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, + 6108, 6108, 6176, 6263, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6571, 6593, 6599, 6656, 6678, + 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, + 7406, 7409, 7413, 7414, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, + 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, + 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, + 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, 11499, 11502, 11506, + 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, + 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295, 12321, 12329, 12337, 12341, 12344, + 12348, 12353, 12438, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, + 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42606, 42623, 42647, 42656, 42735, 42775, + 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43009, 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, + 43138, 43187, 43250, 43255, 43259, 43259, 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43520, 43560, 43584, + 43586, 43588, 43595, 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, + 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44002, 44032, + 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, + 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, + 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500,}; vector unicodeES5IdentifierPart = {170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 768, 884, 886, 887, 890, 893, 902, - 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, - 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, - 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, - 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, - 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, - 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, - 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, - 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, - 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, - 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, - 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, - 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, - 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, - 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, - 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, - 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, - 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, - 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, - 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, - 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, - 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, - 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, - 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, - 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, - 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, - 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, - 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, - 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, - 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, - 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, - 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, - 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, - 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, - 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, - 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, - 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, - 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, - 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, - 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, - 65495, 65498, 65500,}; - + 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1319, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471, + 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1552, 1562, 1568, 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, + 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2048, 2093, 2112, 2139, 2208, 2208, 2210, 2220, 2276, 2302, 2304, + 2403, 2406, 2415, 2417, 2423, 2425, 2431, 2433, 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, + 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, + 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, + 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, + 2768, 2784, 2787, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, + 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, + 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, + 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, + 3161, 3168, 3171, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, + 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3396, 3398, + 3400, 3402, 3406, 3415, 3415, 3424, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, + 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, + 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, + 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, + 3911, 3913, 3948, 3953, 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, + 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, + 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5759, 5761, + 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, + 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6263, 6272, 6314, 6320, 6389, 6400, 6428, 6432, 6443, 6448, 6459, 6470, + 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6617, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6912, + 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7376, 7378, 7380, 7414, 7424, 7654, 7676, 7957, 7960, + 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, + 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8204, 8205, 8255, 8256, 8276, 8276, 8305, 8305, 8319, + 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, + 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358, 11360, 11492, + 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, 11686, 11688, 11694, 11696, + 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 11823, 11823, 12293, 12295, 12321, 12335, + 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12442, 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589, 12593, 12686, 12704, + 12730, 12784, 12799, 13312, 19893, 19968, 40908, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, + 42623, 42647, 42655, 42737, 42775, 42783, 42786, 42888, 42891, 42894, 42896, 42899, 42912, 42922, 43000, 43047, 43072, 43123, 43136, + 43204, 43216, 43225, 43232, 43255, 43259, 43259, 43264, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43520, 43574, + 43584, 43597, 43600, 43609, 43616, 43638, 43642, 43643, 43648, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, + 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43968, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, + 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, + 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65062, 65075, 65076, 65101, 65103, + 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, + 65495, 65498, 65500,}; /** * Generated by scripts/regenerate-unicode-identifier-parts.js on node v12.4.0 with unicode 12.1 @@ -679,142 +678,142 @@ vector unicodeES5IdentifierPart = {170, 170, 181, 181, 186, 186, 192, 214, * unicodeESNextIdentifierPart corresponds to ID_Continue, Other_ID_Continue, plus ID_Start and Other_ID_Start */ vector unicodeESNextIdentifierStart = {65, 90, 97, 122, 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750, 880, 884, 886, - 887, 890, 893, 895, 895, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1327, 1329, 1366, 1369, 1369, 1376, - 1416, 1488, 1514, 1519, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, - 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, - 2136, 2144, 2154, 2208, 2228, 2230, 2237, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2432, 2437, 2444, 2447, 2448, 2451, - 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2556, 2556, 2565, 2570, 2575, - 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, - 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2809, 2809, 2821, 2828, 2831, 2832, 2835, 2856, 2858, - 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, - 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3129, 3133, - 3133, 3160, 3162, 3168, 3169, 3200, 3200, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, - 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3412, 3414, 3423, 3425, 3450, 3455, 3461, 3478, 3482, - 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, - 3749, 3751, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, - 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, - 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, - 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, - 5759, 5761, 5786, 5792, 5866, 5870, 5880, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, - 6103, 6108, 6108, 6176, 6264, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6430, 6480, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6656, - 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7296, - 7304, 7312, 7354, 7357, 7359, 7401, 7404, 7406, 7411, 7413, 7414, 7418, 7418, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, - 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, - 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, - 8469, 8472, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, - 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, - 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, - 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12443, 12447, 12449, 12538, 12540, 12543, 12549, 12591, - 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40943, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, - 42538, 42539, 42560, 42606, 42623, 42653, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42943, 42946, 42950, 42999, 43009, - 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43261, 43262, 43274, 43301, - 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43488, 43492, 43494, 43503, 43514, 43518, 43520, 43560, 43584, 43586, - 43588, 43595, 43616, 43638, 43642, 43642, 43646, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, - 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, - 43868, 43879, 43888, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, - 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, - 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, - 65482, 65487, 65490, 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, - 65664, 65786, 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66335, 66349, 66378, 66384, 66421, 66432, 66461, 66464, 66499, - 66504, 66511, 66513, 66517, 66560, 66717, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 67072, 67382, 67392, 67413, - 67424, 67431, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, - 67808, 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67968, 68023, 68030, 68031, 68096, 68096, 68112, 68115, 68117, 68119, - 68121, 68149, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68324, 68352, 68405, 68416, 68437, 68448, 68466, 68480, 68497, - 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68899, 69376, 69404, 69415, 69415, 69424, 69445, 69600, 69622, 69635, 69687, - 69763, 69807, 69840, 69864, 69891, 69926, 69956, 69956, 69968, 70002, 70006, 70006, 70019, 70066, 70081, 70084, 70106, 70106, - 70108, 70108, 70144, 70161, 70163, 70187, 70272, 70278, 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70366, - 70405, 70412, 70415, 70416, 70419, 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70461, 70461, 70480, 70480, 70493, 70497, - 70656, 70708, 70727, 70730, 70751, 70751, 70784, 70831, 70852, 70853, 70855, 70855, 71040, 71086, 71128, 71131, 71168, 71215, - 71236, 71236, 71296, 71338, 71352, 71352, 71424, 71450, 71680, 71723, 71840, 71903, 71935, 71935, 72096, 72103, 72106, 72144, - 72161, 72161, 72163, 72163, 72192, 72192, 72203, 72242, 72250, 72250, 72272, 72272, 72284, 72329, 72349, 72349, 72384, 72440, - 72704, 72712, 72714, 72750, 72768, 72768, 72818, 72847, 72960, 72966, 72968, 72969, 72971, 73008, 73030, 73030, 73056, 73061, - 73063, 73064, 73066, 73097, 73112, 73112, 73440, 73458, 73728, 74649, 74752, 74862, 74880, 75075, 77824, 78894, 82944, 83526, - 92160, 92728, 92736, 92766, 92880, 92909, 92928, 92975, 92992, 92995, 93027, 93047, 93053, 93071, 93760, 93823, 93952, 94026, - 94032, 94032, 94099, 94111, 94176, 94177, 94179, 94179, 94208, 100343, 100352, 101106, 110592, 110878, 110928, 110930, 110948, - 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 119808, 119892, 119894, 119964, 119966, - 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, 120071, - 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144, 120146, - 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686, 120688, - 120712, 120714, 120744, 120746, 120770, 120772, 120779, 123136, 123180, 123191, 123197, 123214, 123214, 123584, 123627, 124928, - 125124, 125184, 125251, 125259, 125259, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, - 126514, 126516, 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, - 126543, 126545, 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, - 126562, 126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, - 126619, 126625, 126627, 126629, 126633, 126635, 126651, 131072, 173782, 173824, 177972, 177984, 178205, 178208, 183969, 183984, - 191456, 194560, 195101}; + 887, 890, 893, 895, 895, 902, 902, 904, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1327, 1329, 1366, 1369, 1369, 1376, + 1416, 1488, 1514, 1519, 1522, 1568, 1610, 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, + 1808, 1810, 1839, 1869, 1957, 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069, 2074, 2074, 2084, 2084, 2088, 2088, 2112, + 2136, 2144, 2154, 2208, 2228, 2230, 2237, 2308, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2432, 2437, 2444, 2447, 2448, 2451, + 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545, 2556, 2556, 2565, 2570, 2575, + 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, + 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2809, 2809, 2821, 2828, 2831, 2832, 2835, 2856, 2858, + 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, + 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3129, 3133, + 3133, 3160, 3162, 3168, 3169, 3200, 3200, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, + 3297, 3313, 3314, 3333, 3340, 3342, 3344, 3346, 3386, 3389, 3389, 3406, 3406, 3412, 3414, 3423, 3425, 3450, 3455, 3461, 3478, 3482, + 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, + 3749, 3751, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3807, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, + 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4295, 4295, 4301, + 4301, 4304, 4346, 4348, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, + 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, + 5759, 5761, 5786, 5792, 5866, 5870, 5880, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000, 6016, 6067, 6103, + 6103, 6108, 6108, 6176, 6264, 6272, 6312, 6314, 6314, 6320, 6389, 6400, 6430, 6480, 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6656, + 6678, 6688, 6740, 6823, 6823, 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7098, 7141, 7168, 7203, 7245, 7247, 7258, 7293, 7296, + 7304, 7312, 7354, 7357, 7359, 7401, 7404, 7406, 7411, 7413, 7414, 7418, 7418, 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, + 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, + 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455, 8458, 8467, 8469, + 8469, 8472, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, + 11312, 11358, 11360, 11492, 11499, 11502, 11506, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, + 11648, 11670, 11680, 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, + 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438, 12443, 12447, 12449, 12538, 12540, 12543, 12549, 12591, + 12593, 12686, 12704, 12730, 12784, 12799, 13312, 19893, 19968, 40943, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42527, + 42538, 42539, 42560, 42606, 42623, 42653, 42656, 42735, 42775, 42783, 42786, 42888, 42891, 42943, 42946, 42950, 42999, 43009, + 43011, 43013, 43015, 43018, 43020, 43042, 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259, 43261, 43262, 43274, 43301, + 43312, 43334, 43360, 43388, 43396, 43442, 43471, 43471, 43488, 43492, 43494, 43503, 43514, 43518, 43520, 43560, 43584, 43586, + 43588, 43595, 43616, 43638, 43642, 43642, 43646, 43695, 43697, 43697, 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714, + 43739, 43741, 43744, 43754, 43762, 43764, 43777, 43782, 43785, 43790, 43793, 43798, 43808, 43814, 43816, 43822, 43824, 43866, + 43868, 43879, 43888, 44002, 44032, 55203, 55216, 55238, 55243, 55291, 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, + 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, + 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, + 65482, 65487, 65490, 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, + 65664, 65786, 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66335, 66349, 66378, 66384, 66421, 66432, 66461, 66464, 66499, + 66504, 66511, 66513, 66517, 66560, 66717, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 67072, 67382, 67392, 67413, + 67424, 67431, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, + 67808, 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67968, 68023, 68030, 68031, 68096, 68096, 68112, 68115, 68117, 68119, + 68121, 68149, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68324, 68352, 68405, 68416, 68437, 68448, 68466, 68480, 68497, + 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68899, 69376, 69404, 69415, 69415, 69424, 69445, 69600, 69622, 69635, 69687, + 69763, 69807, 69840, 69864, 69891, 69926, 69956, 69956, 69968, 70002, 70006, 70006, 70019, 70066, 70081, 70084, 70106, 70106, + 70108, 70108, 70144, 70161, 70163, 70187, 70272, 70278, 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70366, + 70405, 70412, 70415, 70416, 70419, 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70461, 70461, 70480, 70480, 70493, 70497, + 70656, 70708, 70727, 70730, 70751, 70751, 70784, 70831, 70852, 70853, 70855, 70855, 71040, 71086, 71128, 71131, 71168, 71215, + 71236, 71236, 71296, 71338, 71352, 71352, 71424, 71450, 71680, 71723, 71840, 71903, 71935, 71935, 72096, 72103, 72106, 72144, + 72161, 72161, 72163, 72163, 72192, 72192, 72203, 72242, 72250, 72250, 72272, 72272, 72284, 72329, 72349, 72349, 72384, 72440, + 72704, 72712, 72714, 72750, 72768, 72768, 72818, 72847, 72960, 72966, 72968, 72969, 72971, 73008, 73030, 73030, 73056, 73061, + 73063, 73064, 73066, 73097, 73112, 73112, 73440, 73458, 73728, 74649, 74752, 74862, 74880, 75075, 77824, 78894, 82944, 83526, + 92160, 92728, 92736, 92766, 92880, 92909, 92928, 92975, 92992, 92995, 93027, 93047, 93053, 93071, 93760, 93823, 93952, 94026, + 94032, 94032, 94099, 94111, 94176, 94177, 94179, 94179, 94208, 100343, 100352, 101106, 110592, 110878, 110928, 110930, 110948, + 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 119808, 119892, 119894, 119964, 119966, + 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069, 120071, + 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144, 120146, + 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686, 120688, + 120712, 120714, 120744, 120746, 120770, 120772, 120779, 123136, 123180, 123191, 123197, 123214, 123214, 123584, 123627, 124928, + 125124, 125184, 125251, 125259, 125259, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, + 126514, 126516, 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, + 126543, 126545, 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, + 126562, 126564, 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, + 126619, 126625, 126627, 126629, 126633, 126635, 126651, 131072, 173782, 173824, 177972, 177984, 178205, 178208, 183969, 183984, + 191456, 194560, 195101}; vector unicodeESNextIdentifierPart = {48, 57, 65, 90, 95, 95, 97, 122, 170, 170, 181, 181, 183, 183, 186, 186, 192, 214, 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, - 750, 750, 768, 884, 886, 887, 890, 893, 895, 895, 902, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1327, 1329, - 1366, 1369, 1369, 1376, 1416, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1519, 1522, 1552, 1562, 1568, - 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2045, 2045, 2048, - 2093, 2112, 2139, 2144, 2154, 2208, 2228, 2230, 2237, 2259, 2273, 2275, 2403, 2406, 2415, 2417, 2435, 2437, 2444, 2447, 2448, 2451, - 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2556, - 2556, 2558, 2558, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, - 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, - 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2809, 2815, 2817, 2819, 2821, - 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, - 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, - 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3072, 3084, 3086, 3088, 3090, 3112, 3114, - 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3162, 3168, 3171, 3174, 3183, 3200, 3203, 3205, 3212, 3214, 3216, 3218, - 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3328, - 3331, 3333, 3340, 3342, 3344, 3346, 3396, 3398, 3400, 3402, 3406, 3412, 3415, 3423, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, - 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3558, 3567, 3570, 3571, 3585, - 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3773, 3776, 3780, 3782, 3782, 3784, - 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, - 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, - 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, - 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4969, 4977, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, 5759, 5761, - 5786, 5792, 5866, 5870, 5880, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, - 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6264, 6272, 6314, 6320, 6389, 6400, 6430, 6432, 6443, 6448, 6459, 6470, - 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6618, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6832, - 6845, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7296, 7304, 7312, 7354, 7357, 7359, 7376, - 7378, 7380, 7418, 7424, 7673, 7675, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, - 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, - 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, - 8469, 8472, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, - 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, - 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 12293, 12295, - 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12447, 12449, 12538, 12540, 12543, 12549, 12591, 12593, 12686, 12704, - 12730, 12784, 12799, 13312, 19893, 19968, 40943, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, - 42623, 42737, 42775, 42783, 42786, 42888, 42891, 42943, 42946, 42950, 42999, 43047, 43072, 43123, 43136, 43205, 43216, 43225, 43232, - 43255, 43259, 43259, 43261, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43488, 43518, 43520, 43574, 43584, 43597, - 43600, 43609, 43616, 43638, 43642, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, - 43814, 43816, 43822, 43824, 43866, 43868, 43879, 43888, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, - 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, - 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65071, 65075, 65076, 65101, 65103, - 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, - 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, 65856, 65908, - 66045, 66045, 66176, 66204, 66208, 66256, 66272, 66272, 66304, 66335, 66349, 66378, 66384, 66426, 66432, 66461, 66464, 66499, 66504, - 66511, 66513, 66517, 66560, 66717, 66720, 66729, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 67072, 67382, 67392, 67413, - 67424, 67431, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, 67808, - 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67968, 68023, 68030, 68031, 68096, 68099, 68101, 68102, 68108, 68115, 68117, 68119, - 68121, 68149, 68152, 68154, 68159, 68159, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68326, 68352, 68405, 68416, 68437, 68448, - 68466, 68480, 68497, 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68903, 68912, 68921, 69376, 69404, 69415, 69415, 69424, 69456, - 69600, 69622, 69632, 69702, 69734, 69743, 69759, 69818, 69840, 69864, 69872, 69881, 69888, 69940, 69942, 69951, 69956, 69958, 69968, - 70003, 70006, 70006, 70016, 70084, 70089, 70092, 70096, 70106, 70108, 70108, 70144, 70161, 70163, 70199, 70206, 70206, 70272, 70278, - 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70378, 70384, 70393, 70400, 70403, 70405, 70412, 70415, 70416, 70419, - 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70459, 70468, 70471, 70472, 70475, 70477, 70480, 70480, 70487, 70487, 70493, 70499, - 70502, 70508, 70512, 70516, 70656, 70730, 70736, 70745, 70750, 70751, 70784, 70853, 70855, 70855, 70864, 70873, 71040, 71093, 71096, - 71104, 71128, 71133, 71168, 71232, 71236, 71236, 71248, 71257, 71296, 71352, 71360, 71369, 71424, 71450, 71453, 71467, 71472, 71481, - 71680, 71738, 71840, 71913, 71935, 71935, 72096, 72103, 72106, 72151, 72154, 72161, 72163, 72164, 72192, 72254, 72263, 72263, 72272, - 72345, 72349, 72349, 72384, 72440, 72704, 72712, 72714, 72758, 72760, 72768, 72784, 72793, 72818, 72847, 72850, 72871, 72873, 72886, - 72960, 72966, 72968, 72969, 72971, 73014, 73018, 73018, 73020, 73021, 73023, 73031, 73040, 73049, 73056, 73061, 73063, 73064, 73066, - 73102, 73104, 73105, 73107, 73112, 73120, 73129, 73440, 73462, 73728, 74649, 74752, 74862, 74880, 75075, 77824, 78894, 82944, 83526, - 92160, 92728, 92736, 92766, 92768, 92777, 92880, 92909, 92912, 92916, 92928, 92982, 92992, 92995, 93008, 93017, 93027, 93047, 93053, - 93071, 93760, 93823, 93952, 94026, 94031, 94087, 94095, 94111, 94176, 94177, 94179, 94179, 94208, 100343, 100352, 101106, 110592, - 110878, 110928, 110930, 110948, 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 113821, - 113822, 119141, 119145, 119149, 119154, 119163, 119170, 119173, 119179, 119210, 119213, 119362, 119364, 119808, 119892, 119894, - 119964, 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, - 120069, 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, - 120144, 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, - 120686, 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, 120782, 120831, 121344, 121398, 121403, 121452, 121461, - 121461, 121476, 121476, 121499, 121503, 121505, 121519, 122880, 122886, 122888, 122904, 122907, 122913, 122915, 122916, 122918, - 122922, 123136, 123180, 123184, 123197, 123200, 123209, 123214, 123214, 123584, 123641, 124928, 125124, 125136, 125142, 125184, - 125259, 125264, 125273, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516, - 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, 126543, 126545, - 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, 126562, 126564, - 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, 126619, 126625, - 126627, 126629, 126633, 126635, 126651, 131072, 173782, 173824, 177972, 177984, 178205, 178208, 183969, 183984, 191456, 194560, - 195101, 917760, 917999}; + 750, 750, 768, 884, 886, 887, 890, 893, 895, 895, 902, 906, 908, 908, 910, 929, 931, 1013, 1015, 1153, 1155, 1159, 1162, 1327, 1329, + 1366, 1369, 1369, 1376, 1416, 1425, 1469, 1471, 1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1519, 1522, 1552, 1562, 1568, + 1641, 1646, 1747, 1749, 1756, 1759, 1768, 1770, 1788, 1791, 1791, 1808, 1866, 1869, 1969, 1984, 2037, 2042, 2042, 2045, 2045, 2048, + 2093, 2112, 2139, 2144, 2154, 2208, 2228, 2230, 2237, 2259, 2273, 2275, 2403, 2406, 2415, 2417, 2435, 2437, 2444, 2447, 2448, 2451, + 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507, 2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2545, 2556, + 2556, 2558, 2558, 2561, 2563, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, + 2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689, 2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, + 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2809, 2815, 2817, 2819, 2821, + 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876, 2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, + 2915, 2918, 2927, 2929, 2929, 2946, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, + 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031, 3031, 3046, 3055, 3072, 3084, 3086, 3088, 3090, 3112, 3114, + 3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3162, 3168, 3171, 3174, 3183, 3200, 3203, 3205, 3212, 3214, 3216, 3218, + 3240, 3242, 3251, 3253, 3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302, 3311, 3313, 3314, 3328, + 3331, 3333, 3340, 3342, 3344, 3346, 3396, 3398, 3400, 3402, 3406, 3412, 3415, 3423, 3427, 3430, 3439, 3450, 3455, 3458, 3459, 3461, + 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3558, 3567, 3570, 3571, 3585, + 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3718, 3722, 3724, 3747, 3749, 3749, 3751, 3773, 3776, 3780, 3782, 3782, 3784, + 3789, 3792, 3801, 3804, 3807, 3840, 3840, 3864, 3865, 3872, 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3948, 3953, + 3972, 3974, 3991, 3993, 4028, 4038, 4038, 4096, 4169, 4176, 4253, 4256, 4293, 4295, 4295, 4301, 4301, 4304, 4346, 4348, 4680, 4682, + 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, + 4822, 4824, 4880, 4882, 4885, 4888, 4954, 4957, 4959, 4969, 4977, 4992, 5007, 5024, 5109, 5112, 5117, 5121, 5740, 5743, 5759, 5761, + 5786, 5792, 5866, 5870, 5880, 5888, 5900, 5902, 5908, 5920, 5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, + 6103, 6108, 6109, 6112, 6121, 6155, 6157, 6160, 6169, 6176, 6264, 6272, 6314, 6320, 6389, 6400, 6430, 6432, 6443, 6448, 6459, 6470, + 6509, 6512, 6516, 6528, 6571, 6576, 6601, 6608, 6618, 6656, 6683, 6688, 6750, 6752, 6780, 6783, 6793, 6800, 6809, 6823, 6823, 6832, + 6845, 6912, 6987, 6992, 7001, 7019, 7027, 7040, 7155, 7168, 7223, 7232, 7241, 7245, 7293, 7296, 7304, 7312, 7354, 7357, 7359, 7376, + 7378, 7380, 7418, 7424, 7673, 7675, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, + 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8255, + 8256, 8276, 8276, 8305, 8305, 8319, 8319, 8336, 8348, 8400, 8412, 8417, 8417, 8421, 8432, 8450, 8450, 8455, 8455, 8458, 8467, 8469, + 8469, 8472, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8505, 8508, 8511, 8517, 8521, 8526, 8526, 8544, 8584, 11264, 11310, + 11312, 11358, 11360, 11492, 11499, 11507, 11520, 11557, 11559, 11559, 11565, 11565, 11568, 11623, 11631, 11631, 11647, 11670, 11680, + 11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734, 11736, 11742, 11744, 11775, 12293, 12295, + 12321, 12335, 12337, 12341, 12344, 12348, 12353, 12438, 12441, 12447, 12449, 12538, 12540, 12543, 12549, 12591, 12593, 12686, 12704, + 12730, 12784, 12799, 13312, 19893, 19968, 40943, 40960, 42124, 42192, 42237, 42240, 42508, 42512, 42539, 42560, 42607, 42612, 42621, + 42623, 42737, 42775, 42783, 42786, 42888, 42891, 42943, 42946, 42950, 42999, 43047, 43072, 43123, 43136, 43205, 43216, 43225, 43232, + 43255, 43259, 43259, 43261, 43309, 43312, 43347, 43360, 43388, 43392, 43456, 43471, 43481, 43488, 43518, 43520, 43574, 43584, 43597, + 43600, 43609, 43616, 43638, 43642, 43714, 43739, 43741, 43744, 43759, 43762, 43766, 43777, 43782, 43785, 43790, 43793, 43798, 43808, + 43814, 43816, 43822, 43824, 43866, 43868, 43879, 43888, 44010, 44012, 44013, 44016, 44025, 44032, 55203, 55216, 55238, 55243, 55291, + 63744, 64109, 64112, 64217, 64256, 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, + 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65024, 65039, 65056, 65071, 65075, 65076, 65101, 65103, + 65136, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65382, 65470, 65474, 65479, 65482, 65487, 65490, + 65495, 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594, 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786, 65856, 65908, + 66045, 66045, 66176, 66204, 66208, 66256, 66272, 66272, 66304, 66335, 66349, 66378, 66384, 66426, 66432, 66461, 66464, 66499, 66504, + 66511, 66513, 66517, 66560, 66717, 66720, 66729, 66736, 66771, 66776, 66811, 66816, 66855, 66864, 66915, 67072, 67382, 67392, 67413, + 67424, 67431, 67584, 67589, 67592, 67592, 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669, 67680, 67702, 67712, 67742, 67808, + 67826, 67828, 67829, 67840, 67861, 67872, 67897, 67968, 68023, 68030, 68031, 68096, 68099, 68101, 68102, 68108, 68115, 68117, 68119, + 68121, 68149, 68152, 68154, 68159, 68159, 68192, 68220, 68224, 68252, 68288, 68295, 68297, 68326, 68352, 68405, 68416, 68437, 68448, + 68466, 68480, 68497, 68608, 68680, 68736, 68786, 68800, 68850, 68864, 68903, 68912, 68921, 69376, 69404, 69415, 69415, 69424, 69456, + 69600, 69622, 69632, 69702, 69734, 69743, 69759, 69818, 69840, 69864, 69872, 69881, 69888, 69940, 69942, 69951, 69956, 69958, 69968, + 70003, 70006, 70006, 70016, 70084, 70089, 70092, 70096, 70106, 70108, 70108, 70144, 70161, 70163, 70199, 70206, 70206, 70272, 70278, + 70280, 70280, 70282, 70285, 70287, 70301, 70303, 70312, 70320, 70378, 70384, 70393, 70400, 70403, 70405, 70412, 70415, 70416, 70419, + 70440, 70442, 70448, 70450, 70451, 70453, 70457, 70459, 70468, 70471, 70472, 70475, 70477, 70480, 70480, 70487, 70487, 70493, 70499, + 70502, 70508, 70512, 70516, 70656, 70730, 70736, 70745, 70750, 70751, 70784, 70853, 70855, 70855, 70864, 70873, 71040, 71093, 71096, + 71104, 71128, 71133, 71168, 71232, 71236, 71236, 71248, 71257, 71296, 71352, 71360, 71369, 71424, 71450, 71453, 71467, 71472, 71481, + 71680, 71738, 71840, 71913, 71935, 71935, 72096, 72103, 72106, 72151, 72154, 72161, 72163, 72164, 72192, 72254, 72263, 72263, 72272, + 72345, 72349, 72349, 72384, 72440, 72704, 72712, 72714, 72758, 72760, 72768, 72784, 72793, 72818, 72847, 72850, 72871, 72873, 72886, + 72960, 72966, 72968, 72969, 72971, 73014, 73018, 73018, 73020, 73021, 73023, 73031, 73040, 73049, 73056, 73061, 73063, 73064, 73066, + 73102, 73104, 73105, 73107, 73112, 73120, 73129, 73440, 73462, 73728, 74649, 74752, 74862, 74880, 75075, 77824, 78894, 82944, 83526, + 92160, 92728, 92736, 92766, 92768, 92777, 92880, 92909, 92912, 92916, 92928, 92982, 92992, 92995, 93008, 93017, 93027, 93047, 93053, + 93071, 93760, 93823, 93952, 94026, 94031, 94087, 94095, 94111, 94176, 94177, 94179, 94179, 94208, 100343, 100352, 101106, 110592, + 110878, 110928, 110930, 110948, 110951, 110960, 111355, 113664, 113770, 113776, 113788, 113792, 113800, 113808, 113817, 113821, + 113822, 119141, 119145, 119149, 119154, 119163, 119170, 119173, 119179, 119210, 119213, 119362, 119364, 119808, 119892, 119894, + 119964, 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980, 119982, 119993, 119995, 119995, 119997, 120003, 120005, + 120069, 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121, 120123, 120126, 120128, 120132, 120134, 120134, 120138, + 120144, 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570, 120572, 120596, 120598, 120628, 120630, 120654, 120656, + 120686, 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779, 120782, 120831, 121344, 121398, 121403, 121452, 121461, + 121461, 121476, 121476, 121499, 121503, 121505, 121519, 122880, 122886, 122888, 122904, 122907, 122913, 122915, 122916, 122918, + 122922, 123136, 123180, 123184, 123197, 123200, 123209, 123214, 123214, 123584, 123641, 124928, 125124, 125136, 125142, 125184, + 125259, 125264, 125273, 126464, 126467, 126469, 126495, 126497, 126498, 126500, 126500, 126503, 126503, 126505, 126514, 126516, + 126519, 126521, 126521, 126523, 126523, 126530, 126530, 126535, 126535, 126537, 126537, 126539, 126539, 126541, 126543, 126545, + 126546, 126548, 126548, 126551, 126551, 126553, 126553, 126555, 126555, 126557, 126557, 126559, 126559, 126561, 126562, 126564, + 126564, 126567, 126570, 126572, 126578, 126580, 126583, 126585, 126588, 126590, 126590, 126592, 126601, 126603, 126619, 126625, + 126627, 126629, 126633, 126635, 126651, 131072, 173782, 173824, 177972, 177984, 178205, 178208, 183969, 183984, 191456, 194560, + 195101, 917760, 917999}; /** * Test for whether a single line comment with leading whitespace trimmed's text contains a directive. @@ -838,7 +837,7 @@ bool isConflictMarkerTrivia(const string text, int pos) { auto ch = charCodeAt(text, pos); if ((pos + mergeConflictMarkerLength) < text.size()) { - for (int i = 0; i < mergeConflictMarkerLength; i++) { + for (int i = 0; i < mergeConflictMarkerLength; i ++) { if (charCodeAt(text, pos + i).code != ch.code) { return false; } @@ -852,7 +851,7 @@ bool isConflictMarkerTrivia(const string text, int pos) { } int Scanner::error(DiagnosticMessage message, int errPos, int length) { - if (errPos == -1) errPos = pos; + if (errPos == - 1) errPos = pos; cout << "Error: " << message.code << ": " << message.message << " at " << errPos << "\n"; @@ -861,33 +860,36 @@ int Scanner::error(DiagnosticMessage message, int errPos, int length) { } } -int Scanner::scanConflictMarkerTrivia(string &text, int pos) { - error(Diagnostics::Merge_conflict_marker_encountered, pos, mergeConflictMarkerLength); - +int scanConflictMarkerTrivia(string &text, int pos) { auto ch = charCodeAt(text, pos); auto len = text.size(); if (ch.code == CharacterCodes::lessThan || ch.code == CharacterCodes::greaterThan) { - while (pos < len && !isLineBreak(charCodeAt(text, pos))) { - pos++; + while (pos < len && ! isLineBreak(charCodeAt(text, pos))) { + pos ++; } } else { assert(ch.code == CharacterCodes::bar || ch.code == CharacterCodes::equals); - // Consume everything from the start of a ||||||| or ======= marker to the start - // of the next ======= or >>>>>>> marker. + // Consume everything from the start of a ||||||| or ===== marker to the start + // of the next ===== or >>>>>>> marker. while (pos < len) { auto currentChar = charCodeAt(text, pos); if ((currentChar.code == CharacterCodes::equals || currentChar.code == CharacterCodes::greaterThan) && currentChar.code != ch.code && isConflictMarkerTrivia(text, pos)) { break; } - pos++; + pos ++; } } return pos; } +int Scanner::scanConflictMarkerTrivia(string &text, int pos) { + error(Diagnostics::Merge_conflict_marker_encountered, pos, mergeConflictMarkerLength); + return scanConflictMarkerTrivia(text, pos); +} + bool lookupInUnicodeMap(CharCode code, vector &map) { // Bail out quickly if it couldn't possibly be in the map. if (code.code < map[0]) { @@ -934,15 +936,125 @@ bool isUnicodeIdentifierPart(CharCode ch, ScriptTarget languageVersion) { bool isIdentifierStart(CharCode ch, ScriptTarget languageVersion) { return (ch.code >= CharacterCodes::A && ch.code <= CharacterCodes::Z) || (ch.code >= CharacterCodes::a && ch.code <= CharacterCodes::z) || ch.code == CharacterCodes::$ || ch.code == CharacterCodes::_ || - (ch.code > CharacterCodes::maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion)); + (ch.code > CharacterCodes::maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion)); } bool isIdentifierPart(CharCode ch, ScriptTarget languageVersion, LanguageVariant identifierVariant = LanguageVariant::Standard) { return (ch.code >= CharacterCodes::A && ch.code <= CharacterCodes::Z) || (ch.code >= CharacterCodes::a && ch.code <= CharacterCodes::z) || - (ch.code >= CharacterCodes::_0 && ch.code <= CharacterCodes::_9) || ch.code == CharacterCodes::$ || ch.code == CharacterCodes::_ || + (ch.code >= CharacterCodes::_0 && ch.code <= CharacterCodes::_9) || ch.code == CharacterCodes::$ || ch.code == CharacterCodes::_ || // "-" and ":" are valid in JSX Identifiers (identifierVariant == LanguageVariant::JSX ? (ch.code == CharacterCodes::minus || ch.code == CharacterCodes::colon) : false) || - (ch.code > CharacterCodes::maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion)); + (ch.code > CharacterCodes::maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion)); +} + +const regex shebangTriviaRegex("^#!.*"); + +int scanShebangTrivia(const string &text, int pos) { + smatch m; + if (regex_search(text, m, shebangTriviaRegex)) { + pos = pos + m[1].length(); + } + return pos; +} + +bool isWhiteSpaceLike(CharCode ch) { + return isWhiteSpaceSingleLine(ch) || isLineBreak(ch); +} + +/* @internal */ +int skipTrivia(string &text, int pos, optional stopAfterLineBreak, optional stopAtComments, optional inJSDoc) { + if (positionIsSynthesized(pos)) { + return pos; + } + + auto canConsumeStar = false; + // Keep in sync with couldStartTrivia + while (true) { + auto ch = charCodeAt(text, pos); + switch (ch.code) { + case CharacterCodes::carriageReturn: + if (charCodeAt(text, pos + 1).code == CharacterCodes::lineFeed) { + pos++; + } + // falls through + case CharacterCodes::lineFeed: + pos++; + if (stopAfterLineBreak && *stopAfterLineBreak) { + return pos; + } + canConsumeStar = inJSDoc && *inJSDoc; + continue; + case CharacterCodes::tab: + case CharacterCodes::verticalTab: + case CharacterCodes::formFeed: + case CharacterCodes::space: + pos++; + continue; + case CharacterCodes::slash: + if (stopAtComments && *stopAtComments) { + break; + } + if (charCodeAt(text, pos + 1).code == CharacterCodes::slash) { + pos += 2; + while (pos < text.size()) { + if (isLineBreak(charCodeAt(text, pos))) { + break; + } + pos++; + } + canConsumeStar = false; + continue; + } + if (charCodeAt(text, pos + 1).code == CharacterCodes::asterisk) { + pos += 2; + while (pos < text.size()) { + if (charCodeAt(text, pos).code == CharacterCodes::asterisk && charCodeAt(text, pos + 1).code == CharacterCodes::slash) { + pos += 2; + break; + } + pos++; + } + canConsumeStar = false; + continue; + } + break; + + case CharacterCodes::lessThan: + case CharacterCodes::bar: + case CharacterCodes::equals: + case CharacterCodes::greaterThan: + if (isConflictMarkerTrivia(text, pos)) { + pos = scanConflictMarkerTrivia(text, pos); + canConsumeStar = false; + continue; + } + break; + + case CharacterCodes::hash: + if (pos == 0 && isShebangTrivia(text, pos)) { + pos = scanShebangTrivia(text, pos); + canConsumeStar = false; + continue; + } + break; + + case CharacterCodes::asterisk: + if (canConsumeStar) { + pos++; + canConsumeStar = false; + continue; + } + break; + + default: + if (ch.code > CharacterCodes::maxAsciiCharacter && (isWhiteSpaceLike(ch))) { + pos++; + continue; + } + break; + } + return pos; + } } CharCode Scanner::peekExtendedUnicodeEscape() { @@ -950,11 +1062,11 @@ CharCode Scanner::peekExtendedUnicodeEscape() { auto start = pos; pos += 3; auto escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); - auto escapedValue = escapedValueString.size() ? stoi(escapedValueString, nullptr, 16) : -1; + auto escapedValue = escapedValueString.size() ? stoi(escapedValueString, nullptr, 16) : - 1; pos = start; return {escapedValue, 1}; } - return {-1, 0}; + return {- 1, 0}; } CharCode Scanner::peekUnicodeEscape() { @@ -965,7 +1077,7 @@ CharCode Scanner::peekUnicodeEscape() { pos = start; return {value, 1}; } - return {-1, 0}; + return {- 1, 0}; } string Scanner::scanIdentifierParts() { @@ -985,11 +1097,11 @@ string Scanner::scanIdentifierParts() { continue; } ch = peekUnicodeEscape(); - if (!(ch.code >= 0 && isIdentifierPart(ch, languageVersion))) { + if (! (ch.code >= 0 && isIdentifierPart(ch, languageVersion))) { break; } tokenFlags |= TokenFlags::UnicodeEscape; - result += text.substr(start, pos); + result += substr(text, start, pos); result += fromCharCode(ch.code); // Valid Unicode escape is always six characters pos += 6; @@ -998,12 +1110,12 @@ string Scanner::scanIdentifierParts() { break; } } - result += text.substr(start, pos); + result += substr(text, start, pos); return result; } void Scanner::checkForIdentifierStartAfterNumericLiteral(int numericStart, bool isScientific) { - if (!isIdentifierStart(charCodeAt(text, pos), languageVersion)) { + if (! isIdentifierStart(charCodeAt(text, pos), languageVersion)) { return; } @@ -1029,15 +1141,15 @@ SyntaxKind Scanner::checkBigIntSuffix() { if (tokenFlags & TokenFlags::BinaryOrOctalSpecifier) { tokenValue = parsePseudoBigInt(tokenValue) + "n"; } - pos++; + pos ++; return SyntaxKind::BigIntLiteral; } else { // not a bigint, so can convert to number in simplified form // Number() may not support 0b or 0o, so use parseInt() instead auto numericValue = tokenFlags & TokenFlags::BinarySpecifier - ? stoi(tokenValue.substr(2), 0, 2) // skip "0b" + ? stoi(substr(tokenValue, 2), 0, 2) // skip "0b" : tokenFlags & TokenFlags::OctalSpecifier - ? stoi(tokenValue.substr(2), 0, 8) // skip "0o" + ? stoi(substr(tokenValue, 2), 0, 8) // skip "0o" : stoi(tokenValue); tokenValue = "" + std::to_string(numericValue); return SyntaxKind::NumericLiteral; @@ -1052,6 +1164,127 @@ optional getDirectiveFromComment(const string &text, const } } +SyntaxKind Scanner::scanJsxAttributeValue() { + startPos = pos; + + switch (charCodeAt(text, pos).code) { + case CharacterCodes::doubleQuote: + case CharacterCodes::singleQuote: + tokenValue = scanString(/*jsxAttributeString*/ true); + return token = SyntaxKind::StringLiteral; + default: + // If this scans anything other than `{`, it's a parse error. + return scan(); + } +} + +SyntaxKind Scanner::scanJsxIdentifier() { + if (tokenIsIdentifierOrKeyword(token)) { + // An identifier or keyword has already been parsed - check for a `-` or a single instance of `:` and then append it and + // everything after it to the token + // Do note that this means that `scanJsxIdentifier` effectively _mutates_ the visible token without advancing to a new token + // Any caller should be expecting this behavior and should only read the pos or token value after calling it. + auto namespaceSeparator = false; + while (pos < end) { + auto ch = charCodeAt(text, pos); + if (ch.code == CharacterCodes::minus) { + tokenValue += "-"; + pos ++; + continue; + } else if (ch.code == CharacterCodes::colon && ! namespaceSeparator) { + tokenValue += ":"; + pos ++; + namespaceSeparator = true; + token = SyntaxKind::Identifier; // swap from keyword kind to identifier kind + continue; + } + auto oldPos = pos; + tokenValue += scanIdentifierParts(); // reuse `scanIdentifierParts` so unicode escapes are handled + if (pos == oldPos) { + break; + } + } + // Do not include a trailing namespace separator in the token, since this is against the spec. + if (substr(tokenValue, - 1) == ":") { + tokenValue = substr(tokenValue, 0, - 1); + pos --; + } + return getIdentifierToken(); + } + return token; +} + +SyntaxKind Scanner::scanJsxToken(bool allowMultilineJsxText) { + startPos = tokenPos = pos; + + if (pos >= end) { + return token = SyntaxKind::EndOfFileToken; + } + + auto charCode = charCodeAt(text, pos); + if (charCode.code == CharacterCodes::lessThan) { + if (charCodeAt(text, pos + 1).code == CharacterCodes::slash) { + pos += 2; + return token = SyntaxKind::LessThanSlashToken; + } + pos ++; + return token = SyntaxKind::LessThanToken; + } + + if (charCode.code == CharacterCodes::openBrace) { + pos ++; + return token = SyntaxKind::OpenBraceToken; + } + + // First non-whitespace character on this line. + int firstNonWhitespace = 0; + + // These initial values are special because the first line is: + // firstNonWhitespace = 0 to indicate that we want leading whitespace, + + while (pos < end) { + charCode = charCodeAt(text, pos); + if (charCode.code == CharacterCodes::openBrace) { + break; + } + if (charCode.code == CharacterCodes::lessThan) { + if (isConflictMarkerTrivia(text, pos)) { + pos = scanConflictMarkerTrivia(text, pos); + return token = SyntaxKind::ConflictMarkerTrivia; + } + break; + } + if (charCode.code == CharacterCodes::greaterThan) { + error(Diagnostics::Unexpected_token_Did_you_mean_or_gt, pos, 1); + } + if (charCode.code == CharacterCodes::closeBrace) { + error(Diagnostics::Unexpected_token_Did_you_mean_or_rbrace, pos, 1); + } + + // FirstNonWhitespace is 0, then we only see whitespaces so far. If we see a linebreak, we want to ignore that whitespaces. + // i.e (- : whitespace) + //
---- + //
becomes
+ // + //
----
becomes
----
+ if (isLineBreak(charCode) && firstNonWhitespace == 0) { + firstNonWhitespace = - 1; + } else if (! allowMultilineJsxText && isLineBreak(charCode) && firstNonWhitespace > 0) { + // Stop JsxText on each line during formatting. This allows the formatter to + // indent each line correctly. + break; + } else if (! isWhiteSpaceLike(charCode)) { + firstNonWhitespace = pos; + } + + pos ++; + } + + tokenValue = substr(text, startPos, pos); + + return firstNonWhitespace == - 1 ? SyntaxKind::JsxTextAllWhiteSpaces : SyntaxKind::JsxText; +} + vector Scanner::appendIfCommentDirective( vector &commentDirectives, const string &text, @@ -1059,7 +1292,7 @@ vector Scanner::appendIfCommentDirective( int lineStart ) { auto type = getDirectiveFromComment(trimStringStart(text), commentDirectiveRegEx); - if (!type.has_value()) { + if (! type.has_value()) { return commentDirectives; } @@ -1075,21 +1308,21 @@ ScanNumber Scanner::scanNumber() { string scientificFragment; bool scientificFragmentSet = false; if (charCodeAt(text, pos).code == CharacterCodes::dot) { - pos++; + pos ++; decimalFragment = scanNumberFragment(); decimalFragmentSet = true; } auto end = pos; if (charCodeAt(text, pos).code == CharacterCodes::E || charCodeAt(text, pos).code == CharacterCodes::e) { - pos++; + pos ++; tokenFlags |= TokenFlags::Scientific; - if (charCodeAt(text, pos).code == CharacterCodes::plus || charCodeAt(text, pos).code == CharacterCodes::minus) pos++; + if (charCodeAt(text, pos).code == CharacterCodes::plus || charCodeAt(text, pos).code == CharacterCodes::minus) pos ++; auto preNumericPart = pos; auto finalFragment = scanNumberFragment(); - if (!finalFragment.size()) { + if (! finalFragment.size()) { // error(Diagnostics::Digit_expected); } else { - scientificFragment = text.substr(end, preNumericPart) + finalFragment; + scientificFragment = substr(text, end, preNumericPart) + finalFragment; scientificFragmentSet = true; end = pos; } @@ -1104,11 +1337,11 @@ ScanNumber Scanner::scanNumber() { result += scientificFragment; } } else { - result = text.substr(start, end); // No need to use all the fragments; no _ removal needed + result = substr(text, start, end); // No need to use all the fragments; no _ removal needed } if (decimalFragmentSet || tokenFlags & TokenFlags::Scientific) { - checkForIdentifierStartAfterNumericLiteral(start, !decimalFragmentSet && !!(tokenFlags & TokenFlags::Scientific)); + checkForIdentifierStartAfterNumericLiteral(start, ! decimalFragmentSet && ! ! (tokenFlags & TokenFlags::Scientific)); return { .type = SyntaxKind::NumericLiteral, .value = "" + stoi(result) // if value is not an integer, it can be safely coerced to a number @@ -1140,15 +1373,15 @@ string Scanner::scanBinaryOrOctalDigits(int base) { } else { // error(Diagnostics::Numeric_separators_are_not_allowed_here, pos, 1); } - pos++; + pos ++; continue; } separatorAllowed = true; - if (!isDigit(ch) || ch.code - CharacterCodes::_0 >= base) { + if (! isDigit(ch) || ch.code - CharacterCodes::_0 >= base) { break; } value += text[pos]; - pos++; + pos ++; isPreviousTokenSeparator = false; } if (charCodeAt(text, pos - 1).code == CharacterCodes::_) { @@ -1178,22 +1411,13 @@ SyntaxKind Scanner::scanIdentifier(CharCode startCharacter, ScriptTarget languag if (isIdentifierStart(ch, languageVersion)) { pos += ch.length; while (pos < end && isIdentifierPart(ch = charCodeAt(text, pos), languageVersion)) pos += ch.length; - tokenValue = text.substr(tokenPos, pos); + tokenValue = substr(text, tokenPos, pos); if (ch.code == CharacterCodes::backslash) { tokenValue += scanIdentifierParts(); } return getIdentifierToken(); } -} - -const regex shebangTriviaRegex("^#!.*"); - -int scanShebangTrivia(const string &text, int pos) { - smatch m; - if (regex_search(text, m, shebangTriviaRegex)) { - pos = pos + m[1].length(); - } - return pos; + return SyntaxKind::Unknown; } SyntaxKind Scanner::scan() { @@ -1225,7 +1449,7 @@ SyntaxKind Scanner::scan() { case CharacterCodes::carriageReturn: tokenFlags |= TokenFlags::PrecedingLineBreak; if (skipTrivia) { - pos++; + pos ++; continue; } else { if (ch.code == CharacterCodes::carriageReturn && pos + 1 < end && @@ -1233,7 +1457,7 @@ SyntaxKind Scanner::scan() { // consume both CR and LF pos += 2; } else { - pos++; + pos ++; } return token = SyntaxKind::NewLineTrivia; } @@ -1262,7 +1486,7 @@ SyntaxKind Scanner::scan() { case CharacterCodes::ideographicSpace: case CharacterCodes::byteOrderMark: if (skipTrivia) { - pos++; + pos ++; continue; } else { int size; @@ -1278,7 +1502,7 @@ SyntaxKind Scanner::scan() { } return pos += 2, token = SyntaxKind::ExclamationEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::ExclamationToken; case CharacterCodes::doubleQuote: case CharacterCodes::singleQuote: @@ -1290,7 +1514,7 @@ SyntaxKind Scanner::scan() { if (charCodeAt(text, pos + 1).code == CharacterCodes::equals) { return pos += 2, token = SyntaxKind::PercentEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::PercentToken; case CharacterCodes::ampersand: if (charCodeAt(text, pos + 1).code == CharacterCodes::ampersand) { @@ -1302,13 +1526,13 @@ SyntaxKind Scanner::scan() { if (charCodeAt(text, pos + 1).code == CharacterCodes::equals) { return pos += 2, token = SyntaxKind::AmpersandEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::AmpersandToken; case CharacterCodes::openParen: - pos++; + pos ++; return token = SyntaxKind::OpenParenToken; case CharacterCodes::closeParen: - pos++; + pos ++; return token = SyntaxKind::CloseParenToken; case CharacterCodes::asterisk: if (charCodeAt(text, pos + 1).code == CharacterCodes::equals) { @@ -1320,8 +1544,8 @@ SyntaxKind Scanner::scan() { } return pos += 2, token = SyntaxKind::AsteriskAsteriskToken; } - pos++; - if (inJSDocType && !asteriskSeen && (tokenFlags & TokenFlags::PrecedingLineBreak)) { + pos ++; + if (inJSDocType && ! asteriskSeen && (tokenFlags & TokenFlags::PrecedingLineBreak)) { // decoration at the start of a JSDoc comment line asteriskSeen = true; continue; @@ -1334,10 +1558,10 @@ SyntaxKind Scanner::scan() { if (charCodeAt(text, pos + 1).code == CharacterCodes::equals) { return pos += 2, token = SyntaxKind::PlusEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::PlusToken; case CharacterCodes::comma: - pos++; + pos ++; return token = SyntaxKind::CommaToken; case CharacterCodes::minus: if (charCodeAt(text, pos + 1).code == CharacterCodes::minus) { @@ -1346,7 +1570,7 @@ SyntaxKind Scanner::scan() { if (charCodeAt(text, pos + 1).code == CharacterCodes::equals) { return pos += 2, token = SyntaxKind::MinusEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::MinusToken; case CharacterCodes::dot: if (isDigit(charCodeAt(text, pos + 1))) { @@ -1356,7 +1580,7 @@ SyntaxKind Scanner::scan() { if (charCodeAt(text, pos + 1).code == CharacterCodes::dot && charCodeAt(text, pos + 2).code == CharacterCodes::dot) { return pos += 3, token = SyntaxKind::DotDotDotToken; } - pos++; + pos ++; return token = SyntaxKind::DotToken; case CharacterCodes::slash: // Single-line comment @@ -1367,12 +1591,12 @@ SyntaxKind Scanner::scan() { if (isLineBreak(charCodeAt(text, pos))) { break; } - pos++; + pos ++; } commentDirectives = appendIfCommentDirective( commentDirectives, - text.substr(tokenPos, pos), + substr(text, tokenPos, pos), commentDirectiveRegExSingleLine, tokenPos ); @@ -1401,7 +1625,7 @@ SyntaxKind Scanner::scan() { break; } - pos++; + pos ++; if (isLineBreak(ch)) { lastLineStart = pos; @@ -1409,17 +1633,17 @@ SyntaxKind Scanner::scan() { } } - commentDirectives = appendIfCommentDirective(commentDirectives, text.substr(lastLineStart, pos), + commentDirectives = appendIfCommentDirective(commentDirectives, substr(text, lastLineStart, pos), commentDirectiveRegExMultiLine, lastLineStart); - if (!commentClosed) { + if (! commentClosed) { // error(Diagnostics::Asterisk_Slash_expected); } if (skipTrivia) { continue; } else { - if (!commentClosed) { + if (! commentClosed) { tokenFlags |= TokenFlags::Unterminated; } return token = SyntaxKind::MultiLineCommentTrivia; @@ -1430,7 +1654,7 @@ SyntaxKind Scanner::scan() { return pos += 2, token = SyntaxKind::SlashEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::SlashToken; case CharacterCodes::_0: @@ -1492,10 +1716,10 @@ SyntaxKind Scanner::scan() { return token; } case CharacterCodes::colon: - pos++; + pos ++; return token = SyntaxKind::ColonToken; case CharacterCodes::semicolon: - pos++; + pos ++; return token = SyntaxKind::SemicolonToken; case CharacterCodes::lessThan: if (isConflictMarkerTrivia(text, pos)) { @@ -1521,7 +1745,7 @@ SyntaxKind Scanner::scan() { charCodeAt(text, pos + 2).code != CharacterCodes::asterisk) { return pos += 2, token = SyntaxKind::LessThanSlashToken; } - pos++; + pos ++; return token = SyntaxKind::LessThanToken; case CharacterCodes::equals: if (isConflictMarkerTrivia(text, pos)) { @@ -1542,7 +1766,7 @@ SyntaxKind Scanner::scan() { if (charCodeAt(text, pos + 1).code == CharacterCodes::greaterThan) { return pos += 2, token = SyntaxKind::EqualsGreaterThanToken; } - pos++; + pos ++; return token = SyntaxKind::EqualsToken; case CharacterCodes::greaterThan: if (isConflictMarkerTrivia(text, pos)) { @@ -1554,10 +1778,10 @@ SyntaxKind Scanner::scan() { } } - pos++; + pos ++; return token = SyntaxKind::GreaterThanToken; case CharacterCodes::question: - if (charCodeAt(text, pos + 1).code == CharacterCodes::dot && !isDigit(charCodeAt(text, pos + 2))) { + if (charCodeAt(text, pos + 1).code == CharacterCodes::dot && ! isDigit(charCodeAt(text, pos + 2))) { return pos += 2, token = SyntaxKind::QuestionDotToken; } if (charCodeAt(text, pos + 1).code == CharacterCodes::question) { @@ -1566,22 +1790,22 @@ SyntaxKind Scanner::scan() { } return pos += 2, token = SyntaxKind::QuestionQuestionToken; } - pos++; + pos ++; return token = SyntaxKind::QuestionToken; case CharacterCodes::openBracket: - pos++; + pos ++; return token = SyntaxKind::OpenBracketToken; case CharacterCodes::closeBracket: - pos++; + pos ++; return token = SyntaxKind::CloseBracketToken; case CharacterCodes::caret: if (charCodeAt(text, pos + 1).code == CharacterCodes::equals) { return pos += 2, token = SyntaxKind::CaretEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::CaretToken; case CharacterCodes::openBrace: - pos++; + pos ++; return token = SyntaxKind::OpenBraceToken; case CharacterCodes::bar: if (isConflictMarkerTrivia(text, pos)) { @@ -1602,16 +1826,16 @@ SyntaxKind Scanner::scan() { if (charCodeAt(text, pos + 1).code == CharacterCodes::equals) { return pos += 2, token = SyntaxKind::BarEqualsToken; } - pos++; + pos ++; return token = SyntaxKind::BarToken; case CharacterCodes::closeBrace: - pos++; + pos ++; return token = SyntaxKind::CloseBraceToken; case CharacterCodes::tilde: - pos++; + pos ++; return token = SyntaxKind::TildeToken; case CharacterCodes::at: - pos++; + pos ++; return token = SyntaxKind::AtToken; case CharacterCodes::backslash: { auto extendedCookedChar = peekExtendedUnicodeEscape(); @@ -1631,27 +1855,27 @@ SyntaxKind Scanner::scan() { } error(Diagnostics::Invalid_character); - pos++; + pos ++; return token = SyntaxKind::Unknown; } case CharacterCodes::hash: if (pos != 0 && text[pos + 1] == '!') { error(Diagnostics::can_only_be_used_at_the_start_of_a_file); - pos++; + pos ++; return token = SyntaxKind::Unknown; } if (isIdentifierStart(charCodeAt(text, pos + 1), languageVersion)) { - pos++; + pos ++; scanIdentifier(charCodeAt(text, pos), languageVersion); } else { tokenValue = fromCharCode(charCodeAt(text, pos).code); - error(Diagnostics::Invalid_character, pos++, ch.length); + error(Diagnostics::Invalid_character, pos ++, ch.length); } return token = SyntaxKind::PrivateIdentifier; default: { auto identifierKind = scanIdentifier(ch, languageVersion); - if (identifierKind) { + if (identifierKind != SyntaxKind::Unknown) { return token = identifierKind; } else if (isWhiteSpaceSingleLine(ch)) { pos += ch.length; @@ -1679,19 +1903,45 @@ bool Scanner::isOctalDigit(CharCode ch) { int Scanner::scanOctalDigits() { auto start = pos; while (isOctalDigit(charCodeAt(text, pos))) { - pos++; + pos ++; } - return stoi(text.substr(start, pos)); + return stoi(substr(text, start, pos)); } -bool Scanner::lookAhead(function callback) { - return speculationHelper(callback, /*isLookahead*/ true); +template +T Scanner::lookAhead(function callback) { + return speculationHelper(callback, /*isLookahead*/ true); } -bool Scanner::tryScan(function callback) { - return speculationHelper(callback, /*isLookahead*/ false); +template +T Scanner::tryScan(function callback) { + return speculationHelper(callback, /*isLookahead*/ false); } -bool Scanner::speculationHelper(function callback, bool isLookahead) { - return false; +template +T Scanner::speculationHelper(function callback, bool isLookahead) { + auto savePos = pos; + auto saveStartPos = startPos; + auto saveTokenPos = tokenPos; + auto saveToken = token; + auto saveTokenValue = tokenValue; + auto saveTokenFlags = tokenFlags; + auto result = callback(); + + // If our callback returned something 'falsy' or we're just looking ahead, + // then unconditionally restore us to where we were. + if (! result || isLookahead) { + pos = savePos; + startPos = saveStartPos; + tokenPos = saveTokenPos; + token = saveToken; + tokenValue = saveTokenValue; + tokenFlags = saveTokenFlags; + } + return result;; +} + +SyntaxKind Scanner::reScanJsxToken(bool allowMultilineJsxText) { + pos = tokenPos = startPos; + return token = scanJsxToken(allowMultilineJsxText); }; \ No newline at end of file diff --git a/src/scanner.h b/src/scanner.h index f25b3b6..b81eccd 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -15,10 +15,12 @@ namespace ts { string value; }; using ErrorCallback = function< - void(DiagnosticMessage - message, - int length - )>; + void(DiagnosticMessage + message, + int length + )>; + + int skipTrivia(string &text, int pos, optional stopAfterLineBreak = {}, optional stopAtComments = {}, optional inJSDoc = {}); /** @internal */ static unordered_map textToKeywordObj{ @@ -175,6 +177,13 @@ namespace ts { return get(textToToken, s); } + static auto tokenStrings = reverse(textToToken); + + /* @internal */ + static optional tokenToString(SyntaxKind t) { + return get(tokenStrings, t); + } + /* @internal */ static bool tokenIsIdentifierOrKeyword(SyntaxKind token) { return token >= SyntaxKind::Identifier; @@ -291,20 +300,36 @@ namespace ts { return startPos; } - bool lookAhead(function callback); + template + T lookAhead(function callback); - bool tryScan(function callback); + template + T tryScan(function callback); - bool speculationHelper(function callback, bool isLookahead); + template + T speculationHelper(function callback, bool isLookahead); bool hasPrecedingLineBreak() { return (tokenFlags & TokenFlags::PrecedingLineBreak) != 0; } + int getTokenFlags() { return tokenFlags; } + + bool isUnterminated() { + return (tokenFlags & (int) TokenFlags::Unterminated) != 0; + } + bool isReservedWord() { return token >= SyntaxKind::FirstReservedWord && token <= SyntaxKind::LastReservedWord; } + int getNumericLiteralFlags() { return tokenFlags & (int) TokenFlags::NumericLiteralFlags; } + + SyntaxKind scanJsxToken(bool allowMultilineJsxText = true); + SyntaxKind scanJsxAttributeValue(); + SyntaxKind scanJsxIdentifier(); + SyntaxKind reScanJsxToken(bool allowMultilineJsxText = false); + string getTokenText() { return text.substr(tokenPos, pos); } @@ -315,7 +340,7 @@ namespace ts { tokenFlags = 0; auto ch = charCodeAt(text, pos); auto identifierKind = scanIdentifier(ch, ScriptTarget::ESNext); - if (identifierKind) { + if (identifierKind != SyntaxKind::Unknown) { return token = identifierKind; } pos += ch.length; diff --git a/src/tests/test_core.cpp b/src/tests/test_core.cpp index f5df3c7..e779a38 100644 --- a/src/tests/test_core.cpp +++ b/src/tests/test_core.cpp @@ -328,6 +328,24 @@ TEST(core, replaceLeading) { TEST(core, stringReplace) { EXPECT_EQ(replaceAll("this/is/a/path", "/", "_"), "this_is_a_path"); + EXPECT_EQ(replaceAll("this/is/a/path", "/", "/"), "this/is/a/path"); +} + +TEST(core, endsWith) { + EXPECT_EQ(endsWith("this/is/a/path", "asd"), false); + EXPECT_EQ(endsWith("this/is/a/path", "/path"), true); +} + +TEST(core, startsWith) { + EXPECT_EQ(startsWith("this/is/a/path", "asd"), false); + EXPECT_EQ(startsWith("this/is/a/path", "this"), true); + EXPECT_EQ(startsWith("this/is/a/path", "this/"), true); +} + +TEST(core, substrNegative) { + string a = "abc"; + EXPECT_EQ(substr(a, -1), "c"); + EXPECT_EQ(substr(a, 0, -1), "ab"); } TEST(core, regex) { diff --git a/src/types.h b/src/types.h index 230bec1..f05b82d 100644 --- a/src/types.h +++ b/src/types.h @@ -50,7 +50,7 @@ namespace ts::types { Deferred = 7 }; - enum CommentDirectiveType { + enum class CommentDirectiveType { ExpectError, Ignore, }; @@ -65,11 +65,11 @@ namespace ts::types { CommentDirectiveType type; }; - enum LanguageVariant { + enum class LanguageVariant { Standard, JSX }; - enum DiagnosticCategory { + enum class DiagnosticCategory { Warning, Error, Suggestion, @@ -362,7 +362,7 @@ namespace ts::types { TemplateLiteralLikeFlags = ContainsInvalidEscape, }; - enum SyntaxKind { + enum class SyntaxKind { Unknown, EndOfFileToken, SingleLineCommentTrivia, @@ -981,6 +981,18 @@ namespace ts::types { // Masks // - Additional bitmasks }; + + enum class OuterExpressionKinds { + Parentheses = 1 << 0, + TypeAssertions = 1 << 1, + NonNullAssertions = 1 << 2, + PartiallyEmittedExpressions = 1 << 3, + + Assertions = TypeAssertions | NonNullAssertions, + All = Parentheses | Assertions | PartiallyEmittedExpressions, + + ExcludeJSDocTypeAssertion = 1 << 4, + }; } namespace ts { @@ -988,6 +1000,11 @@ namespace ts { using types::SyntaxKind; + struct PseudoBigInt { + bool negative; + string base10Value; + }; + template void printElem(vector &kinds, const T &x) { kinds.push_back(x.kind); @@ -1007,8 +1024,8 @@ namespace ts { } struct ReadonlyTextRange { - int pos = -1; - int end = -1; + int pos = - 1; + int end = - 1; }; struct Decorator; @@ -1110,11 +1127,17 @@ namespace ts { int pos; int end; bool hasTrailingComma = false; + bool isMissingList = false; //replaces `MissingList extends NodeArray {bool isMissingList;}` /* @internal */ int transformFlags = 0; // Flags for transforms, possibly undefined int length() { return list.size(); } + + vector> slice(int start, int end = 0) { + if (!end) end = list.size(); + return std::vector>(list.begin() + start, list.begin() + end); + } }; #define NodeTypeArray(x...) NodeArray @@ -1153,7 +1176,7 @@ namespace ts { // /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) // /* @internal */ localSymbol?: Symbol; // Local symbol declared by BaseNode (initialized by binding only for exported nodes) // /* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding) -// /* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms) +// /* @internal */ optional emitNode; //?: ; // Associated EmitNode (initialized by transforms) // /* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution // /* @internal */ inferenceContext?: InferenceContext; // Inference context for contextual type @@ -1189,13 +1212,13 @@ namespace ts { //using dynamic_cast template T &cast() { - return dynamic_cast(*this); + return dynamic_cast(*this); } //using dynamic_cast template bool validCast() { - return dynamic_cast(this) != nullptr; + return dynamic_cast(this) != nullptr; } template @@ -1404,7 +1427,9 @@ namespace ts { struct PrimaryExpression: MemberExpression {}; - struct PrivateIdentifier: BrandKind {}; + struct PrivateIdentifier: BrandKind { + string escapedText; + }; template struct Token: BrandKind {}; @@ -1457,8 +1482,8 @@ namespace ts { using PostfixUnaryOperator = SyntaxKind; //SyntaxKind.PlusPlusToken | SyntaxKind.MinusMinusToken struct PrefixUnaryExpression: BrandKind { - Property(operand, LeftHandSideExpression); - Property(operatorKind, PostfixUnaryOperator); + Property(operand, Node); //LeftHandSideExpression + PostfixUnaryOperator operatorKind = SyntaxKind::Unknown; }; struct PartiallyEmittedExpression: BrandKind { @@ -1467,7 +1492,7 @@ namespace ts { struct PostfixUnaryExpression: BrandKind { Property(operand, LeftHandSideExpression); - Property(operatorKind, PostfixUnaryOperator); + PostfixUnaryOperator operatorKind = SyntaxKind::Unknown; }; struct DeleteExpression: BrandKind { @@ -1520,15 +1545,22 @@ namespace ts { struct ModifiersArray: NodeTypeArray(Modifier) {}; - struct LiteralLikeNode { + struct LiteralLikeNode: Node { std::string text; - bool isUnterminated; //optional - bool hasExtendedUnicodeEscape; //optional + optional isUnterminated; + optional hasExtendedUnicodeEscape; }; - struct LiteralExpression: LiteralLikeNode, PrimaryExpression {}; + struct LiteralExpression: LiteralLikeNode {}; - struct StringLiteral: BrandKind {}; + struct Identifier; + struct NoSubstitutionTemplateLiteral; + struct NumericLiteral; + + struct StringLiteral: BrandKind { + OptionalUnionProperty(textSourceNode, Identifier, StringLiteral, NoSubstitutionTemplateLiteral, NumericLiteral); + optional singleQuote; + }; struct ImportSpecifier; @@ -1556,7 +1588,7 @@ namespace ts { string escapedText; optional originalKeywordKind;// Original syntaxKind which get set so that we can report an error later - /*@internal*/ optional autoGenerateFlags; // Specifies whether to auto-generate the text for an identifier. + /*@internal*/ optional autoGenerateFlags; // Specifies whether to auto-generate the text for an identifier. /*@internal*/ optional autoGenerateId; // Ensures unique generated identifiers get unique names, but clones get the same name. /*@internal*/ sharedOpt generatedImportReference; // Reference to the generated import specifier this identifier refers to /*@internal*/ optional typeArguments; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics, quickinfo, and signature help. @@ -1587,17 +1619,24 @@ namespace ts { }; struct TemplateLiteralLikeNode: LiteralLikeNode { - OptionalProperty(rawText, string); + optional rawText = {}; /* @internal */ - optional templateFlags; + optional templateFlags; //types::TokenFlags }; - struct NoSubstitutionTemplateLiteral: BrandKind { - optional templateFlags; + struct RegularExpressionLiteral: BrandKind { + }; + + struct NoSubstitutionTemplateLiteral: BrandKind { + OptionalProperty(rawText, string); + optional templateFlags; //types::TokenFlags }; struct NumericLiteral: BrandKind { - types::TokenFlags numericLiteralFlags; + int numericLiteralFlags = types::TokenFlags::None; + }; + + struct BigIntLiteral: BrandKind { }; struct ComputedPropertyName: BrandKind { @@ -1810,7 +1849,7 @@ namespace ts { struct PropertyAccessExpression: BrandKind { Property(expression, LeftHandSideExpression); OptionalProperty(questionDotToken, QuestionDotToken); - Property(name, MemberName); + UnionProperty(name, Identifier, PrivateIdentifier); }; struct PropertyAccessEntityNameExpression; @@ -2251,7 +2290,7 @@ namespace ts { struct ConstructorTypeNode: BrandKind {}; - struct FunctionDeclaration: BrandKind { + struct FunctionDeclaration: BrandKind { OptionalProperty(name, Identifier); OptionalProperty(body, FunctionBody); }; @@ -2274,7 +2313,7 @@ namespace ts { /* @internal*/ OptionalProperty(exclamationToken, ExclamationToken); // Present for use with reporting a grammar error }; - struct ConstructorDeclaration: FunctionLikeDeclarationBase, ClassElement, BrandKind { + struct ConstructorDeclaration: FunctionLikeDeclarationBase, ClassElement, BrandKind { shared parent; OptionalProperty(body, FunctionBody); @@ -2314,7 +2353,7 @@ namespace ts { /* @internal */ bool multiLine; }; - struct BinaryExpression: BrandKind { + struct BinaryExpression: BrandKind { Property(left, Expression); UnionProperty(operatorToken, Node); //BinaryOperatorToken uses a lot of different NodeType Property(right, Expression); @@ -2389,7 +2428,7 @@ namespace ts { // // export type BindingOrAssignmentPattern = ObjectBindingOrAssignmentPattern | ArrayBindingOrAssignmentPattern; - struct ConditionalExpression: Expression, BrandKind { + struct ConditionalExpression: Expression, BrandKind { Property(condition, Expression); Property(questionToken, QuestionToken); Property(whenTrue, Expression); @@ -2397,7 +2436,7 @@ namespace ts { Property(whenFalse, Expression); }; - struct FunctionExpression: BrandKind { + struct FunctionExpression: BrandKind { OptionalProperty(name, Identifier); OptionalProperty(body, FunctionBody); // Required, whereas the member inherited from FunctionDeclaration is optional }; @@ -2450,19 +2489,19 @@ namespace ts { struct TemplateSpan; struct TemplateLiteralTypeSpan; - struct TemplateHead: BrandKind { + struct TemplateHead: BrandKind { ParentProperty(TemplateExpression, TemplateLiteralTypeNode); /* @internal */ optional templateFlags; }; - struct TemplateMiddle: BrandKind { + struct TemplateMiddle: BrandKind { shared parent; /* @internal */ optional templateFlags; }; - struct TemplateTail: BrandKind { + struct TemplateTail: BrandKind { ParentProperty(TemplateSpan, TemplateLiteralTypeSpan); /* @internal */ optional templateFlags; @@ -2615,7 +2654,7 @@ namespace ts { OptionalProperty(expression, Expression); }; - struct JsxAttribute: BrandKind { + struct JsxAttribute: BrandKind { shared parent; Property(name, Identifier); /// JSX attribute initializers are optional; is sugar for @@ -2682,7 +2721,7 @@ namespace ts { Property(closingFragment, JsxClosingFragment); }; - struct JsxSpreadAttribute: BrandKind { + struct JsxSpreadAttribute: BrandKind { Property(parent, JsxAttributes); Property(expression, Expression); }; diff --git a/src/utilities.h b/src/utilities.h index 34223f6..683838d 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -7,8 +7,11 @@ #include "core.h" #include "types.h" #include "diagnostic_messages.h" +#include "node_test.h" +#include "scanner.h" namespace ts { + using namespace ts::types; using std::vector; using std::string; using std::optional; @@ -29,9 +32,10 @@ namespace ts { /* @internal */ template - void setTextRangePosEnd(T &range, int pos, int end) { + T setTextRangePosEnd(T &range, int pos, int end) { range->pos = pos; range->end = end; + return range; } void setTextRangePosEnd(NodeArray &range, int pos, int end) { @@ -39,6 +43,11 @@ namespace ts { range.end = end; } + template + shared setTextRange(shared range, sharedOpt location) { + return location ? setTextRangePosEnd(range, location->pos, location->end) : range; + } + inline string parsePseudoBigInt(string &stringValue) { int log2Base; switch (charCodeAt(stringValue, 1).code) { // "x" in "0x123" @@ -115,6 +124,36 @@ namespace ts { return (identifier.size() >= 2 && charCodeAt(identifier, 0).code == CharacterCodes::_ && charCodeAt(identifier, 1).code == CharacterCodes::_ ? "_" + identifier : identifier); } + ModifierFlags modifierToFlag(SyntaxKind token) { + switch (token) { + case SyntaxKind::StaticKeyword: return ModifierFlags::Static; + case SyntaxKind::PublicKeyword: return ModifierFlags::Public; + case SyntaxKind::ProtectedKeyword: return ModifierFlags::Protected; + case SyntaxKind::PrivateKeyword: return ModifierFlags::Private; + case SyntaxKind::AbstractKeyword: return ModifierFlags::Abstract; + case SyntaxKind::ExportKeyword: return ModifierFlags::Export; + case SyntaxKind::DeclareKeyword: return ModifierFlags::Ambient; + case SyntaxKind::ConstKeyword: return ModifierFlags::Const; + case SyntaxKind::DefaultKeyword: return ModifierFlags::Default; + case SyntaxKind::AsyncKeyword: return ModifierFlags::Async; + case SyntaxKind::ReadonlyKeyword: return ModifierFlags::Readonly; + case SyntaxKind::OverrideKeyword: return ModifierFlags::Override; + case SyntaxKind::InKeyword: return ModifierFlags::In; + case SyntaxKind::OutKeyword: return ModifierFlags::Out; + } + return ModifierFlags::None; + } + + /* @internal */ + bool isParameterPropertyModifier(SyntaxKind kind) { + return !!((int)modifierToFlag(kind) & (int)ModifierFlags::ParameterPropertyModifier); + } + + /* @internal */ + bool isClassMemberModifier(SyntaxKind idToken) { + return isParameterPropertyModifier(idToken) || idToken == SyntaxKind::StaticKeyword || idToken == SyntaxKind::OverrideKeyword; + } + /* @internal */ bool isModifierKind(SyntaxKind token) { switch (token) { @@ -136,6 +175,38 @@ namespace ts { } return false; } + + + bool isCommaSequence(shared node) { + return (node->kind == SyntaxKind::BinaryExpression && node->to().operatorToken->kind == SyntaxKind::CommaToken) || node->kind == SyntaxKind::CommaListExpression; + } + + bool isLiteralKind(SyntaxKind kind) { + return SyntaxKind::FirstLiteralToken <= kind && kind <= SyntaxKind::LastLiteralToken; + } + + string pseudoBigIntToString(PseudoBigInt bigint) { + return (bigint.negative && bigint.base10Value != "0" ? "-" : "") + bigint.base10Value; + } + + // Pseudo-literals + + /* @internal */ + bool isTemplateLiteralKind(SyntaxKind kind) { + return SyntaxKind::FirstTemplateToken <= kind && kind <= SyntaxKind::LastTemplateToken; + } + + bool isTemplateLiteralToken(shared &node) { + return isTemplateLiteralKind(node->kind); + } + + bool isTemplateMiddleOrTemplateTail(shared &node) { + return node->kind == SyntaxKind::TemplateMiddle || node->kind == SyntaxKind::TemplateTail; + } + + bool isImportOrExportSpecifier(shared &node) { + return isImportSpecifier(node) || isExportSpecifier(node); + } enum class OperatorPrecedence { // Expression: @@ -327,149 +398,409 @@ namespace ts { // -1 is lower than all other precedences. Returning it will cause binary expression // parsing to stop. Invalid = - 1, + }; + + int getBinaryOperatorPrecedence(SyntaxKind kind) { + switch (kind) { + case SyntaxKind::QuestionQuestionToken: + return (int) OperatorPrecedence::Coalesce; + case SyntaxKind::BarBarToken: + return (int) OperatorPrecedence::LogicalOR; + case SyntaxKind::AmpersandAmpersandToken: + return (int) OperatorPrecedence::LogicalAND; + case SyntaxKind::BarToken: + return (int) OperatorPrecedence::BitwiseOR; + case SyntaxKind::CaretToken: + return (int) OperatorPrecedence::BitwiseXOR; + case SyntaxKind::AmpersandToken: + return (int) OperatorPrecedence::BitwiseAND; + case SyntaxKind::EqualsEqualsToken: + case SyntaxKind::ExclamationEqualsToken: + case SyntaxKind::EqualsEqualsEqualsToken: + case SyntaxKind::ExclamationEqualsEqualsToken: + return (int) OperatorPrecedence::Equality; + case SyntaxKind::LessThanToken: + case SyntaxKind::GreaterThanToken: + case SyntaxKind::LessThanEqualsToken: + case SyntaxKind::GreaterThanEqualsToken: + case SyntaxKind::InstanceOfKeyword: + case SyntaxKind::InKeyword: + case SyntaxKind::AsKeyword: + return (int) OperatorPrecedence::Relational; + case SyntaxKind::LessThanLessThanToken: + case SyntaxKind::GreaterThanGreaterThanToken: + case SyntaxKind::GreaterThanGreaterThanGreaterThanToken: + return (int) OperatorPrecedence::Shift; + case SyntaxKind::PlusToken: + case SyntaxKind::MinusToken: + return (int) OperatorPrecedence::Additive; + case SyntaxKind::AsteriskToken: + case SyntaxKind::SlashToken: + case SyntaxKind::PercentToken: + return (int) OperatorPrecedence::Multiplicative; + case SyntaxKind::AsteriskAsteriskToken: + return (int) OperatorPrecedence::Exponentiation; + } + // -1 is lower than all other precedences. Returning it will cause binary expression parsing to stop. + return - 1; } - OperatorPrecedence - getBinaryOperatorPrecedence(SyntaxKind - kind) { - switch (kind) { - case SyntaxKind::QuestionQuestionToken: - return - OperatorPrecedence::Coalesce; - case SyntaxKind::BarBarToken: - return - OperatorPrecedence::LogicalOR; - case SyntaxKind::AmpersandAmpersandToken: - return - OperatorPrecedence::LogicalAND; - case SyntaxKind::BarToken: - return - OperatorPrecedence::BitwiseOR; - case SyntaxKind::CaretToken: - return - OperatorPrecedence::BitwiseXOR; - case SyntaxKind::AmpersandToken: - return - OperatorPrecedence::BitwiseAND; - case SyntaxKind::EqualsEqualsToken: - case SyntaxKind::ExclamationEqualsToken: - case SyntaxKind::EqualsEqualsEqualsToken: - case SyntaxKind::ExclamationEqualsEqualsToken: - return - OperatorPrecedence::Equality; - case SyntaxKind::LessThanToken: - case SyntaxKind::GreaterThanToken: - case SyntaxKind::LessThanEqualsToken: - case SyntaxKind::GreaterThanEqualsToken: - case SyntaxKind::InstanceOfKeyword: - case SyntaxKind::InKeyword: - case SyntaxKind::AsKeyword: - return - OperatorPrecedence::Relational; - case SyntaxKind::LessThanLessThanToken: - case SyntaxKind::GreaterThanGreaterThanToken: - case SyntaxKind::GreaterThanGreaterThanGreaterThanToken: - return - OperatorPrecedence::Shift; - case SyntaxKind::PlusToken: - case SyntaxKind::MinusToken: - return - OperatorPrecedence::Additive; - case SyntaxKind::AsteriskToken: - case SyntaxKind::SlashToken: - case SyntaxKind::PercentToken: - return - OperatorPrecedence::Multiplicative; - case SyntaxKind::AsteriskAsteriskToken: - return - OperatorPrecedence::Exponentiation; -} + inline bool isKeyword(types::SyntaxKind token) { + return SyntaxKind::FirstKeyword <= token && token <= SyntaxKind::LastKeyword; + } -// -1 is lower than all other precedences. Returning it will cause binary expression -// parsing to stop. -return -1; -} + inline bool isContextualKeyword(types::SyntaxKind token) { + return SyntaxKind::FirstContextualKeyword <= token && token <= SyntaxKind::LastContextualKeyword; + } -inline bool isKeyword(types::SyntaxKind token) { - return SyntaxKind::FirstKeyword <= token && token <= SyntaxKind::LastKeyword; -} + //unordered_map localizedDiagnosticMessages{}; -inline bool isContextualKeyword(types::SyntaxKind token) { - return SyntaxKind::FirstContextualKeyword <= token && token <= SyntaxKind::LastContextualKeyword; -} + inline string getLocaleSpecificMessage(DiagnosticMessage message) { +// if (has(localizedDiagnosticMessages, message.key)) { +// return localizedDiagnosticMessages[message.key]; +// } + return message.message; + } -//unordered_map localizedDiagnosticMessages{}; + using DiagnosticArg = string; -inline string getLocaleSpecificMessage(DiagnosticMessage message) { -// if (has(localizedDiagnosticMessages, message.key)) { -// return localizedDiagnosticMessages[message.key]; -// } - return message.message; -} + inline DiagnosticWithDetachedLocation createDetachedDiagnostic(string fileName, int start, int length, DiagnosticMessage message, optional textArg = {}) { + // assertDiagnosticLocation(/*file*/ undefined, start, length); + auto text = getLocaleSpecificMessage(message); -inline DiagnosticWithDetachedLocation createDetachedDiagnostic(string fileName, int start, int length, DiagnosticMessage message) { -// assertDiagnosticLocation(/*file*/ undefined, start, length); - auto text = getLocaleSpecificMessage(message); - -// if (arguments.length > 4) { -// text = formatStringFromArgs(text, arguments, 4); -// } - - return DiagnosticWithDetachedLocation{ - { - { - .messageText = text, - .category = message.category, - .code = message.code, - }, - .reportsUnnecessary = message.reportsUnnecessary, - }, - .fileName = fileName, - .start = start, - .length = length, - }; -} + if (textArg) { + text = *textArg; + } + //if (arguments.length > 4) { + // text = formatStringFromArgs(text, arguments, 4); + //} + + return DiagnosticWithDetachedLocation{ + { + { + .messageText = text, + .category = message.category, + .code = message.code, + }, + .reportsUnnecessary = message.reportsUnnecessary, + }, + .fileName = fileName, + .start = start, + .length = length, + }; + } -ScriptKind ensureScriptKind(string fileName, optional scriptKind) { - // Using scriptKind as a condition handles both: - // - 'scriptKind' is unspecified and thus it is `undefined` - // - 'scriptKind' is set and it is `Unknown` (0) - // If the 'scriptKind' is 'undefined' or 'Unknown' then we attempt - // to get the ScriptKind from the file name. If it cannot be resolved - // from the file name then the default 'TS' script kind is returned. - if (scriptKind) return *scriptKind; + ScriptKind ensureScriptKind(string fileName, optional scriptKind) { + // Using scriptKind as a condition handles both: + // - 'scriptKind' is unspecified and thus it is `undefined` + // - 'scriptKind' is set and it is `Unknown` (0) + // If the 'scriptKind' is 'undefined' or 'Unknown' then we attempt + // to get the ScriptKind from the file name. If it cannot be resolved + // from the file name then the default 'TS' script kind is returned. + if (scriptKind) return *scriptKind; - //todo: Find generic way to logicalOrLastValue + //todo: Find generic way to logicalOrLastValue // return getScriptKindFromFileName(fileName) || ScriptKind::TS; -} + } -string fileExt(const string &filename) { - auto idx = filename.rfind('.'); - if (idx == std::string::npos) return ""; - return filename.substr(idx + 1); -} + string fileExt(const string &filename) { + auto idx = filename.rfind('.'); + if (idx == std::string::npos) return ""; + return filename.substr(idx + 1); + } -ScriptKind getScriptKindFromFileName(const string &fileName) { - auto ext = fileExt(fileName); - - switch (const_hash(ext)) { - case const_hash(Extension::Js): - case const_hash(Extension::Cjs): - case const_hash(Extension::Mjs): - return ScriptKind::JS; - case const_hash(Extension::Jsx): - return ScriptKind::JSX; - case const_hash(Extension::Ts): - case const_hash(Extension::Cts): - case const_hash(Extension::Mts): - return ScriptKind::TS; - case const_hash(Extension::Tsx): - return ScriptKind::TSX; - case const_hash(Extension::Json): - return ScriptKind::JSON; - default: - return ScriptKind::Unknown; + ScriptKind getScriptKindFromFileName(const string &fileName) { + auto ext = fileExt(fileName); + + switch (const_hash(ext)) { + case const_hash(Extension::Js): + case const_hash(Extension::Cjs): + case const_hash(Extension::Mjs): + return ScriptKind::JS; + case const_hash(Extension::Jsx): + return ScriptKind::JSX; + case const_hash(Extension::Ts): + case const_hash(Extension::Cts): + case const_hash(Extension::Mts): + return ScriptKind::TS; + case const_hash(Extension::Tsx): + return ScriptKind::TSX; + case const_hash(Extension::Json): + return ScriptKind::JSON; + default: + return ScriptKind::Unknown; + } } -} + + bool isOuterExpression(shared node, int kinds = (int)OuterExpressionKinds::All) { + switch (node->kind) { + case SyntaxKind::ParenthesizedExpression: +// if (kinds & (int)OuterExpressionKinds::ExcludeJSDocTypeAssertion && isJSDocTypeAssertion(node)) { +// return false; +// } + return (kinds & (int)OuterExpressionKinds::Parentheses) != 0; + case SyntaxKind::TypeAssertionExpression: + case SyntaxKind::AsExpression: + return (kinds & (int)OuterExpressionKinds::TypeAssertions) != 0; + case SyntaxKind::NonNullExpression: + return (kinds & (int)OuterExpressionKinds::NonNullAssertions) != 0; + case SyntaxKind::PartiallyEmittedExpression: + return (kinds & (int)OuterExpressionKinds::PartiallyEmittedExpressions) != 0; + } + return false; + } + + shared getExpression(shared node) { + switch (node->kind) { + case SyntaxKind::ParenthesizedExpression: return node->to().expression; + case SyntaxKind::TypeAssertionExpression: return node->to().expression; + case SyntaxKind::AsExpression: return node->to().expression; + case SyntaxKind::NonNullExpression: return node->to().expression; + case SyntaxKind::PartiallyEmittedExpression: return node->to().expression; + } + throw runtime_error(format("No expression found in type %d", (int)node->kind)); + } + + shared skipOuterExpressions(shared node, int kinds = (int)OuterExpressionKinds::All) { + while (isOuterExpression(node, kinds)) { + node = getExpression(node); + } + return node; + } + + shared skipPartiallyEmittedExpressions(shared node) { + return skipOuterExpressions(node, (int)OuterExpressionKinds::PartiallyEmittedExpressions); + } + + bool isLeftHandSideExpressionKind(SyntaxKind kind) { + switch (kind) { + case SyntaxKind::PropertyAccessExpression: + case SyntaxKind::ElementAccessExpression: + case SyntaxKind::NewExpression: + case SyntaxKind::CallExpression: + case SyntaxKind::JsxElement: + case SyntaxKind::JsxSelfClosingElement: + case SyntaxKind::JsxFragment: + case SyntaxKind::TaggedTemplateExpression: + case SyntaxKind::ArrayLiteralExpression: + case SyntaxKind::ParenthesizedExpression: + case SyntaxKind::ObjectLiteralExpression: + case SyntaxKind::ClassExpression: + case SyntaxKind::FunctionExpression: + case SyntaxKind::Identifier: + case SyntaxKind::PrivateIdentifier: // technically this is only an Expression if it's in a `#field in expr` BinaryExpression + case SyntaxKind::RegularExpressionLiteral: + case SyntaxKind::NumericLiteral: + case SyntaxKind::BigIntLiteral: + case SyntaxKind::StringLiteral: + case SyntaxKind::NoSubstitutionTemplateLiteral: + case SyntaxKind::TemplateExpression: + case SyntaxKind::FalseKeyword: + case SyntaxKind::NullKeyword: + case SyntaxKind::ThisKeyword: + case SyntaxKind::TrueKeyword: + case SyntaxKind::SuperKeyword: + case SyntaxKind::NonNullExpression: + case SyntaxKind::ExpressionWithTypeArguments: + case SyntaxKind::MetaProperty: + case SyntaxKind::ImportKeyword: // technically this is only an Expression if it's in a CallExpression + return true; + default: + return false; + } + } + + bool isUnaryExpressionKind(SyntaxKind kind) { + switch (kind) { + case SyntaxKind::PrefixUnaryExpression: + case SyntaxKind::PostfixUnaryExpression: + case SyntaxKind::DeleteExpression: + case SyntaxKind::TypeOfExpression: + case SyntaxKind::VoidExpression: + case SyntaxKind::AwaitExpression: + case SyntaxKind::TypeAssertionExpression: + return true; + default: + return isLeftHandSideExpressionKind(kind); + } + } + + /* @internal */ + bool isUnaryExpression(shared node) { + return isUnaryExpressionKind(skipPartiallyEmittedExpressions(node)->kind); + } + + int getOperatorPrecedence(SyntaxKind nodeKind, SyntaxKind operatorKind, optional hasArguments = {}) { + switch (nodeKind) { + case SyntaxKind::CommaListExpression: + return (int)OperatorPrecedence::Comma; + + case SyntaxKind::SpreadElement: + return (int)OperatorPrecedence::Spread; + + case SyntaxKind::YieldExpression: + return (int)OperatorPrecedence::Yield; + + case SyntaxKind::ConditionalExpression: + return (int)OperatorPrecedence::Conditional; + + case SyntaxKind::BinaryExpression: + switch (operatorKind) { + case SyntaxKind::CommaToken: + return (int)OperatorPrecedence::Comma; + + case SyntaxKind::EqualsToken: + case SyntaxKind::PlusEqualsToken: + case SyntaxKind::MinusEqualsToken: + case SyntaxKind::AsteriskAsteriskEqualsToken: + case SyntaxKind::AsteriskEqualsToken: + case SyntaxKind::SlashEqualsToken: + case SyntaxKind::PercentEqualsToken: + case SyntaxKind::LessThanLessThanEqualsToken: + case SyntaxKind::GreaterThanGreaterThanEqualsToken: + case SyntaxKind::GreaterThanGreaterThanGreaterThanEqualsToken: + case SyntaxKind::AmpersandEqualsToken: + case SyntaxKind::CaretEqualsToken: + case SyntaxKind::BarEqualsToken: + case SyntaxKind::BarBarEqualsToken: + case SyntaxKind::AmpersandAmpersandEqualsToken: + case SyntaxKind::QuestionQuestionEqualsToken: + return (int)OperatorPrecedence::Assignment; + + default: + return getBinaryOperatorPrecedence(operatorKind); + } + + // TODO: Should prefix `++` and `--` be moved to the `Update` precedence? + case SyntaxKind::TypeAssertionExpression: + case SyntaxKind::NonNullExpression: + case SyntaxKind::PrefixUnaryExpression: + case SyntaxKind::TypeOfExpression: + case SyntaxKind::VoidExpression: + case SyntaxKind::DeleteExpression: + case SyntaxKind::AwaitExpression: + return (int)OperatorPrecedence::Unary; + + case SyntaxKind::PostfixUnaryExpression: + return (int)OperatorPrecedence::Update; + + case SyntaxKind::CallExpression: + return (int)OperatorPrecedence::LeftHandSide; + + case SyntaxKind::NewExpression: + return hasArguments && *hasArguments ? (int)OperatorPrecedence::Member : (int)OperatorPrecedence::LeftHandSide; + + case SyntaxKind::TaggedTemplateExpression: + case SyntaxKind::PropertyAccessExpression: + case SyntaxKind::ElementAccessExpression: + case SyntaxKind::MetaProperty: + return (int)OperatorPrecedence::Member; + + case SyntaxKind::AsExpression: + return (int)OperatorPrecedence::Relational; + + case SyntaxKind::ThisKeyword: + case SyntaxKind::SuperKeyword: + case SyntaxKind::Identifier: + case SyntaxKind::PrivateIdentifier: + case SyntaxKind::NullKeyword: + case SyntaxKind::TrueKeyword: + case SyntaxKind::FalseKeyword: + case SyntaxKind::NumericLiteral: + case SyntaxKind::BigIntLiteral: + case SyntaxKind::StringLiteral: + case SyntaxKind::ArrayLiteralExpression: + case SyntaxKind::ObjectLiteralExpression: + case SyntaxKind::FunctionExpression: + case SyntaxKind::ArrowFunction: + case SyntaxKind::ClassExpression: + case SyntaxKind::RegularExpressionLiteral: + case SyntaxKind::NoSubstitutionTemplateLiteral: + case SyntaxKind::TemplateExpression: + case SyntaxKind::ParenthesizedExpression: + case SyntaxKind::OmittedExpression: + case SyntaxKind::JsxElement: + case SyntaxKind::JsxSelfClosingElement: + case SyntaxKind::JsxFragment: + return (int)OperatorPrecedence::Primary; + + default: + return (int)OperatorPrecedence::Invalid; + } + } + + SyntaxKind getOperator(shared expression) { + if (expression->kind == SyntaxKind::BinaryExpression) { + return expression->to().operatorToken->kind; + } + else if (expression->kind == SyntaxKind::PrefixUnaryExpression) { + return expression->to().operatorKind; + } + else if (expression->kind == SyntaxKind::PostfixUnaryExpression) { + return expression->to().operatorKind; + } + else { + return expression->kind; + } + } + + /* @internal */ + bool isGeneratedIdentifier(shared node) { + return node->kind == SyntaxKind::Identifier && (defaultTo(node->to().autoGenerateFlags, 0) & (int)GeneratedIdentifierFlags::KindMask) > (int)GeneratedIdentifierFlags::None; + } + + int getExpressionPrecedence(shared expression) { + auto operatorNode = getOperator(expression); + bool hasArguments = expression->is() ? !!expression->to().arguments : false; + return getOperatorPrecedence(expression->kind, operatorNode, hasArguments); + } + + + bool isLeftHandSideExpression(shared node) { + return isLeftHandSideExpressionKind(skipPartiallyEmittedExpressions(node)->kind); + } + + bool positionIsSynthesized(int pos) { + // This is a fast way of testing the following conditions: + // pos === undefined || pos === null || isNaN(pos) || pos < 0; + return !(pos >= 0); + } + + // Returns true if this node is missing from the actual source code. A 'missing' node is different + // from 'undefined/defined'. When a node is undefined (which can happen for optional nodes + // in the tree), it is definitely missing. However, a node may be defined, but still be + // missing. This happens whenever the parser knows it needs to parse something, but can't + // get anything in the source code that it expects at that location. For example: + // + // let a: ; + // + // Here, the Type in the Type-Annotation is not-optional (as there is a colon in the source + // code). So the parser will attempt to parse out a type, and will create an actual node. + // However, this node will be 'missing' in the sense that no actual source-code/tokens are + // contained within it. + bool nodeIsMissing(sharedOpt node) { + if (!node) { + return true; + } + + return node->pos == node->end && node->pos >= 0 && node->kind != SyntaxKind::EndOfFileToken; + } + + string getTextOfNodeFromSourceText(string &sourceText, shared node, bool includeTrivia = false){ + if (nodeIsMissing(node)) { + return ""; + } + + auto text = substring(sourceText, includeTrivia ? node->pos : skipTrivia(sourceText, node->pos), node->end); + + if (isJSDocTypeExpressionOrChild(node)) { + // strip space + asterisk at line start + //todo: +// text = text.split(/\r\n|\n|\r/).map(line => trimStringStart(line.replace(/^\s*\*/, ""))).join("\n"); + } + + return text; + } + }