MyDeveloperDay updated this revision to Diff 389488.
MyDeveloperDay added a comment.

Rebasing previously landed but reverted commit


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72326/new/

https://reviews.llvm.org/D72326

Files:
  clang/docs/ClangFormat.rst
  clang/docs/ClangFormatStyleOptions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/unittests/Format/FormatTest.cpp

Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -21343,6 +21343,64 @@
   }());
 }
 
+TEST(FormatStyle, GetStyleFromExteranlFile) {
+  llvm::vfs::InMemoryFileSystem FS;
+  // Explicit format file in parent directory.
+  ASSERT_TRUE(
+      FS.addFile("/e/.clang-format", 0,
+                 llvm::MemoryBuffer::getMemBuffer("BasedOnStyle: LLVM")));
+  ASSERT_TRUE(
+      FS.addFile("/e/explicit.clang-format", 0,
+                 llvm::MemoryBuffer::getMemBuffer("BasedOnStyle: Google")));
+  ASSERT_TRUE(FS.addFile("/e/sub/sub/sub/test.cpp", 0,
+                         llvm::MemoryBuffer::getMemBuffer("int i;")));
+  auto Style = getStyle("file:/e/explicit.clang-format",
+                        "/e/sub/sub/sub/test.cpp", "LLVM", "", &FS);
+  ASSERT_TRUE((bool)Style);
+  ASSERT_EQ(*Style, getGoogleStyle());
+
+  // Relative pah to a format file
+  ASSERT_TRUE(
+      FS.addFile("../../e/explicit.clang-format", 0,
+                 llvm::MemoryBuffer::getMemBuffer("BasedOnStyle: Google")));
+  Style = getStyle("file:../../e/explicit.clang-format",
+                   "/e/sub/sub/sub/test.cpp", "LLVM", "", &FS);
+  ASSERT_TRUE((bool)Style);
+  ASSERT_EQ(*Style, getGoogleStyle());
+
+  // Missing explicit format file
+  Style = getStyle("file:/e/missing.clang-format", "/e/sub/sub/sub/test.cpp",
+                   "LLVM", "", &FS);
+  ASSERT_FALSE((bool)Style);
+  llvm::consumeError(Style.takeError());
+
+  // Format file from the filesystem
+  SmallString<128> FormatFilePath;
+  std::error_code ECF = llvm::sys::fs::createTemporaryFile(
+      "FormatFileTest", "tpl", FormatFilePath);
+  EXPECT_FALSE((bool)ECF);
+  llvm::raw_fd_ostream FormatFileTest(FormatFilePath, ECF);
+  EXPECT_FALSE((bool)ECF);
+  FormatFileTest << "BasedOnStyle: Google\n";
+  FormatFileTest.close();
+
+  SmallString<128> TestFilePath;
+  std::error_code ECT =
+      llvm::sys::fs::createTemporaryFile("CodeFileTest", "cc", TestFilePath);
+  EXPECT_FALSE((bool)ECT);
+  llvm::raw_fd_ostream CodeFileTest(TestFilePath, ECT);
+  CodeFileTest << "int i;\n";
+  CodeFileTest.close();
+
+  std::string format_file_arg = std::string("file:") + FormatFilePath.c_str();
+  Style = getStyle(format_file_arg, TestFilePath, "LLVM", "", nullptr);
+
+  llvm::sys::fs::remove(FormatFilePath.c_str());
+  llvm::sys::fs::remove(TestFilePath.c_str());
+  ASSERT_TRUE((bool)Style);
+  ASSERT_EQ(*Style, getGoogleStyle());
+}
+
 TEST_F(ReplacementTest, FormatCodeAfterReplacements) {
   // Column limit is 20.
   std::string Code = "Type *a =\n"
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -3163,6 +3163,8 @@
     ".clang-format file located in one of the parent\n"
     "directories of the source file (or current\n"
     "directory for stdin).\n"
+    "Use -style=file:<configfile> to explicitly specify"
+    "the configuration file.\n"
     "Use -style=\"{key: value, ...}\" to set specific\n"
     "parameters, e.g.:\n"
     "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
@@ -3211,6 +3213,29 @@
   return GuessedLanguage;
 }
 
