Skip to content

Style conventions#

On this page we first discuss style conventions that developers have to manually take care of, as they are not automatically handled by clang-format. Then we introduce the most important components of our clang-format configuration and motivate the decisions made. Refer to the development setup for installation instructions and see our coding conventions.

As with our other conventions: when something is not specified here and you're in doubt, follow the examples in the existing code.

Things not handled by clang-format#

Strings#

Column width is not enforced for strings, they are left as they are. Please ensure manually that lines stay within 80 characters.

Comments#

// Use this style for short comments.

// TODO: Use this format for todo items.

// Write complete sentences ending with periods.

/* Use imperative if possible: "Return the factorial." is better than "Returns
   the factorial.". */

/*
  Use this style for comments spanning multiple lines and strive to write
  self-explanatory code that doesn't need comments.
*/

/* For shorter multi-line comments (2-3 lines)
   this style is also fine. */
  • Column width is enforced when lines are too long. Stay within the character limit to stop clang-format from changing line breaks.
  • clang-format splits long // comments into multiple lines each starting with //.
  • We generally prefer comments above the code, not next to it.

Conditionals and Loops#

For if, while statements etc. with only a single statement in the body, braces are optional. For constructs with several blocks (if/else, try/catch) either all blocks should have braces or none.

Miscellaneous#

  • Add an empty line between the last group of includes and the remaining code.
  • If using namespace std, put it after all includes.

Things handled by clang-format#

The configuration file contains definitions for all options that we actively thought about. We chose a base style whose default parameters have the greatest overlap with these explicit choices, which happened to be the LLVM style. In the .clang-format file, we list the overlapping options explicitly, along with options that deviate.

Column Width#

We stick to the 80 character column width. A compelling argument for this choice was that it allows viewing of diffs on GitHub without breaking lines, even on laptop screens. clang-format enforces this limit strictly.

Bin Packing#

The options connected to bin packing control how function definitions and calls that do not fit on a single line are formatted. We decided to allow bin packing, that is, that parameters and arguments may fill lines below the function instead of being placed on single lines. The motivation was that we save vertical space and improve readability of plain code, compromising on diff readability. clang-format does not allow member initializer lists in constructors to be bin packed, instead we put entries on single lines for long initializer lists.

Includes#

We allow clang-format to group includes and sort entries alphabetically within groups. The groups are sorted as follows:

  1. header corresponding to .cc file
  2. headers that are neighbors
  3. headers in neighboring subdirectories
  4. headers in parent directory
  5. headers in subdirectories of parent directory
  6. standard libraries

Note that with the current directory structure, where src/search/ contains no subsubdirectories, a file may only include headers from either group 3 (if the file is in src/search/) or from group 4 and 5 (if the file is in a subdirectory of src/search/).

Here is a contrived example for pattern_generation_edelkamp.cc:

#include "pattern_generation_edelkamp.h"

#include "zero_one_pdbs_heuristic.h"

#include "../abstract_task.h"
#include "../causal_graph.h"

#include "../utils/timer.h"

#include <algorithm>
#include <cassert>
#include <vector>

Single Line Function#

We do not allow single line function definitions. This makes diffs more readable and separates the function body more clearly.

Return Type on Its Own Line#

To avoid line breaks like this

virtual bool
are_facts_mutex(const FactPair &fact1, const FactPair &fact2) const = 0;
we increased the penalty for putting the return type on a single line to instead get
virtual bool are_facts_mutex(
    const FactPair &fact1, const FactPair &fact2) const = 0;
in most cases.