diff options
author | Yitzhak Mandelbaum <yitzhakm@google.com> | 2020-05-19 14:26:46 -0400 |
---|---|---|
committer | Yitzhak Mandelbaum <yitzhakm@google.com> | 2020-05-26 09:17:35 -0400 |
commit | ff2743bf047deac7ef6cc6c3efd30ff05e55b2ad (patch) | |
tree | 507a8685fa03b18e7ebcf5bf4a09a1cf90b7ad03 /clang/unittests/Tooling/TransformerTest.cpp | |
parent | 049c16ba93fa77df7984353b1a0124ed64fc0439 (diff) | |
download | llvm-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.cpp | 42 |
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 |