diff options
author | Yitzhak Mandelbaum <yitzhakm@google.com> | 2020-09-02 14:10:22 +0000 |
---|---|---|
committer | Yitzhak Mandelbaum <yitzhakm@google.com> | 2020-09-03 14:39:50 +0000 |
commit | d4f3903131292d36b3bc22c28798b8e9dae20af6 (patch) | |
tree | fc55d686ec64ecdd20060eb6abea25fa00130bad /clang/unittests/Tooling/TransformerTest.cpp | |
parent | 58afaecdc23148219d18d566dbaf79f37950f716 (diff) | |
download | llvm-d4f3903131292d36b3bc22c28798b8e9dae20af6.zip llvm-d4f3903131292d36b3bc22c28798b8e9dae20af6.tar.gz llvm-d4f3903131292d36b3bc22c28798b8e9dae20af6.tar.bz2 |
[libTooling] Provide overloads of `rewriteDescendants` that operate directly on an AST node.
The new overloads apply directly to a node, like the
`clang::ast_matchers::match` functions, Rather than generating an
`EditGenerator` combinator.
Differential Revision: https://reviews.llvm.org/D87031
Diffstat (limited to 'clang/unittests/Tooling/TransformerTest.cpp')
-rw-r--r-- | clang/unittests/Tooling/TransformerTest.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/clang/unittests/Tooling/TransformerTest.cpp b/clang/unittests/Tooling/TransformerTest.cpp index 2c9bd7d..a8d6d3d 100644 --- a/clang/unittests/Tooling/TransformerTest.cpp +++ b/clang/unittests/Tooling/TransformerTest.cpp @@ -25,6 +25,7 @@ using ::testing::ElementsAre; using ::testing::IsEmpty; using transformer::cat; using transformer::changeTo; +using transformer::rewriteDescendants; using transformer::RewriteRule; constexpr char KHeaderContents[] = R"cc( @@ -568,6 +569,88 @@ TEST_F(TransformerTest, RewriteDescendantsInvalidNodeType) { EXPECT_EQ(ErrorCount, 1); } +// +// We include one test per typed overload. We don't test extensively since that +// is already covered by the tests above. +// + +TEST_F(TransformerTest, RewriteDescendantsTypedStmt) { + // Add an unrelated definition to the header that also has a variable named + // "x", to test that the rewrite is limited to the scope we intend. + appendToHeader(R"cc(int g(int x) { return x; })cc"); + std::string Input = + "int f(int x) { int y = x; { int z = x * x; } return x; }"; + std::string Expected = + "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }"; + auto InlineX = + makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3"))); + testRule(makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))), + [&InlineX](const MatchFinder::MatchResult &R) { + const auto *Node = R.Nodes.getNodeAs<Stmt>("body"); + assert(Node != nullptr && "body must be bound"); + return transformer::detail::rewriteDescendants( + *Node, InlineX, R); + }), + Input, Expected); +} + +TEST_F(TransformerTest, RewriteDescendantsTypedDecl) { + std::string Input = + "int f(int x) { int y = x; { int z = x * x; } return x; }"; + std::string Expected = + "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }"; + auto InlineX = + makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3"))); + testRule(makeRule(functionDecl(hasName("f")).bind("fun"), + [&InlineX](const MatchFinder::MatchResult &R) { + const auto *Node = R.Nodes.getNodeAs<Decl>("fun"); + assert(Node != nullptr && "fun must be bound"); + return transformer::detail::rewriteDescendants( + *Node, InlineX, R); + }), + Input, Expected); +} + +TEST_F(TransformerTest, RewriteDescendantsTypedTypeLoc) { + std::string Input = "int f(int *x) { return *x; }"; + std::string Expected = "int f(char *x) { return *x; }"; + auto IntToChar = + makeRule(typeLoc(loc(qualType(isInteger(), builtinType()))).bind("loc"), + changeTo(cat("char"))); + testRule( + makeRule( + functionDecl( + hasName("f"), + hasParameter(0, varDecl(hasTypeLoc(typeLoc().bind("parmType"))))), + [&IntToChar](const MatchFinder::MatchResult &R) { + const auto *Node = R.Nodes.getNodeAs<TypeLoc>("parmType"); + assert(Node != nullptr && "parmType must be bound"); + return transformer::detail::rewriteDescendants(*Node, IntToChar, R); + }), + Input, Expected); +} + +TEST_F(TransformerTest, RewriteDescendantsTypedDynTyped) { + // Add an unrelated definition to the header that also has a variable named + // "x", to test that the rewrite is limited to the scope we intend. + appendToHeader(R"cc(int g(int x) { return x; })cc"); + std::string Input = + "int f(int x) { int y = x; { int z = x * x; } return x; }"; + std::string Expected = + "int f(int x) { int y = 3; { int z = 3 * 3; } return 3; }"; + auto InlineX = + makeRule(declRefExpr(to(varDecl(hasName("x")))), changeTo(cat("3"))); + testRule( + makeRule(functionDecl(hasName("f"), hasBody(stmt().bind("body"))), + [&InlineX](const MatchFinder::MatchResult &R) { + auto It = R.Nodes.getMap().find("body"); + assert(It != R.Nodes.getMap().end() && "body must be bound"); + return transformer::detail::rewriteDescendants(It->second, + InlineX, R); + }), + Input, Expected); +} + TEST_F(TransformerTest, InsertBeforeEdit) { std::string Input = R"cc( int f() { |