IWYU is developed by a small number of loosely knit maintainers, and we rely on external contributions to stand a chance to improve the tool.
We use code reviews as a stage gate for every patch, via the GitHub pull request system. We try our best to make reviews constructive and avoid power struggles, so please accept feedback in the good faith it was delivered.
This document describes the most important of the conventions that contributors are expected to follow, so as to help make code reviews more productive and the code base more consistent and maintainable.
We prefer a linear history on the master branch, so we use a rebase workflow and avoid merge commits.
To post a pull request:
- Fork the
include-what-you-use
repository on GitHub - Clone your fork
- Create a topic branch in your clone
- Make changes
- Push branch to your fork
- Create pull request against the main repo
To address review feedback:
- Make changes in your branch
- Rewrite history in your branch to the way you want the final commit series. No use to keep incremental review feedback as separate commits; we're only interested in what the change set as a whole will look like.
- Make sure your branch is rebased on top of the latest upstream master and all tests pass
- Force-push to your fork. This will update the pull request for the next round of review.
Note that it's fine to rewrite history of throw-away branches such as pull request branches. If you need a more stable history for some reason (sharing with other developers, tagging, etc), use a dedicated branch for the pull request so you're free to rebase and amend it based on review feedback.
There's no strong convention or tooling for commit messages (yet), but please see https://chris.beams.io/posts/git-commit/ for set of guidelines to make the Git log a nice place to visit.
Every source file must have a license header on the form:
//===--- <filename> - <description> ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
(With the corresponding comment prefix/suffix for other languages.)
There is a utility script, iwyu-check-license-header.py
that can be used to
automatically add a license header with the right filename to a new source file.
IWYU originated within Google, so its basic style is based on what Google had in their style guide at that time. Please refer to the Google C++ style guide for details, but note that newer decisions may not apply to IWYU. The most important points:
- At most 80 characters per line
- 2 spaces indentation, 4 spaces for continued lines
- Unix line endings
- PascalCase for types and functions, hacker_case for variables, LOUDMOUTH_CASE for macros
- Pointer asterisk and reference ampersand binds to the type name, not the
declared variable (i.e. declarations look like
Foo* f;
andBar& b;
) - When in doubt, mimic the code around you.
IWYU has a .clang-format
file, so everything should play out nicely if you use
clang-format on your edited lines. PLEASE do not reformat more than lines you
touch, especially not whole files. The git-clang-format tool can help with this.
We observe a few LLVM-inspired rules for IWYU:
-
Use 'auto' sparingly -- we don't subscribe to the "Almost always auto" guideline in IWYU. In line with LLVM tradition we use
auto
when it improves readability, and take that to mean when the type is already clearly visible on the line (e.g.const auto& d = cast<Derived>(b);
) or when iterator declarations would grow too unwieldy (e.g.const auto i = some_map.begin();
). -
Prefer 'static' to anonymous namespaces -- while
static
is decidedly a C-ism, we find it's a readability win compared to anonymous namespaces to mark functions for internal linkage. The LLVM coding standards make the argument well, so no use to repeat it here.
Other than that, we mostly follow mainstream C++ style, if there is such a thing.
Older IWYU Python code follows the Google convention for Python code, but newer scripts typically just use PEP8.
Again, mimic the code around you.
IWYU uses a regression testing framework purpose-built to verify IWYU diagnostics.
There are a few conventions for IWYU testcases we use to keep the test suite maintainable and effective. Note that we have many tests breaking these guidelines, but that's considered a bug that we will work on over time.
IWYU started out with one single testcase -- badinc.cc
-- to cover all aspects
of IWYU. This has proved hard to maintain, as many assertions are subtly
interconnected and it can be difficult to map a test failure back to the feature
that triggered it.
Now that IWYU handles most of the basics, we try to add new testcases organized by the language construct or IWYU feature they cover. This tends to produce a large number of testcases, and we'll probably have to go back and organize them further at some point.
Some things to keep in mind:
- Keep testcase filenames short -- this is a case of "as short as possible, but no shorter". Every file has its name in the license header, the stem is repeated for supporting headers, and testcase names occasionally need to be typed without completion, so it's nice if they're short and sweet. But they also need to be meaningful. Find the balance.
- If a change pertains to a feature covered by an existing testcase, consider extending it instead of creating a new one.
- Don't use another testcase's supporting headers; that creates unwanted coupling between tests. But see below for a set of headers we do encourage sharing.
Prefer the reusable headers for simple constructs.
The test stack contains a few headers aimed for reuse:
indirect.h
-- definesIndirectClass
, a very basic C++ classdirect.h
-- includesindirect.h
subdir/indirect_subdir.h
-- definesIndirectSubDirClass
subdir/direct_subdir.h
-- includessubdir/indirect_subdir.h
subdir/dotdot_indirect.h
-- includes../indirect.h
If you need a basic class as a return type, argument type, variable or template
argument, IndirectClass
should be your preference.
The direct*.h
variants are used to force IWYU to do its analysis and
replacement; it will suggest that you remove direct.h
and include indirect.h
directly. More on this below.
The subdir/
headers can be used to test that IWYU is not confused by directory
structure (which has been known to happen).
Avoid using system headers for regression tests.
It's tempting to phrase your testcase in terms of the library that triggered a bug. But our test runners do not have all libraries installed. The C++ standard library is a non-obvious example of this: it's always available, but IWYU aims to be portable, and standard library implementations differ wildly.
For example, if std::map
triggers a bad behavior with IWYU on your MSVC system
because it uses some template trick in its implementation, it's likely libstdc++
or libc++ do not use the same trick, and exhibit different behavior.
Likewise, the internal physical design details of standard library
implementations are usually wildly different -- libstdc++ has all its private
headers in a directory called bits/
, MSVC prefixes all private library headers
with x
, e.g. xstring
, etc. IWYU uses mappings to overcome these differences.
Since we can't control what standard library IWYU will be tested with, we prefer to avoid standard library types and headers as far as possible, and instead try to reduce constructs that cause problems to a minimal mockup. Clang takes a similar approach in its test suite.
Note that many of IWYU's older tests do use system headers, and as a consequence we have incidental failures on many non-Linux platforms.
When making changes, make sure your testcases fail without your changes, and pass with them. This is an easy way to make sure your tests cover the right thing.
Use IWYU diagnostics for more fine-grained testing.
It's tempting to write a test such that it satisfies all IWYU rules and produces
a (x.cc has correct #includes/fwd-decls)
message.
But it's usually better to use the reusable headers to force some churn. Besides the summary output at the end ("should add/should remove/full include list"), IWYU also emits helpful diagnostics at the point of every use, e.g.
warning: X is defined in "tests/cxx/x.h", which isn't directly #included
warning: X needs a declaration, but does not provide or directly #include...
The test framework has native pattern matching support for these diagnostics, to make it easier to check that IWYU triggers where expected and doesn't suggest keeping a header for some unrelated reason.
Therefore, prefer to include direct.h
when you need IndirectClass
(or the
corresponding per-testcase header) to force a diagnostic on use.
Where the reusable headers are not enough, use per-test headers with a special naming convention.
In order to be able to force diagnostics, it's typically best to split
supporting headers into a direct and indirect pair. For a testcase named x.cc
,
these would be named:
x-indirect.h
for a header containing symbol declarationsx-direct.h
for a header includingx-indirect.h
If you need more than one header, use -i<N>
and -d<N>
for suffixes:
x-i1.h
andx-i2.h
for headers containing symbol declarationsx-d1.h
for a header includingx-i1.h
x-d2.h
for a header includingx-i2.h
Depending on the complexity of your testcase, you can usually use a single
-direct.h
header for multiple -i<N>.h
headers.
It's a good idea to keep the number of headers in a single testcase small, but some tests require more.
Also, beware of the associated header -- if you use a header x.h
for testcase
x.cc
, IWYU will identify it as an associated header and analysis will be
slightly different. That can be used to simplify testing, but it can also
produce results that aren't necessarily the same for non-associated headers.
Name symbols after their role or what sets them apart in the test.
And from the other perspective: don't name symbols for testing after their containing header file.
If it's important that a type is a template, name it Template
. If the defining
trait of a class from IWYU's perspective is that it's nested in another class,
name it Nested
, etc.
With the direct/indirect naming convention for headers, attempting to match up symbol and header names turns into an exercise in obscurity, and we prefer clear and communicative names.
Keeping strictly separate naming schemes for test symbols and headers also makes it easier to rename things without throwing Git's content tracking for a loop.
If a test needs to pass additional command-line args to IWYU, they are coded
into run_iwyu_tests.py
. There are three flag mappings:
flags_map
-- for IWYU flags, e.g.--no_comments
(automatically prefixed with-Xiwyu
)clang_flags_map
-- for Clang flags, e.g.-std=c++17
include_map
-- additional header search paths, e.g.subdir/
(automatically prefixed with-I
)
The maps are all keyed by test file basename.