From f4e12c8c1325ea04b54ed0b5869258254458b091 Mon Sep 17 00:00:00 2001 From: Edwin Vane <edwin.vane@intel.com> Date: Mon, 30 Sep 2013 13:31:48 +0000 Subject: [PATCH] Moving style option formatting to libFormat The help text for clang-format's -style option and the function that processes its value is moved to libFormat in this patch. The goal is to enable other tools that use libFormat and also have a -style option to behave consistently with clang-format. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191666 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Format/Format.h | 24 +++++++++ lib/Format/Format.cpp | 78 +++++++++++++++++++++++++++ tools/clang-format/ClangFormat.cpp | 84 +++--------------------------- 3 files changed, 108 insertions(+), 78 deletions(-) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index c326f66ef26..899087a1473 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -347,6 +347,30 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard = FormatStyle::LS_Cpp11); +/// \brief Description to be used for help text for a llvm::cl option for +/// specifying format style. The description is closely related to the operation +/// of getStyle(). +extern const char *StyleOptionHelpDescription; + +/// \brief Construct a FormatStyle based on \c StyleName. +/// +/// \c StyleName can take several forms: +/// \li "{<key>: <value>, ...}" - Set specic style parameters. +/// \li "<style name>" - One of the style names supported by +/// getPredefinedStyle(). +/// \li "file" - Load style configuration from a file called '.clang-format' +/// located in one of the parent directories of \c FileName or the current +/// directory if \c FileName is empty. +/// +/// \param[in] StyleName Style name to interpret according to the description +/// above. +/// \param[in] FileName Path to start search for .clang-format if \c StyleName +/// == "file". +/// +/// \returns FormatStyle as specified by \c StyleName. If no style could be +/// determined, the default is LLVM Style (see getLLVMStyle()). +FormatStyle getStyle(StringRef StyleName, StringRef FileName); + } // end namespace format } // end namespace clang diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index d6167690611..8ee770af954 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/Path.h" #include <queue> #include <string> @@ -1305,5 +1306,82 @@ LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard) { return LangOpts; } +const char *StyleOptionHelpDescription = + "Coding style, currently supports:\n" + " LLVM, Google, Chromium, Mozilla, WebKit.\n" + "Use -style=file to load style configuration from\n" + ".clang-format file located in one of the parent\n" + "directories of the source file (or current\n" + "directory for stdin).\n" + "Use -style=\"{key: value, ...}\" to set specific\n" + "parameters, e.g.:\n" + " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""; + +FormatStyle getStyle(StringRef StyleName, StringRef FileName) { + // Fallback style in case the rest of this function can't determine a style. + StringRef FallbackStyle = "LLVM"; + FormatStyle Style; + getPredefinedStyle(FallbackStyle, &Style); + + if (StyleName.startswith("{")) { + // Parse YAML/JSON style from the command line. + if (llvm::error_code ec = parseConfiguration(StyleName, &Style)) { + llvm::errs() << "Error parsing -style: " << ec.message() + << ", using " << FallbackStyle << " style\n"; + } + return Style; + } + + if (!StyleName.equals_lower("file")) { + if (!getPredefinedStyle(StyleName, &Style)) + llvm::errs() << "Invalid value for -style, using " << FallbackStyle + << " style\n"; + return Style; + } + + SmallString<128> Path(FileName); + llvm::sys::fs::make_absolute(Path); + for (StringRef Directory = Path; + !Directory.empty(); + Directory = llvm::sys::path::parent_path(Directory)) { + if (!llvm::sys::fs::is_directory(Directory)) + continue; + SmallString<128> ConfigFile(Directory); + + llvm::sys::path::append(ConfigFile, ".clang-format"); + DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); + bool IsFile = false; + // Ignore errors from is_regular_file: we only need to know if we can read + // the file or not. + llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile); + + if (!IsFile) { + // Try _clang-format too, since dotfiles are not commonly used on Windows. + ConfigFile = Directory; + llvm::sys::path::append(ConfigFile, "_clang-format"); + DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); + llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile); + } + + if (IsFile) { + OwningPtr<llvm::MemoryBuffer> Text; + if (llvm::error_code ec = llvm::MemoryBuffer::getFile(ConfigFile, Text)) { + llvm::errs() << ec.message() << "\n"; + continue; + } + if (llvm::error_code ec = parseConfiguration(Text->getBuffer(), &Style)) { + llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message() + << "\n"; + continue; + } + DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n"); + return Style; + } + } + llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle + << " style\n"; + return Style; +} + } // namespace format } // namespace clang diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp index 71dcfc5640b..9334bb5e8ed 100644 --- a/tools/clang-format/ClangFormat.cpp +++ b/tools/clang-format/ClangFormat.cpp @@ -63,15 +63,7 @@ LineRanges("lines", cl::desc("<start line>:<end line> - format a range of\n" cl::cat(ClangFormatCategory)); static cl::opt<std::string> Style("style", - cl::desc("Coding style, currently supports:\n" - " LLVM, Google, Chromium, Mozilla, WebKit.\n" - "Use -style=file to load style configuration from\n" - ".clang-format file located in one of the parent\n" - "directories of the source file (or current\n" - "directory for stdin).\n" - "Use -style=\"{key: value, ...}\" to set specific\n" - "parameters, e.g.:\n" - " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\""), + cl::desc(clang::format::StyleOptionHelpDescription), cl::init("file"), cl::cat(ClangFormatCategory)); static cl::opt<std::string> @@ -114,72 +106,6 @@ static FileID createInMemoryFile(StringRef FileName, const MemoryBuffer *Source, return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User); } -FormatStyle getStyle(StringRef StyleName, StringRef FileName) { - FormatStyle Style; - getPredefinedStyle(FallbackStyle, &Style); - - if (StyleName.startswith("{")) { - // Parse YAML/JSON style from the command line. - if (error_code ec = parseConfiguration(StyleName, &Style)) { - llvm::errs() << "Error parsing -style: " << ec.message() - << ", using " << FallbackStyle << " style\n"; - } - return Style; - } - - if (!StyleName.equals_lower("file")) { - if (!getPredefinedStyle(StyleName, &Style)) - llvm::errs() << "Invalid value for -style, using " << FallbackStyle - << " style\n"; - return Style; - } - - if (FileName == "-") - FileName = AssumeFilename; - SmallString<128> Path(FileName); - llvm::sys::fs::make_absolute(Path); - for (StringRef Directory = Path; - !Directory.empty(); - Directory = llvm::sys::path::parent_path(Directory)) { - if (!llvm::sys::fs::is_directory(Directory)) - continue; - SmallString<128> ConfigFile(Directory); - - llvm::sys::path::append(ConfigFile, ".clang-format"); - DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); - bool IsFile = false; - // Ignore errors from is_regular_file: we only need to know if we can read - // the file or not. - llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile); - - if (!IsFile) { - // Try _clang-format too, since dotfiles are not commonly used on Windows. - ConfigFile = Directory; - llvm::sys::path::append(ConfigFile, "_clang-format"); - DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n"); - llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile); - } - - if (IsFile) { - OwningPtr<MemoryBuffer> Text; - if (error_code ec = MemoryBuffer::getFile(ConfigFile, Text)) { - llvm::errs() << ec.message() << "\n"; - continue; - } - if (error_code ec = parseConfiguration(Text->getBuffer(), &Style)) { - llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message() - << "\n"; - continue; - } - DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n"); - return Style; - } - } - llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle - << " style\n"; - return Style; -} - // Parses <start line>:<end line> input to a pair of line numbers. // Returns true on error. static bool parseLineRange(StringRef Input, unsigned &FromLine, @@ -269,7 +195,8 @@ static bool format(std::string FileName) { if (fillRanges(Sources, ID, Code.get(), Ranges)) return true; - FormatStyle FormatStyle = getStyle(Style, FileName); + FormatStyle FormatStyle = + getStyle(Style, (FileName == "-") ? AssumeFilename : FileName); Lexer Lex(ID, Sources.getBuffer(ID), Sources, getFormattingLangOpts(FormatStyle.Standard)); tooling::Replacements Replaces = reformat(FormatStyle, Lex, Sources, Ranges); @@ -340,8 +267,9 @@ int main(int argc, const char **argv) { cl::PrintHelpMessage(); if (DumpConfig) { - std::string Config = clang::format::configurationAsText( - clang::format::getStyle(Style, FileNames.empty() ? "-" : FileNames[0])); + std::string Config = + clang::format::configurationAsText(clang::format::getStyle( + Style, FileNames.empty() ? AssumeFilename : FileNames[0])); llvm::outs() << Config << "\n"; return 0; } -- GitLab