From d03222069e3eba7061dd831e8ddb3df17caa553a Mon Sep 17 00:00:00 2001 From: James Henderson Date: Tue, 23 Sep 2025 14:40:53 +0100 Subject: [PATCH 1/2] [clang-format] Add -r option for recursing into directories The option recursively replaces any directories on the command-line with all entries within the specified directories, making it easier to reformat an entire directory tree. Fixes #62108 --- clang/docs/ClangFormat.rst | 1 + clang/docs/ReleaseNotes.rst | 1 + clang/test/Format/recursive.test | 21 +++++++++++++++++ clang/tools/clang-format/ClangFormat.cpp | 29 ++++++++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 clang/test/Format/recursive.test diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst index 92af06e5083d6..cd00bedefa21b 100644 --- a/clang/docs/ClangFormat.rst +++ b/clang/docs/ClangFormat.rst @@ -93,6 +93,7 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code. --output-replacements-xml - Output replacements as XML. --qualifier-alignment= - If set, overrides the qualifier alignment style determined by the QualifierAlignment style flag + -r - Recursively format files in any specified directories --sort-includes - If set, overrides the include sorting behavior determined by the SortIncludes style flag --style= - Set coding style. can be: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fb429a675476d..e64ef490d292a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -532,6 +532,7 @@ clang-format literals. - Add ``Leave`` suboption to ``IndentPPDirectives``. - Add ``AllowBreakBeforeQtProperty`` option. +- Add ``-r`` option for recursing into specified directories when formatting. libclang -------- diff --git a/clang/test/Format/recursive.test b/clang/test/Format/recursive.test new file mode 100644 index 0000000000000..f0f3b9e5a3f07 --- /dev/null +++ b/clang/test/Format/recursive.test @@ -0,0 +1,21 @@ +RUN: rm -rf %t && mkdir %t +RUN: split-file %s %t + +RUN: clang-format -i -r --verbose %t 2>&1 | FileCheck %s -DDIR=%t -DSEP=%{fs-sep} + +CHECK: Formatting [1/4] [[DIR]][[SEP]]1.cpp +CHECK: Formatting [2/4] [[DIR]][[SEP]]2[[SEP]]3.cpp +CHECK: Formatting [3/4] [[DIR]][[SEP]]2[[SEP]]4[[SEP]]5.cpp +CHECK: Formatting [4/4] [[DIR]][[SEP]]2[[SEP]]6.cpp + +#--- 1.cpp +int x; + +#--- 2/3.cpp +int x; + +#--- 2/4/5.cpp +int x; + +#--- 2/6.cpp +int x; diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 5f6502f7f18a8..8267417e311f0 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -131,6 +131,10 @@ static cl::opt Files( cl::desc("A file containing a list of files to process, one per line."), cl::value_desc("filename"), cl::init(""), cl::cat(ClangFormatCategory)); +static cl::opt Recursive("r", + cl::desc("Recursively format files in any specified directories"), + cl::cat(ClangFormatCategory)); + static cl::opt Verbose("verbose", cl::desc("If set, shows the list of processed files"), cl::cat(ClangFormatCategory)); @@ -700,6 +704,31 @@ int main(int argc, const char **argv) { errs() << "Clang-formatting " << LineNo << " files\n"; } + if (Recursive) { + SmallVector ExpandedNames; + for (const std::string &Path : FileNames) { + if (sys::fs::is_directory(Path)) { + std::error_code ErrorCode; + for (sys::fs::recursive_directory_iterator I(Path, ErrorCode), E; + I != E && !ErrorCode; I.increment(ErrorCode)) { + bool Result = false; + ErrorCode = sys::fs::is_regular_file(I->path(), Result); + // Conservatively assume that any unopenable entries are also regular + // files. Later code will emit an error when trying to format them, if + // they aren't valid by then. + if (ErrorCode || Result) + ExpandedNames.push_back(I->path()); + } + } else { + ExpandedNames.push_back(std::move(Path)); + } + } + + FileNames.clear(); + for (const std::string &Name : ExpandedNames) + FileNames.push_back(Name); + } + if (FileNames.empty()) { if (isIgnored(AssumeFileName)) return 0; From 6d9932b5337ec5aef7df4da3f369d556660de90a Mon Sep 17 00:00:00 2001 From: James Henderson Date: Tue, 23 Sep 2025 14:50:21 +0100 Subject: [PATCH 2/2] Format --- clang/tools/clang-format/ClangFormat.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 8267417e311f0..bef5924ca74b0 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -131,9 +131,10 @@ static cl::opt Files( cl::desc("A file containing a list of files to process, one per line."), cl::value_desc("filename"), cl::init(""), cl::cat(ClangFormatCategory)); -static cl::opt Recursive("r", - cl::desc("Recursively format files in any specified directories"), - cl::cat(ClangFormatCategory)); +static cl::opt + Recursive("r", + cl::desc("Recursively format files in any specified directories"), + cl::cat(ClangFormatCategory)); static cl::opt Verbose("verbose", cl::desc("If set, shows the list of processed files"),