[PATCH] Config file support for clang-format, part 2.

Alexander Kornienko alexfh at google.com
Tue May 7 11:19:10 PDT 2013


Hi djasper, klimek,

Adds actual config file reading to the clang-format utility.
Configuration file name is .clang-format. It is looked up for each input file
in its parent directories starting from immediate one. First found .clang-format
file is used. When using standard input, .clang-format is searched starting from
the current directory.
Added -dump-config option to easily create configuration files.

http://llvm-reviews.chandlerc.com/D758

Files:
  tools/clang-format/ClangFormat.cpp

Index: tools/clang-format/ClangFormat.cpp
===================================================================
--- tools/clang-format/ClangFormat.cpp
+++ tools/clang-format/ClangFormat.cpp
@@ -36,13 +36,20 @@
                            "Can only be used with one input file."));
 static cl::opt<std::string> Style(
     "style",
-    cl::desc("Coding style, currently supports: LLVM, Google, Chromium, Mozilla."),
+    cl::desc(
+        "Coding style, currently supports: LLVM, Google, Chromium, Mozilla. "
+        "Use '-style file' to load style configuration from .clang-format file "
+        "located in one of the parent directories of the source file (or "
+        "current directory for stdin)."),
     cl::init("LLVM"));
 static cl::opt<bool> Inplace("i",
                              cl::desc("Inplace edit <file>s, if specified."));
 
 static cl::opt<bool> OutputXML(
     "output-replacements-xml", cl::desc("Output replacements as XML."));
+static cl::opt<bool>
+    DumpConfig("dump-config",
+               cl::desc("Dump configuration options to stdout and exit. Can be used with -style option."));
 
 static cl::list<std::string> FileNames(cl::Positional,
                                        cl::desc("[<file> ...]"));
@@ -59,18 +66,36 @@
   return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
 }
 
-static FormatStyle getStyle() {
-  FormatStyle TheStyle = getGoogleStyle();
-  if (Style == "LLVM")
-    TheStyle = getLLVMStyle();
-  else if (Style == "Chromium")
-    TheStyle = getChromiumStyle();
-  else if (Style == "Mozilla")
-    TheStyle = getMozillaStyle();
-  else if (Style != "Google")
-    llvm::errs() << "Unknown style " << Style << ", using Google style.\n";
-
-  return TheStyle;
+FormatStyle getStyle(StringRef StyleName, StringRef FileName) {
+  if (!StyleName.equals_lower("file"))
+    return getPredefinedStyle(StyleName);
+
+  SmallString<128> Path(FileName);
+  llvm::sys::fs::make_absolute(Path);
+  StringRef Directory = llvm::sys::path::parent_path(Path);
+  while (!Directory.empty()) {
+    std::string ConfigFile = Directory.str();
+    ConfigFile += "/.clang-format";
+    bool IsFile;
+    llvm::sys::fs::is_regular_file(ConfigFile, IsFile);
+    if (IsFile) {
+      OwningPtr<MemoryBuffer> Text;
+      if (error_code ec = MemoryBuffer::getFile(ConfigFile, Text)) {
+        llvm::errs() << ec.message() << "\n";
+        continue;
+      }
+      FormatStyle Style;
+      if (error_code ec = parseConfiguration(Text->getBuffer(), &Style)) {
+        llvm::errs() << ec.message() << "\n";
+        continue;
+      }
+      llvm::errs() << "Using configuration file " << ConfigFile << "\n";
+      return Style;
+    }
+    Directory = llvm::sys::path::parent_path(Directory);
+  }
+  llvm::errs() << "Can't find .clang-format, using LLVM style\n";
+  return getLLVMStyle();
 }
 
 // Returns true on error.
@@ -118,7 +143,8 @@
     }
     Ranges.push_back(CharSourceRange::getCharRange(Start, End));
   }
-  tooling::Replacements Replaces = reformat(getStyle(), Lex, Sources, Ranges);
+  tooling::Replacements Replaces =
+      reformat(getStyle(Style, FileName), Lex, Sources, Ranges);
   if (OutputXML) {
     llvm::outs()
         << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n";
@@ -171,6 +197,13 @@
   if (Help)
     cl::PrintHelpMessage();
 
+  if (DumpConfig) {
+    std::string Config = clang::format::configurationAsText(
+        clang::format::getStyle(Style, FileNames.empty() ? "-" : FileNames[0]));
+    llvm::outs() << Config << "\n";
+    return 0;
+  }
+
   bool Error = false;
   switch (FileNames.size()) {
   case 0:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D758.1.patch
Type: text/x-patch
Size: 3634 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130507/4d18a315/attachment.bin>


More information about the cfe-commits mailing list