Skip to content

Conversation

DaanDeMeyer
Copy link
Contributor

@DaanDeMeyer DaanDeMeyer commented Apr 29, 2025

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 an 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 is arguably 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 adding IgnoreExtension
to SortIncludes.

@llvmbot
Copy link
Member

llvmbot commented Apr 29, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-format

Author: Daan De Meyer (DaanDeMeyer)

Changes

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"

We'll now get

#include "analyze.h"
#include "analyze-blame.h"

Full diff: https://github.com/llvm/llvm-project/pull/137840.diff

1 Files Affected:

  • (modified) clang/lib/Format/Format.cpp (+10-8)
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5a1c3f556b331..bc1e681c9be78 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3219,17 +3219,19 @@ static void sortCppIncludes(const FormatStyle &Style,
 
   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
     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);
+      const auto LHSStem = llvm::sys::path::stem(Includes[LHSI].Filename);
+      const auto RHSStem = llvm::sys::path::stem(Includes[RHSI].Filename);
+      const auto LHSStemLower = LHSStem.lower();
+      const auto RHSStemLower = RHSStem.lower();
+      return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem) <
+             std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem);
     });
   } 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);
+      const auto LHSStem = llvm::sys::path::stem(Includes[LHSI].Filename);
+      const auto RHSStem = llvm::sys::path::stem(Includes[RHSI].Filename);
+      return std::tie(Includes[LHSI].Priority, LHSStem) <
+             std::tie(Includes[RHSI].Priority, RHSStem);
     });
   }
 

Copy link
Contributor

@HazardyKnusperkeks HazardyKnusperkeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You definitely need some tests. And I'm not sure if everyone would like that, of if it should be an option.

@DaanDeMeyer
Copy link
Contributor Author

You definitely need some tests. And I'm not sure if everyone would like that, of if it should be an option.

I was hoping to get some feedback on whether it should be an option or not before adding tests.

DaanDeMeyer added a commit to DaanDeMeyer/systemd that referenced this pull request Apr 29, 2025
This was done by running a locally built clang-format with
llvm/llvm-project#137617 and
llvm/llvm-project#137840 applied on all .c
and .h files.
DaanDeMeyer added a commit to DaanDeMeyer/systemd that referenced this pull request Apr 29, 2025
This was done by running a locally built clang-format with
llvm/llvm-project#137617 and
llvm/llvm-project#137840 applied on all .c
and .h files.
DaanDeMeyer added a commit to DaanDeMeyer/systemd that referenced this pull request Apr 29, 2025
This was done by running a locally built clang-format with
llvm/llvm-project#137617 and
llvm/llvm-project#137840 applied on all .c
and .h files.
DaanDeMeyer added a commit to DaanDeMeyer/systemd that referenced this pull request Apr 29, 2025
This was done by running a locally built clang-format with
llvm/llvm-project#137617 and
llvm/llvm-project#137840 applied on all .c
and .h files.
DaanDeMeyer added a commit to DaanDeMeyer/systemd that referenced this pull request Apr 30, 2025
This was done by running a locally built clang-format with
llvm/llvm-project#137617 and
llvm/llvm-project#137840 applied on all .c
and .h files.
DaanDeMeyer added a commit to DaanDeMeyer/systemd that referenced this pull request Apr 30, 2025
This was done by running a locally built clang-format with
llvm/llvm-project#137617 and
llvm/llvm-project#137840 applied on all .c
and .h files.
Copy link
Contributor

@HazardyKnusperkeks HazardyKnusperkeks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you think should files be handled, that only differ in the caseness of the extension?

@HazardyKnusperkeks
Copy link
Contributor

You definitely need some tests. And I'm not sure if everyone would like that, of if it should be an option.

I was hoping to get some feedback on whether it should be an option or not before adding tests.

I would be in favor.

@owenca
Copy link
Contributor

owenca commented May 1, 2025

IMO, unless it's a bug, we need a new option to ensure it's a non-breaking change.

@llvmbot llvmbot added the clang Clang issues not falling into any other category label May 1, 2025
@DaanDeMeyer DaanDeMeyer changed the title clang-format: Sort includes by stem rather than full filename clang-format: Add IncludeSortKey option May 1, 2025
@DaanDeMeyer
Copy link
Contributor Author

@HazardyKnusperkeks @owenca Updated PR to introduce a new option IncludeSortKey, PTAL!

Copy link

github-actions bot commented May 1, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@DaanDeMeyer
Copy link
Contributor Author

Ping @owenca @HazardyKnusperkeks

@owenca
Copy link
Contributor

owenca commented May 13, 2025

I would expect that file extensions be sorted regardless. For example:

#include "a.h"
#include "a.inc"
#include "a-util.def"
#include "a-util.h"

@DaanDeMeyer
Copy link
Contributor Author

I would expect that file extensions be sorted regardless. For example:

#include "a.h"
#include "a.inc"
#include "a-util.def"
#include "a-util.h"

Addressed

@DaanDeMeyer
Copy link
Contributor Author

@owenca @HazardyKnusperkeks Rebased onto latest main to take advantage of @owenca's rework and addressed comments.

@DaanDeMeyer DaanDeMeyer force-pushed the stem branch 2 times, most recently from 33f84b2 to beab0ec Compare May 19, 2025 11:44
Copy link
Contributor

@mydeveloperday mydeveloperday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have the correct current default

@DaanDeMeyer DaanDeMeyer force-pushed the stem branch 3 times, most recently from 6a3e7f0 to 3cf3ada Compare May 20, 2025 15:54
@DaanDeMeyer
Copy link
Contributor Author

Ping? Would love to get this over the finish line

@DaanDeMeyer DaanDeMeyer force-pushed the stem branch 2 times, most recently from 0827e9c to 607b938 Compare June 26, 2025 09:08
Copy link
Contributor

@owenca owenca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix all compiler warnings, e.g.

llvm-project/clang/lib/Format/Format.cpp:667:70: warning: missing field 'IgnoreExtension' initializer [-Wmissing-field-initializers]
  667 |                                                   /*IgnoreCase=*/true}));
      |                                                                      ^

Also, the new option is not recognized:

$ cat .clang-format
SortIncludes:
  Enabled: true
  IgnoreExtension: true
$ clang-format -dump-config
.clang-format:3:3: error: unknown key 'IgnoreExtension'
  IgnoreExtension: true
  ^~~~~~~~~~~~~~~

@DaanDeMeyer DaanDeMeyer force-pushed the stem branch 4 times, most recently from f175705 to 22a095d Compare July 15, 2025 07:30
@owenca owenca changed the title clang-format: Add IncludeSortKey option [clang-format] Add IgnoreExtension to SortIncludes Jul 15, 2025
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.
@owenca owenca removed the clang Clang issues not falling into any other category label Jul 17, 2025
@DaanDeMeyer
Copy link
Contributor Author

@owenca @mydeveloperday @HazardyKnusperkeks Can any of you merge this? I don't have commit rights

@owenca owenca merged commit 1653a09 into llvm:main Jul 17, 2025
10 checks passed
julian-klode pushed a commit to ubuntu/stubble that referenced this pull request Aug 1, 2025
This was done by running a locally built clang-format with
llvm/llvm-project#137617 and
llvm/llvm-project#137840 applied on all .c
and .h files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants