clang-tools 22.0.0git
StringFindStrContainsCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
12#include "clang/AST/ASTContext.h"
13#include "clang/ASTMatchers/ASTMatchers.h"
14#include "clang/Tooling/Transformer/RewriteRule.h"
15#include "clang/Tooling/Transformer/Stencil.h"
16
17// FixItHint - Hint to check documentation script to mark this check as
18// providing a FixIt.
19
20using namespace clang::ast_matchers;
21
22namespace clang::tidy::abseil {
23
24using ::clang::transformer::addInclude;
25using ::clang::transformer::applyFirst;
26using ::clang::transformer::cat;
27using ::clang::transformer::changeTo;
28using ::clang::transformer::makeRule;
29using ::clang::transformer::node;
30using ::clang::transformer::RewriteRuleWith;
31
32namespace {
33AST_MATCHER(Type, isCharType) { return Node.isCharType(); }
34} // namespace
35
36static const char DefaultStringLikeClasses[] = "::std::basic_string;"
37 "::std::basic_string_view;"
38 "::absl::string_view";
39static const char DefaultAbseilStringsMatchHeader[] = "absl/strings/match.h";
40
41static transformer::RewriteRuleWith<std::string>
42makeRewriteRule(ArrayRef<StringRef> StringLikeClassNames,
43 StringRef AbseilStringsMatchHeader) {
44 auto StringLikeClass = cxxRecordDecl(hasAnyName(StringLikeClassNames));
45 auto StringType =
46 hasUnqualifiedDesugaredType(recordType(hasDeclaration(StringLikeClass)));
47 auto CharStarType =
48 hasUnqualifiedDesugaredType(pointerType(pointee(isAnyCharacter())));
49 auto CharType = hasUnqualifiedDesugaredType(isCharType());
50 auto StringNpos = declRefExpr(
51 to(varDecl(hasName("npos"), hasDeclContext(StringLikeClass))));
52 auto StringFind = cxxMemberCallExpr(
53 callee(cxxMethodDecl(
54 hasName("find"), parameterCountIs(2),
55 hasParameter(
56 0, parmVarDecl(anyOf(hasType(StringType), hasType(CharStarType),
57 hasType(CharType)))))),
58 on(hasType(StringType)), hasArgument(0, expr().bind("parameter_to_find")),
59 anyOf(hasArgument(1, integerLiteral(equals(0))),
60 hasArgument(1, cxxDefaultArgExpr())),
61 onImplicitObjectArgument(expr().bind("string_being_searched")));
62
63 RewriteRuleWith<std::string> Rule = applyFirst(
64 {makeRule(
65 binaryOperator(hasOperatorName("=="),
66 hasOperands(ignoringParenImpCasts(StringNpos),
67 ignoringParenImpCasts(StringFind))),
68 {changeTo(cat("!absl::StrContains(", node("string_being_searched"),
69 ", ", node("parameter_to_find"), ")")),
70 addInclude(AbseilStringsMatchHeader)},
71 cat("use !absl::StrContains instead of find() == npos")),
72 makeRule(
73 binaryOperator(hasOperatorName("!="),
74 hasOperands(ignoringParenImpCasts(StringNpos),
75 ignoringParenImpCasts(StringFind))),
76 {changeTo(cat("absl::StrContains(", node("string_being_searched"),
77 ", ", node("parameter_to_find"), ")")),
78 addInclude(AbseilStringsMatchHeader)},
79 cat("use absl::StrContains instead "
80 "of find() != npos"))});
81 return Rule;
82}
83
85 StringRef Name, ClangTidyContext *Context)
86 : TransformerClangTidyCheck(Name, Context),
87 StringLikeClassesOption(utils::options::parseStringList(
88 Options.get("StringLikeClasses", DefaultStringLikeClasses))),
89 AbseilStringsMatchHeaderOption(Options.get(
90 "AbseilStringsMatchHeader", DefaultAbseilStringsMatchHeader)) {
91 setRule(
92 makeRewriteRule(StringLikeClassesOption, AbseilStringsMatchHeaderOption));
93}
94
96 const LangOptions &LangOpts) const {
97 return LangOpts.CPlusPlus11;
98}
99
102 TransformerClangTidyCheck::storeOptions(Opts);
103 Options.store(Opts, "StringLikeClasses",
104 utils::options::serializeStringList(StringLikeClassesOption));
105 Options.store(Opts, "AbseilStringsMatchHeader",
106 AbseilStringsMatchHeaderOption);
107}
108
109} // namespace clang::tidy::abseil
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override
StringFindStrContainsCheck(StringRef Name, ClangTidyContext *Context)
void setRule(transformer::RewriteRuleWith< std::string > R)
Set the rule that this check implements.
TransformerClangTidyCheck(StringRef Name, ClangTidyContext *Context)
static transformer::RewriteRuleWith< std::string > makeRewriteRule(ArrayRef< StringRef > StringLikeClassNames, StringRef AbseilStringsMatchHeader)
static const char DefaultAbseilStringsMatchHeader[]
AST_MATCHER(BinaryOperator, isRelationalOperator)
std::string serializeStringList(ArrayRef< StringRef > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
llvm::StringMap< ClangTidyValue > OptionMap