tidy: add a lint to forbid nlohmann::json::parse

Change-Id: I165c7330d7ea7f17522ade8a0666d0d7d86b9d38
This commit is contained in:
eldritch horrors
2025-03-27 08:56:14 +00:00
parent 0d47773d76
commit b918f1c307
5 changed files with 62 additions and 0 deletions
+1
View File
@@ -163,6 +163,7 @@ template<typename Source>
JSON parse(Source && source, std::optional<std::string_view> context = {})
{
try {
// NOLINTNEXTLINE(lix-disallowed-decls): this is the wrapper for that
return JSON::parse(std::forward<Source>(source));
} catch (JSON::exception & e) {
ParseError error{"failed to parse JSON: %s", e.what()};
@@ -0,0 +1,37 @@
#include "DisallowedDecls.hh"
#include <clang/AST/ASTTypeTraits.h>
#include <clang/AST/Expr.h>
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/Type.h>
#include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/Frontend/FrontendAction.h>
#include <clang/Frontend/FrontendPluginRegistry.h>
#include <clang/Tooling/Transformer/SourceCode.h>
#include <clang/Tooling/Transformer/SourceCodeBuilders.h>
namespace nix::clang_tidy {
using namespace clang::ast_matchers;
using namespace clang;
void DisallowedDeclsCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
Finder->addMatcher(
traverse(clang::TK_AsIs,
callExpr(callee(cxxMethodDecl(hasName("parse"),
ofClass(isSameOrDerivedFrom(
"nlohmann::basic_json")))))
.bind("json-parse")),
this);
}
void DisallowedDeclsCheck::check(
const ast_matchers::MatchFinder::MatchResult &Result) {
if (auto MatchedParse = Result.Nodes.getNodeAs<CallExpr>("json-parse")) {
auto Diag = diag(MatchedParse->getExprLoc(),
"using nlohmann::basic_json::parse is disallowed, use the lix wrapper instead");
Diag << FixItHint::CreateReplacement(MatchedParse->getCallee()->getSourceRange(),
"json::parse");
}
}
}; // namespace nix::clang_tidy
@@ -0,0 +1,21 @@
#pragma once
///@file
#include <clang-tidy/ClangTidyCheck.h>
#include <clang/ASTMatchers/ASTMatchFinder.h>
#include <llvm/ADT/StringRef.h>
namespace nix::clang_tidy {
using namespace clang;
using namespace clang::tidy;
using namespace llvm;
class DisallowedDeclsCheck : public ClangTidyCheck {
public:
DisallowedDeclsCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
}; // namespace nix::clang_tidy
@@ -1,5 +1,6 @@
#include <clang-tidy/ClangTidyModule.h>
#include <clang-tidy/ClangTidyModuleRegistry.h>
#include "DisallowedDecls.hh"
#include "HasPrefixSuffix.hh"
#include "CharPtrCast.hh"
#include "NeverAsync.hh"
@@ -14,6 +15,7 @@ class NixClangTidyChecks : public ClangTidyModule {
CheckFactories.registerCheck<HasPrefixSuffixCheck>("lix-hasprefixsuffix");
CheckFactories.registerCheck<CharPtrCastCheck>("lix-charptrcast");
CheckFactories.registerCheck<NeverAsync>("lix-never-async");
CheckFactories.registerCheck<DisallowedDeclsCheck>("lix-disallowed-decls");
}
};
+1
View File
@@ -6,6 +6,7 @@ project('lix-clang-tidy', ['cpp', 'c'],
llvm = dependency('Clang', version: '>= 16', modules: ['libclang'])
sources = files(
'CharPtrCast.cc',
'DisallowedDecls.cc',
'HasPrefixSuffix.cc',
'LixClangTidyChecks.cc',
'NeverAsync.cc',