forked from lix-project/lix
Jade Lovelace
6b0020749d
This brings in infrastructure for developing new custom clang-tidy lints
and refactors for Lix.
Change-Id: I3df5f5855712ab4f97d4e84d771e5e818f81f881
80 lines
2.7 KiB
C++
80 lines
2.7 KiB
C++
#include "HasPrefixSuffix.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>
|
|
#include <iostream>
|
|
|
|
namespace nix::clang_tidy {
|
|
using namespace clang::ast_matchers;
|
|
using namespace clang;
|
|
|
|
void HasPrefixSuffixCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
|
|
Finder->addMatcher(
|
|
traverse(clang::TK_AsIs,
|
|
callExpr(callee(functionDecl(anyOf(hasName("hasPrefix"),
|
|
hasName("hasSuffix")))
|
|
.bind("callee-decl")),
|
|
optionally(hasArgument(
|
|
0, cxxConstructExpr(
|
|
hasDeclaration(functionDecl(hasParameter(
|
|
0, parmVarDecl(hasType(
|
|
asString("const char *")))))))
|
|
.bind("implicit-cast"))))
|
|
.bind("call")),
|
|
this);
|
|
}
|
|
|
|
void HasPrefixSuffixCheck::check(
|
|
const ast_matchers::MatchFinder::MatchResult &Result) {
|
|
|
|
const auto *CalleeDecl = Result.Nodes.getNodeAs<FunctionDecl>("callee-decl");
|
|
auto FuncName = std::string(CalleeDecl->getName());
|
|
std::string NewName;
|
|
if (FuncName == "hasPrefix") {
|
|
NewName = "starts_with";
|
|
} else if (FuncName == "hasSuffix") {
|
|
NewName = "ends_with";
|
|
} else {
|
|
llvm_unreachable("nix-has-prefix: invalid callee");
|
|
}
|
|
|
|
const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("call");
|
|
const auto *ImplicitConvertArg =
|
|
Result.Nodes.getNodeAs<CXXConstructExpr>("implicit-cast");
|
|
|
|
const auto *Lhs = MatchedDecl->getArg(0);
|
|
const auto *Rhs = MatchedDecl->getArg(1);
|
|
auto Diag = diag(MatchedDecl->getExprLoc(), FuncName + " is deprecated");
|
|
|
|
std::string Text = "";
|
|
|
|
// Form possible cast to string_view, or nothing.
|
|
if (ImplicitConvertArg) {
|
|
Text = "std::string_view(";
|
|
Text.append(tooling::getText(*Lhs, *Result.Context));
|
|
Text.append(").");
|
|
} else {
|
|
Text.append(*tooling::buildAccess(*Lhs, *Result.Context));
|
|
}
|
|
|
|
// Call .starts_with.
|
|
Text.append(NewName);
|
|
Text.push_back('(');
|
|
Text.append(tooling::getText(*Rhs, *Result.Context));
|
|
Text.push_back(')');
|
|
|
|
Diag << FixItHint::CreateReplacement(MatchedDecl->getSourceRange(), Text);
|
|
|
|
// for (const auto *arg : MatchedDecl->arguments()) {
|
|
// arg->dumpColor();
|
|
// arg->getType().dump();
|
|
// }
|
|
}
|
|
}; // namespace nix::clang_tidy
|