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 ::testing::ElementsAre;
25 using ::testing::IsEmpty;
26 using transformer::cat;
27 using transformer::changeTo;
28 using transformer::RewriteRule;
29 
30 constexpr char KHeaderContents[] = R"cc(
31   struct string {
32     string(const char*);
33     char* c_str();
34     int size();
35   };
36   int strlen(const char*);
37 
38   namespace proto {
39   struct PCFProto {
40     int foo();
41   };
42   struct ProtoCommandLineFlag : PCFProto {
43     PCFProto& GetProto();
44   };
45   }  // namespace proto
46   class Logger {};
47   void operator<<(Logger& l, string msg);
48   Logger& log(int level);
49 )cc";
50 
51 static ast_matchers::internal::Matcher<clang::QualType>
52 isOrPointsTo(const clang::ast_matchers::DeclarationMatcher &TypeMatcher) {
53   return anyOf(hasDeclaration(TypeMatcher), pointsTo(TypeMatcher));
54 }
55 
56 static std::string format(StringRef Code) {
57   const std::vector<Range> Ranges(1, Range(0, Code.size()));
58   auto Style = format::getLLVMStyle();
59   const auto Replacements = format::reformat(Style, Code, Ranges);
60   auto Formatted = applyAllReplacements(Code, Replacements);
61   if (!Formatted) {
62     ADD_FAILURE() << "Could not format code: "
63                   << llvm::toString(Formatted.takeError());
64     return std::string();
65   }
66   return *Formatted;
67 }
68 
69 static void compareSnippets(StringRef Expected,
70                      const llvm::Optional<std::string> &MaybeActual) {
71   ASSERT_TRUE(MaybeActual) << "Rewrite failed. Expecting: " << Expected;
72   auto Actual = *MaybeActual;
73   std::string HL = "#include \"header.h\"\n";
74   auto I = Actual.find(HL);
75   if (I != std::string::npos)
76     Actual.erase(I, HL.size());
77   EXPECT_EQ(format(Expected), format(Actual));
78 }
79 
80 // FIXME: consider separating this class into its own file(s).
81 class ClangRefactoringTestBase : public testing::Test {
82 protected:
83   void appendToHeader(StringRef S) { FileContents[0].second += S; }
84 
85   void addFile(StringRef Filename, StringRef Content) {
86     FileContents.emplace_back(std::string(Filename), std::string(Content));
87   }
88 
89   llvm::Optional<std::string> rewrite(StringRef Input) {
90     std::string Code = ("#include \"header.h\"\n" + Input).str();
91     auto Factory = newFrontendActionFactory(&MatchFinder);
92     if (!runToolOnCodeWithArgs(
93             Factory->create(), Code, std::vector<std::string>(), "input.cc",
94             "clang-tool", std::make_shared<PCHContainerOperations>(),
95             FileContents)) {
96       llvm::errs() << "Running tool failed.\n";
97       return None;
98     }
99     if (ErrorCount != 0) {
100       llvm::errs() << "Generating changes failed.\n";
101       return None;
102     }
103     auto ChangedCode =
104         applyAtomicChanges("input.cc", Code, Changes, ApplyChangesSpec());
105     if (!ChangedCode) {
106       llvm::errs() << "Applying changes failed: "
107                    << llvm::toString(ChangedCode.takeError()) << "\n";
108       return None;
109     }
110     return *ChangedCode;
111   }
112 
113   Transformer::ChangeConsumer consumer() {
114     return [this](Expected<AtomicChange> C) {
115       if (C) {
116         Changes.push_back(std::move(*C));
117       } else {
118         // FIXME: stash this error rather then printing.
119         llvm::errs() << "Error generating changes: "
120                      << llvm::toString(C.takeError()) << "\n";
121         ++ErrorCount;
122       }
123     };
124   }
125 
126   template <typename R>
127   void testRule(R Rule, StringRef Input, StringRef Expected) {
128     Transformer T(std::move(Rule), consumer());
129     T.registerMatchers(&MatchFinder);
130     compareSnippets(Expected, rewrite(Input));
131   }
132 
133   clang::ast_matchers::MatchFinder MatchFinder;
134   // Records whether any errors occurred in individual changes.
135   int ErrorCount = 0;
136   AtomicChanges Changes;
137 
138 private:
139   FileContentMappings FileContents = {{"header.h", ""}};
140 };
141 
142 class TransformerTest : public ClangRefactoringTestBase {
143 protected:
144   TransformerTest() { appendToHeader(KHeaderContents); }
145 };
146 
147 // Given string s, change strlen($s.c_str()) to REPLACED.
148 static RewriteRule ruleStrlenSize() {
149   StringRef StringExpr = "strexpr";
150   auto StringType = namedDecl(hasAnyName("::basic_string", "::string"));
151   auto R = makeRule(
152       callExpr(callee(functionDecl(hasName("strlen"))),
153                hasArgument(0, cxxMemberCallExpr(
154                                   on(expr(hasType(isOrPointsTo(StringType)))
155                                          .bind(StringExpr)),
156                                   callee(cxxMethodDecl(hasName("c_str")))))),
157       changeTo(cat("REPLACED")), cat("Use size() method directly on string."));
158   return R;
159 }
160 
161 TEST_F(TransformerTest, StrlenSize) {
162   std::string Input = "int f(string s) { return strlen(s.c_str()); }";
163   std::string Expected = "int f(string s) { return REPLACED; }";
164   testRule(ruleStrlenSize(), Input, Expected);
165 }
166 
167 // Tests that no change is applied when a match is not expected.
168 TEST_F(TransformerTest, NoMatch) {
169   std::string Input = "int f(string s) { return s.size(); }";
170   testRule(ruleStrlenSize(), Input, Input);
171 }
172 
173 // Tests replacing an expression.
174 TEST_F(TransformerTest, Flag) {
175   StringRef Flag = "flag";
176   RewriteRule Rule = makeRule(
177       cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
178                                     hasName("proto::ProtoCommandLineFlag"))))
179                                .bind(Flag)),
180                         unless(callee(cxxMethodDecl(hasName("GetProto"))))),
181       changeTo(node(std::string(Flag)), cat("EXPR")));
182 
183   std::string Input = R"cc(
184     proto::ProtoCommandLineFlag flag;
185     int x = flag.foo();
186     int y = flag.GetProto().foo();
187   )cc";
188   std::string Expected = R"cc(
189     proto::ProtoCommandLineFlag flag;
190     int x = EXPR.foo();
191     int y = flag.GetProto().foo();
192   )cc";
193 
194   testRule(std::move(Rule), Input, Expected);
195 }
196 
197 TEST_F(TransformerTest, AddIncludeQuoted) {
198   RewriteRule Rule =
199       makeRule(callExpr(callee(functionDecl(hasName("f")))),
200                {addInclude("clang/OtherLib.h"), changeTo(cat("other()"))});
201 
202   std::string Input = R"cc(
203     int f(int x);
204     int h(int x) { return f(x); }
205   )cc";
206   std::string Expected = R"cc(#include "clang/OtherLib.h"
207 
208     int f(int x);
209     int h(int x) { return other(); }
210   )cc";
211 
212   testRule(Rule, Input, Expected);
213 }
214 
215 TEST_F(TransformerTest, AddIncludeAngled) {
216   RewriteRule Rule = makeRule(
217       callExpr(callee(functionDecl(hasName("f")))),
218       {addInclude("clang/OtherLib.h", transformer::IncludeFormat::Angled),
219        changeTo(cat("other()"))});
220 
221   std::string Input = R"cc(
222     int f(int x);
223     int h(int x) { return f(x); }
224   )cc";
225   std::string Expected = R"cc(#include <clang/OtherLib.h>
226 
227     int f(int x);
228     int h(int x) { return other(); }
229   )cc";
230 
231   testRule(Rule, Input, Expected);
232 }
233 
234 TEST_F(TransformerTest, AddIncludeQuotedForRule) {
235   RewriteRule Rule = makeRule(callExpr(callee(functionDecl(hasName("f")))),
236                               changeTo(cat("other()")));
237   addInclude(Rule, "clang/OtherLib.h");
238 
239   std::string Input = R"cc(
240     int f(int x);
241     int h(int x) { return f(x); }
242   )cc";
243   std::string Expected = R"cc(#include "clang/OtherLib.h"
244 
245     int f(int x);
246     int h(int x) { return other(); }
247   )cc";
248 
249   testRule(Rule, Input, Expected);
250 }
251 
252 TEST_F(TransformerTest, AddIncludeAngledForRule) {
253   RewriteRule Rule = makeRule(callExpr(callee(functionDecl(hasName("f")))),
254                               changeTo(cat("other()")));
255   addInclude(Rule, "clang/OtherLib.h", transformer::IncludeFormat::Angled);
256 
257   std::string Input = R"cc(
258     int f(int x);
259     int h(int x) { return f(x); }
260   )cc";
261   std::string Expected = R"cc(#include <clang/OtherLib.h>
262 
263     int f(int x);
264     int h(int x) { return other(); }
265   )cc";
266 
267   testRule(Rule, Input, Expected);
268 }
269 
270 TEST_F(TransformerTest, NodePartNameNamedDecl) {
271   StringRef Fun = "fun";
272   RewriteRule Rule = makeRule(functionDecl(hasName("bad")).bind(Fun),
273                               changeTo(name(std::string(Fun)), cat("good")));
274 
275   std::string Input = R"cc(
276     int bad(int x);
277     int bad(int x) { return x * x; }
278   )cc";
279   std::string Expected = R"cc(
280     int good(int x);
281     int good(int x) { return x * x; }
282   )cc";
283 
284   testRule(Rule, Input, Expected);
285 }
286 
287 TEST_F(TransformerTest, NodePartNameDeclRef) {
288   std::string Input = R"cc(
289     template <typename T>
290     T bad(T x) {
291       return x;
292     }
293     int neutral(int x) { return bad<int>(x) * x; }
294   )cc";
295   std::string Expected = R"cc(
296     template <typename T>
297     T bad(T x) {
298       return x;
299     }
300     int neutral(int x) { return good<int>(x) * x; }
301   )cc";
302 
303   StringRef Ref = "ref";
304   testRule(makeRule(declRefExpr(to(functionDecl(hasName("bad")))).bind(Ref),
305                     changeTo(name(std::string(Ref)), cat("good"))),
306            Input, Expected);
307 }
308 
309 TEST_F(TransformerTest, NodePartNameDeclRefFailure) {
310   std::string Input = R"cc(
311     struct Y {
312       int operator*();
313     };
314     int neutral(int x) {
315       Y y;
316       int (Y::*ptr)() = &Y::operator*;
317       return *y + x;
318     }
319   )cc";
320 
321   StringRef Ref = "ref";
322   Transformer T(makeRule(declRefExpr(to(functionDecl())).bind(Ref),
323                          changeTo(name(std::string(Ref)), cat("good"))),
324                 consumer());
325   T.registerMatchers(&MatchFinder);
326   EXPECT_FALSE(rewrite(Input));
327 }
328 
329 TEST_F(TransformerTest, NodePartMember) {
330   StringRef E = "expr";
331   RewriteRule Rule = makeRule(memberExpr(member(hasName("bad"))).bind(E),
332                               changeTo(member(std::string(E)), cat("good")));
333 
334   std::string Input = R"cc(
335     struct S {
336       int bad;
337     };
338     int g() {
339       S s;
340       return s.bad;
341     }
342   )cc";
343   std::string Expected = R"cc(
344     struct S {
345       int bad;
346     };
347     int g() {
348       S s;
349       return s.good;
350     }
351   )cc";
352 
353   testRule(Rule, Input, Expected);
354 }
355 
356 TEST_F(TransformerTest, NodePartMemberQualified) {
357   std::string Input = R"cc(
358     struct S {
359       int bad;
360       int good;
361     };
362     struct T : public S {
363       int bad;
364     };
365     int g() {
366       T t;
367       return t.S::bad;
368     }
369   )cc";
370   std::string Expected = R"cc(
371     struct S {
372       int bad;
373       int good;
374     };
375     struct T : public S {
376       int bad;
377     };
378     int g() {
379       T t;
380       return t.S::good;
381     }
382   )cc";
383 
384   StringRef E = "expr";
385   testRule(makeRule(memberExpr().bind(E),
386                     changeTo(member(std::string(E)), cat("good"))),
387            Input, Expected);
388 }
389 
390 TEST_F(TransformerTest, NodePartMemberMultiToken) {
391   std::string Input = R"cc(
392     struct Y {
393       int operator*();
394       int good();
395       template <typename T> void foo(T t);
396     };
397     int neutral(int x) {
398       Y y;
399       y.template foo<int>(3);
400       return y.operator *();
401     }
402   )cc";
403   std::string Expected = R"cc(
404     struct Y {
405       int operator*();
406       int good();
407       template <typename T> void foo(T t);
408     };
409     int neutral(int x) {
410       Y y;
411       y.template good<int>(3);
412       return y.good();
413     }
414   )cc";
415 
416   StringRef MemExpr = "member";
417   testRule(makeRule(memberExpr().bind(MemExpr),
418                     changeTo(member(std::string(MemExpr)), cat("good"))),
419            Input, Expected);
420 }
421 
422 TEST_F(TransformerTest, NoEdits) {
423   using transformer::noEdits;
424   std::string Input = "int f(int x) { return x; }";
425   testRule(makeRule(returnStmt().bind("return"), noEdits()), Input, Input);
426 }
427 
428 TEST_F(TransformerTest, IfBound2Args) {
429   using transformer::ifBound;
430   std::string Input = "int f(int x) { return x; }";
431   std::string Expected = "int f(int x) { CHANGE; }";
432   testRule(makeRule(returnStmt().bind("return"),
433                     ifBound("return", changeTo(cat("CHANGE;")))),
434            Input, Expected);
435 }
436 
437 TEST_F(TransformerTest, IfBound3Args) {
438   using transformer::ifBound;
439   std::string Input = "int f(int x) { return x; }";
440   std::string Expected = "int f(int x) { CHANGE; }";
441   testRule(makeRule(returnStmt().bind("return"),
442                     ifBound("nothing", changeTo(cat("ERROR")),
443                             changeTo(cat("CHANGE;")))),
444            Input, Expected);
445 }
446 
447 TEST_F(TransformerTest, ShrinkTo) {
448   using transformer::shrinkTo;
449   std::string Input = "int f(int x) { return x; }";
450   std::string Expected = "return x;";
451   testRule(makeRule(functionDecl(hasDescendant(returnStmt().bind("return")))
452                         .bind("function"),
453                     shrinkTo(node("function"), node("return"))),
454            Input, Expected);
455 }
456 
457 // Rewrite various Stmts inside a Decl.
458 TEST_F(TransformerTest, RewriteDescendantsDeclChangeStmt) {
459   std::string Input =
460       "int f(int x) { int y = x; { int z = x * x; } return x; }";
461   std::string Expected =
462       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
463   auto InlineX =
464       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
465   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
466                     rewriteDescendants("fun", InlineX)),
467            Input, Expected);
468 }
469 
470 // Rewrite various TypeLocs inside a Decl.
471 TEST_F(TransformerTest, RewriteDescendantsDeclChangeTypeLoc) {
472   std::string Input = "int f(int *x) { return *x; }";
473   std::string Expected = "char f(char *x) { return *x; }";
474   auto IntToChar = makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))),
475                             changeTo(cat("char")));
476   testRule(makeRule(functionDecl(hasName("f")).bind("fun"),
477                     rewriteDescendants("fun", IntToChar)),
478            Input, Expected);
479 }
480 
481 TEST_F(TransformerTest, RewriteDescendantsStmt) {
482   // Add an unrelated definition to the header that also has a variable named
483   // "x", to test that the rewrite is limited to the scope we intend.
484   appendToHeader(R"cc(int g(int x) { return x; })cc");
485   std::string Input =
486       "int f(int x) { int y = x; { int z = x * x; } return x; }";
487   std::string Expected =
488       "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
489   auto InlineX =
490       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
491   testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))),
492                     rewriteDescendants("body", InlineX)),
493            Input, Expected);
494 }
495 
496 TEST_F(TransformerTest, RewriteDescendantsStmtWithAdditionalChange) {
497   std::string Input =
498       "int f(int x) { int y = x; { int z = x * x; } return x; }";
499   std::string Expected =
500       "int newName(int x) { int y = 3; { int z = 3 * 3; } return 3; }";
501   auto InlineX =
502       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
503   testRule(
504       makeRule(
505           functionDecl(hasName("f"), hasBody(stmt().bind("body"))).bind("f"),
506           flatten(changeTo(name("f"), cat("newName")),
507                   rewriteDescendants("body", InlineX))),
508       Input, Expected);
509 }
510 
511 TEST_F(TransformerTest, RewriteDescendantsTypeLoc) {
512   std::string Input = "int f(int *x) { return *x; }";
513   std::string Expected = "int f(char *x) { return *x; }";
514   auto IntToChar =
515       makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))).bind("loc"),
516                changeTo(cat("char")));
517   testRule(
518       makeRule(functionDecl(hasName("f"),
519                             hasParameter(0, varDecl(hasTypeLoc(
520                                                 typeLoc().bind("parmType"))))),
521                rewriteDescendants("parmType", IntToChar)),
522       Input, Expected);
523 }
524 
525 TEST_F(TransformerTest, RewriteDescendantsReferToParentBinding) {
526   std::string Input =
527       "int f(int p) { int y = p; { int z = p * p; } return p; }";
528   std::string Expected =
529       "int f(int p) { int y = 3; { int z = 3 * 3; } return 3; }";
530   std::string VarId = "var";
531   auto InlineVar = makeRule(declRefExpr(to(varDecl(equalsBoundNode(VarId)))),
532                             changeTo(cat("3")));
533   testRule(makeRule(functionDecl(hasName("f"),
534                                  hasParameter(0, varDecl().bind(VarId)))
535                         .bind("fun"),
536                     rewriteDescendants("fun", InlineVar)),
537            Input, Expected);
538 }
539 
540 TEST_F(TransformerTest, RewriteDescendantsUnboundNode) {
541   std::string Input =
542       "int f(int x) { int y = x; { int z = x * x; } return x; }";
543   auto InlineX =
544       makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3")));
545   Transformer T(makeRule(functionDecl(hasName("f")),
546                          rewriteDescendants("UNBOUND", InlineX)),
547                 consumer());
548   T.registerMatchers(&MatchFinder);
549   EXPECT_FALSE(rewrite(Input));
550   EXPECT_THAT(Changes, IsEmpty());
551   EXPECT_EQ(ErrorCount, 1);
552 }
553 
554 TEST_F(TransformerTest, RewriteDescendantsInvalidNodeType) {
555   std::string Input =
556       "int f(int x) { int y = x; { int z = x * x; } return x; }";
557   auto IntToChar =
558       makeRule(qualType(isInteger(), builtinType()), changeTo(cat("char")));
559   Transformer T(
560       makeRule(functionDecl(
561                    hasName("f"),
562                    hasParameter(0, varDecl(hasType(qualType().bind("type"))))),
563                rewriteDescendants("type", IntToChar)),
564       consumer());
565   T.registerMatchers(&MatchFinder);
566   EXPECT_FALSE(rewrite(Input));
567   EXPECT_THAT(Changes, IsEmpty());
568   EXPECT_EQ(ErrorCount, 1);
569 }
570 
571 TEST_F(TransformerTest, InsertBeforeEdit) {
572   std::string Input = R"cc(
573     int f() {
574       return 7;
575     }
576   )cc";
577   std::string Expected = R"cc(
578     int f() {
579       int y = 3;
580       return 7;
581     }
582   )cc";
583 
584   StringRef Ret = "return";
585   testRule(
586       makeRule(returnStmt().bind(Ret),
587                insertBefore(statement(std::string(Ret)), cat("int y = 3;"))),
588       Input, Expected);
589 }
590 
591 TEST_F(TransformerTest, InsertAfterEdit) {
592   std::string Input = R"cc(
593     int f() {
594       int x = 5;
595       return 7;
596     }
597   )cc";
598   std::string Expected = R"cc(
599     int f() {
600       int x = 5;
601       int y = 3;
602       return 7;
603     }
604   )cc";
605 
606   StringRef Decl = "decl";
607   testRule(
608       makeRule(declStmt().bind(Decl),
609                insertAfter(statement(std::string(Decl)), cat("int y = 3;"))),
610       Input, Expected);
611 }
612 
613 TEST_F(TransformerTest, RemoveEdit) {
614   std::string Input = R"cc(
615     int f() {
616       int x = 5;
617       return 7;
618     }
619   )cc";
620   std::string Expected = R"cc(
621     int f() {
622       return 7;
623     }
624   )cc";
625 
626   StringRef Decl = "decl";
627   testRule(
628       makeRule(declStmt().bind(Decl), remove(statement(std::string(Decl)))),
629       Input, Expected);
630 }
631 
632 TEST_F(TransformerTest, WithMetadata) {
633   auto makeMetadata = [](const MatchFinder::MatchResult &R) -> llvm::Any {
634     int N =
635         R.Nodes.getNodeAs<IntegerLiteral>("int")->getValue().getLimitedValue();
636     return N;
637   };
638 
639   std::string Input = R"cc(
640     int f() {
641       int x = 5;
642       return 7;
643     }
644   )cc";
645 
646   Transformer T(
647       makeRule(
648           declStmt(containsDeclaration(0, varDecl(hasInitializer(
649                                               integerLiteral().bind("int")))))
650               .bind("decl"),
651           withMetadata(remove(statement(std::string("decl"))), makeMetadata)),
652       consumer());
653   T.registerMatchers(&MatchFinder);
654   auto Factory = newFrontendActionFactory(&MatchFinder);
655   EXPECT_TRUE(runToolOnCodeWithArgs(
656       Factory->create(), Input, std::vector<std::string>(), "input.cc",
657       "clang-tool", std::make_shared<PCHContainerOperations>(), {}));
658   ASSERT_EQ(Changes.size(), 1u);
659   const llvm::Any &Metadata = Changes[0].getMetadata();
660   ASSERT_TRUE(llvm::any_isa<int>(Metadata));
661   EXPECT_THAT(llvm::any_cast<int>(Metadata), 5);
662 }
663 
664 TEST_F(TransformerTest, MultiChange) {
665   std::string Input = R"cc(
666     void foo() {
667       if (10 > 1.0)
668         log(1) << "oh no!";
669       else
670         log(0) << "ok";
671     }
672   )cc";
673   std::string Expected = R"(
674     void foo() {
675       if (true) { /* then */ }
676       else { /* else */ }
677     }
678   )";
679 
680   StringRef C = "C", T = "T", E = "E";
681   testRule(
682       makeRule(ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)),
683                       hasElse(stmt().bind(E))),
684                {changeTo(node(std::string(C)), cat("true")),
685                 changeTo(statement(std::string(T)), cat("{ /* then */ }")),
686                 changeTo(statement(std::string(E)), cat("{ /* else */ }"))}),
687       Input, Expected);
688 }
689 
690 TEST_F(TransformerTest, EditList) {
691   using clang::transformer::editList;
692   std::string Input = R"cc(
693     void foo() {
694       if (10 > 1.0)
695         log(1) << "oh no!";
696       else
697         log(0) << "ok";
698     }
699   )cc";
700   std::string Expected = R"(
701     void foo() {
702       if (true) { /* then */ }
703       else { /* else */ }
704     }
705   )";
706 
707   StringRef C = "C", T = "T", E = "E";
708   testRule(makeRule(ifStmt(hasCondition(expr().bind(C)),
709                            hasThen(stmt().bind(T)), hasElse(stmt().bind(E))),
710                     editList({changeTo(node(std::string(C)), cat("true")),
711                               changeTo(statement(std::string(T)),
712                                        cat("{ /* then */ }")),
713                               changeTo(statement(std::string(E)),
714                                        cat("{ /* else */ }"))})),
715            Input, Expected);
716 }
717 
718 TEST_F(TransformerTest, Flatten) {
719   using clang::transformer::editList;
720   std::string Input = R"cc(
721     void foo() {
722       if (10 > 1.0)
723         log(1) << "oh no!";
724       else
725         log(0) << "ok";
726     }
727   )cc";
728   std::string Expected = R"(
729     void foo() {
730       if (true) { /* then */ }
731       else { /* else */ }
732     }
733   )";
734 
735   StringRef C = "C", T = "T", E = "E";
736   testRule(
737       makeRule(
738           ifStmt(hasCondition(expr().bind(C)), hasThen(stmt().bind(T)),
739                  hasElse(stmt().bind(E))),
740           flatten(changeTo(node(std::string(C)), cat("true")),
741                   changeTo(statement(std::string(T)), cat("{ /* then */ }")),
742                   changeTo(statement(std::string(E)), cat("{ /* else */ }")))),
743       Input, Expected);
744 }
745 
746 TEST_F(TransformerTest, FlattenWithMixedArgs) {
747   using clang::transformer::editList;
748   std::string Input = R"cc(
749     void foo() {
750       if (10 > 1.0)
751         log(1) << "oh no!";
752       else
753         log(0) << "ok";
754     }
755   )cc";
756   std::string Expected = R"(
757     void foo() {
758       if (true) { /* then */ }
759       else { /* else */ }
760     }
761   )";
762 
763   StringRef C = "C", T = "T", E = "E";
764   testRule(makeRule(ifStmt(hasCondition(expr().bind(C)),
765                            hasThen(stmt().bind(T)), hasElse(stmt().bind(E))),
766                     flatten(changeTo(node(std::string(C)), cat("true")),
767                             edit(changeTo(statement(std::string(T)),
768                                           cat("{ /* then */ }"))),
769                             editList({changeTo(statement(std::string(E)),
770                                                cat("{ /* else */ }"))}))),
771            Input, Expected);
772 }
773 
774 TEST_F(TransformerTest, OrderedRuleUnrelated) {
775   StringRef Flag = "flag";
776   RewriteRule FlagRule = makeRule(
777       cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
778                                     hasName("proto::ProtoCommandLineFlag"))))
779                                .bind(Flag)),
780                         unless(callee(cxxMethodDecl(hasName("GetProto"))))),
781       changeTo(node(std::string(Flag)), cat("PROTO")));
782 
783   std::string Input = R"cc(
784     proto::ProtoCommandLineFlag flag;
785     int x = flag.foo();
786     int y = flag.GetProto().foo();
787     int f(string s) { return strlen(s.c_str()); }
788   )cc";
789   std::string Expected = R"cc(
790     proto::ProtoCommandLineFlag flag;
791     int x = PROTO.foo();
792     int y = flag.GetProto().foo();
793     int f(string s) { return REPLACED; }
794   )cc";
795 
796   testRule(applyFirst({ruleStrlenSize(), FlagRule}), Input, Expected);
797 }
798 
799 TEST_F(TransformerTest, OrderedRuleRelated) {
800   std::string Input = R"cc(
801     void f1();
802     void f2();
803     void call_f1() { f1(); }
804     void call_f2() { f2(); }
805   )cc";
806   std::string Expected = R"cc(
807     void f1();
808     void f2();
809     void call_f1() { REPLACE_F1; }
810     void call_f2() { REPLACE_F1_OR_F2; }
811   )cc";
812 
813   RewriteRule ReplaceF1 =
814       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
815                changeTo(cat("REPLACE_F1")));
816   RewriteRule ReplaceF1OrF2 =
817       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
818                changeTo(cat("REPLACE_F1_OR_F2")));
819   testRule(applyFirst({ReplaceF1, ReplaceF1OrF2}), Input, Expected);
820 }
821 
822 // Change the order of the rules to get a different result. When `ReplaceF1OrF2`
823 // comes first, it applies for both uses, so `ReplaceF1` never applies.
824 TEST_F(TransformerTest, OrderedRuleRelatedSwapped) {
825   std::string Input = R"cc(
826     void f1();
827     void f2();
828     void call_f1() { f1(); }
829     void call_f2() { f2(); }
830   )cc";
831   std::string Expected = R"cc(
832     void f1();
833     void f2();
834     void call_f1() { REPLACE_F1_OR_F2; }
835     void call_f2() { REPLACE_F1_OR_F2; }
836   )cc";
837 
838   RewriteRule ReplaceF1 =
839       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
840                changeTo(cat("REPLACE_F1")));
841   RewriteRule ReplaceF1OrF2 =
842       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
843                changeTo(cat("REPLACE_F1_OR_F2")));
844   testRule(applyFirst({ReplaceF1OrF2, ReplaceF1}), Input, Expected);
845 }
846 
847 // Verify that a set of rules whose matchers have different base kinds works
848 // properly, including that `applyFirst` produces multiple matchers.  We test
849 // two different kinds of rules: Expr and Decl. We place the Decl rule in the
850 // middle to test that `buildMatchers` works even when the kinds aren't grouped
851 // together.
852 TEST_F(TransformerTest, OrderedRuleMultipleKinds) {
853   std::string Input = R"cc(
854     void f1();
855     void f2();
856     void call_f1() { f1(); }
857     void call_f2() { f2(); }
858   )cc";
859   std::string Expected = R"cc(
860     void f1();
861     void DECL_RULE();
862     void call_f1() { REPLACE_F1; }
863     void call_f2() { REPLACE_F1_OR_F2; }
864   )cc";
865 
866   RewriteRule ReplaceF1 =
867       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
868                changeTo(cat("REPLACE_F1")));
869   RewriteRule ReplaceF1OrF2 =
870       makeRule(callExpr(callee(functionDecl(hasAnyName("f1", "f2")))),
871                changeTo(cat("REPLACE_F1_OR_F2")));
872   RewriteRule DeclRule = makeRule(functionDecl(hasName("f2")).bind("fun"),
873                                   changeTo(name("fun"), cat("DECL_RULE")));
874 
875   RewriteRule Rule = applyFirst({ReplaceF1, DeclRule, ReplaceF1OrF2});
876   EXPECT_EQ(transformer::detail::buildMatchers(Rule).size(), 2UL);
877   testRule(Rule, Input, Expected);
878 }
879 
880 // Verifies that a rule with a top-level matcher for an implicit node (like
881 // `implicitCastExpr`) does not change the code, when the AST traversal skips
882 // implicit nodes. In this test, only the rule with the explicit-node matcher
883 // will fire.
884 TEST_F(TransformerTest, OrderedRuleImplicitIgnored) {
885   std::string Input = R"cc(
886     void f1();
887     int f2();
888     void call_f1() { f1(); }
889     float call_f2() { return f2(); }
890   )cc";
891   std::string Expected = R"cc(
892     void f1();
893     int f2();
894     void call_f1() { REPLACE_F1; }
895     float call_f2() { return f2(); }
896   )cc";
897 
898   RewriteRule ReplaceF1 =
899       makeRule(callExpr(callee(functionDecl(hasName("f1")))),
900                changeTo(cat("REPLACE_F1")));
901   RewriteRule ReplaceF2 =
902       makeRule(implicitCastExpr(hasSourceExpression(callExpr())),
903                changeTo(cat("REPLACE_F2")));
904   testRule(applyFirst({ReplaceF1, ReplaceF2}), Input, Expected);
905 }
906 
907 // Verifies that explicitly setting the traversal kind fixes the problem in the
908 // previous test.
909 TEST_F(TransformerTest, OrderedRuleImplicitMatched) {
910   std::string Input = R"cc(
911     void f1();
912     int f2();
913     void call_f1() { f1(); }
914     float call_f2() { return f2(); }
915   )cc";
916   std::string Expected = R"cc(
917     void f1();
918     int f2();
919     void call_f1() { REPLACE_F1; }
920     float call_f2() { return REPLACE_F2; }
921   )cc";
922 
923   RewriteRule ReplaceF1 = makeRule(
924       traverse(clang::TK_AsIs, callExpr(callee(functionDecl(hasName("f1"))))),
925       changeTo(cat("REPLACE_F1")));
926   RewriteRule ReplaceF2 =
927       makeRule(traverse(clang::TK_AsIs,
928                         implicitCastExpr(hasSourceExpression(callExpr()))),
929                changeTo(cat("REPLACE_F2")));
930   testRule(applyFirst({ReplaceF1, ReplaceF2}), Input, Expected);
931 }
932 
933 //
934 // Negative tests (where we expect no transformation to occur).
935 //
936 
937 // Tests for a conflict in edits from a single match for a rule.
938 TEST_F(TransformerTest, TextGeneratorFailure) {
939   std::string Input = "int conflictOneRule() { return 3 + 7; }";
940   // Try to change the whole binary-operator expression AND one its operands:
941   StringRef O = "O";
942   class AlwaysFail : public transformer::MatchComputation<std::string> {
943     llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &,
944                      std::string *) const override {
945       return llvm::createStringError(llvm::errc::invalid_argument, "ERROR");
946     }
947     std::string toString() const override { return "AlwaysFail"; }
948   };
949   Transformer T(
950       makeRule(binaryOperator().bind(O),
951                changeTo(node(std::string(O)), std::make_shared<AlwaysFail>())),
952       consumer());
953   T.registerMatchers(&MatchFinder);
954   EXPECT_FALSE(rewrite(Input));
955   EXPECT_THAT(Changes, IsEmpty());
956   EXPECT_EQ(ErrorCount, 1);
957 }
958 
959 // Tests for a conflict in edits from a single match for a rule.
960 TEST_F(TransformerTest, OverlappingEditsInRule) {
961   std::string Input = "int conflictOneRule() { return 3 + 7; }";
962   // Try to change the whole binary-operator expression AND one its operands:
963   StringRef O = "O", L = "L";
964   Transformer T(makeRule(binaryOperator(hasLHS(expr().bind(L))).bind(O),
965                          {changeTo(node(std::string(O)), cat("DELETE_OP")),
966                           changeTo(node(std::string(L)), cat("DELETE_LHS"))}),
967                 consumer());
968   T.registerMatchers(&MatchFinder);
969   EXPECT_FALSE(rewrite(Input));
970   EXPECT_THAT(Changes, IsEmpty());
971   EXPECT_EQ(ErrorCount, 1);
972 }
973 
974 // Tests for a conflict in edits across multiple matches (of the same rule).
975 TEST_F(TransformerTest, OverlappingEditsMultipleMatches) {
976   std::string Input = "int conflictOneRule() { return -7; }";
977   // Try to change the whole binary-operator expression AND one its operands:
978   StringRef E = "E";
979   Transformer T(makeRule(expr().bind(E),
980                          changeTo(node(std::string(E)), cat("DELETE_EXPR"))),
981                 consumer());
982   T.registerMatchers(&MatchFinder);
983   // The rewrite process fails because the changes conflict with each other...
984   EXPECT_FALSE(rewrite(Input));
985   // ... but two changes were produced.
986   EXPECT_EQ(Changes.size(), 2u);
987   EXPECT_EQ(ErrorCount, 0);
988 }
989 
990 TEST_F(TransformerTest, ErrorOccurredMatchSkipped) {
991   // Syntax error in the function body:
992   std::string Input = "void errorOccurred() { 3 }";
993   Transformer T(makeRule(functionDecl(hasName("errorOccurred")),
994                          changeTo(cat("DELETED;"))),
995                 consumer());
996   T.registerMatchers(&MatchFinder);
997   // The rewrite process itself fails...
998   EXPECT_FALSE(rewrite(Input));
999   // ... and no changes or errors are produced in the process.
1000   EXPECT_THAT(Changes, IsEmpty());
1001   EXPECT_EQ(ErrorCount, 0);
1002 }
1003 
1004 // Transformation of macro source text when the change encompasses the entirety
1005 // of the expanded text.
1006 TEST_F(TransformerTest, SimpleMacro) {
1007   std::string Input = R"cc(
1008 #define ZERO 0
1009     int f(string s) { return ZERO; }
1010   )cc";
1011   std::string Expected = R"cc(
1012 #define ZERO 0
1013     int f(string s) { return 999; }
1014   )cc";
1015 
1016   StringRef zero = "zero";
1017   RewriteRule R = makeRule(integerLiteral(equals(0)).bind(zero),
1018                            changeTo(node(std::string(zero)), cat("999")));
1019   testRule(R, Input, Expected);
1020 }
1021 
1022 // Transformation of macro source text when the change encompasses the entirety
1023 // of the expanded text, for the case of function-style macros.
1024 TEST_F(TransformerTest, FunctionMacro) {
1025   std::string Input = R"cc(
1026 #define MACRO(str) strlen((str).c_str())
1027     int f(string s) { return MACRO(s); }
1028   )cc";
1029   std::string Expected = R"cc(
1030 #define MACRO(str) strlen((str).c_str())
1031     int f(string s) { return REPLACED; }
1032   )cc";
1033 
1034   testRule(ruleStrlenSize(), Input, Expected);
1035 }
1036 
1037 // Tests that expressions in macro arguments can be rewritten.
1038 TEST_F(TransformerTest, MacroArg) {
1039   std::string Input = R"cc(
1040 #define PLUS(e) e + 1
1041     int f(string s) { return PLUS(strlen(s.c_str())); }
1042   )cc";
1043   std::string Expected = R"cc(
1044 #define PLUS(e) e + 1
1045     int f(string s) { return PLUS(REPLACED); }
1046   )cc";
1047 
1048   testRule(ruleStrlenSize(), Input, Expected);
1049 }
1050 
1051 // Tests that expressions in macro arguments can be rewritten, even when the
1052 // macro call occurs inside another macro's definition.
1053 TEST_F(TransformerTest, MacroArgInMacroDef) {
1054   std::string Input = R"cc(
1055 #define NESTED(e) e
1056 #define MACRO(str) NESTED(strlen((str).c_str()))
1057     int f(string s) { return MACRO(s); }
1058   )cc";
1059   std::string Expected = R"cc(
1060 #define NESTED(e) e
1061 #define MACRO(str) NESTED(strlen((str).c_str()))
1062     int f(string s) { return REPLACED; }
1063   )cc";
1064 
1065   testRule(ruleStrlenSize(), Input, Expected);
1066 }
1067 
1068 // Tests the corner case of the identity macro, specifically that it is
1069 // discarded in the rewrite rather than preserved (like PLUS is preserved in the
1070 // previous test).  This behavior is of dubious value (and marked with a FIXME
1071 // in the code), but we test it to verify (and demonstrate) how this case is
1072 // handled.
1073 TEST_F(TransformerTest, IdentityMacro) {
1074   std::string Input = R"cc(
1075 #define ID(e) e
1076     int f(string s) { return ID(strlen(s.c_str())); }
1077   )cc";
1078   std::string Expected = R"cc(
1079 #define ID(e) e
1080     int f(string s) { return REPLACED; }
1081   )cc";
1082 
1083   testRule(ruleStrlenSize(), Input, Expected);
1084 }
1085 
1086 // Tests that two changes in a single macro expansion do not lead to conflicts
1087 // in applying the changes.
1088 TEST_F(TransformerTest, TwoChangesInOneMacroExpansion) {
1089   std::string Input = R"cc(
1090 #define PLUS(a,b) (a) + (b)
1091     int f() { return PLUS(3, 4); }
1092   )cc";
1093   std::string Expected = R"cc(
1094 #define PLUS(a,b) (a) + (b)
1095     int f() { return PLUS(LIT, LIT); }
1096   )cc";
1097 
1098   testRule(makeRule(integerLiteral(), changeTo(cat("LIT"))), Input, Expected);
1099 }
1100 
1101 // Tests case where the rule's match spans both source from the macro and its
1102 // arg, with the begin location (the "anchor") being the arg.
1103 TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNot) {
1104   std::string Input = R"cc(
1105 #define PLUS_ONE(a) a + 1
1106     int f() { return PLUS_ONE(3); }
1107   )cc";
1108   std::string Expected = R"cc(
1109 #define PLUS_ONE(a) a + 1
1110     int f() { return PLUS_ONE(LIT); }
1111   )cc";
1112 
1113   StringRef E = "expr";
1114   testRule(makeRule(binaryOperator(hasLHS(expr().bind(E))),
1115                     changeTo(node(std::string(E)), cat("LIT"))),
1116            Input, Expected);
1117 }
1118 
1119 // Tests case where the rule's match spans both source from the macro and its
1120 // arg, with the begin location (the "anchor") being inside the macro.
1121 TEST_F(TransformerTest, MatchSpansMacroTextButChangeDoesNotAnchoredInMacro) {
1122   std::string Input = R"cc(
1123 #define PLUS_ONE(a) 1 + a
1124     int f() { return PLUS_ONE(3); }
1125   )cc";
1126   std::string Expected = R"cc(
1127 #define PLUS_ONE(a) 1 + a
1128     int f() { return PLUS_ONE(LIT); }
1129   )cc";
1130 
1131   StringRef E = "expr";
1132   testRule(makeRule(binaryOperator(hasRHS(expr().bind(E))),
1133                     changeTo(node(std::string(E)), cat("LIT"))),
1134            Input, Expected);
1135 }
1136 
1137 // No rewrite is applied when the changed text does not encompass the entirety
1138 // of the expanded text. That is, the edit would have to be applied to the
1139 // macro's definition to succeed and editing the expansion point would not
1140 // suffice.
1141 TEST_F(TransformerTest, NoPartialRewriteOMacroExpansion) {
1142   std::string Input = R"cc(
1143 #define ZERO_PLUS 0 + 3
1144     int f(string s) { return ZERO_PLUS; })cc";
1145 
1146   StringRef zero = "zero";
1147   RewriteRule R = makeRule(integerLiteral(equals(0)).bind(zero),
1148                            changeTo(node(std::string(zero)), cat("0")));
1149   testRule(R, Input, Input);
1150 }
1151 
1152 // This test handles the corner case where a macro expands within another macro
1153 // to matching code, but that code is an argument to the nested macro call.  A
1154 // simple check of isMacroArgExpansion() vs. isMacroBodyExpansion() will get
1155 // this wrong, and transform the code.
1156 TEST_F(TransformerTest, NoPartialRewriteOfMacroExpansionForMacroArgs) {
1157   std::string Input = R"cc(
1158 #define NESTED(e) e
1159 #define MACRO(str) 1 + NESTED(strlen((str).c_str()))
1160     int f(string s) { return MACRO(s); }
1161   )cc";
1162 
1163   testRule(ruleStrlenSize(), Input, Input);
1164 }
1165 
1166 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1167 // Verifies that `Type` and `QualType` are not allowed as top-level matchers in
1168 // rules.
1169 TEST(TransformerDeathTest, OrderedRuleTypes) {
1170   RewriteRule QualTypeRule = makeRule(qualType(), changeTo(cat("Q")));
1171   EXPECT_DEATH(transformer::detail::buildMatchers(QualTypeRule),
1172                "Matcher must be.*node matcher");
1173 
1174   RewriteRule TypeRule = makeRule(arrayType(), changeTo(cat("T")));
1175   EXPECT_DEATH(transformer::detail::buildMatchers(TypeRule),
1176                "Matcher must be.*node matcher");
1177 }
1178 #endif
1179 
1180 // Edits are able to span multiple files; in this case, a header and an
1181 // implementation file.
1182 TEST_F(TransformerTest, MultipleFiles) {
1183   std::string Header = R"cc(void RemoveThisFunction();)cc";
1184   std::string Source = R"cc(#include "input.h"
1185                             void RemoveThisFunction();)cc";
1186   Transformer T(
1187       makeRule(functionDecl(hasName("RemoveThisFunction")), changeTo(cat(""))),
1188       consumer());
1189   T.registerMatchers(&MatchFinder);
1190   auto Factory = newFrontendActionFactory(&MatchFinder);
1191   EXPECT_TRUE(runToolOnCodeWithArgs(
1192       Factory->create(), Source, std::vector<std::string>(), "input.cc",
1193       "clang-tool", std::make_shared<PCHContainerOperations>(),
1194       {{"input.h", Header}}));
1195 
1196   std::sort(Changes.begin(), Changes.end(),
1197             [](const AtomicChange &L, const AtomicChange &R) {
1198               return L.getFilePath() < R.getFilePath();
1199             });
1200 
1201   ASSERT_EQ(Changes[0].getFilePath(), "./input.h");
1202   EXPECT_THAT(Changes[0].getInsertedHeaders(), IsEmpty());
1203   EXPECT_THAT(Changes[0].getRemovedHeaders(), IsEmpty());
1204   llvm::Expected<std::string> UpdatedCode =
1205       clang::tooling::applyAllReplacements(Header,
1206                                            Changes[0].getReplacements());
1207   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1208       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1209   EXPECT_EQ(format(*UpdatedCode), format(R"cc(;)cc"));
1210 
1211   ASSERT_EQ(Changes[1].getFilePath(), "input.cc");
1212   EXPECT_THAT(Changes[1].getInsertedHeaders(), IsEmpty());
1213   EXPECT_THAT(Changes[1].getRemovedHeaders(), IsEmpty());
1214   UpdatedCode = clang::tooling::applyAllReplacements(
1215       Source, Changes[1].getReplacements());
1216   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1217       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1218   EXPECT_EQ(format(*UpdatedCode), format(R"cc(#include "input.h"
1219                         ;)cc"));
1220 }
1221 
1222 TEST_F(TransformerTest, AddIncludeMultipleFiles) {
1223   std::string Header = R"cc(void RemoveThisFunction();)cc";
1224   std::string Source = R"cc(#include "input.h"
1225                             void Foo() {RemoveThisFunction();})cc";
1226   Transformer T(
1227       makeRule(callExpr(callee(
1228                    functionDecl(hasName("RemoveThisFunction")).bind("fun"))),
1229                addInclude(node("fun"), "header.h")),
1230       consumer());
1231   T.registerMatchers(&MatchFinder);
1232   auto Factory = newFrontendActionFactory(&MatchFinder);
1233   EXPECT_TRUE(runToolOnCodeWithArgs(
1234       Factory->create(), Source, std::vector<std::string>(), "input.cc",
1235       "clang-tool", std::make_shared<PCHContainerOperations>(),
1236       {{"input.h", Header}}));
1237 
1238   ASSERT_EQ(Changes.size(), 1U);
1239   ASSERT_EQ(Changes[0].getFilePath(), "./input.h");
1240   EXPECT_THAT(Changes[0].getInsertedHeaders(), ElementsAre("header.h"));
1241   EXPECT_THAT(Changes[0].getRemovedHeaders(), IsEmpty());
1242   llvm::Expected<std::string> UpdatedCode =
1243       clang::tooling::applyAllReplacements(Header,
1244                                            Changes[0].getReplacements());
1245   ASSERT_TRUE(static_cast<bool>(UpdatedCode))
1246       << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
1247   EXPECT_EQ(format(*UpdatedCode), format(Header));
1248 }
1249 } // namespace
1250