aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Tooling/TransformerTest.cpp
diff options
context:
space:
mode:
authorYitzhak Mandelbaum <yitzhakm@google.com>2020-05-19 14:26:46 -0400
committerYitzhak Mandelbaum <yitzhakm@google.com>2020-05-26 09:17:35 -0400
commitff2743bf047deac7ef6cc6c3efd30ff05e55b2ad (patch)
tree507a8685fa03b18e7ebcf5bf4a09a1cf90b7ad03 /clang/unittests/Tooling/TransformerTest.cpp
parent049c16ba93fa77df7984353b1a0124ed64fc0439 (diff)
downloadllvm-ff2743bf047deac7ef6cc6c3efd30ff05e55b2ad.zip
llvm-ff2743bf047deac7ef6cc6c3efd30ff05e55b2ad.tar.gz
llvm-ff2743bf047deac7ef6cc6c3efd30ff05e55b2ad.tar.bz2
[libTooling] In Transformer, allow atomic changes to span multiple files.
Summary: Currently, all changes returned by a single application of a rule must fit in one atomic change and therefore must apply to one file. However, there are patterns in which a single rule will want to modify multiple files; for example, a header and implementation to change a declaration and its definition. This patch relaxes Transformer, libTooling's interpreter of RewriteRules, to support multiple changes. Reviewers: gribozavr Subscribers: mgrang, jfb, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D80239
Diffstat (limited to 'clang/unittests/Tooling/TransformerTest.cpp')
-rw-r--r--clang/unittests/Tooling/TransformerTest.cpp42
1 files changed, 42 insertions, 0 deletions
diff --git a/clang/unittests/Tooling/TransformerTest.cpp b/clang/unittests/Tooling/TransformerTest.cpp
index 1d955cf..c8c6db0 100644
--- a/clang/unittests/Tooling/TransformerTest.cpp
+++ b/clang/unittests/Tooling/TransformerTest.cpp
@@ -817,4 +817,46 @@ TEST(TransformerDeathTest, OrderedRuleTypes) {
"Matcher must be.*node matcher");
}
#endif
+
+// Edits are able to span multiple files; in this case, a header and an
+// implementation file.
+TEST_F(TransformerTest, MultipleFiles) {
+ std::string Header = R"cc(void RemoveThisFunction();)cc";
+ std::string Source = R"cc(#include "input.h"
+ void RemoveThisFunction();)cc";
+ Transformer T(
+ makeRule(functionDecl(hasName("RemoveThisFunction")), changeTo(cat(""))),
+ consumer());
+ T.registerMatchers(&MatchFinder);
+ auto Factory = newFrontendActionFactory(&MatchFinder);
+ EXPECT_TRUE(runToolOnCodeWithArgs(
+ Factory->create(), Source, std::vector<std::string>(), "input.cc",
+ "clang-tool", std::make_shared<PCHContainerOperations>(),
+ {{"input.h", Header}}));
+
+ std::sort(Changes.begin(), Changes.end(),
+ [](const AtomicChange &L, const AtomicChange &R) {
+ return L.getFilePath() < R.getFilePath();
+ });
+
+ ASSERT_EQ(Changes[0].getFilePath(), "./input.h");
+ EXPECT_THAT(Changes[0].getInsertedHeaders(), IsEmpty());
+ EXPECT_THAT(Changes[0].getRemovedHeaders(), IsEmpty());
+ llvm::Expected<std::string> UpdatedCode =
+ clang::tooling::applyAllReplacements(Header,
+ Changes[0].getReplacements());
+ ASSERT_TRUE(static_cast<bool>(UpdatedCode))
+ << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
+ EXPECT_EQ(format(*UpdatedCode), format(R"cc(;)cc"));
+
+ ASSERT_EQ(Changes[1].getFilePath(), "input.cc");
+ EXPECT_THAT(Changes[1].getInsertedHeaders(), IsEmpty());
+ EXPECT_THAT(Changes[1].getRemovedHeaders(), IsEmpty());
+ UpdatedCode = clang::tooling::applyAllReplacements(
+ Source, Changes[1].getReplacements());
+ ASSERT_TRUE(static_cast<bool>(UpdatedCode))
+ << "Could not update code: " << llvm::toString(UpdatedCode.takeError());
+ EXPECT_EQ(format(*UpdatedCode), format(R"cc(#include "input.h"
+ ;)cc"));
+}
} // namespace