blob: 3c4a9b591dcf1c837a4946e5c1c0c15fcbb53e37 [file] [log] [blame]
Haojian Wu357ef992016-09-21 13:18:19 +00001//===-- ClangMoveTest.cpp - clang-move unit tests -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ClangMove.h"
11#include "unittests/Tooling/RewriterTestContext.h"
12#include "clang/Format/Format.h"
13#include "clang/Frontend/FrontendActions.h"
14#include "clang/Frontend/TextDiagnosticPrinter.h"
15#include "clang/Rewrite/Core/Rewriter.h"
16#include "clang/Tooling/Refactoring.h"
17#include "clang/Tooling/Tooling.h"
18#include "llvm/ADT/StringRef.h"
19#include "gtest/gtest.h"
20#include <string>
21#include <vector>
22
23namespace clang {
24namespace move {
25namespace {
26
27const char TestHeaderName[] = "foo.h";
28
29const char TestCCName[] = "foo.cc";
30
31const char TestHeader[] = "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000032 "class C1; // test\n"
Haojian Wu29c38f72016-10-21 19:26:43 +000033 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +000034 "namespace b {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000035 "// This is a Foo class\n"
36 "// which is used in\n"
37 "// test.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000038 "class Foo {\n"
39 "public:\n"
40 " void f();\n"
41 "\n"
42 "private:\n"
43 " C1 *c1;\n"
44 " static int b;\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000045 "}; // abc\n"
Haojian Wu357ef992016-09-21 13:18:19 +000046 "\n"
47 "class Foo2 {\n"
48 "public:\n"
49 " int f();\n"
50 "};\n"
51 "} // namespace b\n"
52 "} // namespace a\n";
53
54const char TestCC[] = "#include \"foo.h\"\n"
55 "namespace a {\n"
56 "namespace b {\n"
57 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000058 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000059 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000060 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000061 "int kConstInt1 = 0;\n"
62 "} // namespace\n"
63 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000064 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +000065 "static int kConstInt2 = 1;\n"
66 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000067 "/** comment4\n"
68 "*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +000069 "static int help() {\n"
70 " int a = 0;\n"
71 " return a;\n"
72 "}\n"
73 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000074 "// comment5\n"
75 "// comment5\n"
Haojian Wu357ef992016-09-21 13:18:19 +000076 "void Foo::f() { f1(); }\n"
77 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000078 "/////////////\n"
79 "// comment //\n"
80 "/////////////\n"
Haojian Wu357ef992016-09-21 13:18:19 +000081 "int Foo::b = 2;\n"
82 "int Foo2::f() {\n"
83 " f1();\n"
84 " return 1;\n"
85 "}\n"
86 "} // namespace b\n"
87 "} // namespace a\n";
88
89const char ExpectedTestHeader[] = "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000090 "class C1; // test\n"
Haojian Wu29c38f72016-10-21 19:26:43 +000091 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +000092 "namespace b {\n"
93 "\n"
94 "class Foo2 {\n"
95 "public:\n"
96 " int f();\n"
97 "};\n"
98 "} // namespace b\n"
99 "} // namespace a\n";
100
101const char ExpectedTestCC[] = "#include \"foo.h\"\n"
102 "namespace a {\n"
103 "namespace b {\n"
104 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000105 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000106 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000107 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000108 "int kConstInt1 = 0;\n"
109 "} // namespace\n"
110 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000111 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000112 "static int kConstInt2 = 1;\n"
113 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000114 "/** comment4\n"
115 "*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000116 "static int help() {\n"
117 " int a = 0;\n"
118 " return a;\n"
119 "}\n"
120 "\n"
121 "int Foo2::f() {\n"
122 " f1();\n"
123 " return 1;\n"
124 "}\n"
125 "} // namespace b\n"
126 "} // namespace a\n";
127
Haojian Wu220c7552016-10-14 13:01:36 +0000128const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
129 "#define NEW_FOO_H\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000130 "\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000131 "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000132 "class C1; // test\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000133 "\n"
Haojian Wu29c38f72016-10-21 19:26:43 +0000134 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000135 "namespace b {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000136 "// This is a Foo class\n"
137 "// which is used in\n"
138 "// test.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000139 "class Foo {\n"
140 "public:\n"
141 " void f();\n"
142 "\n"
143 "private:\n"
144 " C1 *c1;\n"
145 " static int b;\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000146 "}; // abc\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000147 "} // namespace b\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000148 "} // namespace a\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000149 "\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000150 "#endif // NEW_FOO_H\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000151
Haojian Wudaf4cb82016-09-23 13:28:38 +0000152const char ExpectedNewCC[] = "namespace a {\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000153 "namespace b {\n"
154 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000155 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000156 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000157 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000158 "int kConstInt1 = 0;\n"
159 "} // namespace\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000160 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000161 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000162 "static int kConstInt2 = 1;\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000163 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000164 "/** comment4\n"
165 "*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000166 "static int help() {\n"
167 " int a = 0;\n"
168 " return a;\n"
169 "}\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000170 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000171 "// comment5\n"
172 "// comment5\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000173 "void Foo::f() { f1(); }\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000174 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000175 "/////////////\n"
176 "// comment //\n"
177 "/////////////\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000178 "int Foo::b = 2;\n"
179 "} // namespace b\n"
180 "} // namespace a\n";
181
182std::map<std::string, std::string>
Haojian Wub15c8da2016-11-24 10:17:17 +0000183runClangMoveOnCode(const move::MoveDefinitionSpec &Spec,
Haojian Wu2930be12016-11-08 19:55:13 +0000184 const char *const Header = TestHeader,
Haojian Wub15c8da2016-11-24 10:17:17 +0000185 const char *const CC = TestCC,
186 DeclarationReporter *const Reporter = nullptr) {
Haojian Wu357ef992016-09-21 13:18:19 +0000187 clang::RewriterTestContext Context;
188
189 std::map<llvm::StringRef, clang::FileID> FileToFileID;
190 std::vector<std::pair<std::string, std::string>> FileToSourceText = {
Haojian Wu2930be12016-11-08 19:55:13 +0000191 {TestHeaderName, Header}, {TestCCName, CC}};
Haojian Wu357ef992016-09-21 13:18:19 +0000192
193 auto CreateFiles = [&FileToSourceText, &Context, &FileToFileID](
194 llvm::StringRef Name, llvm::StringRef Code) {
195 if (!Name.empty()) {
Haojian Wu357ef992016-09-21 13:18:19 +0000196 FileToFileID[Name] = Context.createInMemoryFile(Name, Code);
197 }
198 };
199 CreateFiles(Spec.NewCC, "");
200 CreateFiles(Spec.NewHeader, "");
Haojian Wu2930be12016-11-08 19:55:13 +0000201 CreateFiles(Spec.OldHeader, Header);
202 CreateFiles(Spec.OldCC, CC);
Haojian Wu357ef992016-09-21 13:18:19 +0000203
204 std::map<std::string, tooling::Replacements> FileToReplacements;
Haojian Wud2a6d7b2016-10-04 09:05:31 +0000205 llvm::SmallString<128> InitialDirectory;
206 std::error_code EC = llvm::sys::fs::current_path(InitialDirectory);
207 assert(!EC);
208 (void)EC;
Haojian Wub15c8da2016-11-24 10:17:17 +0000209 ClangMoveContext MoveContext = {Spec, FileToReplacements,
210 InitialDirectory.str(), "LLVM",
211 Reporter != nullptr};
212
Haojian Wu357ef992016-09-21 13:18:19 +0000213 auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
Haojian Wub15c8da2016-11-24 10:17:17 +0000214 &MoveContext, Reporter);
Haojian Wu357ef992016-09-21 13:18:19 +0000215
216 tooling::runToolOnCodeWithArgs(
Haojian Wu2930be12016-11-08 19:55:13 +0000217 Factory->create(), CC, {"-std=c++11", "-fparse-all-comments"},
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000218 TestCCName, "clang-move", std::make_shared<PCHContainerOperations>(),
219 FileToSourceText);
Haojian Wu357ef992016-09-21 13:18:19 +0000220 formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
221 // The Key is file name, value is the new code after moving the class.
222 std::map<std::string, std::string> Results;
223 for (const auto &It : FileToReplacements) {
224 StringRef FilePath = It.first;
225 Results[FilePath] = Context.getRewrittenText(FileToFileID[FilePath]);
226 }
227 return Results;
228}
229
230TEST(ClangMove, MoveHeaderAndCC) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000231 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000232 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000233 Spec.OldHeader = "foo.h";
234 Spec.OldCC = "foo.cc";
235 Spec.NewHeader = "new_foo.h";
236 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000237 std::string ExpectedHeader = "#include \"" + Spec.NewHeader + "\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000238 auto Results = runClangMoveOnCode(Spec);
239 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
240 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
241 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000242 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000243}
244
245TEST(ClangMove, MoveHeaderOnly) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000246 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000247 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000248 Spec.OldHeader = "foo.h";
249 Spec.NewHeader = "new_foo.h";
250 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000251 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000252 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
253 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
254}
255
256TEST(ClangMove, MoveCCOnly) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000257 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000258 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000259 Spec.OldCC = "foo.cc";
260 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000261 std::string ExpectedHeader = "#include \"foo.h\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000262 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000263 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000264 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000265 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000266}
267
268TEST(ClangMove, MoveNonExistClass) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000269 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000270 Spec.Names = {std::string("NonExistFoo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000271 Spec.OldHeader = "foo.h";
272 Spec.OldCC = "foo.cc";
273 Spec.NewHeader = "new_foo.h";
274 Spec.NewCC = "new_foo.cc";
275 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000276 EXPECT_EQ(0u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000277}
278
Haojian Wu2930be12016-11-08 19:55:13 +0000279TEST(ClangMove, MoveAll) {
280 std::vector<std::string> TestHeaders = {
281 "class A {\npublic:\n int f();\n};",
282 // forward declaration.
283 "class B;\nclass A {\npublic:\n int f();\n};",
284 // template forward declaration.
285 "template <typename T> class B;\nclass A {\npublic:\n int f();\n};",
286 "namespace a {}\nclass A {\npublic:\n int f();\n};",
287 "namespace a {}\nusing namespace a;\nclass A {\npublic:\n int f();\n};",
288 };
289 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
Haojian Wub15c8da2016-11-24 10:17:17 +0000290 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000291 Spec.Names.push_back("A");
292 Spec.OldHeader = "foo.h";
293 Spec.OldCC = "foo.cc";
294 Spec.NewHeader = "new_foo.h";
295 Spec.NewCC = "new_foo.cc";
296 for (const auto& Header : TestHeaders) {
297 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
298 EXPECT_EQ(Header, Results[Spec.NewHeader]);
299 EXPECT_EQ("", Results[Spec.OldHeader]);
300 EXPECT_EQ("", Results[Spec.OldCC]);
301 }
302}
303
304TEST(ClangMove, MoveAllMultipleClasses) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000305 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000306 std::vector<std::string> TestHeaders = {
307 "class C;\nclass A {\npublic:\n int f();\n};\nclass B {};",
308 "class C;\nclass B;\nclass A {\npublic:\n int f();\n};\nclass B {};",
309 };
310 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
311 Spec.Names = {std::string("A"), std::string("B")};
312 Spec.OldHeader = "foo.h";
313 Spec.OldCC = "foo.cc";
314 Spec.NewHeader = "new_foo.h";
315 Spec.NewCC = "new_foo.cc";
316 for (const auto& Header : TestHeaders) {
317 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
318 EXPECT_EQ(Header, Results[Spec.NewHeader]);
319 EXPECT_EQ("", Results[Spec.OldHeader]);
320 EXPECT_EQ("", Results[Spec.OldCC]);
321 }
322}
323
324TEST(ClangMove, DontMoveAll) {
325 const char ExpectedHeader[] = "#ifndef NEW_FOO_H\n"
326 "#define NEW_FOO_H\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000327 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000328 "class A {\npublic:\n int f();\n};\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000329 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000330 "#endif // NEW_FOO_H\n";
331 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
332 std::vector<std::string> TestHeaders = {
Haojian Wu53315a72016-11-15 09:06:59 +0000333 "class B {};\nclass A {\npublic:\n int f();\n};\n",
334 "void f() {};\nclass A {\npublic:\n int f();\n};\n",
Haojian Wu2930be12016-11-08 19:55:13 +0000335 };
Haojian Wub15c8da2016-11-24 10:17:17 +0000336 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000337 Spec.Names.push_back("A");
338 Spec.OldHeader = "foo.h";
339 Spec.OldCC = "foo.cc";
340 Spec.NewHeader = "new_foo.h";
341 Spec.NewCC = "new_foo.cc";
342 for (const auto& Header : TestHeaders) {
343 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
344 EXPECT_EQ(ExpectedHeader, Results[Spec.NewHeader]);
345 // The expected old header should not contain class A definition.
Haojian Wu53315a72016-11-15 09:06:59 +0000346 std::string ExpectedOldHeader = Header.substr(0, Header.size() - 32);
Haojian Wu2930be12016-11-08 19:55:13 +0000347 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
348 }
349}
350
Eric Liu47a42d52016-12-06 10:12:23 +0000351TEST(ClangMove, IgnoreUnsupportedKindsAndMoveAll) {
352 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
353 std::vector<std::string> TestHeaders = {
354 "typedef int Int;\nclass A {\npublic:\n int f();\n};\n",
355 "using Int = int;\nclass A {\npublic:\n int f();\n};\n",
356 "enum Color { RED };\nclass A {\npublic:\n int f();\n};\n",
357 };
358 move::MoveDefinitionSpec Spec;
359 Spec.Names.push_back("A");
360 Spec.OldHeader = "foo.h";
361 Spec.OldCC = "foo.cc";
362 Spec.NewHeader = "new_foo.h";
363 Spec.NewCC = "new_foo.cc";
364 for (const auto &Header : TestHeaders) {
365 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
366 EXPECT_EQ(Header, Results[Spec.NewHeader]);
367 EXPECT_EQ("", Results[Spec.OldHeader]);
368 }
369}
370
Haojian Wu24675392016-11-14 14:46:48 +0000371TEST(ClangMove, MacroInFunction) {
372 const char TestHeader[] = "#define INT int\n"
373 "class A {\npublic:\n int f();\n};\n"
374 "class B {};\n";
375 const char TestCode[] = "#include \"foo.h\"\n"
376 "INT A::f() { return 0; }\n";
377 const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
378 "INT A::f() { return 0; }\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000379 move::MoveDefinitionSpec Spec;
Haojian Wu24675392016-11-14 14:46:48 +0000380 Spec.Names.push_back("A");
381 Spec.OldHeader = "foo.h";
382 Spec.OldCC = "foo.cc";
383 Spec.NewHeader = "new_foo.h";
384 Spec.NewCC = "new_foo.cc";
385 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
386 EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
387}
388
Haojian Wu53315a72016-11-15 09:06:59 +0000389TEST(ClangMove, WellFormattedCode) {
390 const std::string CommonHeader =
391 "namespace a {\n"
392 "namespace b {\n"
393 "namespace c {\n"
394 "class C;\n"
395 "\n"
396 "class A {\npublic:\n void f();\n void f2();\n};\n"
397 "} // namespace c\n"
398 "} // namespace b\n"
399 "\n"
400 "namespace d {\n"
401 "namespace e {\n"
402 "class B {\npublic:\n void f();\n};\n"
403 "} // namespace e\n"
404 "} // namespace d\n"
405 "} // namespace a\n";
406 const std::string CommonCode = "\n"
407 "namespace a {\n"
408 "namespace b {\n"
409 "namespace c {\n"
410 "void A::f() {}\n"
411 "\n"
412 "void A::f2() {}\n"
413 "} // namespace c\n"
414 "} // namespace b\n"
415 "\n"
416 "namespace d {\n"
417 "namespace e {\n"
418 "void B::f() {}\n"
419 "} // namespace e\n"
420 "} // namespace d\n"
421 "} // namespace a\n";
422 // Add dummy class to prevent behavior of moving all declarations from header.
423 const std::string TestHeader = CommonHeader + "class D {};\n";
424 const std::string TestCode = "#include \"foo.h\"\n" + CommonCode;
425 const std::string ExpectedNewHeader = "#ifndef NEW_FOO_H\n"
426 "#define NEW_FOO_H\n"
427 "\n" +
428 CommonHeader +
429 "\n"
430 "#endif // NEW_FOO_H\n";
431 const std::string ExpectedNewCC = "#include \"new_foo.h\"\n" + CommonCode;
Haojian Wub15c8da2016-11-24 10:17:17 +0000432 move::MoveDefinitionSpec Spec;
Haojian Wu53315a72016-11-15 09:06:59 +0000433 Spec.Names.push_back("a::b::c::A");
434 Spec.Names.push_back("a::d::e::B");
435 Spec.OldHeader = "foo.h";
436 Spec.OldCC = "foo.cc";
437 Spec.NewHeader = "new_foo.h";
438 Spec.NewCC = "new_foo.cc";
439 auto Results = runClangMoveOnCode(Spec, TestHeader.c_str(), TestCode.c_str());
440 EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);
441 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
442}
443
Haojian Wu48ac3042016-11-23 10:04:19 +0000444TEST(ClangMove, AddDependentNewHeader) {
445 const char TestHeader[] = "class A {};\n"
446 "class B {};\n";
447 const char TestCode[] = "#include \"foo.h\"\n";
448 const char ExpectedOldHeader[] = "#include \"new_foo.h\"\nclass B {};\n";
449 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
450 "#define NEW_FOO_H\n"
451 "\n"
452 "class A {};\n"
453 "\n"
454 "#endif // NEW_FOO_H\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000455 move::MoveDefinitionSpec Spec;
Haojian Wu48ac3042016-11-23 10:04:19 +0000456 Spec.Names.push_back("A");
457 Spec.OldHeader = "foo.h";
458 Spec.OldCC = "foo.cc";
459 Spec.NewHeader = "new_foo.h";
460 Spec.NewCC = "new_foo.cc";
461 Spec.OldDependOnNew = true;
462 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
463 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
464 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
465}
466
467TEST(ClangMove, AddDependentOldHeader) {
468 const char TestHeader[] = "class A {};\n"
469 "class B {};\n";
470 const char TestCode[] = "#include \"foo.h\"\n";
471 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
472 "#define NEW_FOO_H\n"
473 "\n"
474 "#include \"foo.h\"\n"
475 "\n"
476 "class B {};\n"
477 "\n"
478 "#endif // NEW_FOO_H\n";
479 const char ExpectedOldHeader[] = "class A {};\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000480 move::MoveDefinitionSpec Spec;
Haojian Wu48ac3042016-11-23 10:04:19 +0000481 Spec.Names.push_back("B");
482 Spec.OldHeader = "foo.h";
483 Spec.OldCC = "foo.cc";
484 Spec.NewHeader = "new_foo.h";
485 Spec.NewCC = "new_foo.cc";
486 Spec.NewDependOnOld = true;
487 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
488 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
489 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
490}
491
Haojian Wub15c8da2016-11-24 10:17:17 +0000492TEST(ClangMove, DumpDecls) {
493 const char TestHeader[] = "template <typename T>\n"
494 "class A {\n"
495 " public:\n"
496 " void f();\n"
497 " template <typename U> void h();\n"
498 " static int b;\n"
499 "};\n"
500 "\n"
501 "template <typename T> void A<T>::f() {}\n"
502 "\n"
503 "template <typename T>\n"
504 "template <typename U>\n"
505 "void A<T>::h() {}\n"
506 "\n"
507 "template <typename T> int A<T>::b = 2;\n"
508 "\n"
509 "template <> class A<int> {};\n"
510 "\n"
511 "class B {};\n"
512 "\n"
513 "namespace a {\n"
514 "class Move1 {};\n"
515 "void f1() {}\n"
516 "void f2();\n"
517 "} // namespace a\n"
518 "\n"
519 "namespace a {\n"
520 "namespace b {\n"
521 "class Move1 { public : void f(); };\n"
522 "void f() {}\n"
523 "} // namespace b\n"
524 "} // namespace a\n";
525 const char TestCode[] = "#include \"foo.h\"\n";
526 move::MoveDefinitionSpec Spec;
527 Spec.Names.push_back("B");
528 Spec.OldHeader = "foo.h";
529 Spec.OldCC = "foo.cc";
530 Spec.NewHeader = "new_foo.h";
531 Spec.NewCC = "new_foo.cc";
532 DeclarationReporter Reporter;
533 std::vector<DeclarationReporter::DeclarationPair> ExpectedDeclarations = {
534 {"A", "Class"}, {"B", "Class"}, {"a::Move1", "Class"},
535 {"a::f1", "Function"}, {"a::f2", "Function"}, {"a::b::Move1", "Class"},
536 {"a::b::f", "Function"}};
537 runClangMoveOnCode(Spec, TestHeader, TestCode, &Reporter);
538 const auto& Results = Reporter.getDeclarationList();
539 auto ActualDeclIter = Results.begin();
540 auto ExpectedDeclIter = ExpectedDeclarations.begin();
NAKAMURA Takumi5843abc2016-11-28 14:27:37 +0000541 while (ActualDeclIter != Results.end() &&
542 ExpectedDeclIter != ExpectedDeclarations.end()) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000543 EXPECT_EQ(*ActualDeclIter, *ExpectedDeclIter);
544 ++ActualDeclIter;
545 ++ExpectedDeclIter;
546 }
547 ASSERT_TRUE(ActualDeclIter == Results.end());
548 ASSERT_TRUE(ExpectedDeclIter == ExpectedDeclarations.end());
549}
550
Haojian Wu357ef992016-09-21 13:18:19 +0000551} // namespace
552} // namespce move
553} // namespace clang