Index: tools/clang-format/ClangFormat.cpp =================================================================== --- tools/clang-format/ClangFormat.cpp +++ tools/clang-format/ClangFormat.cpp @@ -22,6 +22,7 @@ #include "clang/Rewrite/Core/Rewriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/Signals.h" using namespace llvm; @@ -51,32 +52,32 @@ "Can only be used with one input file."), cl::cat(ClangFormatCategory)); static cl::list -LineRanges("lines", cl::desc(": - format a range of\n" - "lines (both 1-based).\n" - "Multiple ranges can be formatted by specifying\n" - "several -lines arguments.\n" - "Can't be used with -offset and -length.\n" - "Can only be used with one input file."), - cl::cat(ClangFormatCategory)); + LineRanges("lines", + cl::desc(": - format a range of\n" + "lines (both 1-based).\n" + "Multiple ranges can be formatted by specifying\n" + "several -lines arguments.\n" + "Can't be used with -offset and -length.\n" + "Can only be used with one input file."), + cl::cat(ClangFormatCategory)); static cl::opt - Style("style", - cl::desc(clang::format::StyleOptionHelpDescription), + Style("style", cl::desc(clang::format::StyleOptionHelpDescription), cl::init("file"), cl::cat(ClangFormatCategory)); static cl::opt -FallbackStyle("fallback-style", - cl::desc("The name of the predefined style used as a\n" - "fallback in case clang-format is invoked with\n" - "-style=file, but can not find the .clang-format\n" - "file to use.\n" - "Use -fallback-style=none to skip formatting."), - cl::init("LLVM"), cl::cat(ClangFormatCategory)); + FallbackStyle("fallback-style", + cl::desc("The name of the predefined style used as a\n" + "fallback in case clang-format is invoked with\n" + "-style=file, but can not find the .clang-format\n" + "file to use.\n" + "Use -fallback-style=none to skip formatting."), + cl::init("LLVM"), cl::cat(ClangFormatCategory)); -static cl::opt -AssumeFileName("assume-filename", - cl::desc("When reading from stdin, clang-format assumes this\n" - "filename to look for a style config file (with\n" - "-style=file) and to determine the language."), - cl::init(""), cl::cat(ClangFormatCategory)); +static cl::opt AssumeFileName( + "assume-filename", + cl::desc("When reading from stdin, clang-format assumes this\n" + "filename to look for a style config file (with\n" + "-style=file) and to determine the language."), + cl::init(""), cl::cat(ClangFormatCategory)); static cl::opt Inplace("i", cl::desc("Inplace edit s, if specified."), @@ -91,9 +92,8 @@ "Can be used with -style option."), cl::cat(ClangFormatCategory)); static cl::opt - Cursor("cursor", - cl::desc("The position of the cursor when invoking\n" - "clang-format from an editor integration"), + Cursor("cursor", cl::desc("The position of the cursor when invoking\n" + "clang-format from an editor integration"), cl::init(0), cl::cat(ClangFormatCategory)); static cl::opt SortIncludes( @@ -102,9 +102,23 @@ "SortIncludes style flag"), cl::cat(ClangFormatCategory)); +static cl::opt Recursively("r", + cl::desc("Recursively search for s."), + cl::cat(ClangFormatCategory)); + static cl::list FileNames(cl::Positional, cl::desc("[ ...]"), cl::cat(ClangFormatCategory)); +static bool checkMultipleFilesPreconditions() { + if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) { + errs() << "error: -offset, -length and -lines can only be used for " + "single file.\n"; + return true; + } + + return false; +} + namespace clang { namespace format { @@ -307,9 +321,50 @@ return false; } -} // namespace format -} // namespace clang +static bool formatRecusively() { + if (checkMultipleFilesPreconditions()) { + return false; + } + std::vector files; + + for (unsigned i = 0; i < FileNames.size(); ++i) { + SmallVector currentPath; + std::error_code ec; + llvm::sys::fs::file_status fileStatus; + llvm::sys::fs::current_path(currentPath); + + for (llvm::sys::fs::recursive_directory_iterator I(currentPath, ec), E; + I != E; I.increment(ec)) { + if (ec) { + errs() << "error: error wile recursive files formatting. Error code: " + << ec.value(); + return true; + } + + Regex regex(FileNames[i]); + + I->status(fileStatus); + + if (fileStatus.type() == llvm::sys::fs::file_type::regular_file && + regex.match(I->path())) { + files.push_back(I->path()); + } + } + } + + bool Error = false; + + for (unsigned i = 0; i < files.size(); ++i) { + Error |= clang::format::format(files[i]); + } + + return Error; +} + +} // namespace format +} // namespace clang + static void PrintVersion() { raw_ostream &OS = outs(); OS << clang::getClangToolFullVersion("clang-format") << '\n'; @@ -342,6 +397,10 @@ return 0; } + if (Recursively) { + return clang::format::formatRecusively(); + } + bool Error = false; switch (FileNames.size()) { case 0: @@ -351,15 +410,13 @@ Error = clang::format::format(FileNames[0]); break; default: - if (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty()) { - errs() << "error: -offset, -length and -lines can only be used for " - "single file.\n"; + if (checkMultipleFilesPreconditions()) { return 1; } for (unsigned i = 0; i < FileNames.size(); ++i) Error |= clang::format::format(FileNames[i]); + break; } return Error ? 1 : 0; } -