+/// Attempts to load a format file
+llvm::Expected<FormatStyle> LoadConfigFile(StringRef ConfigFile,
+                                           llvm::vfs::FileSystem *FS,
+                                           bool *IsSuitable) {
+  FormatStyle Style = getLLVMStyle();
+  *IsSuitable = false;
+
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
+      FS->getBufferForFile(ConfigFile.str());
+  if (std::error_code EC = Text.getError())
+    return make_string_error(EC.message());
+  std::error_code ParserErrorCode =
+      parseConfiguration(Text.get()->getBuffer(), &Style);
+  if (ParserErrorCode == ParseError::Unsuitable) {
+    return Style;
+  } else if (ParserErrorCode != ParseError::Success) {
+    return make_string_error("Error reading " + ConfigFile + ": " +
+                             ParserErrorCode.message());
+  }
+  *IsSuitable = true;
+  return Style;
+}
+
 const char *DefaultFormatStyle = "file";
 
 const char *DefaultFallbackStyle = "LLVM";
@@ -3245,6 +3270,23 @@
       return Style;
   }
 
+  llvm::SmallVector<std::string, 2> FilesToLookFor;
+  // User provided clang-format file using -style=file:/path/to/format/file
+  // Check for explicit config filename
+  if (StyleName.startswith_insensitive("file:")) {
+    auto StyleNameFile = StyleName.substr(5);
+    bool IsSuitable = true;
+    auto Style = LoadConfigFile(StyleNameFile, FS, &IsSuitable);
+    if (Style && !IsSuitable) {
+      return make_string_error("Configuration file(s) do(es) not support " +
+                               getLanguageName((*Style).Language) + ": " +
+                               StyleNameFile);
+    }
+    LLVM_DEBUG(llvm::dbgs()
+               << "Using configuration file " << StyleNameFile << "\n");
+    return Style;
+  }
+
   // If the style inherits the parent configuration it is a command line
   // configuration, which wants to inherit, so we have to skip the check of the
   // StyleName.
@@ -3264,7 +3306,6 @@
   if (std::error_code EC = FS->makeAbsolute(Path))
     return make_string_error(EC.message());
 
-  llvm::SmallVector<std::string, 2> FilesToLookFor;
   FilesToLookFor.push_back(".clang-format");
   FilesToLookFor.push_back("_clang-format");
 
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -4065,6 +4065,7 @@
 /// * "file" - Load style configuration from a file called ``.clang-format``
 /// located in one of the parent directories of ``FileName`` or the current
 /// directory if ``FileName`` is empty.
+/// * "file:<configfile>" to explicitly specify the configuration file to use.
 ///
 /// \param[in] StyleName Style name to interpret according to the description
 /// above.
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -264,6 +264,10 @@
   space before parentheses. The custom options can be set using
   ``SpaceBeforeParensOptions``.
 
+- The command line argument `-style=<string>` has been extended so that a specific
+  format file at location <format_file_path> can be selected. This is supported
+  via the syntax: `-style=file:<format_file_path>`.
+
 libclang
 --------
 
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -32,6 +32,10 @@
 of the input file. When the standard input is used, the search is started from
 the current directory.
 
+When using ``-style=file:<format_file_path>, :program:`clang-format` for 
+each input file will use the format file located at `<format_file_path>`.
+The path may be absolute or relative to the working directory.
+
 The ``.clang-format`` file uses YAML format:
 
 .. code-block:: yaml
Index: clang/docs/ClangFormat.rst
===================================================================
--- clang/docs/ClangFormat.rst
+++ clang/docs/ClangFormat.rst
@@ -82,6 +82,10 @@
                                  .clang-format file located in one of the parent
                                  directories of the source file (or current
                                  directory for stdin).
+                                 Use -style=file:<format_file_path> to load style
+                                 configuration from a format file located at
+                                 <format_file_path>. This path can be absolute or
+                                 relative to the working directory.
                                  Use -style="{key: value, ...}" to set specific
                                  parameters, e.g.:
                                    -style="{BasedOnStyle: llvm, IndentWidth: 8}"
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to