[DebugInfo] Limit the number of values that may be referenced by a dbg.value
[llvm-project.git] / clang / unittests / Tooling / RefactoringCallbacksTest.cpp
blob47c1c11ac9fcaf4364521b14c7758b63a7be99b7
1 //===- unittest/Tooling/RefactoringCallbacksTest.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 //===----------------------------------------------------------------------===//
9 #include "RewriterTestContext.h"
10 #include "clang/ASTMatchers/ASTMatchFinder.h"
11 #include "clang/ASTMatchers/ASTMatchers.h"
12 #include "clang/Tooling/RefactoringCallbacks.h"
13 #include "gtest/gtest.h"
15 namespace clang {
16 namespace tooling {
18 using namespace ast_matchers;
20 template <typename T>
21 void expectRewritten(const std::string &Code, const std::string &Expected,
22 const T &AMatcher, RefactoringCallback &Callback) {
23 std::map<std::string, Replacements> FileToReplace;
24 ASTMatchRefactorer Finder(FileToReplace);
25 Finder.addMatcher(traverse(TK_AsIs, AMatcher), &Callback);
26 std::unique_ptr<tooling::FrontendActionFactory> Factory(
27 tooling::newFrontendActionFactory(&Finder));
28 ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), Code))
29 << "Parsing error in \"" << Code << "\"";
30 RewriterTestContext Context;
31 FileID ID = Context.createInMemoryFile("input.cc", Code);
32 EXPECT_TRUE(tooling::applyAllReplacements(FileToReplace["input.cc"],
33 Context.Rewrite));
34 EXPECT_EQ(Expected, Context.getRewrittenText(ID));
37 TEST(RefactoringCallbacksTest, ReplacesStmtsWithString) {
38 std::string Code = "void f() { int i = 1; }";
39 std::string Expected = "void f() { ; }";
40 ReplaceStmtWithText Callback("id", ";");
41 expectRewritten(Code, Expected, declStmt().bind("id"), Callback);
44 TEST(RefactoringCallbacksTest, ReplacesStmtsInCalledMacros) {
45 std::string Code = "#define A void f() { int i = 1; }\nA";
46 std::string Expected = "#define A void f() { ; }\nA";
47 ReplaceStmtWithText Callback("id", ";");
48 expectRewritten(Code, Expected, declStmt().bind("id"), Callback);
51 TEST(RefactoringCallbacksTest, IgnoresStmtsInUncalledMacros) {
52 std::string Code = "#define A void f() { int i = 1; }";
53 std::string Expected = "#define A void f() { int i = 1; }";
54 ReplaceStmtWithText Callback("id", ";");
55 expectRewritten(Code, Expected, declStmt().bind("id"), Callback);
58 TEST(RefactoringCallbacksTest, ReplacesInteger) {
59 std::string Code = "void f() { int i = 1; }";
60 std::string Expected = "void f() { int i = 2; }";
61 ReplaceStmtWithText Callback("id", "2");
62 expectRewritten(Code, Expected, expr(integerLiteral()).bind("id"), Callback);
65 TEST(RefactoringCallbacksTest, ReplacesStmtWithStmt) {
66 std::string Code = "void f() { int i = false ? 1 : i * 2; }";
67 std::string Expected = "void f() { int i = i * 2; }";
68 ReplaceStmtWithStmt Callback("always-false", "should-be");
69 expectRewritten(
70 Code, Expected,
71 conditionalOperator(hasCondition(cxxBoolLiteral(equals(false))),
72 hasFalseExpression(expr().bind("should-be")))
73 .bind("always-false"),
74 Callback);
77 TEST(RefactoringCallbacksTest, ReplacesIfStmt) {
78 std::string Code = "bool a; void f() { if (a) f(); else a = true; }";
79 std::string Expected = "bool a; void f() { f(); }";
80 ReplaceIfStmtWithItsBody Callback("id", true);
81 expectRewritten(Code, Expected,
82 ifStmt(hasCondition(implicitCastExpr(hasSourceExpression(
83 declRefExpr(to(varDecl(hasName("a"))))))))
84 .bind("id"),
85 Callback);
88 TEST(RefactoringCallbacksTest, RemovesEntireIfOnEmptyElse) {
89 std::string Code = "void f() { if (false) int i = 0; }";
90 std::string Expected = "void f() { }";
91 ReplaceIfStmtWithItsBody Callback("id", false);
92 expectRewritten(
93 Code, Expected,
94 ifStmt(hasCondition(cxxBoolLiteral(equals(false)))).bind("id"), Callback);
97 TEST(RefactoringCallbacksTest, TemplateJustText) {
98 std::string Code = "void f() { int i = 1; }";
99 std::string Expected = "void f() { FOO }";
100 auto Callback = ReplaceNodeWithTemplate::create("id", "FOO");
101 EXPECT_FALSE(Callback.takeError());
102 expectRewritten(Code, Expected, declStmt().bind("id"), **Callback);
105 TEST(RefactoringCallbacksTest, TemplateSimpleSubst) {
106 std::string Code = "void f() { int i = 1; }";
107 std::string Expected = "void f() { long x = 1; }";
108 auto Callback = ReplaceNodeWithTemplate::create("decl", "long x = ${init}");
109 EXPECT_FALSE(Callback.takeError());
110 expectRewritten(Code, Expected,
111 varDecl(hasInitializer(expr().bind("init"))).bind("decl"),
112 **Callback);
115 TEST(RefactoringCallbacksTest, TemplateLiteral) {
116 std::string Code = "void f() { int i = 1; }";
117 std::string Expected = "void f() { string x = \"$-1\"; }";
118 auto Callback = ReplaceNodeWithTemplate::create("decl",
119 "string x = \"$$-${init}\"");
120 EXPECT_FALSE(Callback.takeError());
121 expectRewritten(Code, Expected,
122 varDecl(hasInitializer(expr().bind("init"))).bind("decl"),
123 **Callback);
126 static void ExpectStringError(const std::string &Expected,
127 llvm::Error E) {
128 std::string Found;
129 handleAllErrors(std::move(E), [&](const llvm::StringError &SE) {
130 llvm::raw_string_ostream Stream(Found);
131 SE.log(Stream);
133 EXPECT_EQ(Expected, Found);
136 TEST(RefactoringCallbacksTest, TemplateUnterminated) {
137 auto Callback = ReplaceNodeWithTemplate::create("decl",
138 "string x = \"$$-${init\"");
139 ExpectStringError("Unterminated ${...} in replacement template near ${init\"",
140 Callback.takeError());
143 TEST(RefactoringCallbacksTest, TemplateUnknownDollar) {
144 auto Callback = ReplaceNodeWithTemplate::create("decl",
145 "string x = \"$<");
146 ExpectStringError("Invalid $ in replacement template near $<",
147 Callback.takeError());
150 } // namespace tooling
151 } // end namespace clang