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