aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Tooling/TransformerTest.cpp
diff options
context:
space:
mode:
authorYitzhak Mandelbaum <yitzhakm@google.com>2019-05-17 14:23:33 +0000
committerYitzhak Mandelbaum <yitzhakm@google.com>2019-05-17 14:23:33 +0000
commit8369a9beb7edbcebc0a07dd8155ac6e17f12ad93 (patch)
tree8353045ef1bde3c3f6e0ff0b63df1158695c3658 /clang/unittests/Tooling/TransformerTest.cpp
parentf3a3b93f5453e4e07d449c1ed733c9ac8cfb4b58 (diff)
downloadllvm-8369a9beb7edbcebc0a07dd8155ac6e17f12ad93.zip
llvm-8369a9beb7edbcebc0a07dd8155ac6e17f12ad93.tar.gz
llvm-8369a9beb7edbcebc0a07dd8155ac6e17f12ad93.tar.bz2
[LibTooling] Add support to Transformer for composing rules as an ordered choice.
This revision updates `RewriteRule` to support multiple subrules that are interpreted as an ordered-choice (apply the first one that matches). With this feature, users can write the rules that appear later in the list of subrules knowing that previous rules' patterns *have not matched*, freeing them from reasoning about those cases in the current pattern. Reviewers: ilya-biryukov Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D61335 llvm-svn: 361037
Diffstat (limited to 'clang/unittests/Tooling/TransformerTest.cpp')
-rw-r--r--clang/unittests/Tooling/TransformerTest.cpp91
1 files changed, 89 insertions, 2 deletions
diff --git a/clang/unittests/Tooling/TransformerTest.cpp b/clang/unittests/Tooling/TransformerTest.cpp
index e07d9b7..7e8cd6e 100644
--- a/clang/unittests/Tooling/TransformerTest.cpp
+++ b/clang/unittests/Tooling/TransformerTest.cpp
@@ -116,7 +116,8 @@ protected:
};
}
- void testRule(RewriteRule Rule, StringRef Input, StringRef Expected) {
+ template <typename R>
+ void testRule(R Rule, StringRef Input, StringRef Expected) {
Transformer T(std::move(Rule), consumer());
T.registerMatchers(&MatchFinder);
compareSnippets(Expected, rewrite(Input));
@@ -147,7 +148,7 @@ static RewriteRule ruleStrlenSize() {
.bind(StringExpr)),
callee(cxxMethodDecl(hasName("c_str")))))),
change<clang::Expr>("REPLACED"));
- R.Explanation = text("Use size() method directly on string.");
+ R.Cases[0].Explanation = text("Use size() method directly on string.");
return R;
}
@@ -375,6 +376,92 @@ TEST_F(TransformerTest, MultiChange) {
Input, Expected);
}
+TEST_F(TransformerTest, OrderedRuleUnrelated) {
+ StringRef Flag = "flag";
+ RewriteRule FlagRule = makeRule(
+ cxxMemberCallExpr(on(expr(hasType(cxxRecordDecl(
+ hasName("proto::ProtoCommandLineFlag"))))
+ .bind(Flag)),
+ unless(callee(cxxMethodDecl(hasName("GetProto"))))),
+ change<clang::Expr>(Flag, "PROTO"));
+
+ std::string Input = R"cc(
+ proto::ProtoCommandLineFlag flag;
+ int x = flag.foo();
+ int y = flag.GetProto().foo();
+ int f(string s) { return strlen(s.c_str()); }
+ )cc";
+ std::string Expected = R"cc(
+ proto::ProtoCommandLineFlag flag;
+ int x = PROTO.foo();
+ int y = flag.GetProto().foo();
+ int f(string s) { return REPLACED; }
+ )cc";
+
+ testRule(applyFirst({ruleStrlenSize(), FlagRule}), Input, Expected);
+}
+
+// Version of ruleStrlenSizeAny that inserts a method with a different name than
+// ruleStrlenSize, so we can tell their effect apart.
+RewriteRule ruleStrlenSizeDistinct() {
+ StringRef S;
+ return makeRule(
+ callExpr(callee(functionDecl(hasName("strlen"))),
+ hasArgument(0, cxxMemberCallExpr(
+ on(expr().bind(S)),
+ callee(cxxMethodDecl(hasName("c_str")))))),
+ change<clang::Expr>("DISTINCT"));
+}
+
+TEST_F(TransformerTest, OrderedRuleRelated) {
+ std::string Input = R"cc(
+ namespace foo {
+ struct mystring {
+ char* c_str();
+ };
+ int f(mystring s) { return strlen(s.c_str()); }
+ } // namespace foo
+ int g(string s) { return strlen(s.c_str()); }
+ )cc";
+ std::string Expected = R"cc(
+ namespace foo {
+ struct mystring {
+ char* c_str();
+ };
+ int f(mystring s) { return DISTINCT; }
+ } // namespace foo
+ int g(string s) { return REPLACED; }
+ )cc";
+
+ testRule(applyFirst({ruleStrlenSize(), ruleStrlenSizeDistinct()}), Input,
+ Expected);
+}
+
+// Change the order of the rules to get a different result.
+TEST_F(TransformerTest, OrderedRuleRelatedSwapped) {
+ std::string Input = R"cc(
+ namespace foo {
+ struct mystring {
+ char* c_str();
+ };
+ int f(mystring s) { return strlen(s.c_str()); }
+ } // namespace foo
+ int g(string s) { return strlen(s.c_str()); }
+ )cc";
+ std::string Expected = R"cc(
+ namespace foo {
+ struct mystring {
+ char* c_str();
+ };
+ int f(mystring s) { return DISTINCT; }
+ } // namespace foo
+ int g(string s) { return DISTINCT; }
+ )cc";
+
+ testRule(applyFirst({ruleStrlenSizeDistinct(), ruleStrlenSize()}), Input,
+ Expected);
+}
+
//
// Negative tests (where we expect no transformation to occur).
//