Skip to content

Lint includes: analyse include blocks, enforce correct include ordering and block organisation

The developer guide gives precise specifications for how included headers should be grouped, and these groups should be ordered:

  • In order to make the code consistent, header files should be included in the following order, with each section separated by a newline:

    1. In a .cpp file, the associated .h is in first position. In a test source, this is the header file under test.
    2. The project headers.
    3. The test headers.
    4. The 3rd party libraries headers. Different libraries should be in different sections.
    5. The system libraries.
  • All headers should be lexically ordered inside their block.

Prior to now, this has only been enforced manually during code review.

Lint script changes: !1590 (diffs)

The additions to the linter script make some progress towards automatic linting to enforce these rules, as follows:

  • The linter now reads the complete group of #includes for each file, and parses them into blocks for further processing.
  • All blocks of includes are tested for lexical ordering. If one fails, the linter prints the expected ordering, to help the developer.
  • For a .cpp file, if a matching .h file exists, the linter expects this to be included in the first block.
  • If the following block starts with a file in the src/ tree, it is assumed to be the block of project includes, and no includes that do not exist in the project are permitted in this block.
  • If a library is recognised in a block of #includes, that entire block is expected to consist of only includes for that library. Such a block is expected to come after the block of project includes, but before the system includes. Currently recognised libraries:
    • Boost
    • Qt
  • If a standard library or system #include is recognised in a block of includes, that entire block is expected to consist only of standard and system includes. Additionally, this block is expected to come at the end of all other include blocks.
  • Unknown libraries are ignored.
  • Includes gated by preprocessor logic (#ifdef / #endif) are ignored.

Other source changes

Violations of the above rules for the existing code have been resolved.

There are no functional changes to code other than the linter.

Continuous integration

As these changes extend the existing include linter functionality, these additional checks will run in all continuous integration pipelines with no further modification.

Test plan

ninja check-lint-lint-includes
Edited by SlowRiot

Merge request reports