1// RUN: %check_clang_tidy -std=c++17 %s abseil-string-find-startswith %t -- \
2// RUN: -config="{CheckOptions: \
3// RUN: {abseil-string-find-startswith.StringLikeClasses: \
4// RUN: '::std::basic_string;::std::basic_string_view;::basic_string'}}" \
5// RUN: -- -isystem %clang_tidy_headers
6
7#include <string>
8
9using size_t = decltype(sizeof(int));
10
11namespace std {
12struct cxx_string {
13 int find(const char *s, int pos = 0);
14 int rfind(const char *s, int pos = npos);
15 static constexpr size_t npos = -1;
16};
17} // namespace std
18
19struct basic_string : public std::cxx_string {
20 basic_string();
21};
22typedef basic_string global_string;
23
24std::string foo(std::string);
25std::string bar();
26
27#define A_MACRO(x, y) ((x) == (y))
28
29void tests(std::string s, global_string s2, std::string_view sv) {
30 s.find(s: "a") == 0;
31 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith instead of find() == 0 [abseil-string-find-startswith]
32 // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, "a");{{$}}
33
34 s.find(str: s) == 0;
35 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
36 // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
37
38 s.find(s: "aaa") != 0;
39 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
40 // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
41
42 s.find(str: foo(foo(bar()))) != 0;
43 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
44 // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, foo(foo(bar())));{{$}}
45
46 if (s.find(s: "....") == 0) { /* do something */ }
47 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use absl::StartsWith
48 // CHECK-FIXES: {{^[[:space:]]*}}if (absl::StartsWith(s, "....")) { /* do something */ }{{$}}
49
50 0 != s.find(s: "a");
51 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
52 // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}
53
54 s2.find(s: "a") == 0;
55 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
56 // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}
57
58 s.rfind(s: "a", pos: 0) == 0;
59 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith instead of rfind() == 0 [abseil-string-find-startswith]
60 // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, "a");{{$}}
61
62 s.rfind(str: s, pos: 0) == 0;
63 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
64 // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
65
66 s.rfind(s: "aaa", pos: 0) != 0;
67 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
68 // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
69
70 s.rfind(str: foo(foo(bar())), pos: 0) != 0;
71 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
72 // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, foo(foo(bar())));{{$}}
73
74 if (s.rfind(s: "....", pos: 0) == 0) { /* do something */ }
75 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use absl::StartsWith
76 // CHECK-FIXES: {{^[[:space:]]*}}if (absl::StartsWith(s, "....")) { /* do something */ }{{$}}
77
78 0 != s.rfind(s: "a", pos: 0);
79 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
80 // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}
81
82 s2.rfind(s: "a", pos: 0) == 0;
83 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
84 // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}
85
86 sv.find(str: "a") == 0;
87 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
88 // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(sv, "a");{{$}}
89
90 sv.rfind(str: "a", pos: 0) != 0;
91 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
92 // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(sv, "a");{{$}}
93
94 // expressions that don't trigger the check are here.
95 A_MACRO(s.find("a"), 0);
96 A_MACRO(s.rfind("a", 0), 0);
97 s.find(s: "a", pos: 1) == 0;
98 s.find(s: "a", pos: 1) == 1;
99 s.find(s: "a") == 1;
100 s.rfind(s: "a", pos: 1) == 0;
101 s.rfind(s: "a", pos: 1) == 1;
102 s.rfind(s: "a") == 0;
103 s.rfind(s: "a") == 1;
104}
105

source code of clang-tools-extra/test/clang-tidy/checkers/abseil/string-find-startswith.cpp