https://github.com/DaanDeMeyer updated https://github.com/llvm/llvm-project/pull/137840
>From ab2206d22a9d71df807753f193f4110b191ab77b Mon Sep 17 00:00:00 2001 From: Daan De Meyer <daan.j.deme...@gmail.com> Date: Tue, 29 Apr 2025 18:26:36 +0200 Subject: [PATCH] clang-format: Add IgnoreExtension option to SortIncludesOptions Sorting without taking the file extension into account gives nicer results when various header file names are substrings of other header file names, for example, a CLI application with a main header named analyze.h and a analyze-xxx.h header for each subcommand currently will always put analyze.h last after all the analyze-xxx.h headers, but putting analyze.h first instead of last is arguable nicer to read. TLDR; Instead of """ /#include "analyze-blame.h" /#include "analyze.h" """ You'd get """ /#include "analyze.h" /#include "analyze-blame.h" """ Let's allow sorting without taking the file extension into account unless two headers otherwise compare equal by introducing a new boolean option IgnoreExtension for SortIncludesOptions. --- clang/docs/ClangFormatStyleOptions.rst | 3 ++ clang/include/clang/Format/Format.h | 11 ++++++- clang/lib/Format/Format.cpp | 34 +++++++++++++-------- clang/unittests/Format/SortIncludesTest.cpp | 20 ++++++++++++ 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 83716cc049ee3..18095cc09afbe 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6010,6 +6010,9 @@ the configuration (without a prefix: ``Auto``). #include "B/A.h" #include "B/a.h" #include "B/a.h" #include "a/b.h" + * ``bool IgnoreExtension`` :versionbadge:`clang-format 21` + When sorting includes in each block, ignore file extensions. + .. _SortJavaStaticImport: diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 3ac4318824ac0..18e314426c1ae 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4382,8 +4382,17 @@ struct FormatStyle { /// #include "B/a.h" #include "a/b.h" /// \endcode bool IgnoreCase; + /// When sorting includes in each block, Only take file extensions into + /// account if two includes compare equal otherwise. + /// \code + /// true: false: + /// # include "A.h" # include "A-util.h" + /// # include "A.inc" # include "A.h" + /// # include "A-util.h" # include "A.inc" + /// \version 21 + bool IgnoreExtension; bool operator==(const SortIncludesOptions &R) const { - return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase; + return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase && IgnoreExtension == R.IgnoreExtension; } bool operator!=(const SortIncludesOptions &R) const { return !(*this == R); diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index b41a98ecb5be1..6bf951ff61bf0 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave; LLVMStyle.ShortNamespaceLines = 1; LLVMStyle.SkipMacroDefinitionBody = false; - LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false}; + LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, /*IgnoreExtension=*/false}; LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; LLVMStyle.SpaceAfterCStyleCast = false; @@ -3230,19 +3230,27 @@ static void sortCppIncludes(const FormatStyle &Style, SmallVector<unsigned, 16> Indices = llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size())); - if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) { + if (Style.SortIncludes.Enabled) { 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 { - stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) { - return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) < - std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename); + SmallString<128> LHSStem, RHSStem; + if (Style.SortIncludes.IgnoreExtension) { + LHSStem = Includes[LHSI].Filename; + RHSStem = Includes[RHSI].Filename; + llvm::sys::path::replace_extension(LHSStem, ""); + llvm::sys::path::replace_extension(RHSStem, ""); + } + std::string LHSStemLower, RHSStemLower; + std::string LHSFilenameLower, RHSFilenameLower; + if (Style.SortIncludes.IgnoreCase) { + LHSStemLower = LHSStem.str().lower(); + RHSStemLower = RHSStem.str().lower(); + LHSFilenameLower = Includes[LHSI].Filename.lower(); + RHSFilenameLower = Includes[RHSI].Filename.lower(); + } + return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem, + LHSFilenameLower, Includes[LHSI].Filename) < + std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem, + RHSFilenameLower, Includes[RHSI].Filename); }); } diff --git a/clang/unittests/Format/SortIncludesTest.cpp b/clang/unittests/Format/SortIncludesTest.cpp index 994227efdd4f8..3e69ce56d98c5 100644 --- a/clang/unittests/Format/SortIncludesTest.cpp +++ b/clang/unittests/Format/SortIncludesTest.cpp @@ -1483,6 +1483,26 @@ TEST_F(SortIncludesTest, BlockCommentedOutIncludes) { verifyFormat(Code, sort(Code, "input.cpp", 0)); } +TEST_F(SortIncludesTest, IgnoreExtension) { + verifyFormat("#include <a-util.h>\n" + "#include <a.h>\n" + "#include <a.inc>", + sort("#include <a.inc>\n" + "#include <a-util.h>\n" + "#include <a.h>", + "input.h", 1)); + + FmtStyle.SortIncludes.IgnoreExtension = true; + + verifyFormat("#include <a.h>\n" + "#include <a.inc>\n" + "#include <a-util.h>", + sort("#include <a.inc>\n" + "#include <a-util.h>\n" + "#include <a.h>", + "input.h", 1)); +} + } // end namespace } // end namespace format } // end namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits