This folder contains clang-tidy plugins.
The knowledge related to this repo was presented at a C++ meetup event on Febraury 21st, 2024. You can find the slides from this presentation in clang-tidy-coveo.pdf.
To build the plugins, first, you'll need LLVM/Clang version 16.
On Ubuntu, you can install them with the script installClang16.sh
(see testcpp.yml for more details).
Then,
CC=clang-16 CXX=clang++-16 cmake -B build -G Ninja -S .
cmake --build build
To use the plugin,
- You can list the plugin with
clang-tidy-16 \ --checks='*' \ --load build/lib/libAwesomePrefixCheck.so \ --list-checks \ | grep coveo-awesomeprefixcheck
- To use the plugin, you need to compile the code you want to use the plugin on, and to export the compile database with
CMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake -B buildRepoUsingPlugin -S repo-using-plugin \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON cmake --build buildRepoUsingPlugin
- That's it, you can now use the plugin!
clang-tidy-16 \ --checks='coveo-awesomeprefixcheck' \ --load build/lib/libAwesomePrefixCheck.so \ -p buildRepoUsingPlugin/compile_commands.json \ repo-using-plugin/src/code.cpp
Writing a clang-tidy check, finding a file in another repository where the check would apply and running the check on that file can get tedious quickly. Luckily for us, there is a better way.
Create a stub of the code that you want to replace, like in the file src/replace_cglpath_by_std/CGLPathStub.h.
Then, use the methods that you want to replace in a function, like in the file src/replace_cglpath_by_std/TestCallsReplacementsPath.cpp.
Separates const
uses from mutable uses to make sure you don't inadvertently remove constness.
Then, write your custom check, for instance, coveo-replacecglpathbystdcheck
.
Write a file that contains the code that you expect to have after your check has run, like src/replace_cglpath_by_std/ExpectedTestCallsReplacementsPath.cpp.
Now, to test, create a script similar to src/replace_cglpath_by_std/testReplacePath.sh.
This script also has an option that allows you to update the expected file ExpectedTestCallsReplacementsPath.cpp with
src/replace_cglpath_by_std/testReplacePath.sh build 1
where build
is your build directory and 1
is the value that the variable updateExpected
takes.
Note that if you don't want to update the expected file, the script has default values for its parameters, so you can just call
src/replace_cglpath_by_std/testReplacePath.sh
and it will look for a build directory build
in your current working directory.
If you want to run clang-tidy manually, take a look inside the script testReplacePath.sh to see how to do it.
As ExpectedTestCallsReplacementsPath.cpp illustrates, you can sometimes go one step further and write an end to end test.
In that example, you can uncomment TEST_WITH_PATH_BEING_AN_ALIAS_OF_STD_FILESYSTEM
so that the header src/replace_cglpath_by_std/CGLPathIsStdfilesystemPath.h is included instead of CGLPathStub.h.
As the header name suggests, Path
is defined as using Path = std::filesystem::path
in CGLPathIsStdfilesystemPath.h instead of being stubbed.
This is the end goal of the check: replacing our in-house path implementation CGLFile::Path
by the standard std::filesystem::path
.
TEST_WITH_PATH_BEING_AN_ALIAS_OF_STD_FILESYSTEM
allows testing just that.
Finally, to test automatically, compile ExpectedTestCallsReplacementsPath.cpp as illustrated in src/replace_cglpath_by_std/CMakeLists.txt with the target TestCallsReplacementsPathWithStd
.
- Clang Transformer Tutorial
- AST Matcher Reference
- Writing clang-tidy checks
- Stephen Kelly - Refactor your codebase with Clang tooling
- Stephen Kelly - The Future of AST Matcher-based Refactoring
- Stephen Kelly Blog
Every Stephen Kelly references above were written/filmed before that clang-tidy
introduce plugins.