llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.4k stars 11.73k forks source link

[clang-format] Feature request: choose style (file) from within text files for IDEs #60917

Open bersbersbers opened 1 year ago

bersbersbers commented 1 year ago

As far as I have observed (and understand the documentation), using clang-format inside an IDE (e.g., Visual Studio) means that for each file, the closest .clang-format file is used, so one may end up getting different formatting styles for source code files in different directories. This is a great feature!

Now, is there any way of having different styles for files in the same directory? I haven't found one, which is why I am opening this feature request. (And I hope I am wrong, so that someone can close this issue and tell me where to find this in the documentation.) What I would like, for example, is one of the following:

The aim of this exercise, and the benefit of such as feature, is for multiple developers working on files in the same folder to use slightly varying style options for their own files while still being able to correctly format other files in the same directory. This is already possible across directories, and it would be a great addition inside a directory.

llvmbot commented 1 year ago

@llvm/issue-subscribers-clang-format

bersbersbers commented 1 year ago

The patch below achieves the effect I am looking for, by allowing me to put a line such as the following anywhere into the code:

// clang-format style={BasedOnStyle: Google, ColumnLimit: 100}

I wonder if someone could give a rough judgement if it would be worth the effort creating a proper PR based on this idea:

diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index d3062905ad7e..c7cd4fa40255 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3741,6 +3741,25 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
   if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
     return make_string_error("Invalid fallback style \"" + FallbackStyleName);

+  if (StyleName == "file") {
+    // Read style from a magic comment in the code.
+    const char *Prefix{"// clang-format style="};
+    const size_t PrefixPos = Code.find(Prefix);
+
+    // Prefix found and at start of file or preceded by white space?
+    if (PrefixPos != StringRef::npos &&
+        ((PrefixPos == 0) || (Code.substr(PrefixPos - 1, 1).ltrim() == ""))) {
+
+      // Use remainder of line as StyleName
+      const size_t StylePos = PrefixPos + strlen(Prefix);
+      const size_t EndOfLine = Code.find_first_of("\r\n", StylePos);
+      if (EndOfLine != StringRef::npos)
+        StyleName = Code.substr(StylePos, EndOfLine - StylePos);
+      else
+        StyleName = Code.substr(StylePos);
+    }
+  }
+
   llvm::SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1>
       ChildFormatTextToApply;