Skip to content

Commit beab0ec

Browse files
committed
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.
1 parent bca39f4 commit beab0ec

File tree

4 files changed

+63
-14
lines changed

4 files changed

+63
-14
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6010,6 +6010,17 @@ the configuration (without a prefix: ``Auto``).
60106010
#include "B/A.h" #include "B/a.h"
60116011
#include "B/a.h" #include "a/b.h"
60126012

6013+
* ``bool IgnoreExtension`` :versionbadge:`clang-format 21`
6014+
When sorting includes in each block, Only take file extensions into
6015+
account if two includes compare equal otherwise.
6016+
6017+
.. code-block:: c++
6018+
6019+
true: false:
6020+
# include "A.h" # include "A-util.h"
6021+
# include "A.inc" # include "A.h"
6022+
# include "A-util.h" # include "A.inc"
6023+
60136024

60146025
.. _SortJavaStaticImport:
60156026

clang/include/clang/Format/Format.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4382,8 +4382,18 @@ struct FormatStyle {
43824382
/// #include "B/a.h" #include "a/b.h"
43834383
/// \endcode
43844384
bool IgnoreCase;
4385+
/// When sorting includes in each block, Only take file extensions into
4386+
/// account if two includes compare equal otherwise.
4387+
/// \code
4388+
/// true: false:
4389+
/// # include "A.h" # include "A-util.h"
4390+
/// # include "A.inc" # include "A.h"
4391+
/// # include "A-util.h" # include "A.inc"
4392+
/// \endcode
4393+
/// \version 21
4394+
bool IgnoreExtension;
43854395
bool operator==(const SortIncludesOptions &R) const {
4386-
return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase;
4396+
return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase && IgnoreExtension == R.IgnoreExtension;
43874397
}
43884398
bool operator!=(const SortIncludesOptions &R) const {
43894399
return !(*this == R);

clang/lib/Format/Format.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
16471647
LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
16481648
LLVMStyle.ShortNamespaceLines = 1;
16491649
LLVMStyle.SkipMacroDefinitionBody = false;
1650-
LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
1650+
LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, /*IgnoreExtension=*/false};
16511651
LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
16521652
LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
16531653
LLVMStyle.SpaceAfterCStyleCast = false;
@@ -3230,19 +3230,27 @@ static void sortCppIncludes(const FormatStyle &Style,
32303230
SmallVector<unsigned, 16> Indices =
32313231
llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
32323232

3233-
if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) {
3233+
if (Style.SortIncludes.Enabled) {
32343234
stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3235-
const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3236-
const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3237-
return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
3238-
Includes[LHSI].Filename) <
3239-
std::tie(Includes[RHSI].Priority, RHSFilenameLower,
3240-
Includes[RHSI].Filename);
3241-
});
3242-
} else {
3243-
stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3244-
return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
3245-
std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
3235+
SmallString<128> LHSStem, RHSStem;
3236+
if (Style.SortIncludes.IgnoreExtension) {
3237+
LHSStem = Includes[LHSI].Filename;
3238+
RHSStem = Includes[RHSI].Filename;
3239+
llvm::sys::path::replace_extension(LHSStem, "");
3240+
llvm::sys::path::replace_extension(RHSStem, "");
3241+
}
3242+
std::string LHSStemLower, RHSStemLower;
3243+
std::string LHSFilenameLower, RHSFilenameLower;
3244+
if (Style.SortIncludes.IgnoreCase) {
3245+
LHSStemLower = LHSStem.str().lower();
3246+
RHSStemLower = RHSStem.str().lower();
3247+
LHSFilenameLower = Includes[LHSI].Filename.lower();
3248+
RHSFilenameLower = Includes[RHSI].Filename.lower();
3249+
}
3250+
return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem,
3251+
LHSFilenameLower, Includes[LHSI].Filename) <
3252+
std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem,
3253+
RHSFilenameLower, Includes[RHSI].Filename);
32463254
});
32473255
}
32483256

clang/unittests/Format/SortIncludesTest.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,26 @@ TEST_F(SortIncludesTest, BlockCommentedOutIncludes) {
14831483
verifyFormat(Code, sort(Code, "input.cpp", 0));
14841484
}
14851485

1486+
TEST_F(SortIncludesTest, IgnoreExtension) {
1487+
verifyFormat("#include <a-util.h>\n"
1488+
"#include <a.h>\n"
1489+
"#include <a.inc>",
1490+
sort("#include <a.inc>\n"
1491+
"#include <a-util.h>\n"
1492+
"#include <a.h>",
1493+
"input.h", 1));
1494+
1495+
FmtStyle.SortIncludes.IgnoreExtension = true;
1496+
1497+
verifyFormat("#include <a.h>\n"
1498+
"#include <a.inc>\n"
1499+
"#include <a-util.h>",
1500+
sort("#include <a.inc>\n"
1501+
"#include <a-util.h>\n"
1502+
"#include <a.h>",
1503+
"input.h", 1));
1504+
}
1505+
14861506
} // end namespace
14871507
} // end namespace format
14881508
} // end namespace clang

0 commit comments

Comments
 (0)