From ce1098975f521e3f4dbb98fabb23e4e419ce5793 Mon Sep 17 00:00:00 2001 From: imsenyu Date: Sun, 20 Apr 2025 23:03:58 +0800 Subject: [PATCH 1/7] refactor: locStart/End 12/8 --- .../babel-generator/generators/typescript.hpp | 2 +- src/babel/babel-generator/printer.hpp | 2 +- src/babel/babel-parser/parser/node.hpp | 8 ++------ src/babel/babel-parser/plugins/estree.hpp | 1 - .../babel-parser/plugins/typescript/index.hpp | 2 +- src/babel/babel-parser/types.hpp | 20 +++++++------------ 6 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/babel/babel-generator/generators/typescript.hpp b/src/babel/babel-generator/generators/typescript.hpp index 4e52df3..1bab8a7 100644 --- a/src/babel/babel-generator/generators/typescript.hpp +++ b/src/babel/babel-generator/generators/typescript.hpp @@ -128,7 +128,7 @@ namespace BabelGenerator::Generators { template void maybePrintTrailingCommaOrSemicolon(Printer::Printer &printer, PTR(T) node) { - if (!(printer.tokenMap != nullptr) || !node->position().has_start || !node->position().has_end) { + if (!(printer.tokenMap != nullptr) || !node->position().has_start() || !node->position().has_end()) { printer.semicolon(); return; } diff --git a/src/babel/babel-generator/printer.hpp b/src/babel/babel-generator/printer.hpp index 8fd6932..44b946c 100644 --- a/src/babel/babel-generator/printer.hpp +++ b/src/babel/babel-generator/printer.hpp @@ -1365,7 +1365,7 @@ namespace BabelGenerator::Printer { ) { // const nodeLoc = node.loc; // const len = comments.length; - bool hasLoc = node->locStart().has_value(); + bool hasLoc = node->position().has_start(); // const nodeStartLine = hasLoc ? nodeLoc.start.line : 0; // const nodeEndLine = hasLoc ? nodeLoc.end.line : 0; int64_t lastLine = 0; diff --git a/src/babel/babel-parser/parser/node.hpp b/src/babel/babel-parser/parser/node.hpp index 104cfe3..5fbd344 100644 --- a/src/babel/babel-parser/parser/node.hpp +++ b/src/babel/babel-parser/parser/node.hpp @@ -43,8 +43,8 @@ namespace BabelParser { } protected: - Node::PositionInfo startNodeInfo() { return Node::PositionInfo{this->state.start, 0, true, false}; } - Node::PositionInfo startNodeInfoAt(const Position &loc) { return Node::PositionInfo{loc.index(), 0, true, false}; } + Node::PositionInfo startNodeInfo() { return Node::PositionInfo{this->state.start, -1}; } + Node::PositionInfo startNodeInfoAt(const Position &loc) { return Node::PositionInfo{loc.index(), -1}; } Node::PositionInfo startNodeInfoAt(Node::PositionInfo const &nodeInfo) { return nodeInfo; } Node::PositionInfo startNodeInfoAt(PTR(Node::Node) node) { return node->position(); } @@ -114,7 +114,6 @@ namespace BabelParser { PTR(T) finishNodeAt_impl(PTR(T) node, const Position &endLoc) { node->position().end = endLoc.index(); - node->locEnd(true); // if (this.optionFlags & OptionFlags.Ranges) node.range[1] = endLoc.index; if (this->state.lastCommentWSEnd < node->position().start) [[likely]] { DEBUG_PARSER_STAT_COUNT(CommentPosSkip) @@ -134,7 +133,6 @@ namespace BabelParser { template void resetStartLocation_impl(PTR(T) node, const Position &startLoc) { node->position().start = startLoc.index(); - node->locStart(true); // if (this.optionFlags & OptionFlags.Ranges) node.range[0] = startLoc.index; } @@ -144,7 +142,6 @@ namespace BabelParser { void resetStartLocation_impl(Node::PositionInfo &startInfo, const Position &startLoc) { startInfo.start = startLoc.index(); - startInfo.locStart(true); // if (this.optionFlags & OptionFlags.Ranges) node.range[0] = startLoc.index; } @@ -156,7 +153,6 @@ namespace BabelParser { template void resetEndLocation_impl(PTR(T) node, Position const &endLoc) { node->position().end = endLoc.index(); - node->locEnd(true); // if (this.optionFlags & OptionFlags.Ranges) node.range[1] = endLoc.index; } diff --git a/src/babel/babel-parser/plugins/estree.hpp b/src/babel/babel-parser/plugins/estree.hpp index 1d88070..f74c5e9 100644 --- a/src/babel/babel-parser/plugins/estree.hpp +++ b/src/babel/babel-parser/plugins/estree.hpp @@ -276,7 +276,6 @@ namespace BabelParser::Plugins::ESTree { node.typeParameters = nullptr; funcNode->typeParameters = typeParameters; funcNode->position().start = typeParameters->position().start; - funcNode->locStart(true); } if constexpr (BabelTypes::IsClassPrivateMethod) { node.computed = false; diff --git a/src/babel/babel-parser/plugins/typescript/index.hpp b/src/babel/babel-parser/plugins/typescript/index.hpp index e8e5c70..6822a21 100644 --- a/src/babel/babel-parser/plugins/typescript/index.hpp +++ b/src/babel/babel-parser/plugins/typescript/index.hpp @@ -2310,7 +2310,7 @@ namespace BabelParser::Plugins::TypeScript { parseAssignableListItem_impl(PTRS(Node::Decorator) decoratorsMaybeNull) { // Store original location to include modifiers in range auto startLoc = this->state.startLoc; - Node::Declaration_ClassMethodOrDeclareMethodValue modified{Node::PositionInfo{0, 0, false, false}}; + Node::Declaration_ClassMethodOrDeclareMethodValue modified{Node::PositionInfo{-1, -1}}; constexpr auto allowedModifiers = (Node::Modifier::Public | Node::Modifier::Private | Node::Modifier::Protected | Node::Modifier::Override | Node::Modifier::Readonly); this->tsParseModifiers( diff --git a/src/babel/babel-parser/types.hpp b/src/babel/babel-parser/types.hpp index cfb9d2f..c993f1c 100644 --- a/src/babel/babel-parser/types.hpp +++ b/src/babel/babel-parser/types.hpp @@ -27,17 +27,13 @@ namespace BabelParser::Node { struct PositionInfo { BASE::position_t start; BASE::position_t end; - bool has_start; - bool has_end; - explicit PositionInfo(BASE::position_t start, BASE::position_t end, bool has_start, bool has_end) : + explicit PositionInfo(BASE::position_t start, BASE::position_t end) : start(start), - end(end), - has_start(has_start), - has_end(has_end) {} - [[nodiscard]] std::optional locStart() const { return has_start ? std::optional(Position{start}) : std::nullopt; } - [[nodiscard]] std::optional locEnd() const { return has_end ? std::optional(Position{end}) : std::nullopt; } - void locStart(bool v) { this->has_start = v; } - void locEnd(bool v) { this->has_end = v; } + end(end) {} + bool has_start() const { return start >= 0; } + bool has_end() const { return end >= 0; } + [[nodiscard]] std::optional locStart() const { return start >= 0 ? std::optional(Position{start}) : std::nullopt; } + [[nodiscard]] std::optional locEnd() const { return end >= 0 ? std::optional(Position{end}) : std::nullopt; } }; struct NodeExtra { bool parenthesized = false; @@ -66,8 +62,6 @@ namespace BabelParser::Node { [[nodiscard]] NodeExtra &extra() { return this->extra_; } [[nodiscard]] std::optional locStart() const { return this->pos_.locStart(); } [[nodiscard]] std::optional locEnd() const { return this->pos_.locEnd(); } - void locStart(bool v) { this->pos_.locStart(v); } - void locEnd(bool v) { this->pos_.locEnd(v); } template std::optional loc() const { if constexpr (P == PositionType::Start) { @@ -148,7 +142,7 @@ public: bool ignore = false; bool printed = false; explicit Comment(Type type, PositionWithLineColumn const &start, PositionWithLineColumn const &end, BASE::UStringView value) : - Node(type, PositionInfo{start.index(), end.index(), true, true}), + Node(type, PositionInfo{start.index(), end.index()}), value(value), start_(start), end_(end) {} From 2459e98b848d7c47d128a0a8d77b0a140ea536a7 Mon Sep 17 00:00:00 2001 From: imsenyu Date: Sun, 20 Apr 2025 23:10:39 +0800 Subject: [PATCH 2/7] refactor: locStart/End optional --- src/babel/babel-generator/buffer.hpp | 4 +-- src/babel/babel-generator/printer.hpp | 8 +++--- src/babel/babel-parser/parser/expression.hpp | 16 ++++++------ src/babel/babel-parser/parser/lval.hpp | 10 +++---- src/babel/babel-parser/parser/node.hpp | 2 +- src/babel/babel-parser/parser/statement.hpp | 22 ++++++++-------- src/babel/babel-parser/plugins/estree.hpp | 2 +- .../babel-parser/plugins/typescript/index.hpp | 14 +++++----- .../babel-parser/tokenizer/tokenizer.hpp | 4 +-- src/babel/babel-parser/types.hpp | 26 ++++++++++++------- src/babel/babel-parser/util/scope.hpp | 2 +- 11 files changed, 59 insertions(+), 51 deletions(-) diff --git a/src/babel/babel-generator/buffer.hpp b/src/babel/babel-generator/buffer.hpp index aa86be9..595ffdc 100644 --- a/src/babel/babel-generator/buffer.hpp +++ b/src/babel/babel-generator/buffer.hpp @@ -494,10 +494,10 @@ namespace BabelGenerator::Buffer { } template void _normalizePosition(PTR(Node::Node) node, BASE::position_t columnOffset) { - auto const &pos = node->loc(); + auto const &has_pos = node->has_loc(); auto &target = this->_sourcePosition; - if (pos) { + if (has_pos) { // target.line = pos.line; // TODO: Fix https://github.com/babel/babel/issues/15712 in downstream // target.column = std::max(pos.column + columnOffset, 0); diff --git a/src/babel/babel-generator/printer.hpp b/src/babel/babel-generator/printer.hpp index 44b946c..3d2ee1c 100644 --- a/src/babel/babel-generator/printer.hpp +++ b/src/babel/babel-generator/printer.hpp @@ -691,16 +691,16 @@ namespace BabelGenerator::Printer { void _catchUp(PTR(Node::Node) node) { auto const &format = this->format; if (!format.preserveFormat) { - if (format.retainLines && node && node->loc()) { + if (format.retainLines && node && node->has_loc()) { // this->catchUp(loc[prop].line); } return; } // catch up to this nodes newline if we're behind - auto const &pos = node ? node->loc() : std::nullopt; - if (pos != std::nullopt) - this->_catchUpTo(*pos); + auto const &pos = node ? node->has_loc() : false; + if (pos) + this->_catchUpTo(node->loc()); } void _catchUpTo(BabelParser::Util::Location::Position const &pos) { diff --git a/src/babel/babel-parser/parser/expression.hpp b/src/babel/babel-parser/parser/expression.hpp index d6612c4..d396465 100644 --- a/src/babel/babel-parser/parser/expression.hpp +++ b/src/babel/babel-parser/parser/expression.hpp @@ -119,7 +119,7 @@ namespace BabelParser::ExpressionParser { // Store the first redefinition's position, otherwise ignore because // we are parsing ambiguous pattern if (refExpressionErrors->doubleProtoLoc == std::nullopt) { - refExpressionErrors->doubleProtoLoc = *key->locStart(); + refExpressionErrors->doubleProtoLoc = key->locStart(); } } else [[unlikely]] { this->raise(Errors::DuplicateProto, key); @@ -387,7 +387,7 @@ namespace BabelParser::ExpressionParser { this->raise(Errors::PrivateInExpectedIn, left, value->string()); } - this->classScope->usePrivateName(value, *left->locStart()); + this->classScope->usePrivateName(value, left->locStart()); } auto op = this->state.type; @@ -1318,7 +1318,7 @@ namespace BabelParser::ExpressionParser { // then this method will throw a `PipeTopicUnconfiguredToken` error. PTR(Node::Expression) finishTopicReference(Node::PositionInfo const &startInfo, Proposal::Value pipeProposal, TokenType tokenType) { - if (this->testTopicReferenceConfiguration(pipeProposal, *startInfo.locStart(), tokenType)) { + if (this->testTopicReferenceConfiguration(pipeProposal, startInfo.locStart(), tokenType)) { // The token matches the plugin’s configuration. // The token is therefore a topic reference. @@ -1331,7 +1331,7 @@ namespace BabelParser::ExpressionParser { // Raise recoverable errors. pipeProposal == Proposal::smart ? Errors::PrimaryTopicNotAllowed : // In this case, `pipeProposal === "hack"` is true. Errors::PipeTopicUnbound, - *startInfo.locStart() + startInfo.locStart() ); } // Register the topic reference so that its pipe body knows @@ -2170,7 +2170,7 @@ namespace BabelParser::ExpressionParser { // IdentifierReference // CoverInitializedName // Note: `{ eval } = {}` will be checked in `checkLVal` later. - this->checkReservedWord(NODEAS(prop.key, Identifier)->name, *prop.key->locStart(), true, false); + this->checkReservedWord(NODEAS(prop.key, Identifier)->name, prop.key->locStart(), true, false); if constexpr (TIsPattern) { prop.value = this->parseMaybeDefault(startLoc, NODEAS(this->cloneIdentifier(NODEAS(prop.key, Identifier)), Pattern)); @@ -2440,9 +2440,9 @@ namespace BabelParser::ExpressionParser { // @ts-expect-error key may not index node !!inter.key ? // @ts-expect-error node.key has been guarded - *inter.key->locEnd() + inter.key->locEnd() // : node, - : *inter.position.locEnd() + : inter.position.locEnd() ); } else { this->raise(Errors::IllegalLanguageModeDirective, inter.position); @@ -2755,7 +2755,7 @@ namespace BabelParser::ExpressionParser { PTR(Node::YieldExpression) parseYield() { auto startInfo = this->startNodeInfo(); - this->expressionScope->recordParameterInitializerError(Errors::YieldInParameter, *startInfo.locStart()); + this->expressionScope->recordParameterInitializerError(Errors::YieldInParameter, startInfo.locStart()); this->next(); bool delegating = false; diff --git a/src/babel/babel-parser/parser/lval.hpp b/src/babel/babel-parser/parser/lval.hpp index 54276d1..c0109c0 100644 --- a/src/babel/babel-parser/parser/lval.hpp +++ b/src/babel/babel-parser/parser/lval.hpp @@ -128,7 +128,7 @@ namespace BabelParser { // i.e. `([(a) = []] = []) => {}` // see also `recordArrowParameterBindingError` signature in packages/babel-parser/src/util/expression-scope.js if ((*parenthesized)->type() == Node::Type::Identifier) { - this->expressionScope->recordArrowParameterBindingError(Errors::InvalidParenthesizedAssignment, *node->locStart()); + this->expressionScope->recordArrowParameterBindingError(Errors::InvalidParenthesizedAssignment, node->locStart()); } else if ((*parenthesized)->type() != Node::Type::MemberExpression && !this->isOptionalMemberExpression(*parenthesized)) [[unlikely]] { // A parenthesized member expression can be in LHS but not in pattern. // If the LHS is later interpreted as a pattern, `checkLVal` will throw for member expression binding @@ -174,7 +174,7 @@ namespace BabelParser { auto const &key = NODEAS(node, ObjectProperty)->key(); auto &value = NODEAS(node, ObjectProperty)->value; if (this->isPrivateName(key)) [[unlikely]] { - this->classScope->usePrivateName(this->getPrivateNameSV(key), *key->locStart()); + this->classScope->usePrivateName(this->getPrivateNameSV(key), key->locStart()); } this->template toAssignable(value); break; @@ -200,7 +200,7 @@ namespace BabelParser { { auto const &assignExp = NODEAS(node, AssignmentExpression); if (assignExp->_operator != Node::AssignmentOperator::Value::Assign) [[unlikely]] { - this->raise(Errors::MissingEqInAssignment, *(assignExp->left->locEnd())); + this->raise(Errors::MissingEqInAssignment, assignExp->left->locEnd()); } auto assignPattern = this->template startNode(assignExp->position(), NODEAS(assignExp->left, Pattern), assignExp->right); @@ -504,7 +504,7 @@ namespace BabelParser { flags & ParseBindingListFlags::IS_FUNCTION_PARAMS) { this->parseFunctionParamType(left); } - auto elt = this->parseMaybeDefault(*left->locStart(), left); + auto elt = this->parseMaybeDefault(left->locStart(), left); if (decorators) [[unlikely]] { left->decorators = decorators; } @@ -777,7 +777,7 @@ namespace BabelParser { } void declareNameFromIdentifier(PTR(Node::Identifier) identifier, BindingFlag::Value binding) { - this->scope->declareName(identifier->name, binding, *identifier->locStart()); + this->scope->declareName(identifier->name, binding, identifier->locStart()); } template void checkToRestConversion(PTR(Node::Node) node) { diff --git a/src/babel/babel-parser/parser/node.hpp b/src/babel/babel-parser/parser/node.hpp index 5fbd344..51a2726 100644 --- a/src/babel/babel-parser/parser/node.hpp +++ b/src/babel/babel-parser/parser/node.hpp @@ -161,7 +161,7 @@ namespace BabelParser { */ template void resetStartLocationFromNode(Node::PositionInfo &startInfo, Location &&localtionNodeStartInfo) { - this->resetStartLocation(startInfo, *localtionNodeStartInfo.locStart()); + this->resetStartLocation(startInfo, localtionNodeStartInfo.locStart()); } }; } // namespace BabelParser diff --git a/src/babel/babel-parser/parser/statement.hpp b/src/babel/babel-parser/parser/statement.hpp index b6069ef..648d703 100644 --- a/src/babel/babel-parser/parser/statement.hpp +++ b/src/babel/babel-parser/parser/statement.hpp @@ -1325,7 +1325,7 @@ namespace BabelParser::StatementParser { if (kind == Node::VariableDeclarationKind::Using || kind == Node::VariableDeclarationKind::AwaitUsing) { auto type = id->type(); if (type == Node::Type::ArrayPattern || type == Node::Type::ObjectPattern) { - this->raise(Errors::UsingDeclarationHasBindingPattern, *id->locStart()); + this->raise(Errors::UsingDeclarationHasBindingPattern, id->locStart()); } } this->checkLVal( @@ -1456,7 +1456,7 @@ namespace BabelParser::StatementParser { !this->options.annexB || this->state.strict || node->generator || node->async ? this->scope->treatFunctionsAsVar() ? BindingFlag::TYPE_VAR : BindingFlag::TYPE_LEXICAL : BindingFlag::TYPE_FUNCTION, - *nodeId->locStart() + nodeId->locStart() ); } @@ -1914,7 +1914,7 @@ namespace BabelParser::StatementParser { classBody->body->push_back(node); this->classScope->declarePrivateName( - this->getPrivateNameSV(this->getClassPrivatePropertyKey(node)), ClassElementType::OTHER, *this->getClassPrivatePropertyKey(node)->locStart() + this->getPrivateNameSV(this->getClassPrivatePropertyKey(node)), ClassElementType::OTHER, this->getClassPrivatePropertyKey(node)->locStart() ); } template @@ -1929,7 +1929,7 @@ namespace BabelParser::StatementParser { classBody->body->push_back(node); if (isPrivate) { - this->classScope->declarePrivateName(this->getPrivateNameSV(node->key()), ClassElementType::OTHER, *node->key()->locStart()); + this->classScope->declarePrivateName(this->getPrivateNameSV(node->key()), ClassElementType::OTHER, node->key()->locStart()); } } template @@ -1981,7 +1981,7 @@ namespace BabelParser::StatementParser { } void declareClassPrivateMethodInScope_impl(PTR(Node::Node) node, ClassElementType::Value kind) { this->classScope->declarePrivateName( - this->getPrivateNameSV(this->getClassPrivateMethodKey(node)), kind, *this->getClassPrivateMethodKey(node)->locStart() + this->getPrivateNameSV(this->getClassPrivateMethodKey(node)), kind, this->getClassPrivateMethodKey(node)->locStart() ); } @@ -2406,7 +2406,7 @@ namespace BabelParser::StatementParser { this->raise(Errors::ExportBindingIsString, specifier, NODEAS(local, StringLiteral)->value, exportName->string()); } else { // check for keywords used as local names - this->checkReservedWord(NODEAS(local, Identifier)->name, *local->locStart(), true, false); + this->checkReservedWord(NODEAS(local, Identifier)->name, local->locStart(), true, false); // check if export is defined this->scope->checkLocalExport(NODEAS(local, Identifier)); } @@ -2561,19 +2561,19 @@ namespace BabelParser::StatementParser { auto singleBindingType = inter.specifiers->size() == 1 ? inter.specifiers->front()->type() : Node::Type::__Undefined; if (inter.phase == BASE::Id::$source) { if (singleBindingType != Node::Type::ImportDefaultSpecifier) { - this->raise(Errors::SourcePhaseImportRequiresDefault, *inter.specifiers->front()->locStart()); + this->raise(Errors::SourcePhaseImportRequiresDefault, inter.specifiers->front()->locStart()); } } else if (inter.phase == BASE::Id::$defer) { if (singleBindingType != Node::Type::ImportNamespaceSpecifier) { - this->raise(Errors::DeferImportRequiresNamespace, *inter.specifiers->front()->locStart()); + this->raise(Errors::DeferImportRequiresNamespace, inter.specifiers->front()->locStart()); } } if (inter._module.value_or(false)) { if (singleBindingType != Node::Type::ImportDefaultSpecifier) [[unlikely]] { - this->raise(Errors::ImportReflectionNotBinding, *inter.specifiers->front()->locStart()); + this->raise(Errors::ImportReflectionNotBinding, inter.specifiers->front()->locStart()); } if (inter.assertions && inter.assertions->size() > 0) [[unlikely]] { - this->raise(Errors::ImportReflectionHasAssertion, *inter.specifiers->front()->locStart()); + this->raise(Errors::ImportReflectionHasAssertion, inter.specifiers->front()->locStart()); } } } @@ -3036,7 +3036,7 @@ namespace BabelParser::StatementParser { if (importedIsString) [[unlikely]] { this->ThrowRaise(Errors::ImportBindingIsString, inter.position, NODEAS(imported, StringLiteral)->value); } - this->checkReservedWord(NODEAS(imported, Identifier)->name, *inter.position.locStart(), true, true); + this->checkReservedWord(NODEAS(imported, Identifier)->name, inter.position.locStart(), true, true); if (!inter.local) { inter.local = this->cloneIdentifier(REINTERPRET_PTR(Node::Identifier)(imported)); } diff --git a/src/babel/babel-parser/plugins/estree.hpp b/src/babel/babel-parser/plugins/estree.hpp index f74c5e9..803decc 100644 --- a/src/babel/babel-parser/plugins/estree.hpp +++ b/src/babel/babel-parser/plugins/estree.hpp @@ -402,7 +402,7 @@ namespace BabelParser::Plugins::ESTree { auto const &key = NODEAS(node, EstreeProperty)->key(); auto &value = NODEAS(node, EstreeProperty)->value; if (this->isPrivateName(key)) { - this->classScope->usePrivateName(this->getPrivateNameSV(key), *key->locStart()); + this->classScope->usePrivateName(this->getPrivateNameSV(key), key->locStart()); } this->template toAssignable(value); } else { diff --git a/src/babel/babel-parser/plugins/typescript/index.hpp b/src/babel/babel-parser/plugins/typescript/index.hpp index 6822a21..5c1a0e3 100644 --- a/src/babel/babel-parser/plugins/typescript/index.hpp +++ b/src/babel/babel-parser/plugins/typescript/index.hpp @@ -2329,7 +2329,7 @@ namespace BabelParser::Plugins::TypeScript { if (flags & ParseBindingListFlags::IS_FUNCTION_PARAMS) { this->parseFunctionParamType(left); } - auto elt = this->parseMaybeDefault(*left->locStart(), left); + auto elt = this->parseMaybeDefault(left->locStart(), left); if (accessibility || readonly || override) { auto pp = this->startNodeInfoAt(startLoc); if (elt->type() != Node::Type::Identifier && elt->type() != Node::Type::AssignmentPattern) { @@ -2610,7 +2610,7 @@ namespace BabelParser::Plugins::TypeScript { void checkImportReflection_impl(Node::ImportDeclaration::Value &node) { this->Super::checkImportReflection_impl(node); if (node._module && node.importKind != BabelTypes::Enum::ImportExportKind::_value) { - this->raise(TSErrors::ImportReflectionHasImportType, *node.specifiers->front()->locStart()); + this->raise(TSErrors::ImportReflectionHasImportType, node.specifiers->front()->locStart()); } } @@ -3289,7 +3289,7 @@ namespace BabelParser::Plugins::TypeScript { // A single type parameter must either have constraints // or a trailing comma, otherwise it's ambiguous with JSX. this->raise( - TSErrors::SingleTypeParameterWithoutTrailingComma, createPositionWithColumnOffset(*parameter->locEnd(), 1), + TSErrors::SingleTypeParameterWithoutTrailingComma, createPositionWithColumnOffset(parameter->locEnd(), 1), parameter->name_->name->string() ); } @@ -3461,7 +3461,7 @@ namespace BabelParser::Plugins::TypeScript { EXP: if (expression) { if constexpr (isLHS) { - this->expressionScope->recordArrowParameterBindingError(TSErrors::UnexpectedTypeCastInParameter, *node->locStart()); + this->expressionScope->recordArrowParameterBindingError(TSErrors::UnexpectedTypeCastInParameter, node->locStart()); } else { this->raise(TSErrors::UnexpectedTypeCastInParameter, node); } @@ -3669,7 +3669,7 @@ namespace BabelParser::Plugins::TypeScript { default: std::terminate(); } - this->resetEndLocation(expression, *node->typeAnnotation->locEnd()); + this->resetEndLocation(expression, node->typeAnnotation->locEnd()); return expression; } @@ -3930,14 +3930,14 @@ namespace BabelParser::Plugins::TypeScript { if (isImport) { leftOfAs = this->template parseIdentifier(); if (!this->isContextual(TokenType::$_as)) { - this->checkReservedWord(NODEAS(leftOfAs, Identifier)->name, *leftOfAs->locStart(), true, true); + this->checkReservedWord(NODEAS(leftOfAs, Identifier)->name, leftOfAs->locStart(), true, true); } } else { leftOfAs = this->parseModuleExportName(); } } if (hasTypeSpecifier && isInTypeOnlyImportExport) { - this->raise(isImport ? TSErrors::TypeModifierIsUsedInTypeImports : TSErrors::TypeModifierIsUsedInTypeExports, *loc); + this->raise(isImport ? TSErrors::TypeModifierIsUsedInTypeImports : TSErrors::TypeModifierIsUsedInTypeExports, loc); } leftOfAsKey(node) = leftOfAs; diff --git a/src/babel/babel-parser/tokenizer/tokenizer.hpp b/src/babel/babel-parser/tokenizer/tokenizer.hpp index 01a6a1c..d36590c 100644 --- a/src/babel/babel-parser/tokenizer/tokenizer.hpp +++ b/src/babel/babel-parser/tokenizer/tokenizer.hpp @@ -109,11 +109,11 @@ namespace BabelParser::Tokenizer { if constexpr (std::is_same_v) { return node; } else if constexpr (std::is_same_v) { - return *node.locStart(); + return node.locStart(); } else if constexpr (std::is_base_of_v || std::is_same_v) { return *node.locStart(); } else if constexpr (std::is_base_of_v::type>) { - return *node->locStart(); + return node->locStart(); } else { std::terminate(); } diff --git a/src/babel/babel-parser/types.hpp b/src/babel/babel-parser/types.hpp index c993f1c..b5cdb9e 100644 --- a/src/babel/babel-parser/types.hpp +++ b/src/babel/babel-parser/types.hpp @@ -32,8 +32,8 @@ namespace BabelParser::Node { end(end) {} bool has_start() const { return start >= 0; } bool has_end() const { return end >= 0; } - [[nodiscard]] std::optional locStart() const { return start >= 0 ? std::optional(Position{start}) : std::nullopt; } - [[nodiscard]] std::optional locEnd() const { return end >= 0 ? std::optional(Position{end}) : std::nullopt; } + [[nodiscard]] Position locStart() const { return Position{start}; } + [[nodiscard]] Position locEnd() const { return Position{end}; } }; struct NodeExtra { bool parenthesized = false; @@ -60,16 +60,24 @@ namespace BabelParser::Node { [[nodiscard]] PositionInfo &position() { return this->pos_; } [[nodiscard]] NodeExtra const &extra() const { return this->extra_; } [[nodiscard]] NodeExtra &extra() { return this->extra_; } - [[nodiscard]] std::optional locStart() const { return this->pos_.locStart(); } - [[nodiscard]] std::optional locEnd() const { return this->pos_.locEnd(); } + [[nodiscard]] Position locStart() const { return this->pos_.locStart(); } + [[nodiscard]] Position locEnd() const { return this->pos_.locEnd(); } template - std::optional loc() const { + Position loc() const { if constexpr (P == PositionType::Start) { return this->locStart(); } else { return this->locEnd(); } } + template + bool has_loc() const { + if constexpr (P == PositionType::Start) { + return this->position().has_start(); + } else { + return this->position().has_end(); + } + } template inline void unshiftComments(BASE::LinkedItem *comment); template @@ -90,16 +98,16 @@ namespace BabelParser::Node { writer.field("start", this->position().start); writer.field("end", this->position().end); - if (auto _start = this->locStart()) { - auto start = _start->withLineColumn(writer.input()); + if (this->position().has_start()) { + auto start = this->locStart().withLineColumn(writer.input()); writer.field("loc.start.line", start.line()); writer.field("loc.start.column", start.column()); if (!writer.estree()) { writer.field("loc.start.index", start.index()); } } - if (auto _end = this->locEnd()) { - auto end = _end->withLineColumn(writer.input()); + if (this->position().has_end()) { + auto end = this->locEnd().withLineColumn(writer.input()); writer.field("loc.end.line", end.line()); writer.field("loc.end.column", end.column()); if (!writer.estree()) { diff --git a/src/babel/babel-parser/util/scope.hpp b/src/babel/babel-parser/util/scope.hpp index 9308dbb..93ec4bf 100644 --- a/src/babel/babel-parser/util/scope.hpp +++ b/src/babel/babel-parser/util/scope.hpp @@ -296,7 +296,7 @@ namespace BabelParser::Util::Scope { // Modules are strict by default, but the `scriptMode` option // can overwrite this behavior. !topLevelScope->template contains(name)) { - this->undefinedExports.insert(std::make_pair(name, *id->locStart())); + this->undefinedExports.insert(std::make_pair(name, id->locStart())); this->undefinedExportIds.push_back(name); } } From 14908c8cbb53fba22d9e8a0ba84d4a9457724783 Mon Sep 17 00:00:00 2001 From: imsenyu Date: Sun, 20 Apr 2025 23:28:06 +0800 Subject: [PATCH 3/7] refactor: PositionInfo start -1 --- src/babel/babel-parser/parser/node.hpp | 4 ++-- .../babel-parser/plugins/typescript/index.hpp | 20 +++++++++---------- src/babel/babel-parser/tokenizer/state.hpp | 4 ++-- src/babel/babel-parser/types.hpp | 20 ++++++++++++++----- src/babel/babel-parser/util/location.hpp | 20 +++++++++++-------- 5 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/babel/babel-parser/parser/node.hpp b/src/babel/babel-parser/parser/node.hpp index 51a2726..8dcdf2f 100644 --- a/src/babel/babel-parser/parser/node.hpp +++ b/src/babel/babel-parser/parser/node.hpp @@ -43,8 +43,8 @@ namespace BabelParser { } protected: - Node::PositionInfo startNodeInfo() { return Node::PositionInfo{this->state.start, -1}; } - Node::PositionInfo startNodeInfoAt(const Position &loc) { return Node::PositionInfo{loc.index(), -1}; } + Node::PositionInfo startNodeInfo() { return Node::PositionInfo{this->state.startLoc, -1}; } + Node::PositionInfo startNodeInfoAt(const Position &loc) { return Node::PositionInfo{loc, -1}; } Node::PositionInfo startNodeInfoAt(Node::PositionInfo const &nodeInfo) { return nodeInfo; } Node::PositionInfo startNodeInfoAt(PTR(Node::Node) node) { return node->position(); } diff --git a/src/babel/babel-parser/plugins/typescript/index.hpp b/src/babel/babel-parser/plugins/typescript/index.hpp index 5c1a0e3..6364c7d 100644 --- a/src/babel/babel-parser/plugins/typescript/index.hpp +++ b/src/babel/babel-parser/plugins/typescript/index.hpp @@ -534,7 +534,7 @@ namespace BabelParser::Plugins::TypeScript { template PTRS(T) - tsParseDelimitedList(ParsingContext::Value kind, ParseElement &&parseElement, BASE::position_t *refTrailingCommaPos = nullptr) { + tsParseDelimitedList(ParsingContext::Value kind, ParseElement &&parseElement, Position *refTrailingCommaPos = nullptr) { return nonNull(this->tsParseDelimitedListWorker( kind, std::forward(parseElement), /* expectSuccess */ true, refTrailingCommaPos @@ -548,16 +548,16 @@ namespace BabelParser::Plugins::TypeScript { template PTRS(T) tsParseDelimitedListWorker( - ParsingContext::Value kind, ParseElement &&parseElement, bool expectSuccess, BASE::position_t *refTrailingCommaPos = nullptr + ParsingContext::Value kind, ParseElement &&parseElement, bool expectSuccess, Position *refTrailingCommaPos = nullptr ) { auto result = this->allocator.template buildNodeListOf(); - BASE::position_t trailingCommaPos = -1; + Position trailingCommaPos = Position{-1,-1,-1}; for (;;) { if (this->tsIsListTerminator(kind)) { break; } - trailingCommaPos = -1; + trailingCommaPos = Position{-1,-1,-1}; auto element = parseElement(); if (element == nullptr) { @@ -566,7 +566,7 @@ namespace BabelParser::Plugins::TypeScript { result->push_back(element); if (this->eat(TokenType::$_comma)) { - trailingCommaPos = this->state.lastTokStartLoc.index(); + trailingCommaPos = this->state.lastTokStartLoc; continue; } @@ -591,7 +591,7 @@ namespace BabelParser::Plugins::TypeScript { template PTRS(T) tsParseBracketedList( - ParsingContext::Value kind, ParseElement &&parseElement, bool bracket, bool skipFirstToken, BASE::position_t *refTrailingCommaPos = nullptr + ParsingContext::Value kind, ParseElement &&parseElement, bool bracket, bool skipFirstToken, Position *refTrailingCommaPos = nullptr ) { if (!skipFirstToken) { if (bracket) { @@ -801,7 +801,7 @@ namespace BabelParser::Plugins::TypeScript { this->unexpected(); } - BASE::position_t refTrailingCommaPos = -1; + Position refTrailingCommaPos{-1, -1, -1}; auto params = this->template tsParseBracketedList( ParsingContext::TypeParametersOrArguments, [&]() { return this->tsParseTypeParameter(parseModifiers); }, @@ -813,8 +813,8 @@ namespace BabelParser::Plugins::TypeScript { } auto node = this->template finishNode(nodeInfo, params); ; - if (refTrailingCommaPos != -1) { - node->setTrailingCommaLoc(Position{refTrailingCommaPos}); + if (refTrailingCommaPos.index() != -1) { + node->setTrailingCommaLoc(refTrailingCommaPos); } return node; } @@ -2310,7 +2310,7 @@ namespace BabelParser::Plugins::TypeScript { parseAssignableListItem_impl(PTRS(Node::Decorator) decoratorsMaybeNull) { // Store original location to include modifiers in range auto startLoc = this->state.startLoc; - Node::Declaration_ClassMethodOrDeclareMethodValue modified{Node::PositionInfo{-1, -1}}; + Node::Declaration_ClassMethodOrDeclareMethodValue modified{Node::PositionInfo{}}; constexpr auto allowedModifiers = (Node::Modifier::Public | Node::Modifier::Private | Node::Modifier::Protected | Node::Modifier::Override | Node::Modifier::Readonly); this->tsParseModifiers( diff --git a/src/babel/babel-parser/tokenizer/state.hpp b/src/babel/babel-parser/tokenizer/state.hpp index ac58d62..d6142dc 100644 --- a/src/babel/babel-parser/tokenizer/state.hpp +++ b/src/babel/babel-parser/tokenizer/state.hpp @@ -88,7 +88,7 @@ namespace BabelParser::Tokenizer::State { BabelParser::Util::Location::Position lastTokEndLoc; BASE::position_t curLine; BASE::position_t lineStart; - BabelParser::Util::Location::Position curPosition() const { return {this->curLine, this->pos - this->lineStart, this->pos}; } + BabelParser::Util::Location::Position curPosition() const { return Position{this->curLine, this->pos - this->lineStart, this->pos}; } PositionWithLineColumn curPositionWithLineColumn() const { return PositionWithLineColumn{this->pos, this->curLine, this->pos - this->lineStart}; } }; @@ -275,7 +275,7 @@ namespace BabelParser::Tokenizer::State { // Used to track invalid escape sequences in template literals, // that must be reported if the template is not tagged. - BabelParser::Util::Location::Position firstInvalidTemplateEscapePos{-1}; + BabelParser::Util::Location::Position firstInvalidTemplateEscapePos{-1, -1, -1}; // This property is used to track the following errors // - StrictNumericEscape diff --git a/src/babel/babel-parser/types.hpp b/src/babel/babel-parser/types.hpp index b5cdb9e..5136df3 100644 --- a/src/babel/babel-parser/types.hpp +++ b/src/babel/babel-parser/types.hpp @@ -27,13 +27,23 @@ namespace BabelParser::Node { struct PositionInfo { BASE::position_t start; BASE::position_t end; - explicit PositionInfo(BASE::position_t start, BASE::position_t end) : - start(start), + BASE::position_t start_line; + BASE::position_t start_column; + BASE::position_t end_line; + BASE::position_t end_column; + + explicit PositionInfo() : + start(-1), + end(-1) {} + explicit PositionInfo(Position start, BASE::position_t end) : + start(start.index()), + start_line(start.line()), + start_column(start.column()), end(end) {} bool has_start() const { return start >= 0; } bool has_end() const { return end >= 0; } - [[nodiscard]] Position locStart() const { return Position{start}; } - [[nodiscard]] Position locEnd() const { return Position{end}; } + [[nodiscard]] Position locStart() const { return Position{start_line, start_column, start}; } + [[nodiscard]] Position locEnd() const { return Position{end_line, end_column, end}; } }; struct NodeExtra { bool parenthesized = false; @@ -150,7 +160,7 @@ public: bool ignore = false; bool printed = false; explicit Comment(Type type, PositionWithLineColumn const &start, PositionWithLineColumn const &end, BASE::UStringView value) : - Node(type, PositionInfo{start.index(), end.index()}), + Node(type, PositionInfo{start, end.index()}), value(value), start_(start), end_(end) {} diff --git a/src/babel/babel-parser/util/location.hpp b/src/babel/babel-parser/util/location.hpp index 8e6c627..7a97511 100644 --- a/src/babel/babel-parser/util/location.hpp +++ b/src/babel/babel-parser/util/location.hpp @@ -6,14 +6,18 @@ namespace BabelParser::Util::Location { class PositionWithLineColumn; class Position { + protected: BASE::position_t index_; + BASE::position_t line_; + BASE::position_t column_; public: Position() = default; - Position(BASE::position_t _line, BASE::position_t _column, BASE::position_t index) : index_(index) {} - explicit Position(BASE::position_t index) : index_(index) {} + explicit Position(BASE::position_t _line, BASE::position_t _column, BASE::position_t index) : line_(_line), column_(_column), index_(index) {} + // explicit Position(BASE::position_t index) : index_(index) {} [[nodiscard]] BASE::position_t index() const { return index_; } - + [[nodiscard]] BASE::position_t line() const { return line_; } + [[nodiscard]] BASE::position_t column() const { return column_; } [[nodiscard]] PositionWithLineColumn withLineColumn(BASE::UStringView input) const; }; inline std::pair resolveLineColumnFromIndex(BASE::UStringView input, BASE::position_t expectIndex) { @@ -46,12 +50,12 @@ namespace BabelParser::Util::Location { return std::make_pair(line, column); } class PositionWithLineColumn : public Position { - BASE::position_t line_; - BASE::position_t column_; + // BASE::position_t line_; + // BASE::position_t column_; public: - PositionWithLineColumn(BASE::position_t index, BASE::position_t line, BASE::position_t column) : Position(index), line_(line), column_(column) {} - PositionWithLineColumn(BASE::UStringView input, BASE::position_t index) : Position(index) { + PositionWithLineColumn(BASE::position_t index, BASE::position_t line, BASE::position_t column) : Position(line, column, index)/*, line_(line), column_(column)*/ {} + PositionWithLineColumn(BASE::UStringView input, BASE::position_t index) : Position(0, 0, index) { auto [line, column] = resolveLineColumnFromIndex(input, index); line_ = line; column_ = column; @@ -62,6 +66,6 @@ namespace BabelParser::Util::Location { inline PositionWithLineColumn Position::withLineColumn(BASE::UStringView input) const { return PositionWithLineColumn{input, this->index()}; } inline Position createPositionWithColumnOffset(const Position &position, BASE::position_t columnOffset) { - return Position{position.index() + columnOffset}; + return Position{position.line(), position.column() + columnOffset, position.index() + columnOffset}; } } // namespace BabelParser::Util::Location From fa7b144329c8430fd9c3b09dbaf08679490bedff Mon Sep 17 00:00:00 2001 From: imsenyu Date: Sun, 20 Apr 2025 23:48:36 +0800 Subject: [PATCH 4/7] feat: node.line() --- .../babel-generator/generators/classes.hpp | 13 ++- src/babel/babel-generator/printer.hpp | 97 +++++++++---------- src/babel/babel-parser/parser/node.hpp | 4 +- src/babel/babel-parser/types.hpp | 28 +++++- 4 files changed, 81 insertions(+), 61 deletions(-) diff --git a/src/babel/babel-generator/generators/classes.hpp b/src/babel/babel-generator/generators/classes.hpp index 828e413..2fceb5f 100644 --- a/src/babel/babel-generator/generators/classes.hpp +++ b/src/babel/babel-generator/generators/classes.hpp @@ -158,8 +158,8 @@ namespace BabelGenerator::Generators { if (!node->isStatic() && !_this.format.preserveFormat) { // catch up to property key, avoid line break // between member TS modifiers and the property key. - // const endLine = node.key.loc?.end?.line; - // if (endLine) _this.catchUp(endLine); + auto endLine = node->key()->locEndLine(-1); + if (endLine >= 0) _this.catchUp(endLine); } classesTsPrintClassMemberModifiers(_this, node); @@ -201,8 +201,8 @@ namespace BabelGenerator::Generators { // catch up to property key, avoid line break // between member modifiers and the property key. - // const endLine = node.key.loc?.end?.line; - // if (endLine) _this.catchUp(endLine); + auto endLine = node->key()->locEndLine(-1); + if (endLine >= 0) _this.catchUp(endLine); // TS does not support class accessor property yet classesTsPrintClassMemberModifiers(_this, node); @@ -284,9 +284,8 @@ namespace BabelGenerator::Generators { if (!_this.format.preserveFormat) { // catch up to method key, avoid line break // between member modifiers/method heads and the method key. - // const endLine = node.key.loc?.end?.line; - // auto const& endLine = node->key->locEnd(); - // if (endLine) _this.catchUp(endLine); + auto endLine = node->key()->locEndLine(-1); + if (endLine >= 0) _this.catchUp(endLine); } classesTsPrintClassMemberModifiers(_this, node); diff --git a/src/babel/babel-generator/printer.hpp b/src/babel/babel-generator/printer.hpp index 3d2ee1c..18ab36c 100644 --- a/src/babel/babel-generator/printer.hpp +++ b/src/babel/babel-generator/printer.hpp @@ -692,7 +692,7 @@ namespace BabelGenerator::Printer { auto const &format = this->format; if (!format.preserveFormat) { if (format.retainLines && node && node->has_loc()) { - // this->catchUp(loc[prop].line); + this->catchUp(node->locLine(-1)); } return; } @@ -704,16 +704,16 @@ namespace BabelGenerator::Printer { } void _catchUpTo(BabelParser::Util::Location::Position const &pos) { - // const count = line - this->_buf.getCurrentLine(); - // if (count > 0 && this->_noLineTerminator) { - // // We cannot inject new lines when _noLineTemrinator is set - // // to `true`, or we would generate invalid code. - // return; - // } + auto count = pos.line() - this->_buf.getCurrentLine(); + if (count > 0 && this->_noLineTerminator) { + // We cannot inject new lines when _noLineTemrinator is set + // to `true`, or we would generate invalid code. + return; + } - // for (let i = 0; i < count; i++) { - // this->_newline(); - // } + for (size_t i = 0; i < count; i++) { + this->_newline(); + } // const spacesCount = // count > 0 ? column : column - this->_buf.getCurrentColumn(); @@ -786,8 +786,7 @@ namespace BabelGenerator::Printer { // } auto oldInAux = this->_insideAux; - // this->_insideAux = node.loc == null; - this->_insideAux = false; + this->_insideAux = node->position().has_start() == false; this->_maybeAddAuxComment(this->_insideAux && !oldInAux); bool parenthesized = node->extra().parenthesized; @@ -819,21 +818,22 @@ namespace BabelGenerator::Printer { } bool indentParenthesized = false; - // if ( - // !shouldPrintParens && - // this->_noLineTerminator && - // (node.leadingComments?.some(commentIsNewline) || - // (this->format.retainLines && - // node.loc && - // node.loc.start.line > this->_buf.getCurrentLine())) - // ) { - // shouldPrintParens = true; - // indentParenthesized = true; - // } + if ( + !shouldPrintParens && + this->_noLineTerminator && + ( + // node.leadingComments?.some(commentIsNewline) || + (this->format.retainLines && + node->position().has_start() && + node->locStartLine(-1) > this->_buf.getCurrentLine())) + ) { + shouldPrintParens = true; + indentParenthesized = true; + } PTR(Node::Node) oldNoLineTerminatorAfterNode = nullptr; bool oldInForStatementInitWasTrue = false; - // if (!shouldPrintParens) { + if (!shouldPrintParens) { // noLineTerminatorAfter ||= // parent && // this->_noLineTerminatorAfterNode === parent && @@ -846,7 +846,7 @@ namespace BabelGenerator::Printer { // this->_noLineTerminatorAfterNode = node; // } // } - // } + } if (shouldPrintParens) { this->token(u"("); @@ -998,13 +998,12 @@ namespace BabelGenerator::Printer { if (iter_begin == iter_end) [[unlikely]] return; - bool indent; + bool indent = false; if (OPT.indent == BASE::Undefined && this->format.retainLines) { - // const startLine = nodes->at(0)->locStart()->line; - // if (startLine != null && startLine !== this->_buf.getCurrentLine()) { - // indent = true; - indent = true; - // } + auto position = (*iter_begin)->position(); + if (position.has_start() && position.locStart().line() != this->_buf.getCurrentLine()) { + indent = true; + } } else { indent = toBoolean(OPT.indent); } @@ -1047,7 +1046,7 @@ namespace BabelGenerator::Printer { this->newline(1); } else { auto nextNode = *iter_next; - // newlineOpts.nextNodeStartLine = nextNode.loc?.start.line || 0; + nextNodeStartLine = nextNode->locStartLine(0); this->_printNewline(true, nextNodeStartLine); } @@ -1366,8 +1365,8 @@ namespace BabelGenerator::Printer { // const nodeLoc = node.loc; // const len = comments.length; bool hasLoc = node->position().has_start(); - // const nodeStartLine = hasLoc ? nodeLoc.start.line : 0; - // const nodeEndLine = hasLoc ? nodeLoc.end.line : 0; + auto nodeStartLine = node->locStartLine(0); + auto nodeEndLine = node->locEndLine(0); int64_t lastLine = 0; int64_t leadingCommentNewline = 0; @@ -1384,8 +1383,8 @@ namespace BabelGenerator::Printer { break; } if (hasLoc && shouldPrint == PRINT_COMMENT_HINT::ALLOW) { - auto commentStartLine = comment->locStart().line(); - auto commentEndLine = comment->locEnd().line(); + auto commentStartLine = comment->locStartLine(-1); + auto commentEndLine = comment->locEndLine(-1); if constexpr (commentPos == CommentPosition::Leading) { int64_t offset = 0; if (i == 0) { @@ -1404,29 +1403,29 @@ namespace BabelGenerator::Printer { if (comment.next() == nullptr) { this->maybeNewline(leadingCommentNewline); - // maybeNewline( - // Math.max(nodeStartLine - lastLine, leadingCommentNewline), - // ); - // lastLine = nodeStartLine; + maybeNewline( + std::max(nodeStartLine - lastLine, leadingCommentNewline) + ); + lastLine = nodeStartLine; } } else if constexpr (commentPos == CommentPosition::Inner) { - // const offset = - // commentStartLine - (i === 0 ? nodeStartLine : lastLine); + auto offset = + commentStartLine - (i == 0 ? nodeStartLine : lastLine); lastLine = commentEndLine; - // maybeNewline(offset); + maybeNewline(offset); this->_printComment(comment); if (comment.next() == nullptr) { - // maybeNewline(Math.min(1, nodeEndLine - lastLine)); // TODO: Improve here when inner comments processing is stronger - // lastLine = nodeEndLine; + maybeNewline(std::min(1, nodeEndLine - lastLine)); // TODO: Improve here when inner comments processing is stronger + lastLine = nodeEndLine; } } else { - // const offset = - // commentStartLine - (i === 0 ? nodeEndLine - lineOffset : lastLine); + auto offset = + commentStartLine - (i == 0 ? nodeEndLine - lineOffset : lastLine); lastLine = commentEndLine; - // maybeNewline(offset); + maybeNewline(offset); this->_printComment(comment); } } else { @@ -1436,7 +1435,7 @@ namespace BabelGenerator::Printer { } if (commentsHead->next() == nullptr) { - bool singleLine = comment->locStart().line() == comment->locEnd().line(); + bool singleLine = comment->locStartLine(-1) == comment->locEndLine(-1); bool shouldSkipNewline = singleLine && !BabelTypes::isStatement(node) && !BabelTypes::isClassBody(parent) && !BabelTypes::isTSInterfaceBody(parent) && !BabelTypes::isTSEnumMember(node); diff --git a/src/babel/babel-parser/parser/node.hpp b/src/babel/babel-parser/parser/node.hpp index 8dcdf2f..f0f560c 100644 --- a/src/babel/babel-parser/parser/node.hpp +++ b/src/babel/babel-parser/parser/node.hpp @@ -43,8 +43,8 @@ namespace BabelParser { } protected: - Node::PositionInfo startNodeInfo() { return Node::PositionInfo{this->state.startLoc, -1}; } - Node::PositionInfo startNodeInfoAt(const Position &loc) { return Node::PositionInfo{loc, -1}; } + Node::PositionInfo startNodeInfo() { return Node::PositionInfo{this->state.startLoc}; } + Node::PositionInfo startNodeInfoAt(const Position &loc) { return Node::PositionInfo{loc}; } Node::PositionInfo startNodeInfoAt(Node::PositionInfo const &nodeInfo) { return nodeInfo; } Node::PositionInfo startNodeInfoAt(PTR(Node::Node) node) { return node->position(); } diff --git a/src/babel/babel-parser/types.hpp b/src/babel/babel-parser/types.hpp index 5136df3..0fa8634 100644 --- a/src/babel/babel-parser/types.hpp +++ b/src/babel/babel-parser/types.hpp @@ -35,15 +35,27 @@ namespace BabelParser::Node { explicit PositionInfo() : start(-1), end(-1) {} - explicit PositionInfo(Position start, BASE::position_t end) : + explicit PositionInfo(Position start) : start(start.index()), start_line(start.line()), start_column(start.column()), - end(end) {} + end(-1) + {} + explicit PositionInfo(Position start, Position end) : + start(start.index()), + start_line(start.line()), + start_column(start.column()), + end(end.index()), + end_line(end.line()), + end_column(end.column()) + {} bool has_start() const { return start >= 0; } bool has_end() const { return end >= 0; } [[nodiscard]] Position locStart() const { return Position{start_line, start_column, start}; } + [[nodiscard]] BASE::position_t locStartLine(BASE::position_t default_value) const { return start >= 0 ? start_line : default_value; } [[nodiscard]] Position locEnd() const { return Position{end_line, end_column, end}; } + [[nodiscard]] BASE::position_t locEndLine(BASE::position_t default_value) const { return end >= 0 ? end_line : default_value; } + }; struct NodeExtra { bool parenthesized = false; @@ -71,6 +83,8 @@ namespace BabelParser::Node { [[nodiscard]] NodeExtra const &extra() const { return this->extra_; } [[nodiscard]] NodeExtra &extra() { return this->extra_; } [[nodiscard]] Position locStart() const { return this->pos_.locStart(); } + [[nodiscard]] BASE::position_t locStartLine(BASE::position_t default_value) const { return this->pos_.locStartLine(default_value); } + [[nodiscard]] BASE::position_t locEndLine(BASE::position_t default_value) const { return this->pos_.locEndLine(default_value); } [[nodiscard]] Position locEnd() const { return this->pos_.locEnd(); } template Position loc() const { @@ -81,6 +95,14 @@ namespace BabelParser::Node { } } template + BASE::position_t locLine(BASE::position_t default_value) const { + if constexpr (P == PositionType::Start) { + return this->locStartLine(default_value); + } else { + return this->locEndLine(default_value); + } + } + template bool has_loc() const { if constexpr (P == PositionType::Start) { return this->position().has_start(); @@ -160,7 +182,7 @@ public: bool ignore = false; bool printed = false; explicit Comment(Type type, PositionWithLineColumn const &start, PositionWithLineColumn const &end, BASE::UStringView value) : - Node(type, PositionInfo{start, end.index()}), + Node(type, PositionInfo{start, end}), value(value), start_(start), end_(end) {} From b94bad827706ec8b3f5853eb00c2ae7435bbbe60 Mon Sep 17 00:00:00 2001 From: imsenyu Date: Mon, 21 Apr 2025 00:07:29 +0800 Subject: [PATCH 5/7] test: fix babel-generator:regression/comment-before-parentheses-return-arg --- src/babel/babel-parser/tokenizer/tokenizer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/babel/babel-parser/tokenizer/tokenizer.hpp b/src/babel/babel-parser/tokenizer/tokenizer.hpp index d36590c..6d4e1b3 100644 --- a/src/babel/babel-parser/tokenizer/tokenizer.hpp +++ b/src/babel/babel-parser/tokenizer/tokenizer.hpp @@ -394,7 +394,7 @@ namespace BabelParser::Tokenizer { auto input = this->input.data(); auto const &length = this->length; auto pos = state.pos; - auto curLine = state.pos; + auto curLine = state.curLine; auto lineStart = state.lineStart; constexpr static SkipSpaceTable table = InitSkipSpaceTable(); From f997a2a3e41aa4d84818625a7682ba3315b088c3 Mon Sep 17 00:00:00 2001 From: imsenyu Date: Mon, 21 Apr 2025 00:19:33 +0800 Subject: [PATCH 6/7] test: fix babel-generator:comments/simple-statement-comment --- src/babel/babel-parser/parser/node.hpp | 8 +++---- src/babel/babel-parser/plugins/estree.hpp | 4 ++-- src/babel/babel-parser/types.hpp | 26 ++++++++++++++++------- src/babel/babel-parser/util/location.hpp | 12 +++++------ 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/babel/babel-parser/parser/node.hpp b/src/babel/babel-parser/parser/node.hpp index f0f560c..a30926b 100644 --- a/src/babel/babel-parser/parser/node.hpp +++ b/src/babel/babel-parser/parser/node.hpp @@ -113,7 +113,7 @@ namespace BabelParser { template PTR(T) finishNodeAt_impl(PTR(T) node, const Position &endLoc) { - node->position().end = endLoc.index(); + node->position().setEnd(endLoc); // if (this.optionFlags & OptionFlags.Ranges) node.range[1] = endLoc.index; if (this->state.lastCommentWSEnd < node->position().start) [[likely]] { DEBUG_PARSER_STAT_COUNT(CommentPosSkip) @@ -132,7 +132,7 @@ namespace BabelParser { template void resetStartLocation_impl(PTR(T) node, const Position &startLoc) { - node->position().start = startLoc.index(); + node->position().setStart(startLoc); // if (this.optionFlags & OptionFlags.Ranges) node.range[0] = startLoc.index; } @@ -141,7 +141,7 @@ namespace BabelParser { } void resetStartLocation_impl(Node::PositionInfo &startInfo, const Position &startLoc) { - startInfo.start = startLoc.index(); + startInfo.setStart(startLoc); // if (this.optionFlags & OptionFlags.Ranges) node.range[0] = startLoc.index; } @@ -152,7 +152,7 @@ namespace BabelParser { template void resetEndLocation_impl(PTR(T) node, Position const &endLoc) { - node->position().end = endLoc.index(); + node->position().setEnd(endLoc); // if (this.optionFlags & OptionFlags.Ranges) node.range[1] = endLoc.index; } diff --git a/src/babel/babel-parser/plugins/estree.hpp b/src/babel/babel-parser/plugins/estree.hpp index 803decc..f1e792c 100644 --- a/src/babel/babel-parser/plugins/estree.hpp +++ b/src/babel/babel-parser/plugins/estree.hpp @@ -272,10 +272,10 @@ namespace BabelParser::Plugins::ESTree { // @ts-expect-error mutate AST types node.value = funcNode; auto typeParameters = node.typeParameters; - if (typeParameters) { + if (typeParameters) [[unlikely]] { node.typeParameters = nullptr; funcNode->typeParameters = typeParameters; - funcNode->position().start = typeParameters->position().start; + funcNode->position().setStart(typeParameters->position().locStart()); } if constexpr (BabelTypes::IsClassPrivateMethod) { node.computed = false; diff --git a/src/babel/babel-parser/types.hpp b/src/babel/babel-parser/types.hpp index 0fa8634..7823b3f 100644 --- a/src/babel/babel-parser/types.hpp +++ b/src/babel/babel-parser/types.hpp @@ -28,9 +28,9 @@ namespace BabelParser::Node { BASE::position_t start; BASE::position_t end; BASE::position_t start_line; - BASE::position_t start_column; + // BASE::position_t start_column; BASE::position_t end_line; - BASE::position_t end_column; + // BASE::position_t end_column; explicit PositionInfo() : start(-1), @@ -38,23 +38,33 @@ namespace BabelParser::Node { explicit PositionInfo(Position start) : start(start.index()), start_line(start.line()), - start_column(start.column()), + // start_column(start.column()), end(-1) {} explicit PositionInfo(Position start, Position end) : start(start.index()), start_line(start.line()), - start_column(start.column()), + // start_column(start.column()), end(end.index()), - end_line(end.line()), - end_column(end.column()) + end_line(end.line()) + // end_column(end.column()) {} bool has_start() const { return start >= 0; } bool has_end() const { return end >= 0; } - [[nodiscard]] Position locStart() const { return Position{start_line, start_column, start}; } + [[nodiscard]] Position locStart() const { return Position{start_line, -1, start}; } [[nodiscard]] BASE::position_t locStartLine(BASE::position_t default_value) const { return start >= 0 ? start_line : default_value; } - [[nodiscard]] Position locEnd() const { return Position{end_line, end_column, end}; } + [[nodiscard]] Position locEnd() const { return Position{end_line, -1, end}; } [[nodiscard]] BASE::position_t locEndLine(BASE::position_t default_value) const { return end >= 0 ? end_line : default_value; } + void setStart(Position start) { + this->start = start.index(); + this->start_line = start.line(); + // this->start_column = start.column(); + } + void setEnd(Position end) { + this->end = end.index(); + this->end_line = end.line(); + // this->end_column = end.column(); + } }; struct NodeExtra { diff --git a/src/babel/babel-parser/util/location.hpp b/src/babel/babel-parser/util/location.hpp index 7a97511..d5d19da 100644 --- a/src/babel/babel-parser/util/location.hpp +++ b/src/babel/babel-parser/util/location.hpp @@ -9,15 +9,15 @@ namespace BabelParser::Util::Location { protected: BASE::position_t index_; BASE::position_t line_; - BASE::position_t column_; + // BASE::position_t column_; public: Position() = default; - explicit Position(BASE::position_t _line, BASE::position_t _column, BASE::position_t index) : line_(_line), column_(_column), index_(index) {} + explicit Position(BASE::position_t _line, BASE::position_t _column, BASE::position_t index) : line_(_line) /*, column_(_column)*/, index_(index) {} // explicit Position(BASE::position_t index) : index_(index) {} [[nodiscard]] BASE::position_t index() const { return index_; } [[nodiscard]] BASE::position_t line() const { return line_; } - [[nodiscard]] BASE::position_t column() const { return column_; } + // [[nodiscard]] BASE::position_t column() const { return column_; } [[nodiscard]] PositionWithLineColumn withLineColumn(BASE::UStringView input) const; }; inline std::pair resolveLineColumnFromIndex(BASE::UStringView input, BASE::position_t expectIndex) { @@ -51,10 +51,10 @@ namespace BabelParser::Util::Location { } class PositionWithLineColumn : public Position { // BASE::position_t line_; - // BASE::position_t column_; + BASE::position_t column_; public: - PositionWithLineColumn(BASE::position_t index, BASE::position_t line, BASE::position_t column) : Position(line, column, index)/*, line_(line), column_(column)*/ {} + PositionWithLineColumn(BASE::position_t index, BASE::position_t line, BASE::position_t column) : Position(line, column, index)/*, line_(line)*/, column_(column) {} PositionWithLineColumn(BASE::UStringView input, BASE::position_t index) : Position(0, 0, index) { auto [line, column] = resolveLineColumnFromIndex(input, index); line_ = line; @@ -66,6 +66,6 @@ namespace BabelParser::Util::Location { inline PositionWithLineColumn Position::withLineColumn(BASE::UStringView input) const { return PositionWithLineColumn{input, this->index()}; } inline Position createPositionWithColumnOffset(const Position &position, BASE::position_t columnOffset) { - return Position{position.line(), position.column() + columnOffset, position.index() + columnOffset}; + return Position{position.line(), -1, position.index() + columnOffset}; } } // namespace BabelParser::Util::Location From 1ef14662a502af884c2f92112ab013f00b1e04fc Mon Sep 17 00:00:00 2001 From: imsenyu Date: Mon, 21 Apr 2025 01:09:39 +0800 Subject: [PATCH 7/7] fix: comment position --- src/babel/babel-generator/printer.hpp | 8 ++-- src/babel/babel-parser/parser/comments.hpp | 26 +++++------ src/babel/babel-parser/types.hpp | 52 ++++++++++++++-------- 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/babel/babel-generator/printer.hpp b/src/babel/babel-generator/printer.hpp index 18ab36c..0476675 100644 --- a/src/babel/babel-generator/printer.hpp +++ b/src/babel/babel-generator/printer.hpp @@ -1373,10 +1373,10 @@ namespace BabelGenerator::Printer { size_t i = 0; for (auto iter = commentsHead; iter != nullptr; iter = iter->next(), i++) { auto &comment = *iter; - if (comment->commentPos != commentPos) [[unlikely]] { - --i; - continue; - } + // if (comment->commentPos != commentPos) [[unlikely]] { + // --i; + // continue; + // } PRINT_COMMENT_HINT::Value shouldPrint = this->_shouldPrintComment(comment /*, nextToken*/); if (shouldPrint == PRINT_COMMENT_HINT::DEFER) { hasLoc = false; diff --git a/src/babel/babel-parser/parser/comments.hpp b/src/babel/babel-parser/parser/comments.hpp index 81aff85..0e36e98 100644 --- a/src/babel/babel-parser/parser/comments.hpp +++ b/src/babel/babel-parser/parser/comments.hpp @@ -111,14 +111,14 @@ namespace BabelParser { auto comments = commentWS.comments; if (commentWS.leadingNode != nullptr || commentWS.trailingNode != nullptr) { if (commentWS.leadingNode != nullptr) { - setTrailingComments(commentWS.leadingNode, comments); + setTrailingComments(commentWS.leadingNode->makeComments(this->allocator.node()), comments); } if (commentWS.trailingNode != nullptr) { - setLeadingComments(commentWS.trailingNode, comments); + setLeadingComments(commentWS.trailingNode->makeComments(this->allocator.node()), comments); } } else { /*:: invariant(commentWS.containingNode !== null) */ - auto node = commentWS.containingNode; + auto node = commentWS.containingNode->makeComments(this->allocator.node()); auto commentStart = commentWS.start; if (this->input[this->offsetToSourcePos(commentStart) - 1] == CharCodes::comma) { // If a commentWhitespace follows a comma and the containingNode allows @@ -173,16 +173,16 @@ namespace BabelParser { case Node::Type::ImportDeclaration: adjustInnerComments(node, NODES(NODEAS(node, ImportDeclaration)->specifiers), commentWS); break; - // case "TSEnumDeclaration": - // if (!process.env.BABEL_8_BREAKING) { - // adjustInnerComments(node, node.members, commentWS); - // } else { - // setInnerComments(node, comments); - // } - // break; - // case "TSEnumBody": - // adjustInnerComments(node, node.members, commentWS); - // break; + case Node::Type::TSEnumDeclaration: + if (!BASE::process::env.BABEL_8_BREAKING) { + adjustInnerComments(node, NODES(NODEAS(node, TSEnumDeclaration)->members), commentWS); + } else { + setInnerComments(node, comments); + } + break; + case Node::Type::TSEnumBody: + adjustInnerComments(node, NODES(NODEAS(node, TSEnumBody)->members), commentWS); + break; default: { setInnerComments(node, comments); diff --git a/src/babel/babel-parser/types.hpp b/src/babel/babel-parser/types.hpp index 7823b3f..b7f8351 100644 --- a/src/babel/babel-parser/types.hpp +++ b/src/babel/babel-parser/types.hpp @@ -71,12 +71,27 @@ namespace BabelParser::Node { bool parenthesized = false; void setParenthesized() { this->parenthesized = true; } }; + struct CommentInfo { + BASE::LinkedItem* leading; + BASE::LinkedItem* inner; + BASE::LinkedItem* trailing; + template + BASE::LinkedItem*& ref() { + if constexpr (TYPE == CommentPosition::Leading) return this->leading; + else if constexpr (TYPE == CommentPosition::Inner) return this->inner; + else if constexpr (TYPE == CommentPosition::Trailing) return this->trailing; + else { + unreachable(); + } + } + }; class Node { Type type_; - CommentPosition::Type commentPosBits = CommentPosition::Unknown; + // CommentPosition::Type commentPosBits = CommentPosition::Unknown; NodeExtra extra_; PositionInfo pos_; - BASE::LinkedItem *comment = nullptr; + CommentInfo *comments = nullptr; + // BASE::LinkedItem *comment = nullptr; #ifdef NDEBUG #else virtual Type vtype() const { return this->type_; } @@ -124,6 +139,12 @@ namespace BabelParser::Node { inline void unshiftComments(BASE::LinkedItem *comment); template [[nodiscard]] inline BASE::LinkedItem *getComments() const; + Node* makeComments(BASE::Memory::Allocator* allocator) { + if (!this->comments) { + this->comments = allocator->template allocate(1); + } + return this; + } void unshiftLeadingComments(BASE::LinkedItem *comment) { this->unshiftComments(comment); } void unshiftInnerComments(BASE::LinkedItem *comment) { this->unshiftComments(comment); } void unshiftTrailingComments(BASE::LinkedItem *comment) { this->unshiftComments(comment); } @@ -185,7 +206,7 @@ public: class Comment : public Node { public: - CommentPosition::Value commentPos = CommentPosition::Unknown; + // CommentPosition::Value commentPos = CommentPosition::Unknown; BASE::UStringView value; PositionWithLineColumn start_; PositionWithLineColumn end_; @@ -3648,31 +3669,26 @@ public: // impl template inline void Node::unshiftComments(BASE::LinkedItem *comment) { - this->commentPosBits |= TYPE; auto next = &comment; while (*next) { - (***next).commentPos = TYPE; + // (***next).commentPos = TYPE; next = &(*next)->next(); } - if (this->comment == nullptr) { - this->comment = comment; + auto& ref = this->comments->ref(); + if (ref == nullptr) { + ref = comment; } else { - *next = this->comment; - this->comment = comment; + *next = ref; + ref = comment; } } template [[nodiscard]] inline BASE::LinkedItem *Node::getComments() const { - if (this->commentPosBits & TYPE) [[unlikely]] { - auto comment = this->comment; - while (comment != nullptr) [[unlikely]] { - if ((*comment)->commentPos == TYPE) { - return comment; - } - comment = comment->next(); - } + if (this->comments) { + return this->comments->ref(); + } else { + return nullptr; } - return nullptr; } inline void ExpressionStatement::format(Writer::NodeWriter &writer) const { writer.node("expression", this->expression);