summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/clang/unittests/Tooling/RefactoringCallbacksTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/clang/unittests/Tooling/RefactoringCallbacksTest.cpp')
-rw-r--r--gnu/llvm/clang/unittests/Tooling/RefactoringCallbacksTest.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/gnu/llvm/clang/unittests/Tooling/RefactoringCallbacksTest.cpp b/gnu/llvm/clang/unittests/Tooling/RefactoringCallbacksTest.cpp
new file mode 100644
index 00000000000..4a883c38c85
--- /dev/null
+++ b/gnu/llvm/clang/unittests/Tooling/RefactoringCallbacksTest.cpp
@@ -0,0 +1,152 @@
+//===- unittest/Tooling/RefactoringCallbacksTest.cpp ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RewriterTestContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/RefactoringCallbacks.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tooling {
+
+using namespace ast_matchers;
+
+template <typename T>
+void expectRewritten(const std::string &Code, const std::string &Expected,
+ const T &AMatcher, RefactoringCallback &Callback) {
+ std::map<std::string, Replacements> FileToReplace;
+ ASTMatchRefactorer Finder(FileToReplace);
+ Finder.addMatcher(AMatcher, &Callback);
+ std::unique_ptr<tooling::FrontendActionFactory> Factory(
+ tooling::newFrontendActionFactory(&Finder));
+ ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), Code))
+ << "Parsing error in \"" << Code << "\"";
+ RewriterTestContext Context;
+ FileID ID = Context.createInMemoryFile("input.cc", Code);
+ EXPECT_TRUE(tooling::applyAllReplacements(FileToReplace["input.cc"],
+ Context.Rewrite));
+ EXPECT_EQ(Expected, Context.getRewrittenText(ID));
+}
+
+TEST(RefactoringCallbacksTest, ReplacesStmtsWithString) {
+ std::string Code = "void f() { int i = 1; }";
+ std::string Expected = "void f() { ; }";
+ ReplaceStmtWithText Callback("id", ";");
+ expectRewritten(Code, Expected, declStmt().bind("id"), Callback);
+}
+
+TEST(RefactoringCallbacksTest, ReplacesStmtsInCalledMacros) {
+ std::string Code = "#define A void f() { int i = 1; }\nA";
+ std::string Expected = "#define A void f() { ; }\nA";
+ ReplaceStmtWithText Callback("id", ";");
+ expectRewritten(Code, Expected, declStmt().bind("id"), Callback);
+}
+
+TEST(RefactoringCallbacksTest, IgnoresStmtsInUncalledMacros) {
+ std::string Code = "#define A void f() { int i = 1; }";
+ std::string Expected = "#define A void f() { int i = 1; }";
+ ReplaceStmtWithText Callback("id", ";");
+ expectRewritten(Code, Expected, declStmt().bind("id"), Callback);
+}
+
+TEST(RefactoringCallbacksTest, ReplacesInteger) {
+ std::string Code = "void f() { int i = 1; }";
+ std::string Expected = "void f() { int i = 2; }";
+ ReplaceStmtWithText Callback("id", "2");
+ expectRewritten(Code, Expected, expr(integerLiteral()).bind("id"), Callback);
+}
+
+TEST(RefactoringCallbacksTest, ReplacesStmtWithStmt) {
+ std::string Code = "void f() { int i = false ? 1 : i * 2; }";
+ std::string Expected = "void f() { int i = i * 2; }";
+ ReplaceStmtWithStmt Callback("always-false", "should-be");
+ expectRewritten(
+ Code, Expected,
+ conditionalOperator(hasCondition(cxxBoolLiteral(equals(false))),
+ hasFalseExpression(expr().bind("should-be")))
+ .bind("always-false"),
+ Callback);
+}
+
+TEST(RefactoringCallbacksTest, ReplacesIfStmt) {
+ std::string Code = "bool a; void f() { if (a) f(); else a = true; }";
+ std::string Expected = "bool a; void f() { f(); }";
+ ReplaceIfStmtWithItsBody Callback("id", true);
+ expectRewritten(Code, Expected,
+ ifStmt(hasCondition(implicitCastExpr(hasSourceExpression(
+ declRefExpr(to(varDecl(hasName("a"))))))))
+ .bind("id"),
+ Callback);
+}
+
+TEST(RefactoringCallbacksTest, RemovesEntireIfOnEmptyElse) {
+ std::string Code = "void f() { if (false) int i = 0; }";
+ std::string Expected = "void f() { }";
+ ReplaceIfStmtWithItsBody Callback("id", false);
+ expectRewritten(
+ Code, Expected,
+ ifStmt(hasCondition(cxxBoolLiteral(equals(false)))).bind("id"), Callback);
+}
+
+TEST(RefactoringCallbacksTest, TemplateJustText) {
+ std::string Code = "void f() { int i = 1; }";
+ std::string Expected = "void f() { FOO }";
+ auto Callback = ReplaceNodeWithTemplate::create("id", "FOO");
+ EXPECT_FALSE(Callback.takeError());
+ expectRewritten(Code, Expected, declStmt().bind("id"), **Callback);
+}
+
+TEST(RefactoringCallbacksTest, TemplateSimpleSubst) {
+ std::string Code = "void f() { int i = 1; }";
+ std::string Expected = "void f() { long x = 1; }";
+ auto Callback = ReplaceNodeWithTemplate::create("decl", "long x = ${init}");
+ EXPECT_FALSE(Callback.takeError());
+ expectRewritten(Code, Expected,
+ varDecl(hasInitializer(expr().bind("init"))).bind("decl"),
+ **Callback);
+}
+
+TEST(RefactoringCallbacksTest, TemplateLiteral) {
+ std::string Code = "void f() { int i = 1; }";
+ std::string Expected = "void f() { string x = \"$-1\"; }";
+ auto Callback = ReplaceNodeWithTemplate::create("decl",
+ "string x = \"$$-${init}\"");
+ EXPECT_FALSE(Callback.takeError());
+ expectRewritten(Code, Expected,
+ varDecl(hasInitializer(expr().bind("init"))).bind("decl"),
+ **Callback);
+}
+
+static void ExpectStringError(const std::string &Expected,
+ llvm::Error E) {
+ std::string Found;
+ handleAllErrors(std::move(E), [&](const llvm::StringError &SE) {
+ llvm::raw_string_ostream Stream(Found);
+ SE.log(Stream);
+ });
+ EXPECT_EQ(Expected, Found);
+}
+
+TEST(RefactoringCallbacksTest, TemplateUnterminated) {
+ auto Callback = ReplaceNodeWithTemplate::create("decl",
+ "string x = \"$$-${init\"");
+ ExpectStringError("Unterminated ${...} in replacement template near ${init\"",
+ Callback.takeError());
+}
+
+TEST(RefactoringCallbacksTest, TemplateUnknownDollar) {
+ auto Callback = ReplaceNodeWithTemplate::create("decl",
+ "string x = \"$<");
+ ExpectStringError("Invalid $ in replacement template near $<",
+ Callback.takeError());
+}
+
+
+} // end namespace ast_matchers
+} // end namespace clang