[llvm-branch-commits] [clang] 3395a33 - [clang-format] add case aware include sorting
Marek Kurdej via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jan 25 09:57:39 PST 2021
Author: Lukas Barth
Date: 2021-01-25T18:53:22+01:00
New Revision: 3395a336b02538d0bb768ccfae11c9b6151b102e
URL: https://github.com/llvm/llvm-project/commit/3395a336b02538d0bb768ccfae11c9b6151b102e
DIFF: https://github.com/llvm/llvm-project/commit/3395a336b02538d0bb768ccfae11c9b6151b102e.diff
LOG: [clang-format] add case aware include sorting
* Adds an option to [clang-format] which sorts
headers in an alphabetical manner using case
only for tie-breakers. The options is off by
default in favor of the current ASCIIbetical
sorting style.
Reviewed By: curdeius, HazardyKnusperkeks
Differential Revision: https://reviews.llvm.org/D95017
Added:
Modified:
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Tooling/Inclusions/IncludeStyle.h
clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/SortIncludesTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 3141dd5510fc..d5ce1b7b2e8e 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -2282,6 +2282,26 @@ the configuration (without a prefix: ``Auto``).
``ClassImpl.hpp`` would not have the main include file put on top
before any other include.
+**IncludeSortAlphabetically** (``bool``)
+ Specify if sorting should be done in an alphabetical and
+ case sensitive fashion.
+
+ When ``false``, includes are sorted in an ASCIIbetical
+ fashion.
+ When ``true``, includes are sorted in an alphabetical
+ fashion with case used as a tie-breaker.
+
+ .. code-block:: c++
+
+ false: true:
+ #include "A/B.h" vs. #include "A/B.h"
+ #include "A/b.h" #include "A/b.h"
+ #include "B/A.h" #include "a/b.h"
+ #include "B/a.h" #include "B/A.h"
+ #include "a/b.h" #include "B/a.h"
+
+ This option is off by default.
+
**IndentCaseBlocks** (``bool``)
Indent case label blocks one level from the case label.
diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
index 4caaf4121f15..652a7b61a0a4 100644
--- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -147,6 +147,26 @@ struct IncludeStyle {
/// ``ClassImpl.hpp`` would not have the main include file put on top
/// before any other include.
std::string IncludeIsMainSourceRegex;
+
+ /// Specify if sorting should be done in an alphabetical and
+ /// case sensitive fashion.
+ ///
+ /// When ``false``, includes are sorted in an ASCIIbetical
+ /// fashion.
+ /// When ``true``, includes are sorted in an alphabetical
+ /// fashion with case used as a tie-breaker.
+ ///
+ /// \code
+ /// false: true:
+ /// #include "A/B.h" vs. #include "A/B.h"
+ /// #include "A/b.h" #include "A/b.h"
+ /// #include "B/A.h" #include "a/b.h"
+ /// #include "B/a.h" #include "B/A.h"
+ /// #include "a/b.h" #include "B/a.h"
+ /// \endcode
+ ///
+ /// This option is off by default.
+ bool IncludeSortAlphabetically;
};
} // namespace tooling
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index cd1c6e4f6023..0986ef845a4e 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -571,6 +571,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
IO.mapOptional("IncludeIsMainSourceRegex",
Style.IncludeStyle.IncludeIsMainSourceRegex);
+ IO.mapOptional("IncludeSortAlphabetically",
+ Style.IncludeStyle.IncludeSortAlphabetically);
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels);
@@ -940,6 +942,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
{".*", 1, 0, false}};
LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
+ LLVMStyle.IncludeStyle.IncludeSortAlphabetically = false;
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentCaseBlocks = false;
LLVMStyle.IndentGotoLabels = true;
@@ -2194,10 +2197,23 @@ static void sortCppIncludes(const FormatStyle &Style,
for (unsigned i = 0, e = Includes.size(); i != e; ++i) {
Indices.push_back(i);
}
- llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
- return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
- });
+
+ if (Style.IncludeStyle.IncludeSortAlphabetically) {
+ llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
+ const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
+ const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
+ return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
+ Includes[LHSI].Filename) <
+ std::tie(Includes[RHSI].Priority, RHSFilenameLower,
+ Includes[RHSI].Filename);
+ });
+ } else {
+ llvm::stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
+ return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
+ std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
+ });
+ }
+
// The index of the include on which the cursor will be put after
// sorting/deduplicating.
unsigned CursorIndex;
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 0c37d1188f15..cbb368d4f605 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -15145,6 +15145,8 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(DeriveLineEnding);
CHECK_PARSE_BOOL(DerivePointerAlignment);
CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding");
+ CHECK_PARSE_BOOL_FIELD(IncludeStyle.IncludeSortAlphabetically,
+ "IncludeSortAlphabetically");
CHECK_PARSE_BOOL(DisableFormat);
CHECK_PARSE_BOOL(IndentCaseLabels);
CHECK_PARSE_BOOL(IndentCaseBlocks);
diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp
index 41ff7afad10e..a506218f537d 100644
--- a/clang/unittests/Format/SortIncludesTest.cpp
+++ b/clang/unittests/Format/SortIncludesTest.cpp
@@ -598,6 +598,49 @@ TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) {
"a.cc"));
}
+TEST_F(SortIncludesTest, SupportOptionalAlphabeticalSorting) {
+ EXPECT_FALSE(Style.IncludeSortAlphabetically);
+
+ Style.IncludeSortAlphabetically = true;
+
+ EXPECT_EQ("#include \"A/B.h\"\n"
+ "#include \"A/b.h\"\n"
+ "#include \"a/b.h\"\n"
+ "#include \"B/A.h\"\n"
+ "#include \"B/a.h\"\n",
+ sort("#include \"B/a.h\"\n"
+ "#include \"B/A.h\"\n"
+ "#include \"A/B.h\"\n"
+ "#include \"a/b.h\"\n"
+ "#include \"A/b.h\"\n",
+ "a.h"));
+
+ Style.IncludeBlocks = clang::tooling::IncludeStyle::IBS_Regroup;
+ Style.IncludeCategories = {
+ {"^\"", 1, 0, false}, {"^<.*\\.h>$", 2, 0, false}, {"^<", 3, 0, false}};
+
+ StringRef UnsortedCode = "#include \"qt.h\"\n"
+ "#include <algorithm>\n"
+ "#include <qtwhatever.h>\n"
+ "#include <Qtwhatever.h>\n"
+ "#include <Algorithm>\n"
+ "#include \"vlib.h\"\n"
+ "#include \"Vlib.h\"\n"
+ "#include \"AST.h\"\n";
+
+ EXPECT_EQ("#include \"AST.h\"\n"
+ "#include \"qt.h\"\n"
+ "#include \"Vlib.h\"\n"
+ "#include \"vlib.h\"\n"
+ "\n"
+ "#include <Qtwhatever.h>\n"
+ "#include <qtwhatever.h>\n"
+ "\n"
+ "#include <Algorithm>\n"
+ "#include <algorithm>\n",
+ sort(UnsortedCode));
+}
+
TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) {
// Setup an regex for main includes so we can cover those as well.
Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
More information about the llvm-branch-commits
mailing list