[clang] [clang-format] Add MainIncludeChar option. (PR #78752)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 21 12:56:39 PST 2024
https://github.com/j-jorge updated https://github.com/llvm/llvm-project/pull/78752
>From 7e06f6b5c5f5a156ce01a8fe219b8f5b6b8c9a24 Mon Sep 17 00:00:00 2001
From: Julien Jorge <julien.jorge at stuff-o-matic.com>
Date: Fri, 19 Jan 2024 18:44:58 +0100
Subject: [PATCH] [clang-format] Add MainIncludeChar option.
Resolves #27008, #39735, #53013, #63619.
---
clang/docs/ClangFormatStyleOptions.rst | 19 +++
clang/include/clang/Format/Format.h | 1 +
.../clang/Tooling/Inclusions/IncludeStyle.h | 23 ++++
clang/lib/Format/Format.cpp | 2 +
.../lib/Tooling/Inclusions/HeaderIncludes.cpp | 14 ++-
clang/lib/Tooling/Inclusions/IncludeStyle.cpp | 7 ++
clang/unittests/Format/SortIncludesTest.cpp | 108 +++++++++++++++++-
7 files changed, 171 insertions(+), 3 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 4dc0de3a90f265..ac74db2c2bdf58 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4116,6 +4116,25 @@ the configuration (without a prefix: ``Auto``).
A(z); -> z;
A(a, b); // will not be expanded.
+.. _MainIncludeChar:
+
+**MainIncludeChar** (``MainIncludeCharDiscriminator``) :versionbadge:`clang-format 18` :ref:`¶ <MainIncludeChar>`
+ When guessing whether a #include is the "main" include, only the include
+ directives that use the specified character are considered.
+
+ Possible values:
+
+ * ``MICD_Quote`` (in configuration: ``Quote``)
+ Main include uses quotes: ``#include "foo.hpp"`` (the default).
+
+ * ``MICD_AngleBracket`` (in configuration: ``AngleBracket``)
+ Main include uses angle brackets: ``#include <foo.hpp>``.
+
+ * ``MICD_Any`` (in configuration: ``Any``)
+ Main include uses either quotes or angle brackets.
+
+
+
.. _MaxEmptyLinesToKeep:
**MaxEmptyLinesToKeep** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ <MaxEmptyLinesToKeep>`
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index bc9eecd42f9ebf..a37d5f28c53e9b 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4842,6 +4842,7 @@ struct FormatStyle {
R.IncludeStyle.IncludeIsMainRegex &&
IncludeStyle.IncludeIsMainSourceRegex ==
R.IncludeStyle.IncludeIsMainSourceRegex &&
+ IncludeStyle.MainIncludeChar == R.IncludeStyle.MainIncludeChar &&
IndentAccessModifiers == R.IndentAccessModifiers &&
IndentCaseBlocks == R.IndentCaseBlocks &&
IndentCaseLabels == R.IndentCaseLabels &&
diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
index d6b2b0192477dc..c91e4a6b0ac54a 100644
--- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -151,6 +151,21 @@ struct IncludeStyle {
/// before any other include.
/// \version 10
std::string IncludeIsMainSourceRegex;
+
+ /// Character to consider in the include directives for the main header.
+ enum MainIncludeCharDiscriminator : int8_t {
+ /// Main include uses quotes: ``#include "foo.hpp"`` (the default).
+ MICD_Quote,
+ /// Main include uses angle brackets: ``#include <foo.hpp>``.
+ MICD_AngleBracket,
+ /// Main include uses either quotes or angle brackets.
+ MICD_Any
+ };
+
+ /// When guessing whether a #include is the "main" include, only the include
+ /// directives that use the specified character are considered.
+ /// \version 18
+ MainIncludeCharDiscriminator MainIncludeChar;
};
} // namespace tooling
@@ -174,6 +189,14 @@ struct ScalarEnumerationTraits<
enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value);
};
+template <>
+struct ScalarEnumerationTraits<
+ clang::tooling::IncludeStyle::MainIncludeCharDiscriminator> {
+ static void enumeration(
+ IO &IO,
+ clang::tooling::IncludeStyle::MainIncludeCharDiscriminator &Value);
+};
+
} // namespace yaml
} // namespace llvm
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index ff326dc784783b..3d0eaf74e14dba 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1032,6 +1032,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
IO.mapOptional("Macros", Style.Macros);
+ IO.mapOptional("MainIncludeChar", Style.IncludeStyle.MainIncludeChar);
IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
IO.mapOptional("NamespaceMacros", Style.NamespaceMacros);
@@ -1515,6 +1516,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
{".*", 1, 0, false}};
LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
+ LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
LLVMStyle.IndentAccessModifiers = false;
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentCaseBlocks = false;
diff --git a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
index d275222ac6b587..4313da66efc0b7 100644
--- a/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ b/clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -234,8 +234,18 @@ int IncludeCategoryManager::getSortIncludePriority(StringRef IncludeName,
return Ret;
}
bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
- if (!IncludeName.starts_with("\""))
- return false;
+ switch (Style.MainIncludeChar) {
+ case IncludeStyle::MICD_Quote:
+ if (!IncludeName.starts_with("\""))
+ return false;
+ break;
+ case IncludeStyle::MICD_AngleBracket:
+ if (!IncludeName.starts_with("<"))
+ return false;
+ break;
+ case IncludeStyle::MICD_Any:
+ break;
+ }
IncludeName =
IncludeName.drop_front(1).drop_back(1); // remove the surrounding "" or <>
diff --git a/clang/lib/Tooling/Inclusions/IncludeStyle.cpp b/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
index da5bb00d1013a6..05dfb50589de0c 100644
--- a/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
+++ b/clang/lib/Tooling/Inclusions/IncludeStyle.cpp
@@ -28,5 +28,12 @@ void ScalarEnumerationTraits<IncludeStyle::IncludeBlocksStyle>::enumeration(
IO.enumCase(Value, "Regroup", IncludeStyle::IBS_Regroup);
}
+void ScalarEnumerationTraits<IncludeStyle::MainIncludeCharDiscriminator>::
+ enumeration(IO &IO, IncludeStyle::MainIncludeCharDiscriminator &Value) {
+ IO.enumCase(Value, "Quote", IncludeStyle::MICD_Quote);
+ IO.enumCase(Value, "AngleBracket", IncludeStyle::MICD_AngleBracket);
+ IO.enumCase(Value, "Any", IncludeStyle::MICD_Any);
+}
+
} // namespace yaml
} // namespace llvm
diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp
index ec142e03b12854..7d0dace964ce14 100644
--- a/clang/unittests/Format/SortIncludesTest.cpp
+++ b/clang/unittests/Format/SortIncludesTest.cpp
@@ -973,7 +973,113 @@ TEST_F(SortIncludesTest,
std::string Code = "#include \"b.h\"\r\n"
"\r\n"
"#include <a.h>\r\n";
- EXPECT_EQ(Code, sort(Code, "input.h", 0));
+ EXPECT_EQ(Code, sort(Code, "input.h", 1));
+}
+
+TEST_F(SortIncludesTest, MainIncludeChar) {
+ std::string Code = "#include <a>\n"
+ "#include \"quote/input.h\"\n"
+ "#include <angle-bracket/input.h>\n";
+
+ // Default behavior
+ EXPECT_EQ("#include \"quote/input.h\"\n"
+ "#include <a>\n"
+ "#include <angle-bracket/input.h>\n",
+ sort(Code, "input.cc", 1));
+
+ Style.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
+ EXPECT_EQ("#include \"quote/input.h\"\n"
+ "#include <a>\n"
+ "#include <angle-bracket/input.h>\n",
+ sort(Code, "input.cc", 1));
+
+ Style.MainIncludeChar = tooling::IncludeStyle::MICD_AngleBracket;
+ EXPECT_EQ("#include <angle-bracket/input.h>\n"
+ "#include \"quote/input.h\"\n"
+ "#include <a>\n",
+ sort(Code, "input.cc", 1));
+}
+
+TEST_F(SortIncludesTest, MainIncludeCharAnyPickQuote) {
+ Style.MainIncludeChar = tooling::IncludeStyle::MICD_Any;
+ EXPECT_EQ("#include \"input.h\"\n"
+ "#include <a>\n"
+ "#include <b>\n",
+ sort("#include <a>\n"
+ "#include \"input.h\"\n"
+ "#include <b>\n", "input.cc", 1));
+}
+
+TEST_F(SortIncludesTest, MainIncludeCharAnyPickAngleBracket) {
+ Style.MainIncludeChar = tooling::IncludeStyle::MICD_Any;
+ EXPECT_EQ("#include <input.h>\n"
+ "#include <a>\n"
+ "#include <b>\n",
+ sort("#include <a>\n"
+ "#include <input.h>\n"
+ "#include <b>\n", "input.cc", 1));
+}
+
+TEST_F(SortIncludesTest, MainIncludeCharQuoteAndRegroup) {
+ Style.IncludeCategories = {{"lib-a", 1, 0, false},
+ {"lib-b", 2, 0, false},
+ {"lib-c", 3, 0, false}};
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
+ Style.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
+
+ EXPECT_EQ("#include \"lib-b/input.h\"\n"
+ "\n"
+ "#include <lib-a/h-1.h>\n"
+ "#include <lib-a/h-3.h>\n"
+ "#include <lib-a/input.h>\n"
+ "\n"
+ "#include <lib-b/h-1.h>\n"
+ "#include <lib-b/h-3.h>\n"
+ "\n"
+ "#include <lib-c/h-1.h>\n"
+ "#include <lib-c/h-2.h>\n"
+ "#include <lib-c/h-3.h>\n",
+ sort("#include <lib-c/h-1.h>\n"
+ "#include <lib-c/h-2.h>\n"
+ "#include <lib-c/h-3.h>\n"
+ "#include <lib-b/h-1.h>\n"
+ "#include \"lib-b/input.h\"\n"
+ "#include <lib-b/h-3.h>\n"
+ "#include <lib-a/h-1.h>\n"
+ "#include <lib-a/input.h>\n"
+ "#include <lib-a/h-3.h>\n",
+ "input.cc"));
+}
+
+TEST_F(SortIncludesTest, MainIncludeCharAngleBracketAndRegroup) {
+ Style.IncludeCategories = {{"lib-a", 1, 0, false},
+ {"lib-b", 2, 0, false},
+ {"lib-c", 3, 0, false}};
+ Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
+ Style.MainIncludeChar = tooling::IncludeStyle::MICD_AngleBracket;
+
+ EXPECT_EQ("#include <lib-a/input.h>\n"
+ "\n"
+ "#include <lib-a/h-1.h>\n"
+ "#include <lib-a/h-3.h>\n"
+ "\n"
+ "#include \"lib-b/input.h\"\n"
+ "#include <lib-b/h-1.h>\n"
+ "#include <lib-b/h-3.h>\n"
+ "\n"
+ "#include <lib-c/h-1.h>\n"
+ "#include <lib-c/h-2.h>\n"
+ "#include <lib-c/h-3.h>\n",
+ sort("#include <lib-c/h-1.h>\n"
+ "#include <lib-c/h-2.h>\n"
+ "#include <lib-c/h-3.h>\n"
+ "#include <lib-b/h-1.h>\n"
+ "#include \"lib-b/input.h\"\n"
+ "#include <lib-b/h-3.h>\n"
+ "#include <lib-a/h-1.h>\n"
+ "#include <lib-a/input.h>\n"
+ "#include <lib-a/h-3.h>\n",
+ "input.cc"));
}
TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) {
More information about the cfe-commits
mailing list