From b8737e3f117d44a56e5d588facd2339eea5debf1 Mon Sep 17 00:00:00 2001 From: jayson wang Date: Mon, 23 Feb 2026 22:31:38 +0800 Subject: [PATCH] Add the disable-next-line instruction to disable formatting for the next line --- .../src/Format/Analyzer/FormatDocAnalyze.cpp | 21 ++++++ CodeFormatCore/src/Format/FormatState.cpp | 27 ++++--- Test/src/FormatResult_unitest.cpp | 70 +++++++++++++++++++ 3 files changed, 109 insertions(+), 9 deletions(-) diff --git a/CodeFormatCore/src/Format/Analyzer/FormatDocAnalyze.cpp b/CodeFormatCore/src/Format/Analyzer/FormatDocAnalyze.cpp index f7d07f4a..1d78fc15 100644 --- a/CodeFormatCore/src/Format/Analyzer/FormatDocAnalyze.cpp +++ b/CodeFormatCore/src/Format/Analyzer/FormatDocAnalyze.cpp @@ -105,6 +105,27 @@ void FormatDocAnalyze::AnalyzeDocFormat(LuaSyntaxNode n, FormatState &f, const L AddIgnoreRange(IndexRange(n.GetIndex(), nextNode.GetIndex()), t); } + break; + } else if (action == "disable-next-line") { + const std::size_t ignoreLine = n.GetStartLine(t) + 1; + auto isIgnore = [&] (const LuaSyntaxNode node) -> bool { + return !node.IsNull(t) && node.GetStartLine(t) == ignoreLine; + }; + + auto endNode = n.GetNextSibling(t); + while (isIgnore(endNode)) { + if (endNode.GetEndLine(t) > ignoreLine) { + endNode = endNode.GetFirstChild(t); + } else if (const auto next = endNode.GetNextSibling(t); isIgnore(next)) { + endNode.ToNext(t); + } else { + break; + } + } + + if (!endNode.IsNull(t)) { + AddIgnoreRange(IndexRange(n.GetIndex(), endNode.GetIndex()), t); + } break; } else if (action == "on") { state = ParseState::List; diff --git a/CodeFormatCore/src/Format/FormatState.cpp b/CodeFormatCore/src/Format/FormatState.cpp index e7041bcb..21d7f90c 100644 --- a/CodeFormatCore/src/Format/FormatState.cpp +++ b/CodeFormatCore/src/Format/FormatState.cpp @@ -156,21 +156,20 @@ void FormatState::DfsForeach(std::vector &startNodes, resolve.Reset(); if (traverse.Event == TraverseEvent::Enter) { traverseStack.back().Event = TraverseEvent::Exit; - if (_ignoreRange.EndIndex != 0) { - auto index = traverse.Node.GetIndex(); - if (index >= _ignoreRange.StartIndex && index <= _ignoreRange.EndIndex) { - continue; - } - } - for (auto &analyzer: _analyzers) { - analyzer->Query(*this, traverse.Node, t, resolve); - } + + // We need to first add all child nodes to the traversal list. auto children = traverse.Node.GetChildren(t); // 不采用 for (auto rIt = children.rbegin(); rIt != children.rend(); rIt++) { traverseStack.emplace_back(*rIt, TraverseEvent::Enter); } + // For the code that has already been ignored, we also need to + // analyze it to determine how to indent next. + for (auto &analyzer: _analyzers) { + analyzer->Query(*this, traverse.Node, t, resolve); + } + if (resolve.GetIndentStrategy() != IndentStrategy::None) { auto indent = resolve.GetIndent(); if (indent == 0 && resolve.GetIndentStrategy() != IndentStrategy::Absolute) { @@ -204,6 +203,16 @@ void FormatState::DfsForeach(std::vector &startNodes, } } + // Skip the nodes that need to be ignored. Since the range of ignoring starts + // from the @format node, we need to execute enterHandle once when entering + // the ignore range to output all the ignored content. + if (_ignoreRange.EndIndex != 0) { + auto index = traverse.Node.GetIndex(); + if (index > _ignoreRange.StartIndex && index <= _ignoreRange.EndIndex) { + continue; + } + } + enterHandle(traverse.Node, t, resolve); if (!_foreachContinue) { return; diff --git a/Test/src/FormatResult_unitest.cpp b/Test/src/FormatResult_unitest.cpp index 3a5e0886..e7bf6954 100644 --- a/Test/src/FormatResult_unitest.cpp +++ b/Test/src/FormatResult_unitest.cpp @@ -891,6 +891,76 @@ local t = { lcc = 123, gjopepgo = 123, } +)")); + + EXPECT_TRUE(TestHelper::TestFormatted( + R"( +local t = { + ---@format disable-next-line + foo = 123, bar = 234, + baz = 345, +} +)", + R"( +local t = { + ---@format disable-next-line + foo = 123, bar = 234, + baz = 345, +} +)")); + + EXPECT_TRUE(TestHelper::TestFormatted( + R"( +local t = { + ---@format disable-next-line + foo = function( a, b ) + return { + foo = a, + bar = b, + } + end, + bar = 1, +} +)", + R"( +local t = { + ---@format disable-next-line + foo = function( a, b ) + return { + foo = a, + bar = b, + } + end, + bar = 1, +} +)")); + + EXPECT_TRUE(TestHelper::TestFormatted( + R"( +local t = { + ---@format disable-next-line + foo = function( a, b ) + return { + foo = a, + bar = b, + } + end, + bar = 1, +} +---@format disable-next-line +)", + R"( +local t = { + ---@format disable-next-line + foo = function( a, b ) + return { + foo = a, + bar = b, + } + end, + bar = 1, +} +---@format disable-next-line )")); }