11050e8b2252d89a0004a6fd25a58dab88b5ee625Chandler Carruth//===- unittest/Tooling/RefactoringCallbacksTest.cpp ----------------------===//
2fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper//
3fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper//                     The LLVM Compiler Infrastructure
4fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper//
5fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper// This file is distributed under the University of Illinois Open Source
6fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper// License. See LICENSE.TXT for details.
7fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper//
8fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper//===----------------------------------------------------------------------===//
9fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
10d5c66dd664b005866c9f7fc91eb0d49164bca36fDaniel Jasper#include "clang/Tooling/RefactoringCallbacks.h"
11d5c66dd664b005866c9f7fc91eb0d49164bca36fDaniel Jasper#include "RewriterTestContext.h"
121050e8b2252d89a0004a6fd25a58dab88b5ee625Chandler Carruth#include "clang/ASTMatchers/ASTMatchFinder.h"
137cc315ccf80382fab7674735fbfda95990d28f8eChandler Carruth#include "clang/ASTMatchers/ASTMatchers.h"
14f27762b1beced898e47aeae1bcb557addd8a148dDouglas Gregor#include "gtest/gtest.h"
15fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
16fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jaspernamespace clang {
178ee04480df468a11667dbfad1049d2b08c4b9482Daniel Jaspernamespace tooling {
188ee04480df468a11667dbfad1049d2b08c4b9482Daniel Jasper
198ee04480df468a11667dbfad1049d2b08c4b9482Daniel Jasperusing namespace ast_matchers;
20fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
21fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jaspertemplate <typename T>
22fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jaspervoid expectRewritten(const std::string &Code,
23fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper                     const std::string &Expected,
24fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper                     const T &AMatcher,
25fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper                     RefactoringCallback &Callback) {
26fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  MatchFinder Finder;
27fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  Finder.addMatcher(AMatcher, &Callback);
28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<tooling::FrontendActionFactory> Factory(
29fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      tooling::newFrontendActionFactory(&Finder));
30fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), Code))
31fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      << "Parsing error in \"" << Code << "\"";
32fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  RewriterTestContext Context;
33fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  FileID ID = Context.createInMemoryFile("input.cc", Code);
34fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  EXPECT_TRUE(tooling::applyAllReplacements(Callback.getReplacements(),
35fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper                                            Context.Rewrite));
36fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  EXPECT_EQ(Expected, Context.getRewrittenText(ID));
37fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
38fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
39fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel JasperTEST(RefactoringCallbacksTest, ReplacesStmtsWithString) {
40fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Code = "void f() { int i = 1; }";
41fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Expected = "void f() { ; }";
42fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ReplaceStmtWithText Callback("id", ";");
432dc75ed2ef2fa3cbfd8b2ed88eb2369f3fcd98a9Daniel Jasper  expectRewritten(Code, Expected, id("id", declStmt()), Callback);
44fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
45fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
46fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel JasperTEST(RefactoringCallbacksTest, ReplacesStmtsInCalledMacros) {
47fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Code = "#define A void f() { int i = 1; }\nA";
48fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Expected = "#define A void f() { ; }\nA";
49fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ReplaceStmtWithText Callback("id", ";");
502dc75ed2ef2fa3cbfd8b2ed88eb2369f3fcd98a9Daniel Jasper  expectRewritten(Code, Expected, id("id", declStmt()), Callback);
51fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
52fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
53fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel JasperTEST(RefactoringCallbacksTest, IgnoresStmtsInUncalledMacros) {
54fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Code = "#define A void f() { int i = 1; }";
55fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Expected = "#define A void f() { int i = 1; }";
56fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ReplaceStmtWithText Callback("id", ";");
572dc75ed2ef2fa3cbfd8b2ed88eb2369f3fcd98a9Daniel Jasper  expectRewritten(Code, Expected, id("id", declStmt()), Callback);
58fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
59fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
60fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel JasperTEST(RefactoringCallbacksTest, ReplacesInteger) {
61fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Code = "void f() { int i = 1; }";
62fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Expected = "void f() { int i = 2; }";
63fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ReplaceStmtWithText Callback("id", "2");
642dc75ed2ef2fa3cbfd8b2ed88eb2369f3fcd98a9Daniel Jasper  expectRewritten(Code, Expected, id("id", expr(integerLiteral())),
65fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper                  Callback);
66fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
67fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
68fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel JasperTEST(RefactoringCallbacksTest, ReplacesStmtWithStmt) {
69fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Code = "void f() { int i = false ? 1 : i * 2; }";
70fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Expected = "void f() { int i = i * 2; }";
71fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ReplaceStmtWithStmt Callback("always-false", "should-be");
72fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  expectRewritten(Code, Expected,
73fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      id("always-false", conditionalOperator(
74fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper          hasCondition(boolLiteral(equals(false))),
752dc75ed2ef2fa3cbfd8b2ed88eb2369f3fcd98a9Daniel Jasper          hasFalseExpression(id("should-be", expr())))),
76fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      Callback);
77fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
78fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
79fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel JasperTEST(RefactoringCallbacksTest, ReplacesIfStmt) {
80fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Code = "bool a; void f() { if (a) f(); else a = true; }";
81fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Expected = "bool a; void f() { f(); }";
82fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ReplaceIfStmtWithItsBody Callback("id", true);
83fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  expectRewritten(Code, Expected,
84fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      id("id", ifStmt(
852dc75ed2ef2fa3cbfd8b2ed88eb2369f3fcd98a9Daniel Jasper          hasCondition(implicitCastExpr(hasSourceExpression(
862dc75ed2ef2fa3cbfd8b2ed88eb2369f3fcd98a9Daniel Jasper              declRefExpr(to(varDecl(hasName("a"))))))))),
87fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      Callback);
88fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
89fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
90fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel JasperTEST(RefactoringCallbacksTest, RemovesEntireIfOnEmptyElse) {
91fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Code = "void f() { if (false) int i = 0; }";
92fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  std::string Expected = "void f() {  }";
93fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  ReplaceIfStmtWithItsBody Callback("id", false);
94fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper  expectRewritten(Code, Expected,
95fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      id("id", ifStmt(hasCondition(boolLiteral(equals(false))))),
96fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper      Callback);
97fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper}
98fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper
99fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper} // end namespace ast_matchers
100fe7beeb421b90f66b4a96c2358c5a838c376a0a8Daniel Jasper} // end namespace clang
101