tnorth updated this revision to Diff 240888.
tnorth added a comment.

- Add a unit-test loading a format and test file from temporary files.


Repository:
  rC Clang

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

https://reviews.llvm.org/D72326

Files:
  include/clang/Format/Format.h
  lib/Format/Format.cpp
  unittests/Format/FormatTest.cpp

Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -14350,6 +14350,59 @@
   auto StyleTd = getStyle("file", "x.td", "llvm", "", &FS);
   ASSERT_TRUE((bool)StyleTd);
   ASSERT_EQ(*StyleTd, getLLVMStyle(FormatStyle::LK_TableGen));
+
+  // Test 9: 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 Style8 = getStyle("file:/e/explicit.clang-format",
+                         "/e/sub/sub/sub/test.cpp", "LLVM", "", &FS);
+  ASSERT_TRUE((bool)Style8);
+  ASSERT_EQ(*Style8, getGoogleStyle());
+
+  // Test 10: relative pah to a format file
+  ASSERT_TRUE(
+      FS.addFile("../../e/explicit.clang-format", 0,
+                 llvm::MemoryBuffer::getMemBuffer("BasedOnStyle: Google")));
+  auto Style9 = getStyle("file:../../e/explicit.clang-format",
+                         "/e/sub/sub/sub/test.cpp", "LLVM", "", &FS);
+  ASSERT_TRUE((bool)Style9);
+  ASSERT_EQ(*Style9, getGoogleStyle());
+
+  // Test 11: missing explicit format file
+  auto Style10 = getStyle("file:/e/missing.clang-format",
+                          "/e/sub/sub/sub/test.cpp", "LLVM", "", &FS);
+  ASSERT_FALSE((bool)Style10);
+  llvm::consumeError(Style10.takeError());
+
+  // Test 12: 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();
+  auto Style11 = getStyle(format_file_arg, TestFilePath, "LLVM", "", nullptr);
+  
+  llvm::sys::fs::remove(FormatFilePath.c_str());
+  llvm::sys::fs::remove(TestFilePath.c_str());
+  ASSERT_TRUE((bool)Style11);
+  ASSERT_EQ(*Style11, getGoogleStyle());
 }
 
 TEST_F(ReplacementTest, FormatCodeAfterReplacements) {
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -2519,6 +2519,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}\"";
@@ -2568,6 +2570,22 @@
 
 const char *DefaultFallbackStyle = "LLVM";
 
+/// Attempts to load a format file
+llvm::Expected<FormatStyle> LoadConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS) {
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
+      FS->getBufferForFile(ConfigFile.str());
+  std::error_code ReadFileError = Text.getError();
+  if (ReadFileError) {
+    return make_string_error("Error reading config file " + ReadFileError.message());
+  }
+  FormatStyle Style = getLLVMStyle();
+  std::error_code ParseFileError = parseConfiguration(Text.get()->getBuffer(), &Style);
+  if (ParseFileError != ParseError::Success) {
+    return make_string_error("Error parsing config file " + ParseFileError.message());
+  }
+  return Style;
+}
+
 llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
                                      StringRef FallbackStyleName,
                                      StringRef Code,
@@ -2588,6 +2606,12 @@
     return Style;
   }
 
+  // User provided clang-format file using -style=file:/path/to/format/file
+  // Check for explicit config filename
+  if (StyleName.startswith_lower("file:")) {
+    return LoadConfigFile(StyleName.substr(5), FS);
+  }
+
   if (!StyleName.equals_lower("file")) {
     if (!getPredefinedStyle(StyleName, Style.Language, &Style))
       return make_string_error("Invalid value for -style");
@@ -2628,24 +2652,7 @@
     }
 
     if (FoundConfigFile) {
-      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());
-      if (std::error_code ec =
-              parseConfiguration(Text.get()->getBuffer(), &Style)) {
-        if (ec == ParseError::Unsuitable) {
-          if (!UnsuitableConfigFiles.empty())
-            UnsuitableConfigFiles.append(", ");
-          UnsuitableConfigFiles.append(ConfigFile);
-          continue;
-        }
-        return make_string_error("Error reading " + ConfigFile + ": " +
-                                 ec.message());
-      }
-      LLVM_DEBUG(llvm::dbgs()
-                 << "Using configuration file " << ConfigFile << "\n");
-      return Style;
+      return LoadConfigFile(ConfigFile, FS);
     }
   }
   if (!UnsuitableConfigFiles.empty())
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -2338,6 +2338,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.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to