Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clang-format file #5092

Closed
wants to merge 1 commit into from

Conversation

roligugus
Copy link
Contributor

@roligugus roligugus commented Jun 23, 2020

clang-format allows to auto-format C code. The settings here are set up to follow the code style, see https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Coding_Style.

Some bike shedding should still happen. Includes sample formatted code.

DO NOT MERGE AS IS.
This is not about reformatting all source code. That would be another discussion.

Make sure these boxes are signed before submitting your Pull Request -- thank you.

Link to redmine ticket:
https://redmine.openinfosecfoundation.org/issues/3736

Describe changes

  • FOOD FOR THOUGHT, DO NOT MERGE AS IS
  • clang-format is the standard way of formatting C style code
  • This pull request add a .clang-format configuration file so that clang-format can be used by people that do not want to manually format code or set up their editors. See below for sample usage.
    • Adding (minimal) .clang-format configuration implementing the Suricata code style. Best to discuss format through comments on the sample_formatted_code.do_not_merge.c file.
    • Included also alternative "full" config not based on other project (llvm in our case), see clang-format.full.do_not_merge
  • Included sample C code file showing the formatting style as applied, see file sample_formatted_code.do_not_merge.c.
    • Comments refer to the corresponding Suricata code style section where applicable. Other settings are interpretations of existing code, but I might have picked the wrong format out of multiple.
    • Initial version was created using https://github.com/mikr/whatstyle but lots of manual configurations afterwards resulted in essentially a different config.

Discussion and decisions

  1. Is this useful? I personally find it very useful as it helps avoiding formatting discussions during code review and it allows to enforce consistency. However, you guys might think differently.
  2. One can set up a minimal .clang-format "based on an existing project's style" or specify all settings. Includes both for people to compare the approaches. I'd recommend to pick the diff-based one, but the all settings approach can also be useful.
  3. Would it be useful to include the "sample formatted source code" somewhere? Parts of that should eventually make it into the "Code Style" wiki page.
  4. Bikeshedding some of the settings? I ran it through a few files to see how much it changes. I could have missed some common code style.
  5. If format is agreed upon, the Coding_Style wiki page could be updated.

Requires

  • Requires clang, e.g. on fedora: sudo dnf install clang
  • Tested with clang 9: clang-format version 9.0.1 (Fedora 9.0.1-2.fc31) and latest trunk (clang 11)
  • Have not tested with older versions

How to use it?

  • You can limit the formatting to your changes only by using "git format-patch". Requires a separate package, e.g. on fedora: sudo dnf install git-clang-format. This works surprisingly well, but it might not always work as well as the context might be missing.
  • You can format the whole file if you want to go nuts
# git clang-format can work off commits, i.e. you commit all your changes before using it, format code, and then commit the formatting changes separately.
# 
# To format changes in all commits in your branch, e.g. if branched off master:
$ git clang-format master

# To format changes in last commit only
$ git clang-format HEAD^

# git clang-format can also work off staged changes, i.e. you need to git add your changed files as a minimum
# To format current changes:
$ git clang-format

# clang-format proper works off the file, not just your changes. It has more context.
#
# To format the whole file
$ clang-format -i {file}

# e.g. to format all source files. Don't do this. Lots of changes.
$ clang-format -i src/*.h src/*.c

Other Notes

  • Trailing empty lines (at end of file) are removed
  • One can always disable clang-format for sections where the formatting might not be to the liking.
    • This probably applies mostly to macros, arrays (single or multi-dimensional ones), struct initialization, or where one manually formatted code as that might be quite different.
  • Rewriting of comments to fit to 80 chars length is disabled.
  • See notes in sample formatted file
  • clang-format settings documentation: https://clang.llvm.org/docs/ClangFormatStyleOptions.html

PRScript output (if applicable):
n/a

clang-format allows to auto-format C code. The settings here are set up to follow the code style, see https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Coding_Style.

Some bike shedding should still happen. Includes sample formatted code.

One can set up .clang-format as "differential setting based on an existing project" or specify all settings. Includes both for people to compare.

DO NOT MERGE AS IS.
@roligugus roligugus requested a review from a team as a code owner June 23, 2020 00:26
@@ -0,0 +1,562 @@
// Formatted using
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know these are C++ style comments. This is not meant to be committed, imho. I can always fix the commend style up if some form of this should be committed.


//--- Line Length ---
// https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Coding_Style#Line-length
// ColumnLimit: 80
Copy link
Contributor Author

@roligugus roligugus Jun 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ColumnLimit is the config that impacts the formatting here. I typically mentioned most of the important configs throughout the file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in favor of looking at relaxing the 80 chars. I think we've so far called this a soft limit and ~100 a hard limit. I'm okay with wider, where the main consideration should probably be the width of the review layout of github and gitlab.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what it's worth, Linux recently switched over to 100 chars.

Anyhow, clang-format only has a hard limit. I.e. whatever the number, that'll be the limit. Downside of making it bigger than the mostly used 80 chars is that it'll reformat to 100 chars some of the code that exceeded 80 chars.

struct bla {
// AlignConsecutiveDeclarations
// AlignTrailingComments
int a; /* comment */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the code aligns the struct fields, some not. Which one is preferred.

