lix/subprojects/lix-clang-tidy
Jade Lovelace 3daeeaefb1 build: implement clang-tidy using our plugin
The principle of this is that you can either externally build it with
Nix (actual implementation will be in a future commit), or it can be
built with meson if the Nix one is not passed in.

The idea I have is that dev shells don't receive the one from Nix to
avoid having to build it, but CI can use the one from Nix and save some
gratuitous rebuilds.

The design of this is that you can run `ninja -C build clang-tidy` and
it will simply correctly clang-tidy the codebase in spite of PCH
bullshit caused by the cc-wrapper.

This is a truly horrendous number of hacks in a ball, caused by bugs in
several pieces of software, and I am not even getting started.

I don't consider this to fix the clang-tidy issue filing, since we still
have a fair number of issues to fix even on the existing minimal
configuration, and I have not yet implemented it in CI. Realistically we
will need to do something like https://github.com/Ericsson/codechecker
to be able to silence warnings without physically touching the code, or
at least *diff* reports between versions.

Also, the run-clang-tidy output design is rather atrocious and must
not be inflicted upon anyone I have respect for, since it buries the
diagnostics in a pile of invocation logs. We would do really well to
integrate with the Gerrit SARIF stuff so we can dump the reports on
people in a user-friendly manner.

Related: https://git.lix.systems/lix-project/lix/issues/147

Change-Id: Ifefe533f3b56874795de231667046b2da6ff2461
2024-08-04 20:41:19 -07:00
..
.clang-format build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
.editorconfig build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
default.nix build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
FixIncludes.cc build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
FixIncludes.hh build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
HasPrefixSuffix.cc build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
HasPrefixSuffix.hh build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
LixClangTidyChecks.cc build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
meson.build build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
meson.options build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00
README.md build: implement clang-tidy using our plugin 2024-08-04 20:41:19 -07:00

Clang tidy lints for Lix

This is a skeleton of a clang-tidy lints library for Lix.

Currently there is one check (which is already obsolete as it has served its goal and is there as an example), HasPrefixSuffixCheck.

Running fixes/checks

One file:

ninja -C build && clang-tidy --checks='-*,lix-*' --load=build/liblix-clang-tidy.so -p ../compile_commands.json -header-filter '\.\./src/.*\.h' --fix ../src/libcmd/installables.cc

Several files, in parallel:

ninja -C build && run-clang-tidy -checks='-*,lix-*' -load=build/liblix-clang-tidy.so -p .. -header-filter '\.\./src/.*\.h' -fix ../src | tee -a clang-tidy-result

Resources

Developing new checks

Put something like so in myquery.txt:

set traversal     IgnoreUnlessSpelledInSource
# ^ Ignore implicit AST nodes. May need to use AsIs depending on how you are
# working.
set bind-root     true
# ^ true unless you use any .bind("foo") commands
set print-matcher true
enable output     dump
match callExpr(callee(functionDecl(hasName("hasPrefix"))), optionally(hasArgument( 0, cxxConstructExpr(hasDeclaration(functionDecl(hasParameter(0, parmVarDecl(hasType(asString("const char *"))).bind("meow2"))))))))

Then run, e.g. clang-query --preload hasprefix.query -p compile_commands.json src/libcmd/installables.cc.

With this you can iterate a query before writing it in C++ and suffering from C++.

Tips and tricks for the C++

There is a function dump() on many things that will dump to stderr. Also llvm::errs() lets you print to stderr.

When I wrote HasPrefixSuffixCheck, I was not really able to figure out how the structured replacement system was supposed to work. In principle you can describe the replacement with a nice DSL. Look up the Stencil system in Clang for details.