In clang-format, what do the penalties do?

C++Clang Format

C++ Problem Overview


The clang-format sytle options documentation includes a number of options called PenaltyXXX. The documentation doesn't explain how these penalties should be used. Can you describe how to use these penalty values and what effect they achieve (perhaps with an example)?

C++ Solutions


Solution 1 - C++

When you have a line that's over the line length limit, clang-format will need to insert one or more breaks somewhere. You can think of penalties as a way of discouraging certain line-breaking behavior. For instance, say you have:

Namespaces::Are::Pervasive::SomeReallyVerySuperDuperLongFunctionName(args);
// and the column limit is here:                                        ^

Clang-format will probably format to look a little strange:

Namespaces::Are::Pervasive::SomeReallyVerySuperDuperLongFunctionName(
    args);

You might decide that you're willing to violate the line length by a character or two for cases like this, so you could steer that by setting the PenaltyExcessCharacter to a low number and PenaltyBreakBeforeFirstCallParameter to a higher number.

Personally, I really dislike when the return type is on its own line, so I set PenaltyReturnTypeOnItsOwnLine to an absurdly large number.

An aside, this system was inherited from Latex, which allows you to specify all kinds of penalties for line-breaking, pagination, and hyphenation.

Solution 2 - C++

> Can you describe how to use these penalty values and what effect they achieve (perhaps with an example)?

You can see an example in this Git 2.15 (Q4 2017) clang-format for the Git project written in C:

See commit 42efde4 (29 Sep 2017) by Johannes Schindelin (dscho).
(Merged by Johannes Schindelin -- dscho -- in commit 42efde4, 01 Oct 2017)

You can see the old and new values here:

clang

To illustrate those values:

> ## clang-format: adjust line break penalties

> We really, really, really want to limit the columns to 80 per line: One of the few consistent style comments on the Git mailing list is that the lines should not have more than 80 columns/line (even if 79 columns/line would make more sense, given that the code is frequently viewed as diff, and diffs adding an extra character).

> The penalty of 5 for excess characters is way too low to guarantee that, though, as pointed out by Brandon Williams.

(See this thread)

> From the existing clang-format examples and documentation, it appears that 100 is a penalty deemed appropriate for Stuff You Really Don't Want, so let's assign that as the penalty for "excess characters", i.e. overly long lines.

> While at it, adjust the penalties further: we are actually not that keen on preventing new line breaks within comments or string literals, so the penalty of 100 seems awfully high.

> Likewise, we are not all that adamant about keeping line breaks away from assignment operators (a lot of Git's code breaks immediately after the = character just to keep that 80 columns/line limit).

> We do frown a little bit more about functions' return types being on their own line than the penalty 0 would suggest, so this was adjusted, too.

> Finally, we do not particularly fancy breaking before the first parameter in a call, but if it keeps the line shorter than 80 columns/line, that's what we do, so lower the penalty for breaking before a call's first parameter, but not quite as much as introducing new line breaks to comments.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionScott LanghamView Question on Stackoverflow
Solution 1 - C++JHumphreyView Answer on Stackoverflow
Solution 2 - C++VonCView Answer on Stackoverflow