Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 672f179

Browse filesBrowse files
committed
clang-format: Add IncludeSortKey option
Sorting by stem 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 by stem instead of full path by introducing a new option IncludeSortKey with two values "Path" and "Stem".
1 parent bb21a68 commit 672f179
Copy full SHA for 672f179

File tree

Expand file treeCollapse file tree

5 files changed

+55
-15
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+55
-15
lines changed

‎clang/docs/ClangFormatStyleOptions.rst

Copy file name to clipboardExpand all lines: clang/docs/ClangFormatStyleOptions.rst
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4226,6 +4226,11 @@ the configuration (without a prefix: ``Auto``).
42264226
``ClassImpl.hpp`` would not have the main include file put on top
42274227
before any other include.
42284228

4229+
.. _IncludeSortIgnoreExtension:
4230+
4231+
**IncludeSortIgnoreExtension** (``Boolean``) :versionbadge:`clang-format 21` :ref:`<IncludeSortIgnoreExtension>`
4232+
When sorting includes in each block, ignore file extensions.
4233+
42294234
.. _IndentAccessModifiers:
42304235

42314236
**IndentAccessModifiers** (``Boolean``) :versionbadge:`clang-format 13` :ref:`<IndentAccessModifiers>`

‎clang/include/clang/Format/Format.h

Copy file name to clipboardExpand all lines: clang/include/clang/Format/Format.h
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5368,6 +5368,8 @@ struct FormatStyle {
53685368
IncludeStyle.IncludeIsMainSourceRegex ==
53695369
R.IncludeStyle.IncludeIsMainSourceRegex &&
53705370
IncludeStyle.MainIncludeChar == R.IncludeStyle.MainIncludeChar &&
5371+
IncludeStyle.IncludeSortIgnoreExtension ==
5372+
R.IncludeStyle.IncludeSortIgnoreExtension &&
53715373
IndentAccessModifiers == R.IndentAccessModifiers &&
53725374
IndentCaseBlocks == R.IndentCaseBlocks &&
53735375
IndentCaseLabels == R.IndentCaseLabels &&

‎clang/include/clang/Tooling/Inclusions/IncludeStyle.h

Copy file name to clipboardExpand all lines: clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ struct IncludeStyle {
152152
/// \version 10
153153
std::string IncludeIsMainSourceRegex;
154154

155+
/// When sorting includes in each block, ignore file extensions.
156+
/// \version 21
157+
bool IncludeSortIgnoreExtension;
158+
155159
/// Character to consider in the include directives for the main header.
156160
enum MainIncludeCharDiscriminator : int8_t {
157161
/// Main include uses quotes: ``#include "foo.hpp"`` (the default).

‎clang/lib/Format/Format.cpp

Copy file name to clipboardExpand all lines: clang/lib/Format/Format.cpp
+24-15Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,8 @@ template <> struct MappingTraits<FormatStyle> {
10621062
IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
10631063
IO.mapOptional("IncludeIsMainSourceRegex",
10641064
Style.IncludeStyle.IncludeIsMainSourceRegex);
1065+
IO.mapOptional("IncludeSortIgnoreExtension",
1066+
Style.IncludeStyle.IncludeSortIgnoreExtension);
10651067
IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
10661068
IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
10671069
IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
@@ -1581,6 +1583,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
15811583
{"^(<|\"(gtest|gmock|isl|json)/)", 3, 0, false},
15821584
{".*", 1, 0, false}};
15831585
LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
1586+
LLVMStyle.IncludeStyle.IncludeSortIgnoreExtension = false;
15841587
LLVMStyle.IncludeStyle.MainIncludeChar = tooling::IncludeStyle::MICD_Quote;
15851588
LLVMStyle.IndentAccessModifiers = false;
15861589
LLVMStyle.IndentCaseBlocks = false;
@@ -3217,21 +3220,27 @@ static void sortCppIncludes(const FormatStyle &Style,
32173220
SmallVector<unsigned, 16> Indices =
32183221
llvm::to_vector<16>(llvm::seq<unsigned>(0, Includes.size()));
32193222

3220-
if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
3221-
stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3222-
const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
3223-
const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
3224-
return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
3225-
Includes[LHSI].Filename) <
3226-
std::tie(Includes[RHSI].Priority, RHSFilenameLower,
3227-
Includes[RHSI].Filename);
3228-
});
3229-
} else {
3230-
stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3231-
return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
3232-
std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
3233-
});
3234-
}
3223+
stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
3224+
SmallString<128> LHSStem, RHSStem;
3225+
if (Style.IncludeStyle.IncludeSortIgnoreExtension) {
3226+
LHSStem = Includes[LHSI].Filename;
3227+
RHSStem = Includes[RHSI].Filename;
3228+
llvm::sys::path::replace_extension(LHSStem, "");
3229+
llvm::sys::path::replace_extension(RHSStem, "");
3230+
}
3231+
std::string LHSStemLower, RHSStemLower;
3232+
std::string LHSFilenameLower, RHSFilenameLower;
3233+
if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
3234+
LHSStemLower = LHSStem.str().lower();
3235+
RHSStemLower = RHSStem.str().lower();
3236+
LHSFilenameLower = Includes[LHSI].Filename.lower();
3237+
RHSFilenameLower = Includes[RHSI].Filename.lower();
3238+
}
3239+
return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem,
3240+
LHSFilenameLower, Includes[LHSI].Filename) <
3241+
std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem,
3242+
RHSFilenameLower, Includes[RHSI].Filename);
3243+
});
32353244

32363245
// The index of the include on which the cursor will be put after
32373246
// sorting/deduplicating.

‎clang/unittests/Format/SortIncludesTest.cpp

Copy file name to clipboardExpand all lines: clang/unittests/Format/SortIncludesTest.cpp
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,26 @@ TEST_F(SortIncludesTest, BlockCommentedOutIncludes) {
14851485
verifyFormat(Code, sort(Code, "input.cpp", 0));
14861486
}
14871487

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

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.