Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can clang-format tell me if formatting changes are necessary?

Is there an way that you can run clang-format in a mode where it reports if the file meets the specified format? A kind of dry-run mode where it reports if a change is needed, but doesn't make the change. Ideally I'd like clang-format to just return a non-zero exit code if the file needs changes. Or, even more ideally, a non-zero exit code and a list of the files that need changes on standard output.

I'm trying to keep the question generic, so that more people can answer, but what I am trying to do is write a git pre-commit hook that will reject any commits that don't match the expected .clang-format . It's easy to run clang-format on the list of files in the index. But it's hard to know if clang-format actually changed anything.

I have one potential solution based on -output-replacements-xml (that I will post as an answer), but it's a hack and I feel like this should be more straightforward. Comments/suggestions, edits, different answers/approaches are all welcome.

like image 450
David Ogren Avatar asked Apr 04 '14 15:04

David Ogren


People also ask

What is clang format check?

Use clang-format to see if your C/C++/Protobuf code is formatted according to project guidelines.

Where does clang format look for clang format?

Standalone Tool clang-format is located in clang/tools/clang-format and can be used to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code.

What is Clang format and how does ReSharper support it?

What is Clang-Format and how does ReSharper support it? Clang-Format is a widely-used C++ code formatter. As it provides an option to define code style options in YAML-formatted files — named .clang-format or _clang-format — these files often become a part of your project where you keep all code style rules.

How do I change the style of a clang file?

clang-format supports two ways to provide custom style options: directly specify style configuration in the -style= command line option or use -style=file and put style configuration in the .clang-format or _clang-format file in the project directory.

What is the style argument used for in Clang-format?

The style argument is used to determine the style rules that clang-format will apply. You can use any of the styles described above, or -style=file to tell clang-format that it must use your .clang-format file. By default, clang-format will display formatting discrepancies as shell output. I prefer to have clang-format update the files directly.

How do I enable Clang without a clang-format file?

clang-format can also be enabled without a .clang-format file. In this case, CLion prompts you to create one based on the current IDE settings or the default LLVM style. Download the latest Visual Studio extension from the alpha build site. The default key-binding is Ctrl-R,Ctrl-F.


2 Answers

One of the reasons I feel like this should be easier than it is because -output-replacements-xml essentially gives me the answer that I want, it just doesn't give it to me in an easy to consume way. However, since the output if no replacements are needed is very predictable, parsing the output isn't too hard.

What I have right now is

clang-format -style=file -output-replacements-xml | grep -c "<replacement " >/dev/null 

This actually returns the inverse of the exit code I want, since grep returns 0 if something matches, 1 if nothing does. But that is easy enough to deal with.

So the relevant bit of my git pre-commit hook would be

git diff --cached --name-only --diff-filter=ACMRT |   grep "\.[cmh]$" |   xargs -n1 clang-format -style=file -output-replacements-xml |   grep "<replacement " >/dev/null if [ $? -ne 1 ]; then      echo "Commit did not match clang-format"     exit 1 fi 
  1. Get the full filenames of the files in the index (excluding files that are being deleted and other unusual cases where I might not want to process the file)
  2. Only keep the filenames of things I want to check the formatting of (in my case just c,m, and h files)
  3. Run the results through xargs to essentially "for each" the next command
  4. Run clang-format with the -output-replacements-xml option on all of the files
  5. Search for replacement (as opposed to replacements) that indicates that clang-format has found a replacement that it wants to make. (Discarding all output as the XML won't be meaningful to the user.)
  6. The last command exits 1 (grep says we found nothing) we are done and things are fine.
  7. If not, display a message and exit 1, which cancels the commit. Unfortunately we don't have an easy way to tell the user which file was the problem, but they can run clang-format themselves and see.
like image 62
David Ogren Avatar answered Sep 28 '22 10:09

David Ogren


Use the --dry-run and -Werror command line options. They will cause ClangFormat to output any formatting violations to stdout and return a non-zero exit status if any input file was not correctly formatted.

$ clang-format --dry-run --Werror foo.cpp foo.cpp:129:23: error: code should be clang-formatted [-Wclang-format-violations]         if (rc <= 0) { $ echo $? 1 

Originally from my website here: https://rigtorp.se/notes/clang-format/

like image 39
Erik Avatar answered Sep 28 '22 08:09

Erik