blob: 45e3f682321f599c2d96a9192327125b3497018a [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
Haojian Wu357ef992016-09-21 13:18:19 +000027const char TestHeader[] = "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000028 "class C1; // test\n"
Haojian Wu29c38f72016-10-21 19:26:43 +000029 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +000030 "namespace b {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000031 "// This is a Foo class\n"
32 "// which is used in\n"
33 "// test.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000034 "class Foo {\n"
35 "public:\n"
36 " void f();\n"
37 "\n"
38 "private:\n"
39 " C1 *c1;\n"
40 " static int b;\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000041 "}; // abc\n"
Haojian Wu357ef992016-09-21 13:18:19 +000042 "\n"
43 "class Foo2 {\n"
44 "public:\n"
45 " int f();\n"
46 "};\n"
47 "} // namespace b\n"
48 "} // namespace a\n";
49
50const char TestCC[] = "#include \"foo.h\"\n"
51 "namespace a {\n"
52 "namespace b {\n"
53 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000054 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000055 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000056 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +000057 "int kConstInt1 = 0;\n"
58 "} // namespace\n"
59 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000060 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +000061 "static int kConstInt2 = 1;\n"
62 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000063 "/** comment4\n"
Krasimir Georgiev8fcdd5a2017-02-16 13:17:38 +000064 " */\n"
Haojian Wu357ef992016-09-21 13:18:19 +000065 "static int help() {\n"
66 " int a = 0;\n"
67 " return a;\n"
68 "}\n"
69 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000070 "// comment5\n"
71 "// comment5\n"
Haojian Wu36265162017-01-03 09:00:51 +000072 "void Foo::f() {\n"
73 " f1();\n"
74 " kConstInt1;\n"
75 " kConstInt2;\n"
76 " help();\n"
77 "}\n"
Haojian Wu357ef992016-09-21 13:18:19 +000078 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000079 "/////////////\n"
80 "// comment //\n"
81 "/////////////\n"
Haojian Wu357ef992016-09-21 13:18:19 +000082 "int Foo::b = 2;\n"
83 "int Foo2::f() {\n"
Haojian Wu36265162017-01-03 09:00:51 +000084 " kConstInt1;\n"
85 " kConstInt2;\n"
86 " help();\n"
Haojian Wu357ef992016-09-21 13:18:19 +000087 " f1();\n"
88 " return 1;\n"
89 "}\n"
90 "} // namespace b\n"
91 "} // namespace a\n";
92
93const char ExpectedTestHeader[] = "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +000094 "class C1; // test\n"
Haojian Wu29c38f72016-10-21 19:26:43 +000095 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +000096 "namespace b {\n"
97 "\n"
98 "class Foo2 {\n"
99 "public:\n"
100 " int f();\n"
101 "};\n"
102 "} // namespace b\n"
103 "} // namespace a\n";
104
105const char ExpectedTestCC[] = "#include \"foo.h\"\n"
106 "namespace a {\n"
107 "namespace b {\n"
108 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000109 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000110 "void f1() {}\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000111 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000112 "int kConstInt1 = 0;\n"
113 "} // namespace\n"
114 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000115 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000116 "static int kConstInt2 = 1;\n"
117 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000118 "/** comment4\n"
Krasimir Georgiev8fcdd5a2017-02-16 13:17:38 +0000119 " */\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000120 "static int help() {\n"
121 " int a = 0;\n"
122 " return a;\n"
123 "}\n"
124 "\n"
125 "int Foo2::f() {\n"
Haojian Wu36265162017-01-03 09:00:51 +0000126 " kConstInt1;\n"
127 " kConstInt2;\n"
128 " help();\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000129 " f1();\n"
130 " return 1;\n"
131 "}\n"
132 "} // namespace b\n"
133 "} // namespace a\n";
134
Haojian Wu220c7552016-10-14 13:01:36 +0000135const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
136 "#define NEW_FOO_H\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000137 "\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000138 "namespace a {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000139 "class C1; // test\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000140 "\n"
Haojian Wu29c38f72016-10-21 19:26:43 +0000141 "template <typename T> class C2;\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000142 "namespace b {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000143 "// This is a Foo class\n"
144 "// which is used in\n"
145 "// test.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000146 "class Foo {\n"
147 "public:\n"
148 " void f();\n"
149 "\n"
150 "private:\n"
151 " C1 *c1;\n"
152 " static int b;\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000153 "}; // abc\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000154 "} // namespace b\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000155 "} // namespace a\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000156 "\n"
Haojian Wu220c7552016-10-14 13:01:36 +0000157 "#endif // NEW_FOO_H\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000158
Haojian Wudaf4cb82016-09-23 13:28:38 +0000159const char ExpectedNewCC[] = "namespace a {\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000160 "namespace b {\n"
161 "namespace {\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000162 "// comment1.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000163 "void f1() {}\n"
Haojian Wu36265162017-01-03 09:00:51 +0000164 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000165 "/// comment2.\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000166 "int kConstInt1 = 0;\n"
167 "} // namespace\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000168 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000169 "/* comment 3*/\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000170 "static int kConstInt2 = 1;\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000171 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000172 "/** comment4\n"
Krasimir Georgiev8fcdd5a2017-02-16 13:17:38 +0000173 " */\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000174 "static int help() {\n"
175 " int a = 0;\n"
176 " return a;\n"
177 "}\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000178 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000179 "// comment5\n"
180 "// comment5\n"
Haojian Wu36265162017-01-03 09:00:51 +0000181 "void Foo::f() {\n"
182 " f1();\n"
183 " kConstInt1;\n"
184 " kConstInt2;\n"
185 " help();\n"
186 "}\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000187 "\n"
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000188 "/////////////\n"
189 "// comment //\n"
190 "/////////////\n"
Haojian Wu357ef992016-09-21 13:18:19 +0000191 "int Foo::b = 2;\n"
192 "} // namespace b\n"
193 "} // namespace a\n";
194
Eric Liudb53a522018-05-18 16:08:18 +0000195#ifdef _WIN32
196const char WorkingDir[] = "C:\\test";
197#else
198const char WorkingDir[] = "/test";
199#endif
200
201const char TestHeaderName[] = "foo.h";
202const char TestCCName[] = "foo.cc";
203
Haojian Wu357ef992016-09-21 13:18:19 +0000204std::map<std::string, std::string>
Haojian Wub15c8da2016-11-24 10:17:17 +0000205runClangMoveOnCode(const move::MoveDefinitionSpec &Spec,
Haojian Wu2930be12016-11-08 19:55:13 +0000206 const char *const Header = TestHeader,
Haojian Wub15c8da2016-11-24 10:17:17 +0000207 const char *const CC = TestCC,
208 DeclarationReporter *const Reporter = nullptr) {
Haojian Wu357ef992016-09-21 13:18:19 +0000209 clang::RewriterTestContext Context;
210
Eric Liudb53a522018-05-18 16:08:18 +0000211 Context.InMemoryFileSystem->setCurrentWorkingDirectory(WorkingDir);
212
Haojian Wu357ef992016-09-21 13:18:19 +0000213 std::map<llvm::StringRef, clang::FileID> FileToFileID;
Haojian Wu357ef992016-09-21 13:18:19 +0000214
Malcolm Parsonse65b1022017-01-13 19:02:50 +0000215 auto CreateFiles = [&Context, &FileToFileID](llvm::StringRef Name,
216 llvm::StringRef Code) {
Haojian Wu357ef992016-09-21 13:18:19 +0000217 if (!Name.empty()) {
Haojian Wu357ef992016-09-21 13:18:19 +0000218 FileToFileID[Name] = Context.createInMemoryFile(Name, Code);
219 }
220 };
221 CreateFiles(Spec.NewCC, "");
222 CreateFiles(Spec.NewHeader, "");
Eric Liudb53a522018-05-18 16:08:18 +0000223 CreateFiles(TestHeaderName, Header);
224 CreateFiles(TestCCName, CC);
Haojian Wu357ef992016-09-21 13:18:19 +0000225
226 std::map<std::string, tooling::Replacements> FileToReplacements;
Eric Liudb53a522018-05-18 16:08:18 +0000227 ClangMoveContext MoveContext = {Spec, FileToReplacements, WorkingDir, "LLVM",
Haojian Wub15c8da2016-11-24 10:17:17 +0000228 Reporter != nullptr};
229
Haojian Wu357ef992016-09-21 13:18:19 +0000230 auto Factory = llvm::make_unique<clang::move::ClangMoveActionFactory>(
Haojian Wub15c8da2016-11-24 10:17:17 +0000231 &MoveContext, Reporter);
Haojian Wu357ef992016-09-21 13:18:19 +0000232
Eric Liudb53a522018-05-18 16:08:18 +0000233 // std::string IncludeArg = Twine("-I" + WorkingDir;
Haojian Wu357ef992016-09-21 13:18:19 +0000234 tooling::runToolOnCodeWithArgs(
Eric Liudb53a522018-05-18 16:08:18 +0000235 Factory->create(), CC, Context.InMemoryFileSystem,
236 {"-std=c++11", "-fparse-all-comments", "-I."}, TestCCName, "clang-move",
237 std::make_shared<PCHContainerOperations>());
Haojian Wu357ef992016-09-21 13:18:19 +0000238 formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");
239 // The Key is file name, value is the new code after moving the class.
240 std::map<std::string, std::string> Results;
241 for (const auto &It : FileToReplacements) {
Simon Marchi83953232018-07-05 14:53:17 +0000242 // The path may come out as "./foo.h", normalize to "foo.h".
243 SmallString<32> FilePath (It.first);
244 llvm::sys::path::remove_dots(FilePath);
245 Results[FilePath.str().str()] = Context.getRewrittenText(FileToFileID[FilePath]);
Haojian Wu357ef992016-09-21 13:18:19 +0000246 }
247 return Results;
248}
249
250TEST(ClangMove, MoveHeaderAndCC) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000251 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000252 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000253 Spec.OldHeader = "foo.h";
254 Spec.OldCC = "foo.cc";
255 Spec.NewHeader = "new_foo.h";
256 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000257 std::string ExpectedHeader = "#include \"" + Spec.NewHeader + "\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000258 auto Results = runClangMoveOnCode(Spec);
259 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
260 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
261 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000262 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000263}
264
265TEST(ClangMove, MoveHeaderOnly) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000266 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000267 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000268 Spec.OldHeader = "foo.h";
269 Spec.NewHeader = "new_foo.h";
270 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000271 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000272 EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);
273 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
274}
275
276TEST(ClangMove, MoveCCOnly) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000277 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000278 Spec.Names = {std::string("a::b::Foo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000279 Spec.OldCC = "foo.cc";
280 Spec.NewCC = "new_foo.cc";
Haojian Wu9abbeaa2016-10-06 08:59:24 +0000281 std::string ExpectedHeader = "#include \"foo.h\"\n\n";
Haojian Wu357ef992016-09-21 13:18:19 +0000282 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000283 EXPECT_EQ(2u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000284 EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);
Haojian Wudaf4cb82016-09-23 13:28:38 +0000285 EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);
Haojian Wu357ef992016-09-21 13:18:19 +0000286}
287
288TEST(ClangMove, MoveNonExistClass) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000289 move::MoveDefinitionSpec Spec;
NAKAMURA Takumi0cfbbae2016-10-17 05:09:58 +0000290 Spec.Names = {std::string("NonExistFoo")};
Haojian Wu357ef992016-09-21 13:18:19 +0000291 Spec.OldHeader = "foo.h";
292 Spec.OldCC = "foo.cc";
293 Spec.NewHeader = "new_foo.h";
294 Spec.NewCC = "new_foo.cc";
295 auto Results = runClangMoveOnCode(Spec);
Haojian Wu62ba4462016-09-21 15:19:04 +0000296 EXPECT_EQ(0u, Results.size());
Haojian Wu357ef992016-09-21 13:18:19 +0000297}
298
Haojian Wufb68ca12018-01-31 12:12:29 +0000299TEST(ClangMove, HeaderIncludeSelf) {
300 move::MoveDefinitionSpec Spec;
301 Spec.Names = {std::string("Foo")};
302 Spec.OldHeader = "foo.h";
303 Spec.OldCC = "foo.cc";
304 Spec.NewHeader = "new_foo.h";
305 Spec.NewCC = "new_foo.cc";
306
307 const char TestHeader[] = "#ifndef FOO_H\n"
308 "#define FOO_H\n"
309 "#include \"foo.h\"\n"
310 "class Foo {};\n"
311 "#endif\n";
312 const char TestCode[] = "#include \"foo.h\"";
313 const char ExpectedNewHeader[] = "#ifndef FOO_H\n"
314 "#define FOO_H\n"
315 "#include \"new_foo.h\"\n"
316 "class Foo {};\n"
317 "#endif\n";
318 const char ExpectedNewCC[] = "#include \"new_foo.h\"";
319 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
320 EXPECT_EQ("", Results[Spec.OldHeader]);
321 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
322 EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);
323}
324
Haojian Wu2930be12016-11-08 19:55:13 +0000325TEST(ClangMove, MoveAll) {
326 std::vector<std::string> TestHeaders = {
327 "class A {\npublic:\n int f();\n};",
328 // forward declaration.
329 "class B;\nclass A {\npublic:\n int f();\n};",
330 // template forward declaration.
331 "template <typename T> class B;\nclass A {\npublic:\n int f();\n};",
332 "namespace a {}\nclass A {\npublic:\n int f();\n};",
333 "namespace a {}\nusing namespace a;\nclass A {\npublic:\n int f();\n};",
334 };
335 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
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(Header, Results[Spec.NewHeader]);
345 EXPECT_EQ("", Results[Spec.OldHeader]);
346 EXPECT_EQ("", Results[Spec.OldCC]);
347 }
348}
349
350TEST(ClangMove, MoveAllMultipleClasses) {
Haojian Wub15c8da2016-11-24 10:17:17 +0000351 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000352 std::vector<std::string> TestHeaders = {
353 "class C;\nclass A {\npublic:\n int f();\n};\nclass B {};",
354 "class C;\nclass B;\nclass A {\npublic:\n int f();\n};\nclass B {};",
355 };
356 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
357 Spec.Names = {std::string("A"), std::string("B")};
358 Spec.OldHeader = "foo.h";
359 Spec.OldCC = "foo.cc";
360 Spec.NewHeader = "new_foo.h";
361 Spec.NewCC = "new_foo.cc";
362 for (const auto& Header : TestHeaders) {
363 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
364 EXPECT_EQ(Header, Results[Spec.NewHeader]);
365 EXPECT_EQ("", Results[Spec.OldHeader]);
366 EXPECT_EQ("", Results[Spec.OldCC]);
367 }
368}
369
370TEST(ClangMove, DontMoveAll) {
371 const char ExpectedHeader[] = "#ifndef NEW_FOO_H\n"
372 "#define NEW_FOO_H\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000373 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000374 "class A {\npublic:\n int f();\n};\n"
Haojian Wu53315a72016-11-15 09:06:59 +0000375 "\n"
Haojian Wu2930be12016-11-08 19:55:13 +0000376 "#endif // NEW_FOO_H\n";
377 const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";
378 std::vector<std::string> TestHeaders = {
Haojian Wu53315a72016-11-15 09:06:59 +0000379 "class B {};\nclass A {\npublic:\n int f();\n};\n",
380 "void f() {};\nclass A {\npublic:\n int f();\n};\n",
Haojian Wu2930be12016-11-08 19:55:13 +0000381 };
Haojian Wub15c8da2016-11-24 10:17:17 +0000382 move::MoveDefinitionSpec Spec;
Haojian Wu2930be12016-11-08 19:55:13 +0000383 Spec.Names.push_back("A");
384 Spec.OldHeader = "foo.h";
385 Spec.OldCC = "foo.cc";
386 Spec.NewHeader = "new_foo.h";
387 Spec.NewCC = "new_foo.cc";
388 for (const auto& Header : TestHeaders) {
389 auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);
390 EXPECT_EQ(ExpectedHeader, Results[Spec.NewHeader]);
391 // The expected old header should not contain class A definition.
Haojian Wu53315a72016-11-15 09:06:59 +0000392 std::string ExpectedOldHeader = Header.substr(0, Header.size() - 32);
Haojian Wu2930be12016-11-08 19:55:13 +0000393 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
394 }
395}
396
Haojian Wud4786342018-02-09 15:57:30 +0000397TEST(ClangMove, IgnoreMacroSymbolsAndMoveAll) {
398 const char TestCode[] = "#include \"foo.h\"";
399 std::vector<std::string> TestHeaders = {
400 "#define DEFINE_Foo int Foo = 1;\nDEFINE_Foo;\nclass Bar {};\n",
401 "#define DEFINE(x) int var_##x = 1;\nDEFINE(foo);\nclass Bar {};\n",
402 };
403 move::MoveDefinitionSpec Spec;
404 Spec.Names.push_back("Bar");
405 Spec.OldHeader = "foo.h";
406 Spec.OldCC = "foo.cc";
407 Spec.NewHeader = "new_foo.h";
408 Spec.NewCC = "new_foo.cc";
409
410 for (const auto& Header : TestHeaders) {
411 auto Results = runClangMoveOnCode(Spec, Header.c_str(), TestCode);
412 EXPECT_EQ("", Results[Spec.OldHeader]);
413 EXPECT_EQ(Header, Results[Spec.NewHeader]);
414 }
415}
416
Haojian Wu24675392016-11-14 14:46:48 +0000417TEST(ClangMove, MacroInFunction) {
418 const char TestHeader[] = "#define INT int\n"
419 "class A {\npublic:\n int f();\n};\n"
420 "class B {};\n";
421 const char TestCode[] = "#include \"foo.h\"\n"
422 "INT A::f() { return 0; }\n";
423 const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
424 "INT A::f() { return 0; }\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000425 move::MoveDefinitionSpec Spec;
Haojian Wu24675392016-11-14 14:46:48 +0000426 Spec.Names.push_back("A");
427 Spec.OldHeader = "foo.h";
428 Spec.OldCC = "foo.cc";
429 Spec.NewHeader = "new_foo.h";
430 Spec.NewCC = "new_foo.cc";
431 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
432 EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
433}
434
Haojian Wudc4edba2016-12-13 15:35:47 +0000435TEST(ClangMove, DefinitionInMacro) {
436 const char TestHeader[] = "#define DEF(CLASS) void CLASS##_::f() {}\n"
Haojian Wucee20592018-02-12 12:26:12 +0000437 "#define DEF2(CLASS, ...) void CLASS##_::f2() {}\n"
438 "class A_ {\nvoid f();\nvoid f2();\n};\n"
Haojian Wudc4edba2016-12-13 15:35:47 +0000439 "class B {};\n";
440 const char TestCode[] = "#include \"foo.h\"\n"
Haojian Wucee20592018-02-12 12:26:12 +0000441 "DEF(A)\n\n"
442 "DEF2(A,\n"
443 " 123)\n";
Haojian Wudc4edba2016-12-13 15:35:47 +0000444 const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"
Haojian Wucee20592018-02-12 12:26:12 +0000445 "DEF(A)\n\n"
446 "DEF2(A, 123)\n";
Haojian Wudc4edba2016-12-13 15:35:47 +0000447 move::MoveDefinitionSpec Spec;
448 Spec.Names.push_back("A_");
449 Spec.OldHeader = "foo.h";
450 Spec.OldCC = "foo.cc";
451 Spec.NewHeader = "new_foo.h";
452 Spec.NewCC = "new_foo.cc";
453 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
454 EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);
455}
456
Haojian Wu53315a72016-11-15 09:06:59 +0000457TEST(ClangMove, WellFormattedCode) {
458 const std::string CommonHeader =
459 "namespace a {\n"
460 "namespace b {\n"
461 "namespace c {\n"
462 "class C;\n"
463 "\n"
464 "class A {\npublic:\n void f();\n void f2();\n};\n"
465 "} // namespace c\n"
466 "} // namespace b\n"
467 "\n"
468 "namespace d {\n"
469 "namespace e {\n"
470 "class B {\npublic:\n void f();\n};\n"
471 "} // namespace e\n"
472 "} // namespace d\n"
473 "} // namespace a\n";
474 const std::string CommonCode = "\n"
475 "namespace a {\n"
476 "namespace b {\n"
477 "namespace c {\n"
478 "void A::f() {}\n"
479 "\n"
480 "void A::f2() {}\n"
481 "} // namespace c\n"
482 "} // namespace b\n"
483 "\n"
484 "namespace d {\n"
485 "namespace e {\n"
486 "void B::f() {}\n"
487 "} // namespace e\n"
488 "} // namespace d\n"
489 "} // namespace a\n";
490 // Add dummy class to prevent behavior of moving all declarations from header.
491 const std::string TestHeader = CommonHeader + "class D {};\n";
492 const std::string TestCode = "#include \"foo.h\"\n" + CommonCode;
493 const std::string ExpectedNewHeader = "#ifndef NEW_FOO_H\n"
494 "#define NEW_FOO_H\n"
495 "\n" +
496 CommonHeader +
497 "\n"
498 "#endif // NEW_FOO_H\n";
499 const std::string ExpectedNewCC = "#include \"new_foo.h\"\n" + CommonCode;
Haojian Wub15c8da2016-11-24 10:17:17 +0000500 move::MoveDefinitionSpec Spec;
Haojian Wu53315a72016-11-15 09:06:59 +0000501 Spec.Names.push_back("a::b::c::A");
502 Spec.Names.push_back("a::d::e::B");
503 Spec.OldHeader = "foo.h";
504 Spec.OldCC = "foo.cc";
505 Spec.NewHeader = "new_foo.h";
506 Spec.NewCC = "new_foo.cc";
507 auto Results = runClangMoveOnCode(Spec, TestHeader.c_str(), TestCode.c_str());
508 EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);
509 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
510}
511
Haojian Wu48ac3042016-11-23 10:04:19 +0000512TEST(ClangMove, AddDependentNewHeader) {
513 const char TestHeader[] = "class A {};\n"
514 "class B {};\n";
515 const char TestCode[] = "#include \"foo.h\"\n";
516 const char ExpectedOldHeader[] = "#include \"new_foo.h\"\nclass B {};\n";
517 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
518 "#define NEW_FOO_H\n"
519 "\n"
520 "class A {};\n"
521 "\n"
522 "#endif // NEW_FOO_H\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000523 move::MoveDefinitionSpec Spec;
Haojian Wu48ac3042016-11-23 10:04:19 +0000524 Spec.Names.push_back("A");
525 Spec.OldHeader = "foo.h";
526 Spec.OldCC = "foo.cc";
527 Spec.NewHeader = "new_foo.h";
528 Spec.NewCC = "new_foo.cc";
529 Spec.OldDependOnNew = true;
530 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
531 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
532 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
533}
534
535TEST(ClangMove, AddDependentOldHeader) {
536 const char TestHeader[] = "class A {};\n"
537 "class B {};\n";
538 const char TestCode[] = "#include \"foo.h\"\n";
539 const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"
540 "#define NEW_FOO_H\n"
541 "\n"
542 "#include \"foo.h\"\n"
543 "\n"
544 "class B {};\n"
545 "\n"
546 "#endif // NEW_FOO_H\n";
547 const char ExpectedOldHeader[] = "class A {};\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000548 move::MoveDefinitionSpec Spec;
Haojian Wu48ac3042016-11-23 10:04:19 +0000549 Spec.Names.push_back("B");
550 Spec.OldHeader = "foo.h";
551 Spec.OldCC = "foo.cc";
552 Spec.NewHeader = "new_foo.h";
553 Spec.NewCC = "new_foo.cc";
554 Spec.NewDependOnOld = true;
555 auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);
556 EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);
557 EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);
558}
559
Haojian Wub15c8da2016-11-24 10:17:17 +0000560TEST(ClangMove, DumpDecls) {
561 const char TestHeader[] = "template <typename T>\n"
562 "class A {\n"
563 " public:\n"
564 " void f();\n"
565 " template <typename U> void h();\n"
566 " static int b;\n"
567 "};\n"
568 "\n"
569 "template <typename T> void A<T>::f() {}\n"
570 "\n"
571 "template <typename T>\n"
572 "template <typename U>\n"
573 "void A<T>::h() {}\n"
574 "\n"
575 "template <typename T> int A<T>::b = 2;\n"
576 "\n"
577 "template <> class A<int> {};\n"
578 "\n"
579 "class B {};\n"
580 "\n"
581 "namespace a {\n"
582 "class Move1 {};\n"
583 "void f1() {}\n"
584 "void f2();\n"
585 "} // namespace a\n"
586 "\n"
Haojian Wu03c89632017-05-02 12:15:11 +0000587 "class ForwardClass;\n"
Haojian Wub15c8da2016-11-24 10:17:17 +0000588 "namespace a {\n"
589 "namespace b {\n"
590 "class Move1 { public : void f(); };\n"
591 "void f() {}\n"
Haojian Wu85867722017-01-16 09:34:07 +0000592 "enum E1 { Green };\n"
593 "enum class E2 { Red };\n"
594 "typedef int Int2;\n"
Haojian Wu03c89632017-05-02 12:15:11 +0000595 "typedef A<double> A_d;"
Haojian Wu85867722017-01-16 09:34:07 +0000596 "using Int = int;\n"
Haojian Wu4a920502017-02-27 13:19:13 +0000597 "extern int kGlobalInt;\n"
598 "extern const char* const kGlobalStr;\n"
Haojian Wub15c8da2016-11-24 10:17:17 +0000599 "} // namespace b\n"
Haojian Wud4786342018-02-09 15:57:30 +0000600 "} // namespace a\n"
601 "#define DEFINE_FOO class Foo {};\n"
602 "DEFINE_FOO\n";
Haojian Wub15c8da2016-11-24 10:17:17 +0000603 const char TestCode[] = "#include \"foo.h\"\n";
604 move::MoveDefinitionSpec Spec;
605 Spec.Names.push_back("B");
606 Spec.OldHeader = "foo.h";
607 Spec.OldCC = "foo.cc";
608 Spec.NewHeader = "new_foo.h";
609 Spec.NewCC = "new_foo.cc";
610 DeclarationReporter Reporter;
Haojian Wu85867722017-01-16 09:34:07 +0000611 std::set<DeclarationReporter::DeclarationPair> ExpectedDeclarations = {
Haojian Wu03c89632017-05-02 12:15:11 +0000612 {"A", "Class"},
613 {"B", "Class"},
614 {"a::Move1", "Class"},
615 {"a::f1", "Function"},
616 {"a::f2", "Function"},
617 {"a::b::Move1", "Class"},
618 {"a::b::f", "Function"},
619 {"a::b::E1", "Enum"},
620 {"a::b::E2", "Enum"},
621 {"a::b::Int2", "TypeAlias"},
622 {"a::b::A_d", "TypeAlias"},
623 {"a::b::Int", "TypeAlias"},
624 {"a::b::kGlobalInt", "Variable"},
625 {"a::b::kGlobalStr", "Variable"}};
Haojian Wub15c8da2016-11-24 10:17:17 +0000626 runClangMoveOnCode(Spec, TestHeader, TestCode, &Reporter);
Haojian Wu85867722017-01-16 09:34:07 +0000627 std::set<DeclarationReporter::DeclarationPair> Results;
628 for (const auto& DelPair : Reporter.getDeclarationList())
629 Results.insert(DelPair);
630 EXPECT_EQ(ExpectedDeclarations, Results);
Haojian Wub15c8da2016-11-24 10:17:17 +0000631}
632
Haojian Wu357ef992016-09-21 13:18:19 +0000633} // namespace
634} // namespce move
635} // namespace clang