1 //===- unittest/Tooling/TransformerTest.cpp -------------------------------===//
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 
9 #include "clang/Tooling/Transformer/Transformer.h"
10 #include "clang/ASTMatchers/ASTMatchers.h"
11 #include "clang/Tooling/Tooling.h"
12 #include "clang/Tooling/Transformer/RangeSelector.h"
13 #include "clang/Tooling/Transformer/RewriteRule.h"
14 #include "clang/Tooling/Transformer/Stencil.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/Error.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 
20 using namespace clang;
21 using namespace tooling;
22 using namespace ast_matchers;
23 namespace {
24 using ::clang::transformer::addInclude;
25 using ::clang::transformer::applyFirst;
26 using ::clang::transformer::before;
27 using ::clang::transformer::cat;
28 using ::clang::transformer::changeTo;
29 using ::clang::transformer::editList;
30 using ::clang::transformer::makeRule;
31 using ::clang::transformer::member;
32 using ::clang::transformer::name;
33 using ::clang::transformer::node;
34 using ::clang::transformer::noEdits;
35 using ::clang::transformer::remove;
36 using ::clang::transformer::rewriteDescendants;
37 using ::clang::transformer::RewriteRule;
38 using ::clang::transformer::RewriteRuleWith;
39 using ::clang::transformer::statement;
40 using ::testing::ElementsAre;
41 using ::testing::IsEmpty;
42 using ::testing::ResultOf;
43 using ::testing::UnorderedElementsAre;
44 
45 constexpr char KHeaderContents[] = R"cc(
46   struct string {
47     string(const char*);
48     char* c_str();
49     int size();
50   };
51   int strlen(const char*);
52 
53   namespace proto {
54   struct PCFProto {
55     int foo();
56   };
57   struct ProtoCommandLineFlag : PCFProto {
58     PCFProto& GetProto();
59   };
60   }  // namespace proto
61   class Logger {};
62   void operator<<(Logger& l, string msg);
63   Logger& log(int level);
64 )cc";
65 
66 static ast_matchers::internal::Matcher<clang::QualType>
67 isOrPointsTo(const clang::ast_matchers::DeclarationMatcher &TypeMatcher) {
68   return anyOf(hasDeclaration(TypeMatcher), pointsTo(TypeMatcher));
69 }
70 
71 static std::string format(StringRef Code) {
72   const std::vector<Range> Ranges(1, Range(0, Code.size()));
73   auto Style = format::getLLVMStyle();
74   const auto Replacements = format::reformat(Style, Code, Ranges);
75   auto Formatted = applyAllReplacements(Code, Replacements);
76   if (!Formatted) {
77     ADD_FAILURE() << "Could not format code: "
78                   << llvm::toString(Formatted.takeError());
79     return std::string();
80   }
81   return *Formatted;
82 }
83 
84 static void compareSnippets(StringRef Expected,
85                             const llvm::Optional<std::string> &MaybeActual) {
86   ASSERT_TRUE(MaybeActual) << "Rewrite failed. Expecting: " << Expected;
87   auto Actual = *MaybeActual;
88   std::string HL = "#include \"header.h\"\n";
89   auto I = Actual.find(HL);
90   if (I != std::string::npos)
91     Actual.erase(I, HL.size());
92   EXPECT_EQ(format(Expected), format(Actual));
93 }
94 
95 // FIXME: consider separating this class into its own file(s).
96 class ClangRefactoringTestBase : public testing::Test {
97 protected:
98   void appendToHeader(StringRef S) { FileContents[0].second += S; }
99 
100   void addFile(StringRef Filename, StringRef Content) {
101     FileContents.emplace_back(std::string(Filename), std::string(Content));
102   }
103 
104   llvm::Optional<std::string> rewrite(StringRef Input) {
105     std::string Code = ("#include \"header.h\"\n" + Input).str();
106     auto Factory = newFrontendActionFactory(&MatchFinder);
107     if (!runToolOnCodeWithArgs(
108             Factory->create(), Code, std::vector<std::string>(), "input.cc",
109             "clang-tool", std::make_shared<PCHContainerOperations>(),
110             FileContents)) {
111       llvm::errs() << "Running tool failed.\n";
112       return None;
113     }
114     if (ErrorCount != 0) {
115       llvm::errs() << "Generating changes failed.\n";
116       return None;
117     }
118     auto ChangedCode =
119         applyAtomicChanges("input.cc", Code, Changes, ApplyChangesSpec());
120     if (!ChangedCode) {
121       llvm::errs() << "Applying changes failed: "
122                    << llvm::toString(ChangedCode.takeError()) << "\n";
123       return None;
124     }
125     return *ChangedCode;
126   }
127 
128   Transformer::ChangeSetConsumer consumer() {
129     return [this](Expected<MutableArrayRef<AtomicChange>> C) {
130       if (C) {
131         Changes.insert(Changes.end(), std::make_move_iterator(C->begin()),
132                        std::make_move_iterator(C->end()));
133       } else {
134         // FIXME: stash this error rather than printing.
135         llvm::errs() << "Error generating changes: "
136                      << llvm::toString(C.takeError()) << "\n";
137         ++ErrorCount;
138       }
139     };
140   }
141 
142   auto consumerWithStringMetadata() {
143     return [this](Expected<TransformerResult<std::string>> C) {
144       if (C) {
145         Changes.insert(Changes.end(),
146                        std::make_move_iterator(C->Changes.begin()),
147                        std::make_move_iterator(C->Changes.end()));
148         StringMetadata.push_back(std::move(C->Metadata));
149       } else {
150         // FIXME: stash this error rather than printing.
151         llvm::errs() << "Error generating changes: "
152                      << llvm::toString(C.takeError()) << "\n";
153         ++ErrorCount;
154       }
155     };
156   }
157 
158   void testRule(RewriteRule Rule, StringRef Input, StringRef Expected) {
159     Transformers.push_back(
160         std::make_unique<Transformer>(std::move(Rule), consumer()));
161     Transformers.back()->registerMatchers(&MatchFinder);
162     compareSnippets(Expected, rewrite(Input));
163   }
164 
165   void testRule(RewriteRuleWith<std::string> Rule, StringRef Input,
166                 StringRef Expected) {
167     Transformers.push_back(std::make_unique<Transformer>(
168         std::move(Rule), consumerWithStringMetadata()));
169     Transformers.back()->registerMatchers(&MatchFinder);
170     compareSnippets(Expected, rewrite(Input));
171   }
172 
173   void testRuleFailure(RewriteRule Rule, StringRef Input) {
174     Transformers.push_back(
175         std::make_unique<Transformer>(std::move(Rule), consumer()));
176     Transformers.back()->registerMatchers(&MatchFinder);
177     ASSERT_FALSE(rewrite(Input)) << "Expected failure to rewrite code";
178   }
179 
180   void testRuleFailure(RewriteRuleWith<std::string> Rule, StringRef Input) {
181     Transformers.push_back(std::make_unique<Transformer>(
182         std::move(Rule), consumerWithStringMetadata()));
183     Transformers.back()->registerMatchers(&MatchFinder);
184     ASSERT_FALSE(rewrite(Input)) << "Expected failure to rewrite code";
185   }
186 
187   // Transformers are referenced by MatchFinder.
188   std::vector<std::unique_ptr<Transformer>> Transformers;
189   clang::ast_matchers::MatchFinder MatchFinder;
190   // Records whether any errors occurred in individual changes.
191   int ErrorCount = 0;
192   AtomicChanges Changes;
193   std::vector<std::string> StringMetadata;
194 
195 private:
196   FileContentMappings FileContents = {{"header.h", ""}};
197 };
198 
199 class TransformerTest : public ClangRefactoringTestBase {
200 protected:
201   TransformerTest() { appendToHeader(KHeaderContents); }
202 };
203 
204 // Given string s, change strlen($s.c_str()) to REPLACED.
205 static RewriteRuleWith<std::string> ruleStrlenSize() {
206   StringRef StringExpr = "strexpr";
207   auto StringType = namedDecl(hasAnyName("::basic_string", "::string"));
208   auto R = makeRule(
209       callExpr(callee(functionDecl(hasName("strlen"))),
210                hasArgument(0, cxxMemberCallExpr(
211                                   on(expr(hasType(isOrPointsTo(StringType)))
212                                          .bind(StringExpr)),
213                                   callee(cxxMethodDecl(hasName("c_str")))))),
214       changeTo(cat("REPLACED")), cat("Use size() method directly on string."));
215   return R;
216 }
217 
218 TEST_F(TransformerTest, StrlenSize) {
219   std::string Input = "int f(string s) { return strlen(s.c_str()); }";
220   std::string Expected = "int f(string s) { return REPLACED; }";
221   testRule(ruleStrlenSize(), Input, Expected);
222 }
223 
224 // Tests that no change is applied when a match is not expected.
225 TEST_F(TransformerTest, NoMatch) {
226   std::string Input = "int f(string s) { return s.size(); }";
227   testRule(ruleStrlenSize(), Input, Input);
228 }
229 
230 // Tests replacing an expression.
231 TEST_F(TransformerTest, Flag) {
232   StringRef Flag = "flag";
233   RewriteRule Rule = makeRule(
234       cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
235                                     hasName("proto::ProtoCommandLineFlag"))))
236                                .bind(Flag)),
237                         unless(callee(cxxMethodDecl(hasName("GetProto"))))),
238       changeTo(node(std::string(Flag)), cat("EXPR")));
239 
240   std::string Input = R"cc(
241     proto::ProtoCommandLineFlag flag;
242     int x = flag.foo();
243     int y = flag.GetProto().foo();
244   )cc";
245   std::string Expected = R"cc(
246     proto::ProtoCommandLineFlag flag;
247     int x = EXPR.foo();
248     int y = flag.GetProto().foo();
249   )cc";
250 
251   testRule(std::move(Rule), Input, Expected);
252 }
253 
254 TEST_F(TransformerTest, AddIncludeQuoted) {
255   RewriteRule Rule =
256       makeRule(callExpr(callee(functionDecl(hasName("f")))),
257                {addInclude("clang/OtherLib.h"), changeTo(cat("other()"))});
258 
259   std::string Input = R"cc(
260     int f(int x);
261     int h(int x) { return f(x); }
262   )cc";
263   std::string Expected = R"cc(#include "clang/OtherLib.h"
264 
265     int f(int x);
266     int h(int x) { return other(); }
267   )cc";
268 
269   testRule(Rule, Input, Expected);
270 }
271 
272 TEST_F(TransformerTest, AddIncludeAngled) {
273   RewriteRule Rule = makeRule(
274       callExpr(callee(functionDecl(hasName("f")))),
275       {addInclude("clang/OtherLib.h", transformer::IncludeFormat::Angled),
276        changeTo(cat("other()"))});
277 
278   std::string Input = R"cc(
279     int f(int x);
280     int h(int x) { return f(x); }
281   )cc";
282   std::string Expected = R"cc(#include <clang/OtherLib.h>
283 
284     int f(int x);
285     int h(int x) { return other(); }
286   )cc";
287 
288   testRule(Rule, Input, Expected);
289 }
290 
291 TEST_F(TransformerTest, AddIncludeQuotedForRule) {
292   RewriteRule Rule = makeRule(callExpr(callee(functionDecl(hasName("f")))),
293                               changeTo(cat("other()")));
294   addInclude(Rule, "clang/OtherLib.h");
295 
296   std::string Input = R"cc(
297     int f(int x);
298     int h(int x) { return f(x); }
299   )cc";
300   std::string Expected = R"cc(#include "clang/OtherLib.h"
301 
302     int f(int x);
303     int h(int x) { return other(); }
304   )cc";
305 
306   testRule(Rule, Input, Expected);
307 }
308 
309 TEST_F(TransformerTest, AddIncludeAngledForRule) {
310   RewriteRule Rule = makeRule(callExpr(callee(functionDecl(hasName("f")))),
311                               changeTo(cat("other()")));
312   addInclude(Rule, "clang/OtherLib.h", transformer::IncludeFormat::Angled);
313 
314   std::string Input = R"cc(
315     int f(int x);
316     int h(int x) { return f(x); }
317   )cc";
318   std::string Expected = R"cc(#include <clang/OtherLib.h>
319 
320     int f(int x);
321     int h(int x) { return other(); }
322   )cc";
323 
324   testRule(Rule, Input, Expected);
325 }
326 
327 TEST_F(TransformerTest, NodePartNameNamedDecl) {
328   StringRef Fun = "fun";
329   RewriteRule Rule = makeRule(functionDecl(hasName("bad")).bind(Fun),
330                               changeTo(name(std::string(Fun)), cat("good")));
331 
332   std::string Input = R"cc(
333     int bad(int x);
334     int bad(int x) { return x * x; }
335   )cc";
336   std::string Expected = R"cc(
337     int good(int x);
338     int good(int x) { return x * x; }
339   )cc";
340 
341   testRule(Rule, Input, Expected);
342 }
343 
344 TEST_F(TransformerTest, NodePartNameDeclRef) {
345   std::string Input = R"cc(
346     template <typename T>
347     T bad(T x) {
348       return x;
349     }
350     int neutral(int x) { return bad<int>(x) * x; }
351   )cc";
352   std::string Expected = R"cc(
353     template <typename T>
354     T bad(T x) {
355       return x;
356     }
357     int neutral(int x) { return good<int>(x) * x; }
358   )cc";
359 
360   StringRef Ref = "ref";
361   testRule(makeRule(declRefExpr(to(functionDecl(hasName("bad")))).bind(Ref),
362                     changeTo(name(std::string(Ref)), cat("good"))),
363            Input, Expected);
364 }
365 
366 TEST_F(TransformerTest, NodePartNameDeclRefFailure) {
367   std::string Input = R"cc(
368     struct Y {
369       int operator*();
370     };
371     int neutral(int x) {
372       Y y;
373       int (Y::*ptr)() = &Y::operator*;
374       return *y + x;
375     }
376   )cc";
377 
378   StringRef Ref = "ref";
379   Transformer T(makeRule(declRefExpr(to(functionDecl())).bind(Ref),
380                          changeTo(name(std::string(Ref)), cat("good"))),
381                 consumer());
382   T.registerMatchers(&MatchFinder);
383   EXPECT_FALSE(rewrite(Input));
384 }
385 
386 TEST_F(TransformerTest, NodePartMember) {
387   StringRef E = "expr";
388   RewriteRule Rule =
389       makeRule(memberExpr(clang::ast_matchers::member(hasName("bad"))).bind(E),
390                changeTo(member(std::string(E)), cat("good")));
391 
392   std::string Input = R"cc(
393     struct S {
394       int bad;
395     };
396     int g() {
397       S s;
398       return s.bad;
399     }
400   )cc";
401   std::string Expected = R"cc(
402     struct S {
403       int bad;
404     };
405     int g() {
406       S s;
407       return s.good;
408     }
409   )cc";
410 
411   testRule(Rule, Input, Expected);
412 }
413 
414 TEST_F(TransformerTest, NodePartMemberQualified) {
415   std::string Input = R"cc(
416     struct S {
417       int bad;
418       int good;
419     };
420     struct T : public S {
421       int bad;
422     };
423     int g() {
424       T t;
425       return t.S::bad;
426     }
427   )cc";
428   std::string Expected = R"cc(
429     struct S {
430       int bad;
431       int good;
432     };
433     struct T : public S {
434       int bad;
435     };
436     int g() {
437       T t;
438       return t.S::good;
439     }
440   )cc";
441 
442   StringRef E = "expr";
443   testRule(makeRule(memberExpr().bind(E),
444                     changeTo(member(std::string(E)), cat("good"))),
445            Input, Expected);
446 }
447 
448 TEST_F(TransformerTest, NodePartMemberMultiToken) {
449   std::string Input = R"cc(
450     struct Y {
451       int operator*();
452       int good();
453       template <typename T> void foo(T t);
454     };
455     int neutral(int x) {
456       Y y;
457       y.template foo<int>(3);
458       return y.operator *();
459     }
460   )cc";
461   std::string Expected = R"cc(
462     struct Y {
463       int operator*();
464       int good();
465       template <typename T> void foo(T t);
466     };
467     int neutral(int x) {
468       Y y;
469       y.template good<int>(3);
470       return y.good();
471     }
472   )cc";
473 
474   StringRef MemExpr = "member";
475   testRule(makeRule(memberExpr().bind(MemExpr),
476                     changeTo(member(std::string(MemExpr)), cat("good"))),
477            Input, Expected);
478 }
479 
480 TEST_F(TransformerTest, NoEdits) {
481   using transformer::noEdits;
482   std::string Input = "int f(int x) { return x; }";
483   testRule(makeRule(returnStmt().bind("return"), noEdits()), Input, Input);
484 }
485 
486 TEST_F(TransformerTest, NoopEdit) {
487   using transformer::node;
488   using transformer::noopEdit;
489   std::string Input = "int f(int x) { return x; }";
490   testRule(makeRule(returnStmt().bind("return"), noopEdit(node("return"))),
491            Input, Input);
492 }
493 
494 TEST_F(TransformerTest, IfBound2Args) {
495   using transformer::ifBound;
496   std::string Input = "int f(int x) { return x; }";
497   std::string Expected = "int f(int x) { CHANGE; }";
498   testRule(makeRule(returnStmt().bind("return"),
499                     ifBound("return", changeTo(cat("CHANGE;")))),
500            Input, Expected);
501 }
502 
503 TEST_F(TransformerTest, IfBound3Args) {
504   using transformer::ifBound;
505   std::string Input = "int f(int x) { return x; }";
506   std::string Expected = "int f(int x) { CHANGE; }";
507   testRule(makeRule(returnStmt().bind("return"),
508                     ifBound("nothing", changeTo(cat("ERROR")),
509                             changeTo(cat("CHANGE;")))),
510            Input, Expected);
511 }
512 
513 TEST_F(TransformerTest, ShrinkTo) {
514   using transformer::shrinkTo;
515   std::string Input = "int f(int x) { return x; }";
516   std::string Expected = "return x;";
517   testRule(makeRule(functionDecl(hasDescendant(returnStmt().bind("return")))
518                         .bind("function"),
519                     shrinkTo(node("function"), node("return"))),
520            Input, Expected);
521 }
522 
523 // Rewrite various Stmts inside a Decl.
524 TEST_F(TransformerTest, RewriteDescendantsDeclChangeStmt) {
525   std::string Input =
526       "int f(int x) { int y = x; { int z = x * x; } return x; }";
527   std::string Expected =
528       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
529   auto InlineX =
530       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
531   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
532                     rewriteDescendants("fun", InlineX)),
533            Input, Expected);
534 }
535 
536 // Rewrite various TypeLocs inside a Decl.
537 TEST_F(TransformerTest, RewriteDescendantsDeclChangeTypeLoc) {
538   std::string Input = "int f(int *x) { return *x; }";
539   std::string Expected = "char f(char *x) { return *x; }";
540   auto IntToChar = makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))),
541                             changeTo(cat("char")));
542   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
543                     rewriteDescendants("fun", IntToChar)),
544            Input, Expected);
545 }
546 
547 TEST_F(TransformerTest, RewriteDescendantsStmt) {
548   // Add an unrelated definition to the header that also has a variable named
549   // "x", to test that the rewrite is limited to the scope we intend.
550   appendToHeader(R"cc(int g(int x) { return x; })cc");
551   std::string Input =
552       "int f(int x) { int y = x; { int z = x * x; } return x; }";
553   std::string Expected =
554       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
555   auto InlineX =
556       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
557   testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
558                     rewriteDescendants("body", InlineX)),
559            Input, Expected);
560 }
561 
562 TEST_F(TransformerTest, RewriteDescendantsStmtWithAdditionalChange) {
563   std::string Input =
564       "int f(int x) { int y = x; { int z = x * x; } return x; }";
565   std::string Expected =
566       "int newName(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
567   auto InlineX =
568       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
569   testRule(
570       makeRule(
571           functionDecl(hasName("f"), hasBody(stmt().bind("body"))).bind("f"),
572           flatten(changeTo(name("f"), cat("newName")),
573                   rewriteDescendants("body", InlineX))),
574       Input, Expected);
575 }
576 
577 TEST_F(TransformerTest, RewriteDescendantsTypeLoc) {
578   std::string Input = "int f(int *x) { return *x; }";
579   std::string Expected = "int f(char *x) { return *x; }";
580   auto IntToChar =
581       makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))).bind("loc"),
582                changeTo(cat("char")));
583   testRule(
584       makeRule(functionDecl(hasName("f"),
585                             hasParameter(0, varDecl(hasTypeLoc(
586                                                 typeLoc().bind("parmType"))))),
587                rewriteDescendants("parmType", IntToChar)),
588       Input, Expected);
589 }
590 
591 TEST_F(TransformerTest, RewriteDescendantsReferToParentBinding) {
592   std::string Input =
593       "int f(int p) { int y = p; { int z = p * p; } return p; }";
594   std::string Expected =
595       "int f(int p) { int y = 3; { int z = 3 * 3; } return 3; }";
596   std::string VarId = "var";
597   auto InlineVar = makeRule(declRefExpr(to(varDecl(equalsBoundNode(VarId)))),
598                             changeTo(cat("3")));
599   testRule(makeRule(functionDecl(hasName("f"),
600                                  hasParameter(0, varDecl().bind(VarId)))
601                         .bind("fun"),
602                     rewriteDescendants("fun", InlineVar)),
603            Input, Expected);
604 }
605 
606 TEST_F(TransformerTest, RewriteDescendantsUnboundNode) {
607   std::string Input =
608       "int f(int x) { int y = x; { int z = x * x; } return x; }";
609   auto InlineX =
610       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
611   Transformer T(makeRule(functionDecl(hasName("f")),
612                          rewriteDescendants("UNBOUND", InlineX)),
613                 consumer());
614   T.registerMatchers(&MatchFinder);
615   EXPECT_FALSE(rewrite(Input));
616   EXPECT_THAT(Changes, IsEmpty());
617   EXPECT_EQ(ErrorCount, 1);
618 }
619 
620 TEST_F(TransformerTest, RewriteDescendantsInvalidNodeType) {
621   std::string Input =
622       "int f(int x) { int y = x; { int z = x * x; } return x; }";
623   auto IntToChar =
624       makeRule(qualType(isInteger(), builtinType()), changeTo(cat("char")));
625   Transformer T(
626       makeRule(functionDecl(
627                    hasName("f"),
628                    hasParameter(0, varDecl(hasType(qualType().bind("type"))))),
629                rewriteDescendants("type", IntToChar)),
630       consumer());
631   T.registerMatchers(&MatchFinder);
632   EXPECT_FALSE(rewrite(Input));
633   EXPECT_THAT(Changes, IsEmpty());
634   EXPECT_EQ(ErrorCount, 1);
635 }
636 
637 //
638 // We include one test per typed overload. We don't test extensively since that
639 // is already covered by the tests above.
640 //
641 
642 TEST_F(TransformerTest, RewriteDescendantsTypedStmt) {
643   // Add an unrelated definition to the header that also has a variable named
644   // "x", to test that the rewrite is limited to the scope we intend.
645   appendToHeader(R"cc(int g(int x) { return x; })cc");
646   std::string Input =
647       "int f(int x) { int y = x; { int z = x * x; } return x; }";
648   std::string Expected =
649       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
650   auto InlineX =
651       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
652   testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
653                     [&InlineX](const MatchFinder::MatchResult &R) {
654                       const auto *Node = R.Nodes.getNodeAs<Stmt>("body");
655                       assert(Node != nullptr && "body must be bound");
656                       return transformer::detail::rewriteDescendants(
657                           *Node, InlineX, R);
658                     }),
659            Input, Expected);
660 }
661 
662 TEST_F(TransformerTest, RewriteDescendantsTypedDecl) {
663   std::string Input =
664       "int f(int x) { int y = x; { int z = x * x; } return x; }";
665   std::string Expected =
666       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
667   auto InlineX =
668       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
669   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
670                     [&InlineX](const MatchFinder::MatchResult &R) {
671                       const auto *Node = R.Nodes.getNodeAs<Decl>("fun");
672                       assert(Node != nullptr && "fun must be bound");
673                       return transformer::detail::rewriteDescendants(
674                           *Node, InlineX, R);
675                     }),
676            Input, Expected);
677 }
678 
679 TEST_F(TransformerTest, RewriteDescendantsTypedTypeLoc) {
680   std::string Input = "int f(int *x) { return *x; }";
681   std::string Expected = "int f(char *x) { return *x; }";
682   auto IntToChar =
683       makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))).bind("loc"),
684                changeTo(cat("char")));
685   testRule(
686       makeRule(
687           functionDecl(
688               hasName("f"),
689               hasParameter(0, varDecl(hasTypeLoc(typeLoc().bind("parmType"))))),
690           [&IntToChar](const MatchFinder::MatchResult &R) {
691             const auto *Node = R.Nodes.getNodeAs<TypeLoc>("parmType");
692             assert(Node != nullptr && "parmType must be bound");
693             return transformer::detail::rewriteDescendants(*Node, IntToChar, R);
694           }),
695       Input, Expected);
696 }
697 
698 TEST_F(TransformerTest, RewriteDescendantsTypedDynTyped) {
699   // Add an unrelated definition to the header that also has a variable named
700   // "x", to test that the rewrite is limited to the scope we intend.
701   appendToHeader(R"cc(int g(int x) { return x; })cc");
702   std::string Input =
703       "int f(int x) { int y = x; { int z = x * x; } return x; }";
704   std::string Expected =
705       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
706   auto InlineX =
707       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
708   testRule(
709       makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
710                [&InlineX](const MatchFinder::MatchResult &R) {
711                  auto It = R.Nodes.getMap().find("body");
712                  assert(It != R.Nodes.getMap().end() && "body must be bound");
713                  return transformer::detail::rewriteDescendants(It->second,
714                                                                 InlineX, R);
715                }),
716       Input, Expected);
717 }
718 
719 TEST_F(TransformerTest, InsertBeforeEdit) {
720   std::string Input = R"cc(
721     int f() {
722       return 7;
723     }
724   )cc";
725   std::string Expected = R"cc(
726     int f() {
727       int y = 3;
728       return 7;
729     }
730   )cc";
731 
732   StringRef Ret = "return";
733   testRule(
734       makeRule(returnStmt().bind(Ret),
735                insertBefore(statement(std::string(Ret)), cat("int y = 3;"))),
736       Input, Expected);
737 }
738 
739 TEST_F(TransformerTest, InsertAfterEdit) {
740   std::string Input = R"cc(
741     int f() {
742       int x = 5;
743       return 7;
744     }
745   )cc";
746   std::string Expected = R"cc(
747     int f() {
748       int x = 5;
749       int y = 3;
750       return 7;
751     }
752   )cc";
753 
754   StringRef Decl = "decl";
755   testRule(
756       makeRule(declStmt().bind(Decl),
757                insertAfter(statement(std::string(Decl)), cat("int y = 3;"))),
758       Input, Expected);
759 }
760 
761 TEST_F(TransformerTest, RemoveEdit) {
762   std::string Input = R"cc(
763     int f() {
764       int x = 5;
765       return 7;
766     }
767   )cc";
768   std::string Expected = R"cc(
769     int f() {
770       return 7;
771     }
772   )cc";
773 
774   StringRef Decl = "decl";
775   testRule(
776       makeRule(declStmt().bind(Decl), remove(statement(std::string(Decl)))),
777       Input, Expected);
778 }
779 
780 TEST_F(TransformerTest, WithMetadata) {
781   auto makeMetadata = [](const MatchFinder::MatchResult &R) -> llvm::Any {
782     int N =
783         R.Nodes.getNodeAs<IntegerLiteral>("int")->getValue().getLimitedValue();
784     return N;
785   };
786 
787   std::string Input = R"cc(
788     int f() {
789       int x = 5;
790       return 7;
791     }
792   )cc";
793 
794   Transformer T(
795       makeRule(
796           declStmt(containsDeclaration(0, varDecl(hasInitializer(
797                                               integerLiteral().bind("int")))))
798               .bind("decl"),
799           withMetadata(remove(statement(std::string("decl"))), makeMetadata)),
800       consumer());
801   T.registerMatchers(&MatchFinder);
802   auto Factory = newFrontendActionFactory(&MatchFinder);
803   EXPECT_TRUE(runToolOnCodeWithArgs(
804       Factory->create(), Input, std::vector<std::string>(), "input.cc",
805       "clang-tool", std::make_shared<PCHContainerOperations>(), {}));
806   ASSERT_EQ(Changes.size(), 1u);
807   const llvm::Any &Metadata = Changes[0].getMetadata();
808   ASSERT_TRUE(llvm::any_isa<int>(Metadata));
809   EXPECT_THAT(llvm::any_cast<int>(Metadata), 5);
810 }
811 
812 TEST_F(TransformerTest, MultiChange) {
813   std::string Input = R"cc(
814     void foo() {
815       if (10 > 1.0)
816         log(1) << "oh no!";
817       else
818         log(0) << "ok";
819     }
820   )cc";
821   std::string Expected = R"(
822     void foo() {
823       if (true) { /* then */ }
824       else { /* else */ }
825     }
826   )";
827 
828   StringRef C = "C", T = "T", E = "E";
829   testRule(
830       makeRule(ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)),
831                       hasElse(stmt().bind(E))),
832                {changeTo(node(std::string(C)), cat("true")),
833                 changeTo(statement(std::string(T)), cat("{ /* then */ }")),
834                 changeTo(statement(std::string(E)), cat("{ /* else */ }"))}),
835       Input, Expected);
836 }
837 
838 TEST_F(TransformerTest, EditList) {
839   std::string Input = R"cc(
840     void foo() {
841       if (10 > 1.0)
842         log(1) << "oh no!";
843       else
844         log(0) << "ok";
845     }
846   )cc";
847   std::string Expected = R"(
848     void foo() {
849       if (true) { /* then */ }
850       else { /* else */ }
851     }
852   )";
853 
854   StringRef C = "C", T = "T", E = "E";
855   testRule(makeRule(ifStmt(hasCondition(expr().bind(C)),
856                            hasThen(stmt().bind(T)), hasElse(stmt().bind(E))),
857                     editList({changeTo(node(std::string(C)), cat("true")),
858                               changeTo(statement(std::string(T)),
859                                        cat("{ /* then */ }")),
860                               changeTo(statement(std::string(E)),
861                                        cat("{ /* else */ }"))})),
862            Input, Expected);
863 }
864 
865 TEST_F(TransformerTest, Flatten) {
866   std::string Input = R"cc(
867     void foo() {
868       if (10 > 1.0)
869         log(1) << "oh no!";
870       else
871         log(0) << "ok";
872     }
873   )cc";
874   std::string Expected = R"(
875     void foo() {
876       if (true) { /* then */ }
877       else { /* else */ }
878     }
879   )";
880 
881   StringRef C = "C", T = "T", E = "E";
882   testRule(
883       makeRule(
884           ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)),
885                  hasElse(stmt().bind(E))),
886           flatten(changeTo(node(std::string(C)), cat("true")),
887                   changeTo(statement(std::string(T)), cat("{ /* then */ }")),
888                   changeTo(statement(std::string(E)), cat("{ /* else */ }")))),
889       Input, Expected);
890 }
891 
892 TEST_F(TransformerTest, FlattenWithMixedArgs) {
893   using clang::transformer::editList;
894   std::string Input = R"cc(
895     void foo() {
896       if (10 > 1.0)
897         log(1) << "oh no!";
898       else
899         log(0) << "ok";
900     }
901   )cc";
902   std::string Expected = R"(
903     void foo() {
904       if (true) { /* then */ }
905       else { /* else */ }
906     }
907   )";
908 
909   StringRef C = "C", T = "T", E = "E";
910   testRule(makeRule(ifStmt(hasCondition(expr().bind(C)),
911                            hasThen(stmt().bind(T)), hasElse(stmt().bind(E))),
912                     flatten(changeTo(node(std::string(C)), cat("true")),
913                             edit(changeTo(statement(std::string(T)),
914                                           cat("{ /* then */ }"))),
915                             editList({changeTo(statement(std::string(E)),
916                                                cat("{ /* else */ }"))}))),
917            Input, Expected);
918 }
919 
920 TEST_F(TransformerTest, OrderedRuleUnrelated) {
921   StringRef Flag = "flag";
922   RewriteRuleWith<std::string> FlagRule = makeRule(
923       cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
924                                     hasName("proto::ProtoCommandLineFlag"))))
925                                .bind(Flag)),
926                         unless(callee(cxxMethodDecl(hasName("GetProto"))))),
927       changeTo(node(std::string(Flag)), cat("PROTO")), cat(""));
928 
929   std::string Input = R"cc(
930     proto::ProtoCommandLineFlag flag;
931     int x = flag.foo();
932     int y = flag.GetProto().foo();
933     int f(string s) { return strlen(s.c_str()); }
934   )cc";
935   std::string Expected = R"cc(
936     proto::ProtoCommandLineFlag flag;
937     int x = PROTO.foo();
938     int y = flag.GetProto().foo();
939     int f(string s) { return REPLACED; }
940   )cc";
941 
942   testRule(applyFirst({ruleStrlenSize(), FlagRule}), Input, Expected);
943 }
944 
945 TEST_F(TransformerTest, OrderedRuleRelated) {
946   std::string Input = R"cc(
947     void f1();
948     void f2();
949     void call_f1() { f1(); }
950     void call_f2() { f2(); }
951   )cc";
952   std::string Expected = R"cc(
953     void f1();
954     void f2();
955     void call_f1() { REPLACE_F1; }
956     void call_f2() { REPLACE_F1_OR_F2; }
957   )cc";
958 
959   RewriteRule ReplaceF1 =
960       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
961                changeTo(cat("REPLACE_F1")));
962   RewriteRule ReplaceF1OrF2 =
963       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
964                changeTo(cat("REPLACE_F1_OR_F2")));
965   testRule(applyFirst({ReplaceF1, ReplaceF1OrF2}), Input, Expected);
966 }
967 
968 // Change the order of the rules to get a different result. When `ReplaceF1OrF2`
969 // comes first, it applies for both uses, so `ReplaceF1` never applies.
970 TEST_F(TransformerTest, OrderedRuleRelatedSwapped) {
971   std::string Input = R"cc(
972     void f1();
973     void f2();
974     void call_f1() { f1(); }
975     void call_f2() { f2(); }
976   )cc";
977   std::string Expected = R"cc(
978     void f1();
979     void f2();
980     void call_f1() { REPLACE_F1_OR_F2; }
981     void call_f2() { REPLACE_F1_OR_F2; }
982   )cc";
983 
984   RewriteRule ReplaceF1 =
985       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
986                changeTo(cat("REPLACE_F1")));
987   RewriteRule ReplaceF1OrF2 =
988       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
989                changeTo(cat("REPLACE_F1_OR_F2")));
990   testRule(applyFirst({ReplaceF1OrF2, ReplaceF1}), Input, Expected);
991 }
992 
993 // Verify that a set of rules whose matchers have different base kinds works
994 // properly, including that `applyFirst` produces multiple matchers.  We test
995 // two different kinds of rules: Expr and Decl. We place the Decl rule in the
996 // middle to test that `buildMatchers` works even when the kinds aren't grouped
997 // together.
998 TEST_F(TransformerTest, OrderedRuleMultipleKinds) {
999   std::string Input = R"cc(
1000     void f1();
1001     void f2();
1002     void call_f1() { f1(); }
1003     void call_f2() { f2(); }
1004   )cc";
1005   std::string Expected = R"cc(
1006     void f1();
1007     void DECL_RULE();
1008     void call_f1() { REPLACE_F1; }
1009     void call_f2() { REPLACE_F1_OR_F2; }
1010   )cc";
1011 
1012   RewriteRule ReplaceF1 =
1013       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
1014                changeTo(cat("REPLACE_F1")));
1015   RewriteRule ReplaceF1OrF2 =
1016       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
1017                changeTo(cat("REPLACE_F1_OR_F2")));
1018   RewriteRule DeclRule = makeRule(functionDecl(hasName("f2")).bind("fun"),
1019                                   changeTo(name("fun"), cat("DECL_RULE")));
1020 
1021   RewriteRule Rule = applyFirst({ReplaceF1, DeclRule, ReplaceF1OrF2});
1022   EXPECT_EQ(transformer::detail::buildMatchers(Rule).size(), 2UL);
1023   testRule(Rule, Input, Expected);
1024 }
1025 
1026 // Verifies that a rule with a top-level matcher for an implicit node (like
1027 // `implicitCastExpr`) works correctly -- the implicit nodes are not skipped.
1028 TEST_F(TransformerTest, OrderedRuleImplicitMatched) {
1029   std::string Input = R"cc(
1030     void f1();
1031     int f2();
1032     void call_f1() { f1(); }
1033     float call_f2() { return f2(); }
1034   )cc";
1035   std::string Expected = R"cc(
1036     void f1();
1037     int f2();
1038     void call_f1() { REPLACE_F1; }
1039     float call_f2() { return REPLACE_F2; }
1040   )cc";
1041 
1042   RewriteRule ReplaceF1 =
1043       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
1044                changeTo(cat("REPLACE_F1")));
1045   RewriteRule ReplaceF2 =
1046       makeRule(implicitCastExpr(hasSourceExpression(callExpr())),
1047                changeTo(cat("REPLACE_F2")));
1048   testRule(applyFirst({ReplaceF1, ReplaceF2}), Input, Expected);
1049 }
1050 
1051 //
1052 // Negative tests (where we expect no transformation to occur).
1053 //
1054 
1055 // Tests for a conflict in edits from a single match for a rule.
1056 TEST_F(TransformerTest, TextGeneratorFailure) {
1057   std::string Input = "int conflictOneRule() { return 3 + 7; }";
1058   // Try to change the whole binary-operator expression AND one its operands:
1059   StringRef O = "O";
1060   class AlwaysFail : public transformer::MatchComputation<std::string> {
1061     llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &,
1062                      std::string *) const override {
1063       return llvm::createStringError(llvm::errc::invalid_argument, "ERROR");
1064     }
1065     std::string toString() const override { return "AlwaysFail"; }
1066   };
1067   Transformer T(
1068       makeRule(binaryOperator().bind(O),
1069                changeTo(node(std::string(O)), std::make_shared<AlwaysFail>())),
1070       consumer());
1071   T.registerMatchers(&MatchFinder);
1072   EXPECT_FALSE(rewrite(Input));
1073   EXPECT_THAT(Changes, IsEmpty());
1074   EXPECT_EQ(ErrorCount, 1);
1075 }
1076 
1077 // Tests for a conflict in edits from a single match for a rule.
1078 TEST_F(TransformerTest, OverlappingEditsInRule) {
1079   std::string Input = "int conflictOneRule() { return 3 + 7; }";
1080   // Try to change the whole binary-operator expression AND one its operands:
1081   StringRef O = "O", L = "L";
1082   Transformer T(makeRule(binaryOperator(hasLHS(expr().bind(L))).bind(O),
1083                          {changeTo(node(std::string(O)), cat("DELETE_OP")),
1084                           changeTo(node(std::string(L)), cat("DELETE_LHS"))}),
1085                 consumer());
1086   T.registerMatchers(&MatchFinder);
1087   EXPECT_FALSE(rewrite(Input));
1088   EXPECT_THAT(Changes, IsEmpty());
1089   EXPECT_EQ(ErrorCount, 1);
1090 }
1091 
1092 // Tests for a conflict in edits across multiple matches (of the same rule).
1093 TEST_F(TransformerTest, OverlappingEditsMultipleMatches) {
1094   std::string Input = "int conflictOneRule() { return -7; }";
1095   // Try to change the whole binary-operator expression AND one its operands:
1096   StringRef E = "E";
1097   Transformer T(makeRule(expr().bind(E),
1098                          changeTo(node(std::string(E)), cat("DELETE_EXPR"))),
1099                 consumer());
1100   T.registerMatchers(&MatchFinder);
1101   // The rewrite process fails because the changes conflict with each other...
1102   EXPECT_FALSE(rewrite(Input));
1103   // ... but two changes were produced.
1104   EXPECT_EQ(Changes.size(), 2u);
1105   EXPECT_EQ(ErrorCount, 0);
1106 }
1107 
1108 TEST_F(TransformerTest, ErrorOccurredMatchSkipped) {
1109   // Syntax error in the function body:
1110   std::string Input = "void errorOccurred() { 3 }";
1111   Transformer T(makeRule(functionDecl(hasName("errorOccurred")),
1112                          changeTo(cat("DELETED;"))),
1113                 consumer());
1114   T.registerMatchers(&MatchFinder);
1115   // The rewrite process itself fails...
1116   EXPECT_FALSE(rewrite(Input));
1117   // ... and no changes or errors are produced in the process.
1118   EXPECT_THAT(Changes, IsEmpty());
1119   EXPECT_EQ(ErrorCount, 0);
1120 }
1121 
1122 TEST_F(TransformerTest, ImplicitNodes_ConstructorDecl) {
1123 
1124   std::string OtherStructPrefix = R"cpp(
1125 struct Other {
1126 )cpp";
1127   std::string OtherStructSuffix = "};";
1128 
1129   std::string CopyableStructName = "struct Copyable";
1130   std::string BrokenStructName = "struct explicit Copyable";
1131 
1132   std::string CodeSuffix = R"cpp(
1133 {
1134     Other m_i;
1135     Copyable();
1136 };
1137 )cpp";
1138 
1139   std::string CopyCtor = "Other(const Other&) = default;";
1140   std::string ExplicitCopyCtor = "explicit Other(const Other&) = default;";
1141   std::string BrokenExplicitCopyCtor =
1142       "explicit explicit explicit Other(const Other&) = default;";
1143 
1144   std::string RewriteInput = OtherStructPrefix + CopyCtor + OtherStructSuffix +
1145                              CopyableStructName + CodeSuffix;
1146   std::string ExpectedRewriteOutput = OtherStructPrefix + ExplicitCopyCtor +
1147                                       OtherStructSuffix + CopyableStructName +
1148                                       CodeSuffix;
1149   std::string BrokenRewriteOutput = OtherStructPrefix + BrokenExplicitCopyCtor +
1150                                     OtherStructSuffix + BrokenStructName +
1151                                     CodeSuffix;
1152 
1153   auto MatchedRecord =
1154       cxxConstructorDecl(isCopyConstructor()).bind("copyConstructor");
1155 
1156   auto RewriteRule =
1157       changeTo(before(node("copyConstructor")), cat("explicit "));
1158 
1159   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedRecord),
1160                     RewriteRule),
1161            RewriteInput, ExpectedRewriteOutput);
1162 
1163   testRule(makeRule(traverse(TK_AsIs, MatchedRecord), RewriteRule),
1164            RewriteInput, BrokenRewriteOutput);
1165 }
1166 
1167 TEST_F(TransformerTest, ImplicitNodes_RangeFor) {
1168 
1169   std::string CodePrefix = R"cpp(
1170 struct Container
1171 {
1172     int* begin() const;
1173     int* end() const;
1174     int* cbegin() const;
1175     int* cend() const;
1176 };
1177 
1178 void foo()
1179 {
1180   const Container c;
1181 )cpp";
1182 
1183   std::string BeginCallBefore = "  c.begin();";
1184   std::string BeginCallAfter = "  c.cbegin();";
1185 
1186   std::string ForLoop = "for (auto i : c)";
1187   std::string BrokenForLoop = "for (auto i :.cbegin() c)";
1188 
1189   std::string CodeSuffix = R"cpp(
1190   {
1191   }
1192 }
1193 )cpp";
1194 
1195   std::string RewriteInput =
1196       CodePrefix + BeginCallBefore + ForLoop + CodeSuffix;
1197   std::string ExpectedRewriteOutput =
1198       CodePrefix + BeginCallAfter + ForLoop + CodeSuffix;
1199   std::string BrokenRewriteOutput =
1200       CodePrefix + BeginCallAfter + BrokenForLoop + CodeSuffix;
1201 
1202   auto MatchedRecord =
1203       cxxMemberCallExpr(on(expr(hasType(qualType(isConstQualified(),
1204                                                  hasDeclaration(cxxRecordDecl(
1205                                                      hasName("Container"))))))
1206                                .bind("callTarget")),
1207                         callee(cxxMethodDecl(hasName("begin"))))
1208           .bind("constBeginCall");
1209 
1210   auto RewriteRule =
1211       changeTo(node("constBeginCall"), cat(name("callTarget"), ".cbegin()"));
1212 
1213   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedRecord),
1214                     RewriteRule),
1215            RewriteInput, ExpectedRewriteOutput);
1216 
1217   testRule(makeRule(traverse(TK_AsIs, MatchedRecord), RewriteRule),
1218            RewriteInput, BrokenRewriteOutput);
1219 }
1220 
1221 TEST_F(TransformerTest, ImplicitNodes_ForStmt) {
1222 
1223   std::string CodePrefix = R"cpp(
1224 struct NonTrivial {
1225     NonTrivial() {}
1226     NonTrivial(NonTrivial&) {}
1227     NonTrivial& operator=(NonTrivial const&) { return *this; }
1228 
1229     ~NonTrivial() {}
1230 };
1231 
1232 struct ContainsArray {
1233     NonTrivial arr[2];
1234     ContainsArray& operator=(ContainsArray const&) = default;
1235 };
1236 
1237 void testIt()
1238 {
1239     ContainsArray ca1;
1240     ContainsArray ca2;
1241     ca2 = ca1;
1242 )cpp";
1243 
1244   auto CodeSuffix = "}";
1245 
1246   auto LoopBody = R"cpp(
1247     {
1248 
1249     }
1250 )cpp";
1251 
1252   auto RawLoop = "for (auto i = 0; i != 5; ++i)";
1253 
1254   auto RangeLoop = "for (auto i : boost::irange(5))";
1255 
1256   // Expect to rewrite the raw loop to the ranged loop.
1257   // This works in TK_IgnoreUnlessSpelledInSource mode, but TK_AsIs
1258   // mode also matches the hidden for loop generated in the copy assignment
1259   // operator of ContainsArray. Transformer then fails to transform the code at
1260   // all.
1261 
1262   auto RewriteInput =
1263       CodePrefix + RawLoop + LoopBody + RawLoop + LoopBody + CodeSuffix;
1264 
1265   auto RewriteOutput =
1266       CodePrefix + RangeLoop + LoopBody + RangeLoop + LoopBody + CodeSuffix;
1267 
1268   auto MatchedLoop = forStmt(
1269       has(declStmt(hasSingleDecl(
1270           varDecl(hasInitializer(integerLiteral(equals(0)))).bind("loopVar")))),
1271       has(binaryOperator(hasOperatorName("!="),
1272                          hasLHS(ignoringImplicit(declRefExpr(
1273                              to(varDecl(equalsBoundNode("loopVar")))))),
1274                          hasRHS(expr().bind("upperBoundExpr")))),
1275       has(unaryOperator(hasOperatorName("++"),
1276                         hasUnaryOperand(declRefExpr(
1277                             to(varDecl(equalsBoundNode("loopVar"))))))
1278               .bind("incrementOp")));
1279 
1280   auto RewriteRule =
1281       changeTo(transformer::enclose(node("loopVar"), node("incrementOp")),
1282                cat("auto ", name("loopVar"), " : boost::irange(",
1283                    node("upperBoundExpr"), ")"));
1284 
1285   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedLoop),
1286                     RewriteRule),
1287            RewriteInput, RewriteOutput);
1288 
1289   testRuleFailure(makeRule(traverse(TK_AsIs, MatchedLoop), RewriteRule),
1290                   RewriteInput);
1291 }
1292 
1293 TEST_F(TransformerTest, ImplicitNodes_ForStmt2) {
1294 
1295   std::string CodePrefix = R"cpp(
1296 struct NonTrivial {
1297     NonTrivial() {}
1298     NonTrivial(NonTrivial&) {}
1299     NonTrivial& operator=(NonTrivial const&) { return *this; }
1300 
1301     ~NonTrivial() {}
1302 };
1303 
1304 struct ContainsArray {
1305     NonTrivial arr[2];
1306     ContainsArray& operator=(ContainsArray const&) = default;
1307 };
1308 
1309 void testIt()
1310 {
1311     ContainsArray ca1;
1312     ContainsArray ca2;
1313     ca2 = ca1;
1314 )cpp";
1315 
1316   auto CodeSuffix = "}";
1317 
1318   auto LoopBody = R"cpp(
1319     {
1320 
1321     }
1322 )cpp";
1323 
1324   auto RawLoop = "for (auto i = 0; i != 5; ++i)";
1325 
1326   auto RangeLoop = "for (auto i : boost::irange(5))";
1327 
1328   // Expect to rewrite the raw loop to the ranged loop.
1329   // This works in TK_IgnoreUnlessSpelledInSource mode, but TK_AsIs
1330   // mode also matches the hidden for loop generated in the copy assignment
1331   // operator of ContainsArray. Transformer then fails to transform the code at
1332   // all.
1333 
1334   auto RewriteInput =
1335       CodePrefix + RawLoop + LoopBody + RawLoop + LoopBody + CodeSuffix;
1336 
1337   auto RewriteOutput =
1338       CodePrefix + RangeLoop + LoopBody + RangeLoop + LoopBody + CodeSuffix;
1339   auto MatchedLoop = forStmt(
1340       hasLoopInit(declStmt(hasSingleDecl(
1341           varDecl(hasInitializer(integerLiteral(equals(0)))).bind("loopVar")))),
1342       hasCondition(binaryOperator(hasOperatorName("!="),
1343                                   hasLHS(ignoringImplicit(declRefExpr(to(
1344                                       varDecl(equalsBoundNode("loopVar")))))),
1345                                   hasRHS(expr().bind("upperBoundExpr")))),
1346       hasIncrement(unaryOperator(hasOperatorName("++"),
1347                                  hasUnaryOperand(declRefExpr(
1348                                      to(varDecl(equalsBoundNode("loopVar"))))))
1349                        .bind("incrementOp")));
1350 
1351   auto RewriteRule =
1352       changeTo(transformer::enclose(node("loopVar"), node("incrementOp")),
1353                cat("auto ", name("loopVar"), " : boost::irange(",
1354                    node("upperBoundExpr"), ")"));
1355 
1356   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedLoop),
1357                     RewriteRule),
1358            RewriteInput, RewriteOutput);
1359 
1360   testRuleFailure(makeRule(traverse(TK_AsIs, MatchedLoop), RewriteRule),
1361                   RewriteInput);
1362 }
1363 
1364 TEST_F(TransformerTest, TemplateInstantiation) {
1365 
1366   std::string NonTemplatesInput = R"cpp(
1367 struct S {
1368   int m_i;
1369 };
1370 )cpp";
1371   std::string NonTemplatesExpected = R"cpp(
1372 struct S {
1373   safe_int m_i;
1374 };
1375 )cpp";
1376 
1377   std::string TemplatesInput = R"cpp(
1378 template<typename T>
1379 struct TemplStruct {
1380   TemplStruct() {}
1381   ~TemplStruct() {}
1382 
1383 private:
1384   T m_t;
1385 };
1386 
1387 void instantiate()
1388 {
1389   TemplStruct<int> ti;
1390 }
1391 )cpp";
1392 
1393   auto MatchedField = fieldDecl(hasType(asString("int"))).bind("theField");
1394 
1395   // Changes the 'int' in 'S', but not the 'T' in 'TemplStruct':
1396   testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedField),
1397                     changeTo(cat("safe_int ", name("theField"), ";"))),
1398            NonTemplatesInput + TemplatesInput,
1399            NonTemplatesExpected + TemplatesInput);
1400 
1401   // In AsIs mode, template instantiations are modified, which is
1402   // often not desired:
1403 
1404   std::string IncorrectTemplatesExpected = R"cpp(
1405 template<typename T>
1406 struct TemplStruct {
1407   TemplStruct() {}
1408   ~TemplStruct() {}
1409 
1410 private:
1411   safe_int m_t;
1412 };
1413 
1414 void instantiate()
1415 {
1416   TemplStruct<int> ti;
1417 }
1418 )cpp";
1419 
1420   // Changes the 'int' in 'S', and (incorrectly) the 'T' in 'TemplStruct':
1421   testRule(makeRule(traverse(TK_AsIs, MatchedField),
1422                     changeTo(cat("safe_int ", name("theField"), ";"))),
1423 
1424            NonTemplatesInput + TemplatesInput,
1425            NonTemplatesExpected + IncorrectTemplatesExpected);
1426 }
1427 
1428 // Transformation of macro source text when the change encompasses the entirety
1429 // of the expanded text.
1430 TEST_F(TransformerTest, SimpleMacro) {
1431   std::string Input = R"cc(
1432 #define ZERO 0
1433     int f(string s) { return ZERO; }
1434   )cc";
1435   std::string Expected = R"cc(
1436 #define ZERO 0
1437     int f(string s) { return 999; }
1438   )cc";
1439 
1440   StringRef zero = "zero";
1441   RewriteRule R = makeRule(integerLiteral(equals(0)).bind(zero),
1442                            changeTo(node(std::string(zero)), cat("999")));
1443   testRule(R, Input, Expected);
1444 }
1445 
1446 // Transformation of macro source text when the change encompasses the entirety
1447 // of the expanded text, for the case of function-style macros.
1448 TEST_F(TransformerTest, FunctionMacro) {
1449   std::string Input = R"cc(
1450 #define MACRO(str) strlen((str).c_str())
1451     int f(string s) { return MACRO(s); }
1452   )cc";
1453   std::string Expected = R"cc(
1454 #define MACRO(str) strlen((str).c_str())
1455     int f(string s) { return REPLACED; }
1456   )cc";
1457 
1458   testRule(ruleStrlenSize(), Input, Expected);
1459 }
1460 
1461 // Tests that expressions in macro arguments can be rewritten.
1462 TEST_F(TransformerTest, MacroArg) {
1463   std::string Input = R"cc(
1464 #define PLUS(e) e + 1
1465     int f(string s) { return PLUS(strlen(s.c_str())); }
1466   )cc";
1467   std::string Expected = R"cc(
1468 #define PLUS(e) e + 1
1469     int f(string s) { return PLUS(REPLACED); }
1470   )cc";
1471 
1472   testRule(ruleStrlenSize(), Input, Expected);
1473 }
1474 
1475 // Tests that expressions in macro arguments can be rewritten, even when the
1476 // macro call occurs inside another macro's definition.
1477 TEST_F(TransformerTest, MacroArgInMacroDef) {
1478   std::string Input = R"cc(
1479 #define NESTED(e) e
1480 #define MACRO(str) NESTED(strlen((str).c_str()))
1481     int f(string s) { return MACRO(s); }
1482   )cc";
1483   std::string Expected = R"cc(
1484 #define NESTED(e) e
1485 #define MACRO(str) NESTED(strlen((str).c_str()))
1486     int f(string s) { return REPLACED; }
1487   )cc";
1488 
1489   testRule(ruleStrlenSize(), Input, Expected);
1490 }
1491 
1492 // Tests the corner case of the identity macro, specifically that it is
1493 // discarded in the rewrite rather than preserved (like PLUS is preserved in the
1494 // previous test).  This behavior is of dubious value (and marked with a FIXME
1495 // in the code), but we test it to verify (and demonstrate) how this case is
1496 // handled.
1497 TEST_F(TransformerTest, IdentityMacro) {
1498   std::string Input = R"cc(
1499 #define ID(e) e
1500     int f(string s) { return ID(strlen(s.c_str())); }
1501   )cc";
1502   std::string Expected = R"cc(
1503 #define ID(e) e
1504     int f(string s) { return REPLACED; }
1505   )cc";
1506 
1507   testRule(ruleStrlenSize(), Input, Expected);
1508 }
1509 
1510 // Tests that two changes in a single macro expansion do not lead to conflicts
1511 // in applying the changes.
1512 TEST_F(TransformerTest, TwoChangesInOneMacroExpansion) {
1513   std::string Input = R"cc(
1514 #define PLUS(a,b) (a) + (b)
1515     int f() { return PLUS(3, 4); }
1516   )cc";
1517   std::string Expected = R"cc(
1518 #define PLUS(a,b) (a) + (b)
1519     int f() { return PLUS(LIT, LIT); }
1520   )cc";
1521 
1522   testRule(makeRule(integerLiteral(), changeTo(cat("LIT"))), Input, Expected);
1523 }
1524 
1525 // Tests case where the rule's match spans both source from the macro and its
1526 // arg, with the begin location (the "anchor") being the arg.
1527 TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNot) {
1528   std::string Input = R"cc(
1529 #define PLUS_ONE(a) a + 1
1530     int f() { return PLUS_ONE(3); }
1531   )cc";
1532   std::string Expected = R"cc(
1533 #define PLUS_ONE(a) a + 1
1534     int f() { return PLUS_ONE(LIT); }
1535   )cc";
1536 
1537   StringRef E = "expr";
1538   testRule(makeRule(binaryOperator(hasLHS(expr().bind(E))),
1539                     changeTo(node(std::string(E)), cat("LIT"))),
1540            Input, Expected);
1541 }
1542 
1543 // Tests case where the rule's match spans both source from the macro and its
1544 // arg, with the begin location (the "anchor") being inside the macro.
1545 TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNotAnchoredInMacro) {
1546   std::string Input = R"cc(
1547 #define PLUS_ONE(a) 1 + a
1548     int f() { return PLUS_ONE(3); }
1549   )cc";
1550   std::string Expected = R"cc(
1551 #define PLUS_ONE(a) 1 + a
1552     int f() { return PLUS_ONE(LIT); }
1553   )cc";
1554 
1555   StringRef E = "expr";
1556   testRule(makeRule(binaryOperator(hasRHS(expr().bind(E))),
1557                     changeTo(node(std::string(E)), cat("LIT"))),
1558            Input, Expected);
1559 }
1560 
1561 // No rewrite is applied when the changed text does not encompass the entirety
1562 // of the expanded text. That is, the edit would have to be applied to the
1563 // macro's definition to succeed and editing the expansion point would not
1564 // suffice.
1565 TEST_F(TransformerTest, NoPartialRewriteOMacroExpansion) {
1566   std::string Input = R"cc(
1567 #define ZERO_PLUS 0 + 3
1568     int f(string s) { return ZERO_PLUS; })cc";
1569 
1570   StringRef zero = "zero";
1571   RewriteRule R = makeRule(integerLiteral(equals(0)).bind(zero),
1572                            changeTo(node(std::string(zero)), cat("0")));
1573   testRule(R, Input, Input);
1574 }
1575 
1576 // This test handles the corner case where a macro expands within another macro
1577 // to matching code, but that code is an argument to the nested macro call.  A
1578 // simple check of isMacroArgExpansion() vs. isMacroBodyExpansion() will get
1579 // this wrong, and transform the code.
1580 TEST_F(TransformerTest, NoPartialRewriteOfMacroExpansionForMacroArgs) {
1581   std::string Input = R"cc(
1582 #define NESTED(e) e
1583 #define MACRO(str) 1 + NESTED(strlen((str).c_str()))
1584     int f(string s) { return MACRO(s); }
1585   )cc";
1586 
1587   testRule(ruleStrlenSize(), Input, Input);
1588 }
1589 
1590 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1591 // Verifies that `Type` and `QualType` are not allowed as top-level matchers in
1592 // rules.
1593 TEST(TransformerDeathTest, OrderedRuleTypes) {
1594   RewriteRule QualTypeRule = makeRule(qualType(), changeTo(cat("Q")));
1595   EXPECT_DEATH(transformer::detail::buildMatchers(QualTypeRule),
1596                "Matcher must be.*node matcher");
1597 
1598   RewriteRule TypeRule = makeRule(arrayType(), changeTo(cat("T")));
1599   EXPECT_DEATH(transformer::detail::buildMatchers(TypeRule),
1600                "Matcher must be.*node matcher");
1601 }
1602 #endif
1603 
1604 // Edits are able to span multiple files; in this case, a header and an
1605 // implementation file.
1606 TEST_F(TransformerTest, MultipleFiles) {
1607   std::string Header = R"cc(void RemoveThisFunction();)cc";
1608   std::string Source = R"cc(#include "input.h"
1609                             void RemoveThisFunction();)cc";
1610   Transformer T(
1611       makeRule(functionDecl(hasName("RemoveThisFunction")), changeTo(cat(""))),
1612       consumer());
1613   T.registerMatchers(&MatchFinder);
1614   auto Factory = newFrontendActionFactory(&MatchFinder);
1615   EXPECT_TRUE(runToolOnCodeWithArgs(
1616       Factory->create(), Source, std::vector<std::string>(), "input.cc",
1617       "clang-tool", std::make_shared<PCHContainerOperations>(),
1618       {{"input.h", Header}}));
1619 
1620   std::sort(Changes.begin(), Changes.end(),
1621             [](const AtomicChange &L, const AtomicChange &R) {
1622               return L.getFilePath() < R.getFilePath();
1623             });
1624 
1625   ASSERT_EQ(Changes[0].getFilePath(), "./input.h");
1626   EXPECT_THAT(Changes[0].getInsertedHeaders(), IsEmpty());
1627   EXPECT_THAT(Changes[0].getRemovedHeaders(), IsEmpty());
1628   llvm::Expected<std::string> UpdatedCode =
1629       clang::tooling::applyAllReplacements(Header,
1630                                            Changes[0].getReplacements());
1631   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1632       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1633   EXPECT_EQ(format(*UpdatedCode), "");
1634 
1635   ASSERT_EQ(Changes[1].getFilePath(), "input.cc");
1636   EXPECT_THAT(Changes[1].getInsertedHeaders(), IsEmpty());
1637   EXPECT_THAT(Changes[1].getRemovedHeaders(), IsEmpty());
1638   UpdatedCode = clang::tooling::applyAllReplacements(
1639       Source, Changes[1].getReplacements());
1640   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1641       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1642   EXPECT_EQ(format(*UpdatedCode), format("#include \"input.h\"\n"));
1643 }
1644 
1645 TEST_F(TransformerTest, AddIncludeMultipleFiles) {
1646   std::string Header = R"cc(void RemoveThisFunction();)cc";
1647   std::string Source = R"cc(#include "input.h"
1648                             void Foo() {RemoveThisFunction();})cc";
1649   Transformer T(
1650       makeRule(callExpr(callee(
1651                    functionDecl(hasName("RemoveThisFunction")).bind("fun"))),
1652                addInclude(node("fun"), "header.h")),
1653       consumer());
1654   T.registerMatchers(&MatchFinder);
1655   auto Factory = newFrontendActionFactory(&MatchFinder);
1656   EXPECT_TRUE(runToolOnCodeWithArgs(
1657       Factory->create(), Source, std::vector<std::string>(), "input.cc",
1658       "clang-tool", std::make_shared<PCHContainerOperations>(),
1659       {{"input.h", Header}}));
1660 
1661   ASSERT_EQ(Changes.size(), 1U);
1662   ASSERT_EQ(Changes[0].getFilePath(), "./input.h");
1663   EXPECT_THAT(Changes[0].getInsertedHeaders(), ElementsAre("header.h"));
1664   EXPECT_THAT(Changes[0].getRemovedHeaders(), IsEmpty());
1665   llvm::Expected<std::string> UpdatedCode =
1666       clang::tooling::applyAllReplacements(Header,
1667                                            Changes[0].getReplacements());
1668   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1669       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1670   EXPECT_EQ(format(*UpdatedCode), format(Header));
1671 }
1672 
1673 // A single change set can span multiple files.
1674 TEST_F(TransformerTest, MultiFileEdit) {
1675   // NB: The fixture is unused for this test, but kept for the test suite name.
1676   std::string Header = R"cc(void Func(int id);)cc";
1677   std::string Source = R"cc(#include "input.h"
1678                             void Caller() {
1679                               int id = 0;
1680                               Func(id);
1681                             })cc";
1682   int ErrorCount = 0;
1683   std::vector<AtomicChanges> ChangeSets;
1684   clang::ast_matchers::MatchFinder MatchFinder;
1685   Transformer T(
1686       makeRule(callExpr(callee(functionDecl(hasName("Func"))),
1687                         forEachArgumentWithParam(expr().bind("arg"),
1688                                                  parmVarDecl().bind("param"))),
1689                {changeTo(node("arg"), cat("ARG")),
1690                 changeTo(node("param"), cat("PARAM"))}),
1691       [&](Expected<MutableArrayRef<AtomicChange>> Changes) {
1692         if (Changes)
1693           ChangeSets.push_back(AtomicChanges(Changes->begin(), Changes->end()));
1694         else
1695           ++ErrorCount;
1696       });
1697   T.registerMatchers(&MatchFinder);
1698   auto Factory = newFrontendActionFactory(&MatchFinder);
1699   EXPECT_TRUE(runToolOnCodeWithArgs(
1700       Factory->create(), Source, std::vector<std::string>(), "input.cc",
1701       "clang-tool", std::make_shared<PCHContainerOperations>(),
1702       {{"input.h", Header}}));
1703 
1704   EXPECT_EQ(ErrorCount, 0);
1705   EXPECT_THAT(
1706       ChangeSets,
1707       UnorderedElementsAre(UnorderedElementsAre(
1708           ResultOf([](const AtomicChange &C) { return C.getFilePath(); },
1709                    "input.cc"),
1710           ResultOf([](const AtomicChange &C) { return C.getFilePath(); },
1711                    "./input.h"))));
1712 }
1713 
1714 TEST_F(TransformerTest, GeneratesMetadata) {
1715   std::string Input = R"cc(int target = 0;)cc";
1716   std::string Expected = R"cc(REPLACE)cc";
1717   RewriteRuleWith<std::string> Rule = makeRule(
1718       varDecl(hasName("target")), changeTo(cat("REPLACE")), cat("METADATA"));
1719   testRule(std::move(Rule), Input, Expected);
1720   EXPECT_EQ(ErrorCount, 0);
1721   EXPECT_THAT(StringMetadata, UnorderedElementsAre("METADATA"));
1722 }
1723 
1724 TEST_F(TransformerTest, GeneratesMetadataWithNoEdits) {
1725   std::string Input = R"cc(int target = 0;)cc";
1726   RewriteRuleWith<std::string> Rule = makeRule(
1727       varDecl(hasName("target")).bind("var"), noEdits(), cat("METADATA"));
1728   testRule(std::move(Rule), Input, Input);
1729   EXPECT_EQ(ErrorCount, 0);
1730   EXPECT_THAT(StringMetadata, UnorderedElementsAre("METADATA"));
1731 }
1732 
1733 TEST_F(TransformerTest, PropagateMetadataErrors) {
1734   class AlwaysFail : public transformer::MatchComputation<std::string> {
1735     llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &,
1736                      std::string *) const override {
1737       return llvm::createStringError(llvm::errc::invalid_argument, "ERROR");
1738     }
1739     std::string toString() const override { return "AlwaysFail"; }
1740   };
1741   std::string Input = R"cc(int target = 0;)cc";
1742   RewriteRuleWith<std::string> Rule = makeRule<std::string>(
1743       varDecl(hasName("target")).bind("var"), changeTo(cat("REPLACE")),
1744       std::make_shared<AlwaysFail>());
1745   testRuleFailure(std::move(Rule), Input);
1746   EXPECT_EQ(ErrorCount, 1);
1747 }
1748 
1749 } // namespace
1750