Small sidenote: there's a bug/feature in clang-format that it does not correctly indent the * if pointer is right-aligned and fields are aligned,
E.g.

struct bla {
    int      a;   /* comment */
    unsigned bb;  /* comment */
    int *    ccc; /* comment */
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer the non-aligned for members, but aligned for the comments. But not a strong opinion.

// pointers
// DerivePointerAlignment
// PointerAlignment
void *ptr;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw mostly right-aligned pointers so that's what I set up.

DerivePointerAlignment could be useful for whole-file formatting to "follow the prevalent left/centre/right aligned style". I disabled that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah right aligned it is


struct Bitfields {
// AlignConsecutiveBitFields
int aaaa : 1;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be spaces around the colon for bitfields which is different than used in e.g. app-layer-dnp3-objects.h

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the comment // AlignConsecutiveBitFields required here? What would happen if left off?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, sorry. It's my poor way of tracking that "this is the clang-format setting that impacts this". None of the // comments are required, just FYI. These settings are only set in the .clang-format file.

I am currently updating the code_style.rst where it should be easier to follow.

I was trying to avoid including a "this vs that" comparison for each setting, but it probably would be helpful for the bikeshedding discussion on the format. ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AlignConsecutiveBitFields (bool)
If true, aligns consecutive bitfield members.

This will align the bitfield separators of consecutive lines. This will result in formattings like

int aaaa : 1;
int b    : 12;
int ccc  : 8;

Oh, this is only supported as of clang 11 which is not yet out. I don't think this should be set at all then. Explains why you won't find this setting in clang-format.full.do_not_merge. I've used clang 9 which is recent enough yet old enough to be supported by different dists.

//--- comment wrapping ---
void multi_line_comments()
{
// ReflowComments: false does not trim comments to ColumnLimit chars
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disabled limiting comments to 80 chars in the config. Hence, clang-format does not reformat comments.

While it's great to use in my experience, changing an existing code base can be messy. It requires manual fixing up of comments as we devs suck at formatting comments to a length.

Having said that, it probably would be great to enable it so that new code could take advantage of it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like it when an IDE reflows my comments to 80 chars. So I'd like to see this on by default, if it doesn't get in the way too often.

@catenacyber catenacyber marked this pull request as draft June 23, 2020 06:35
@catenacyber
Copy link
Contributor

Thanks for this proposition.
Is there a way that CI can check that Pull Request's commits are properly formatted ? Running git clang-format on them ?

@roligugus
Copy link
Contributor Author

Thanks for this proposition.

Cool, just learnt that there's a draft in github.

Is there a way that CI can check that Pull Request's commits are properly formatted ? Running git clang-format on them ?

Don't know github actions myself, but there should be a way.
Initial idea would be to add a stage similar to the fuzz and cocci builds and have it fail if formatting is wrong, i.e. git clang-format does not produce the code in the same format. Have not had time to look into it. Will play with it.

We could probably add a new make target as well that could be used in the github action.

From what I can tell, these are the different potential steps:

  1. Create the clang-format config and update code style. I am currently updating the devguide and will add to this PR once done.
  2. Enforce formatting for new pull requests, or have at least some warnings. I would not recommend to auto-format it through CI, but rather force the dev do the leg work. Anyhow, that work lends itself to the CI infra, i.e. github actions.
  3. We could probably provide a git pre-commit hook for people to do that. Not a big fan personally of git hooks as they are optional and some projects go crazy over it, but it could be one possible option.
  4. Reformat all code if there is a willingness. That will need a proper strategy and multiple iterations to prep the code as well.

Reformatting all code shall be out-of-scope for this PR.

@victorjulien
Copy link
Member

Thanks Roland, this is great work. The git clang-format trick looks interesting. As you can imagine my biggest worry is a massive reformat. The result of that would be nice, but what it will do to our git history... (and think of the painful rebases for anyone still sitting on unmerged branches).

@roligugus
Copy link
Contributor Author

roligugus commented Jul 2, 2020

Rebases of unmerged branches can be handled with git filter-branch. I will add some make targets to help with that use case.

I fully understand the worries about massive reformatting. Been there, done that. ;)

No easy solution, really. For git bisect driven workflows, we clang-format the old version as well and then do diffs that way in case one version is formatted, and one not. Not ideal, but workable. The pain is if you quickly want to diff across the "reformatting boundary". Pre-reformat and post-reformat diffs are the albeit somewhat mundane solution. Key is to have "pure formatting commits" to indicate these boundaries.

@victorjulien
Copy link
Member

Continued in #5147

@roligugus roligugus mentioned this pull request Jul 15, 2020
3 tasks
@roligugus
Copy link
Contributor Author

Real continuation of this is #5186

#5147 was only a test for github actions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants