|
| 1 | +# Clang-Tidy |
| 2 | + |
| 3 | +The library comes with a [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) plugin. |
| 4 | +It is disabled by default but can be enabled by enabling the `JSON_ClangTidyPlugin` [CMake option](cmake.md#json_clangtidyplugin). |
| 5 | +Clang-tidy [Plugins](https://clang.llvm.org/extra/clang-tidy/ExternalClang-TidyExamples.html) are only supported by Clang 16 and later. |
| 6 | + |
| 7 | +## Building the plugin |
| 8 | + |
| 9 | +You will need to have the development files matching your version of clang-tidy installed to build the plugin. |
| 10 | +For example, if you are running on a Debian-derived Linux distribution: |
| 11 | + |
| 12 | +```sh |
| 13 | +apt install clang-tidy libclang-dev |
| 14 | +``` |
| 15 | +but if this installs a version that is older than Clang 16 then you might be able to specify a newer version. For example: |
| 16 | +```sh |
| 17 | +apt install clang-tidy-19 libclang-19-dev |
| 18 | +``` |
| 19 | + |
| 20 | +```sh |
| 21 | +mkdir build |
| 22 | +cd build |
| 23 | +cmake -DJSON_ClangTidyPlugin=ON .. |
| 24 | +cmake -build . |
| 25 | +``` |
| 26 | + |
| 27 | +# Running the plugin |
| 28 | +To tell clang-tidy to use the plugin you must pass a path to it as an argument to the `-load` option. |
| 29 | +For example, you can run clang-tidy with only the _modernize-nlohmann-json-explicit-conversion_ check using the plugin on a single file with: |
| 30 | +```sh |
| 31 | +clang-tidy -load .../path/to/build/clang_tidy_plugin/libNlohmannJsonClangTidyPlugin.so -checks='-*,modernize-nlohmann-json-explicit-conversions` -fix source.cpp |
| 32 | +clang-tidy |
| 33 | +``` |
| 34 | +or you can create a `.clang-tidy` file to enable the checks you require. |
| 35 | +
|
| 36 | +# Checks |
| 37 | +
|
| 38 | +At the moment the plugin contains only a single check. |
| 39 | +
|
| 40 | +## modernize-nlohmann-json-explicit-conversions |
| 41 | +
|
| 42 | +This check converts code that takes advantage of [implicit conversions](../api/macros/json_use_implicit_conversions.md) to use explicit `get()` calls using the correct templated type. |
| 43 | +For example, it turns: |
| 44 | +```c++ |
| 45 | +void f(const nlohmann::json &j1, const nlohmann::json &j2) |
| 46 | +{ |
| 47 | + int i = j1; |
| 48 | + double d = j2.at("value"); |
| 49 | + bool b = *j2.find("valid"); |
| 50 | + std::cout << i << " " << d << " " << b << "\n"; |
| 51 | +} |
| 52 | +``` |
| 53 | +into |
| 54 | +```c++ |
| 55 | +void f(const nlohmann::json &j1, const nlohmann::json &j2) |
| 56 | +{ |
| 57 | + int i = j1.get<int>(); |
| 58 | + double d = j2.at("value").get<double>(); |
| 59 | + bool b = j2.find("valid")->get<bool>(); |
| 60 | + std::cout << i << " " << d << " " << b << "\n"; |
| 61 | +} |
| 62 | +``` |
| 63 | +by knowing what the target type is for the implicit conversion and turning |
| 64 | +that into an explicit call to the `get()` method with that type as the |
| 65 | +template parameter. |
| 66 | +
|
| 67 | +Unfortunately the check does not work very well if the implicit conversion |
| 68 | +occurs in templated code or in a system header. For example, the following |
| 69 | +won't be fixed because the implicit conversion will happen inside |
| 70 | +`std::optional`'s constructor: |
| 71 | +```c++ |
| 72 | +void f(const nlohmann::json &j) |
| 73 | +{ |
| 74 | + std::optional<int> oi; |
| 75 | + const auto &it = j.find("value"); |
| 76 | + if (it != j.end()) |
| 77 | + oi = *it; |
| 78 | + // ... |
| 79 | +} |
| 80 | +``` |
| 81 | +After you have run this check you can set [JSON_USE_IMPLICIT_CONVERSIONS=0](../api/macros/json_use_implicit_conversions.md) to find any occurrences that the check have not been fixed automatically. |
0 commit comments