[clang] [clang-format] Preserve trailing NOLINTEND placement with SeparateDefinitionBlocks (PR #190741)
Jiaqi He via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 16 19:04:23 PDT 2026
https://github.com/heturing updated https://github.com/llvm/llvm-project/pull/190741
>From 862abd37c0b0760d496c1b91e6665a8c65cd22da Mon Sep 17 00:00:00 2001
From: Jiaqi He <heturing at gmail.com>
Date: Mon, 6 Apr 2026 23:36:15 -0600
Subject: [PATCH 1/3] [clang-format] Preserve trailing NOLINTEND placement with
SeparateDefinitionBlocks
---
clang/include/clang/Format/Format.h | 2 ++
clang/lib/Format/DefinitionBlockSeparator.cpp | 3 ++-
clang/lib/Format/Format.cpp | 20 +++++++++++++++++++
.../Format/DefinitionBlockSeparatorTest.cpp | 8 ++++++++
4 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 48ce5aa2bdfa1..cdd704e199cff 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -6430,6 +6430,8 @@ inline StringRef getLanguageName(FormatStyle::LanguageKind Language) {
bool isClangFormatOn(StringRef Comment);
bool isClangFormatOff(StringRef Comment);
+bool isNoLintEnd(StringRef Comment);
+bool isNoLintBegin(StringRef Comment);
} // end namespace format
} // end namespace clang
diff --git a/clang/lib/Format/DefinitionBlockSeparator.cpp b/clang/lib/Format/DefinitionBlockSeparator.cpp
index 855f2efad1e53..e1fab2b088225 100644
--- a/clang/lib/Format/DefinitionBlockSeparator.cpp
+++ b/clang/lib/Format/DefinitionBlockSeparator.cpp
@@ -147,7 +147,8 @@ void DefinitionBlockSeparator::separateBlocks(
return false;
if (const auto *Tok = OperateLine->First;
- Tok->is(tok::comment) && !isClangFormatOn(Tok->TokenText)) {
+ Tok->is(tok::comment) && !isClangFormatOn(Tok->TokenText) &&
+ !isNoLintEnd(Tok->TokenText)) {
return true;
}
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 42190604b3881..e68b867c73f82 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -4768,5 +4768,25 @@ bool isClangFormatOff(StringRef Comment) {
return isClangFormatOnOff(Comment, /*On=*/false);
}
+static bool isNoLintBeginEnd(StringRef Comment, bool On) {
+ if (Comment == (On ? "/* NOLINTBEGIN */" : "/* NOLINTEND */"))
+ return true;
+
+ static const char NoLintBegin[] = "// NOLINTBEGIN";
+ static const char NoLintEnd[] = "// NOLINTEND";
+ const unsigned Size = (On ? sizeof NoLintBegin : sizeof NoLintEnd) - 1;
+
+ return Comment.starts_with(On ? NoLintBegin : NoLintEnd) &&
+ (Comment.size() == Size || Comment[Size] == ':');
+}
+
+bool isNoLintEnd(StringRef Comment) {
+ return isNoLintBeginEnd(Comment, /*On=*/false);
+}
+
+bool isNoLintBegin(StringRef Comment) {
+ return isNoLintBeginEnd(Comment, /*On=*/true);
+}
+
} // namespace format
} // namespace clang
diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
index b1b4b1d047523..e5b7a2b256395 100644
--- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
+++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
@@ -291,6 +291,14 @@ TEST_F(DefinitionBlockSeparatorTest, Always) {
"struct E {};",
Style);
+ verifyFormat("// NOLINTBEGIN\n"
+ "int x = 1;\n"
+ "int y = 2;\n"
+ "// NOLINTEND\n"
+ "\n"
+ "void some_function() {}\n",
+ Style);
+
std::string Prefix = "namespace {\n";
std::string Infix = "\n"
"// Enum test1\n"
>From e779368d776e922ff7f58fa04a6e593e878b2dde Mon Sep 17 00:00:00 2001
From: Jiaqi He <heturing at gmail.com>
Date: Tue, 7 Apr 2026 17:55:03 -0600
Subject: [PATCH 2/3] [clang-format] Removed unused function and unsupported
comment type
---
clang/include/clang/Format/Format.h | 1 -
clang/lib/Format/Format.cpp | 21 ++++---------------
.../Format/DefinitionBlockSeparatorTest.cpp | 12 +++++------
3 files changed, 10 insertions(+), 24 deletions(-)
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index cdd704e199cff..6a14fc995efd6 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -6431,7 +6431,6 @@ inline StringRef getLanguageName(FormatStyle::LanguageKind Language) {
bool isClangFormatOn(StringRef Comment);
bool isClangFormatOff(StringRef Comment);
bool isNoLintEnd(StringRef Comment);
-bool isNoLintBegin(StringRef Comment);
} // end namespace format
} // end namespace clang
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index e68b867c73f82..0a080bbece682 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -4768,24 +4768,11 @@ bool isClangFormatOff(StringRef Comment) {
return isClangFormatOnOff(Comment, /*On=*/false);
}
-static bool isNoLintBeginEnd(StringRef Comment, bool On) {
- if (Comment == (On ? "/* NOLINTBEGIN */" : "/* NOLINTEND */"))
- return true;
-
- static const char NoLintBegin[] = "// NOLINTBEGIN";
- static const char NoLintEnd[] = "// NOLINTEND";
- const unsigned Size = (On ? sizeof NoLintBegin : sizeof NoLintEnd) - 1;
-
- return Comment.starts_with(On ? NoLintBegin : NoLintEnd) &&
- (Comment.size() == Size || Comment[Size] == ':');
-}
-
bool isNoLintEnd(StringRef Comment) {
- return isNoLintBeginEnd(Comment, /*On=*/false);
-}
-
-bool isNoLintBegin(StringRef Comment) {
- return isNoLintBeginEnd(Comment, /*On=*/true);
+ static const char NoLintEnd[] = "// NOLINTEND";
+ const unsigned Size = sizeof NoLintEnd - 1;
+ return Comment.starts_with(NoLintEnd) &&
+ (Comment.size() == Size || Comment[Size] == '(');
}
} // namespace format
diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
index e5b7a2b256395..32aea2f4d2b14 100644
--- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
+++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
@@ -292,12 +292,12 @@ TEST_F(DefinitionBlockSeparatorTest, Always) {
Style);
verifyFormat("// NOLINTBEGIN\n"
- "int x = 1;\n"
- "int y = 2;\n"
- "// NOLINTEND\n"
- "\n"
- "void some_function() {}\n",
- Style);
+ "int x = 1;\n"
+ "int y = 2;\n"
+ "// NOLINTEND\n"
+ "\n"
+ "void some_function() {}\n",
+ Style);
std::string Prefix = "namespace {\n";
std::string Infix = "\n"
>From 9e2ce0c5e50d44218bb44a449cc122669f82aebe Mon Sep 17 00:00:00 2001
From: Jiaqi He <heturing at gmail.com>
Date: Thu, 16 Apr 2026 19:57:49 -0600
Subject: [PATCH 3/3] [clang-format] Preserve clearly trailing comment blocks
---
clang/include/clang/Format/Format.h | 1 -
clang/lib/Format/DefinitionBlockSeparator.cpp | 8 ++++---
clang/lib/Format/Format.cpp | 7 ------
.../Format/DefinitionBlockSeparatorTest.cpp | 24 ++++++++++++++++++-
4 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 6a14fc995efd6..48ce5aa2bdfa1 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -6430,7 +6430,6 @@ inline StringRef getLanguageName(FormatStyle::LanguageKind Language) {
bool isClangFormatOn(StringRef Comment);
bool isClangFormatOff(StringRef Comment);
-bool isNoLintEnd(StringRef Comment);
} // end namespace format
} // end namespace clang
diff --git a/clang/lib/Format/DefinitionBlockSeparator.cpp b/clang/lib/Format/DefinitionBlockSeparator.cpp
index e1fab2b088225..0a085042b1c18 100644
--- a/clang/lib/Format/DefinitionBlockSeparator.cpp
+++ b/clang/lib/Format/DefinitionBlockSeparator.cpp
@@ -147,9 +147,11 @@ void DefinitionBlockSeparator::separateBlocks(
return false;
if (const auto *Tok = OperateLine->First;
- Tok->is(tok::comment) && !isClangFormatOn(Tok->TokenText) &&
- !isNoLintEnd(Tok->TokenText)) {
- return true;
+ Tok->is(tok::comment) && !isClangFormatOn(Tok->TokenText)) {
+ const bool IsEndComment =
+ Tok->NewlinesBefore == 1 && OperateIndex + 1 < Lines.size() &&
+ Lines[OperateIndex + 1]->First->NewlinesBefore > 1;
+ return !IsEndComment;
}
// A single line identifier that is not in the last line.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 0a080bbece682..42190604b3881 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -4768,12 +4768,5 @@ bool isClangFormatOff(StringRef Comment) {
return isClangFormatOnOff(Comment, /*On=*/false);
}
-bool isNoLintEnd(StringRef Comment) {
- static const char NoLintEnd[] = "// NOLINTEND";
- const unsigned Size = sizeof NoLintEnd - 1;
- return Comment.starts_with(NoLintEnd) &&
- (Comment.size() == Size || Comment[Size] == '(');
-}
-
} // namespace format
} // namespace clang
diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
index 32aea2f4d2b14..b42605927ec61 100644
--- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
+++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp
@@ -297,7 +297,29 @@ TEST_F(DefinitionBlockSeparatorTest, Always) {
"// NOLINTEND\n"
"\n"
"void some_function() {}\n",
- Style);
+ Style,
+ "// NOLINTBEGIN\n"
+ "int x = 1;\n"
+ "int y = 2;\n"
+ "// NOLINTEND\n"
+ "\n"
+ "void some_function() {}\n",
+ false);
+
+ verifyFormat("int x = 0;\n"
+ "int y = 0;\n"
+ "// trailing comment 1\n"
+ "// trailing comment 2\n"
+ "\n"
+ "void some_function() {}\n",
+ Style,
+ "int x = 0;\n"
+ "int y = 0;\n"
+ "// trailing comment 1\n"
+ "// trailing comment 2\n"
+ "\n"
+ "void some_function() {}\n",
+ false);
std::string Prefix = "namespace {\n";
std::string Infix = "\n"
More information about the cfe-commits
mailing list