10.5. Style

Todo

This is very preliminary. We’ll extend it over time. It’s also not consistently applied everywhere yet. Working on that.

10.5.1. Tooling

Spicy ships with a set of linter configurations to enforce some of the style guidelines documented below. We use pre-commit to run linters on each commit.

After cloning the repository, one can install the commit hooks by running the following command from the root of the checkout:

$ pre-commit install && pre-commit install --hook-type commit-msg
pre-commit installed at .git/hooks/pre-commit
pre-commit installed at .git/hooks/commit-msg

With installed hooks the configured linters check the code after each commit. To run linters standalone one can use the following:

$ pre-commit run -a

See the pre-commit CLI documentation for more information on how pre-commit can be used.

Note

Some linters might require that a full build was performed or additional external tooling, see e.g., Formatting.

10.5.2. Commit Messages

  • Provide meaningful commit messages. Start the commit message with a one line summary and then explain at a high-level what’s going on, including in particular any new functionality and changes to existing semantics. Include short examples of functionality if possibles. (Expect people to read your commit messages. :)
  • If the commit refers to ticket or PR, include the number into the commit message.
  • Aim to make commits self-containing chunks of functionality. Rebase and squash before pushing upstream.
  • Formatting aspects of commit messages are linted with gitlint via pre-commit hooks, see Tooling. In particular we enforce that summary lines start with a captial letter and end in a period, and length limits for both summary and body lines.

10.5.3. Formatting

Spicy comes with a clang-format configuration that enforces a canonical style. We require clang-format version >= 10 because we need a style option that wasn’t available earlier. There’s a format target in the top-level Makefile that checks all relevant source files for conformance with our style. A second target format-fixit reformats Spicy’s code where it doesn’t confirm.

To ensure the right clang-format version is being used, either have it in your PATH or set the environment variable CLANG_FORMAT to the full path of the binary before running either of these targets.

Spicy’s CI runs make format as part of its code checks and will abort if there’s anything not formatted as expected.

10.5.4. Static analysis

Spicy also comes with a clang-tidy configuration, as well as Makefile targets similar to the ones for formatting: make tidy will check the code, and make tidy-fixit will apply fixes automatically where clang-tidy is able to. Note that the latter can sometimes make things worse: Double-check git diff before committing anything.

You can set the environment variable CLANG_TIDY to the full path of the clang-tidy to ensure the right version is found (which, similar to clang-format, needs to be from Clang >= 10).

Spicy’s CI runs make tidy as part of its code checks and will abort if there’s anything not formatted as expected.

10.5.5. Code Conventions

Identifiers

  • Class methods: lowerCamelCase() for public and protected methods; _lowerCamelCase() for private methods.
  • Class member constants & variables: lower_case for public members, and _lower_case_with_leading_underscore for private members.
  • Global function: lowerCamelCase()

Comments

  • In header files:

    • Public namespace (i.e., anything not in *::detail::*)

      • Add Doxygen comments to all namespace elements.
      • Add Doxygen comments to all public and protected members of classes. (Exceptions: Default constructors; destructors; default operators; “obvious” operators, such as basic constructors and straight-forward comparisons; obvious getters/setters).
    • Private namespace (i.e., anything in *::detail::*)

      • Add a brief sentence or two to all namespace elements that aren’t obvious.
      • Add a brief sentence or two to all class members that aren’t obvious.
  • In implementation files

    • For elements that aren’t declared in a separate header file, follow the rules for headers defining elements of the private namespace.
    • Inside methods and functions, comment liberally but not needlessly. Briefly explain the main reasoning behind non-obvious logic, and introduce separate parts inside larger chunks of code.

Doxygen style

  • Always start with a brief one-sentence summary in active voice (“Changes X to Y.”)
  • For functions and methods, include @param and @return tags even if it seems obvious what’s going on. Add @throws if the function/method raises an exception in a way that’s considered part of its specific semantics.