blob: 84546696da7560edf3911ad8107f11db2e5c462f [file] [log] [blame]
Benjamin Kramer6b236262016-04-20 12:43:43 +00001//===-- IncludeFixerTest.cpp - Include fixer 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
Benjamin Kramera3d82332016-05-13 09:27:54 +000010#include "InMemorySymbolIndex.h"
Benjamin Kramer6b236262016-04-20 12:43:43 +000011#include "IncludeFixer.h"
Benjamin Kramera3d82332016-05-13 09:27:54 +000012#include "SymbolIndexManager.h"
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000013#include "unittests/Tooling/RewriterTestContext.h"
Benjamin Kramer6b236262016-04-20 12:43:43 +000014#include "clang/Tooling/Tooling.h"
15#include "gtest/gtest.h"
Benjamin Kramer6b236262016-04-20 12:43:43 +000016
17namespace clang {
18namespace include_fixer {
19namespace {
20
Haojian Wu631e5f22016-05-13 15:17:17 +000021using find_all_symbols::SymbolInfo;
Sam McCallb27dc222017-02-28 08:13:15 +000022using find_all_symbols::SymbolAndSignals;
Haojian Wu631e5f22016-05-13 15:17:17 +000023
Benjamin Kramer6b236262016-04-20 12:43:43 +000024static bool runOnCode(tooling::ToolAction *ToolAction, StringRef Code,
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000025 StringRef FileName,
26 const std::vector<std::string> &ExtraArgs) {
Benjamin Kramer6b236262016-04-20 12:43:43 +000027 llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
28 new vfs::InMemoryFileSystem);
29 llvm::IntrusiveRefCntPtr<FileManager> Files(
30 new FileManager(FileSystemOptions(), InMemoryFileSystem));
Benjamin Kramer2ecd0902016-05-18 09:28:45 +000031 // FIXME: Investigate why -fms-compatibility breaks tests.
32 std::vector<std::string> Args = {"include_fixer", "-fsyntax-only",
33 "-fno-ms-compatibility", FileName};
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000034 Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
Benjamin Kramer6b236262016-04-20 12:43:43 +000035 tooling::ToolInvocation Invocation(
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000036 Args, ToolAction, Files.get(),
37 std::make_shared<PCHContainerOperations>());
Benjamin Kramer6b236262016-04-20 12:43:43 +000038
39 InMemoryFileSystem->addFile(FileName, 0,
40 llvm::MemoryBuffer::getMemBuffer(Code));
41
42 InMemoryFileSystem->addFile("foo.h", 0,
43 llvm::MemoryBuffer::getMemBuffer("\n"));
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000044 InMemoryFileSystem->addFile("dir/bar.h", 0,
45 llvm::MemoryBuffer::getMemBuffer("\n"));
46 InMemoryFileSystem->addFile("dir/otherdir/qux.h", 0,
Benjamin Kramer6b236262016-04-20 12:43:43 +000047 llvm::MemoryBuffer::getMemBuffer("\n"));
Haojian Wu9c6cb032016-06-03 11:26:02 +000048 InMemoryFileSystem->addFile("header.h", 0,
49 llvm::MemoryBuffer::getMemBuffer("bar b;"));
Benjamin Kramer6b236262016-04-20 12:43:43 +000050 return Invocation.run();
51}
52
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000053static std::string runIncludeFixer(
54 StringRef Code,
55 const std::vector<std::string> &ExtraArgs = std::vector<std::string>()) {
Sam McCallb27dc222017-02-28 08:13:15 +000056 std::vector<SymbolAndSignals> Symbols = {
Sam McCall573050e2017-03-09 10:47:44 +000057 {SymbolInfo("string", SymbolInfo::SymbolKind::Class, "<string>",
Sam McCallb27dc222017-02-28 08:13:15 +000058 {{SymbolInfo::ContextType::Namespace, "std"}}),
59 SymbolInfo::Signals{}},
Sam McCall573050e2017-03-09 10:47:44 +000060 {SymbolInfo("sting", SymbolInfo::SymbolKind::Class, "\"sting\"",
Sam McCallb27dc222017-02-28 08:13:15 +000061 {{SymbolInfo::ContextType::Namespace, "std"}}),
62 SymbolInfo::Signals{}},
63 {SymbolInfo("foo", SymbolInfo::SymbolKind::Class,
Sam McCall573050e2017-03-09 10:47:44 +000064 "\"dir/otherdir/qux.h\"",
Sam McCallb27dc222017-02-28 08:13:15 +000065 {{SymbolInfo::ContextType::Namespace, "b"},
66 {SymbolInfo::ContextType::Namespace, "a"}}),
67 SymbolInfo::Signals{}},
Sam McCall573050e2017-03-09 10:47:44 +000068 {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar.h\"",
Sam McCallb27dc222017-02-28 08:13:15 +000069 {{SymbolInfo::ContextType::Namespace, "b"},
70 {SymbolInfo::ContextType::Namespace, "a"}}),
71 SymbolInfo::Signals{}},
Sam McCall573050e2017-03-09 10:47:44 +000072 {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar2.h\"",
Sam McCallb27dc222017-02-28 08:13:15 +000073 {{SymbolInfo::ContextType::Namespace, "c"},
74 {SymbolInfo::ContextType::Namespace, "a"}}),
75 SymbolInfo::Signals{}},
Sam McCall573050e2017-03-09 10:47:44 +000076 {SymbolInfo("Green", SymbolInfo::SymbolKind::Class, "\"color.h\"",
Sam McCallb27dc222017-02-28 08:13:15 +000077 {{SymbolInfo::ContextType::EnumDecl, "Color"},
78 {SymbolInfo::ContextType::Namespace, "b"},
79 {SymbolInfo::ContextType::Namespace, "a"}}),
80 SymbolInfo::Signals{}},
Sam McCall573050e2017-03-09 10:47:44 +000081 {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"",
Sam McCallb27dc222017-02-28 08:13:15 +000082 {{SymbolInfo::ContextType::Namespace, "__a"},
83 {SymbolInfo::ContextType::Namespace, "a"}}),
84 SymbolInfo::Signals{/*Seen=*/2, 0}},
Sam McCall573050e2017-03-09 10:47:44 +000085 {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"",
Sam McCallb27dc222017-02-28 08:13:15 +000086 {{SymbolInfo::ContextType::Namespace, "a"}}),
87 SymbolInfo::Signals{/*Seen=*/2, 0}},
Sam McCall573050e2017-03-09 10:47:44 +000088 {SymbolInfo("StrCat", SymbolInfo::SymbolKind::Class, "\"strcat.h\"",
Sam McCallb27dc222017-02-28 08:13:15 +000089 {{SymbolInfo::ContextType::Namespace, "str"}}),
90 SymbolInfo::Signals{}},
Sam McCall573050e2017-03-09 10:47:44 +000091 {SymbolInfo("str", SymbolInfo::SymbolKind::Class, "\"str.h\"", {}),
Sam McCallb27dc222017-02-28 08:13:15 +000092 SymbolInfo::Signals{}},
Sam McCall573050e2017-03-09 10:47:44 +000093 {SymbolInfo("foo2", SymbolInfo::SymbolKind::Class, "\"foo2.h\"", {}),
Sam McCallb27dc222017-02-28 08:13:15 +000094 SymbolInfo::Signals{}},
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000095 };
Sam McCallb27dc222017-02-28 08:13:15 +000096 auto SymbolIndexMgr = llvm::make_unique<SymbolIndexManager>();
97 SymbolIndexMgr->addSymbolIndex(
98 [=]() { return llvm::make_unique<InMemorySymbolIndex>(Symbols); });
Eric Liu692aca62016-05-04 08:22:35 +000099
Haojian Wuc99f7282016-08-09 08:26:19 +0000100 std::vector<IncludeFixerContext> FixerContexts;
101 IncludeFixerActionFactory Factory(*SymbolIndexMgr, FixerContexts, "llvm");
Haojian Wu627ca962016-07-08 09:10:29 +0000102 std::string FakeFileName = "input.cc";
103 runOnCode(&Factory, Code, FakeFileName, ExtraArgs);
Haojian Wuc99f7282016-08-09 08:26:19 +0000104 assert(FixerContexts.size() == 1);
105 if (FixerContexts.front().getHeaderInfos().empty())
Eric Liuf83187d2016-05-31 13:52:59 +0000106 return Code;
Sam McCallb27dc222017-02-28 08:13:15 +0000107 auto Replaces = createIncludeFixerReplacements(Code, FixerContexts.front());
Eric Liua452db42016-07-11 13:53:21 +0000108 EXPECT_TRUE(static_cast<bool>(Replaces))
109 << llvm::toString(Replaces.takeError()) << "\n";
110 if (!Replaces)
111 return "";
Sam McCallb27dc222017-02-28 08:13:15 +0000112 RewriterTestContext Context;
113 FileID ID = Context.createInMemoryFile(FakeFileName, Code);
114 tooling::applyAllReplacements(*Replaces, Context.Rewrite);
Benjamin Kramer6b236262016-04-20 12:43:43 +0000115 return Context.getRewrittenText(ID);
116}
117
118TEST(IncludeFixer, Typo) {
Eric Liu516f18e2016-05-31 14:48:45 +0000119 EXPECT_EQ("#include <string>\nstd::string foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000120 runIncludeFixer("std::string foo;\n"));
121
Eric Liu4bf67af2016-12-02 11:23:07 +0000122 EXPECT_EQ("// comment\n#include \"foo.h\"\n#include <string>\n"
123 "std::string foo;\n#include \"dir/bar.h\"\n",
124 runIncludeFixer("// comment\n#include \"foo.h\"\nstd::string foo;\n"
125 "#include \"dir/bar.h\"\n"));
Benjamin Kramer6b236262016-04-20 12:43:43 +0000126
Eric Liu702cfd12016-05-19 08:21:09 +0000127 EXPECT_EQ("#include \"foo.h\"\n#include <string>\nstd::string foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000128 runIncludeFixer("#include \"foo.h\"\nstd::string foo;\n"));
129
130 EXPECT_EQ(
Eric Liu702cfd12016-05-19 08:21:09 +0000131 "#include \"foo.h\"\n#include <string>\nstd::string::size_type foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000132 runIncludeFixer("#include \"foo.h\"\nstd::string::size_type foo;\n"));
133
Haojian Wu627ca962016-07-08 09:10:29 +0000134 EXPECT_EQ("#include <string>\nstd::string foo;\n",
Eric Liu692aca62016-05-04 08:22:35 +0000135 runIncludeFixer("string foo;\n"));
Benjamin Kramer9b15b6f2016-05-19 12:41:56 +0000136
Benjamin Kramer9b15b6f2016-05-19 12:41:56 +0000137 // Should not match std::string.
138 EXPECT_EQ("::string foo;\n", runIncludeFixer("::string foo;\n"));
Benjamin Kramer6b236262016-04-20 12:43:43 +0000139}
140
141TEST(IncludeFixer, IncompleteType) {
142 EXPECT_EQ(
Eric Liu702cfd12016-05-19 08:21:09 +0000143 "#include \"foo.h\"\n#include <string>\n"
Haojian Wu627ca962016-07-08 09:10:29 +0000144 "namespace std {\nclass string;\n}\nstd::string foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000145 runIncludeFixer("#include \"foo.h\"\n"
146 "namespace std {\nclass string;\n}\nstring foo;\n"));
Benjamin Kramerbc805ae2016-12-16 16:09:06 +0000147
148 EXPECT_EQ("#include <string>\n"
149 "class string;\ntypedef string foo;\nfoo f;\n",
150 runIncludeFixer("class string;\ntypedef string foo;\nfoo f;\n"));
Benjamin Kramer6b236262016-04-20 12:43:43 +0000151}
152
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000153TEST(IncludeFixer, MinimizeInclude) {
154 std::vector<std::string> IncludePath = {"-Idir/"};
Eric Liu516f18e2016-05-31 14:48:45 +0000155 EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000156 runIncludeFixer("a::b::foo bar;\n", IncludePath));
157
158 IncludePath = {"-isystemdir"};
Eric Liu516f18e2016-05-31 14:48:45 +0000159 EXPECT_EQ("#include <otherdir/qux.h>\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000160 runIncludeFixer("a::b::foo bar;\n", IncludePath));
161
162 IncludePath = {"-iquotedir"};
Eric Liu516f18e2016-05-31 14:48:45 +0000163 EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000164 runIncludeFixer("a::b::foo bar;\n", IncludePath));
165
166 IncludePath = {"-Idir", "-Idir/otherdir"};
Eric Liu516f18e2016-05-31 14:48:45 +0000167 EXPECT_EQ("#include \"qux.h\"\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000168 runIncludeFixer("a::b::foo bar;\n", IncludePath));
169}
170
Benjamin Kramerad935002016-05-10 08:25:31 +0000171TEST(IncludeFixer, NestedName) {
Eric Liu516f18e2016-05-31 14:48:45 +0000172 EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
Benjamin Krameraf34e062016-05-17 12:35:18 +0000173 "int x = a::b::foo(0);\n",
Benjamin Kramer04666a22016-05-19 11:39:56 +0000174 runIncludeFixer("int x = a::b::foo(0);\n"));
Benjamin Krameraf34e062016-05-17 12:35:18 +0000175
176 // FIXME: Handle simple macros.
177 EXPECT_EQ("#define FOO a::b::foo\nint x = FOO;\n",
178 runIncludeFixer("#define FOO a::b::foo\nint x = FOO;\n"));
179 EXPECT_EQ("#define FOO(x) a::##x\nint x = FOO(b::foo);\n",
180 runIncludeFixer("#define FOO(x) a::##x\nint x = FOO(b::foo);\n"));
181
Eric Liu516f18e2016-05-31 14:48:45 +0000182 // The empty namespace is cleaned up by clang-format after include-fixer
183 // finishes.
184 EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
185 "\nint a = a::b::foo(0);\n",
Benjamin Kramer04666a22016-05-19 11:39:56 +0000186 runIncludeFixer("namespace a {}\nint a = a::b::foo(0);\n"));
Benjamin Kramerad935002016-05-10 08:25:31 +0000187}
188
Benjamin Kramerc3459a52016-05-10 08:25:28 +0000189TEST(IncludeFixer, MultipleMissingSymbols) {
Eric Liu516f18e2016-05-31 14:48:45 +0000190 EXPECT_EQ("#include <string>\nstd::string bar;\nstd::sting foo;\n",
Benjamin Kramerc3459a52016-05-10 08:25:28 +0000191 runIncludeFixer("std::string bar;\nstd::sting foo;\n"));
192}
193
Haojian Wu57cdcb02016-05-13 15:44:16 +0000194TEST(IncludeFixer, ScopedNamespaceSymbols) {
Eric Liu516f18e2016-05-31 14:48:45 +0000195 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000196 runIncludeFixer("namespace a {\nb::bar b;\n}"));
Eric Liu516f18e2016-05-31 14:48:45 +0000197 EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000198 runIncludeFixer("namespace A {\na::b::bar b;\n}"));
Eric Liu516f18e2016-05-31 14:48:45 +0000199 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nvoid func() { b::bar b; }\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000200 runIncludeFixer("namespace a {\nvoid func() { b::bar b; }\n}"));
Haojian Wu57cdcb02016-05-13 15:44:16 +0000201 EXPECT_EQ("namespace A { c::b::bar b; }\n",
202 runIncludeFixer("namespace A { c::b::bar b; }\n"));
203 // FIXME: The header should not be added here. Remove this after we support
204 // full match.
Haojian Wu627ca962016-07-08 09:10:29 +0000205 EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000206 runIncludeFixer("namespace A {\nb::bar b;\n}"));
Haojian Wuadedac62016-08-02 10:43:10 +0000207
208 // Finds candidates for "str::StrCat".
209 EXPECT_EQ("#include \"strcat.h\"\nnamespace foo2 {\nstr::StrCat b;\n}",
210 runIncludeFixer("namespace foo2 {\nstr::StrCat b;\n}"));
211 // str::StrCat2 doesn't exist.
212 // In these two cases, StrCat2 is a nested class of class str.
213 EXPECT_EQ("#include \"str.h\"\nnamespace foo2 {\nstr::StrCat2 b;\n}",
214 runIncludeFixer("namespace foo2 {\nstr::StrCat2 b;\n}"));
215 EXPECT_EQ("#include \"str.h\"\nnamespace ns {\nstr::StrCat2 b;\n}",
216 runIncludeFixer("namespace ns {\nstr::StrCat2 b;\n}"));
Haojian Wu57cdcb02016-05-13 15:44:16 +0000217}
Haojian Wuff6d1952016-05-18 09:04:43 +0000218
219TEST(IncludeFixer, EnumConstantSymbols) {
Eric Liu516f18e2016-05-31 14:48:45 +0000220 EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
Haojian Wuff6d1952016-05-18 09:04:43 +0000221 runIncludeFixer("int test = a::b::Green;\n"));
222}
223
Haojian Wu9c6cb032016-06-03 11:26:02 +0000224TEST(IncludeFixer, IgnoreSymbolFromHeader) {
225 std::string Code = "#include \"header.h\"";
226 EXPECT_EQ(Code, runIncludeFixer(Code));
227}
228
Eric Liu702cfd12016-05-19 08:21:09 +0000229// FIXME: add test cases for inserting and sorting multiple headers when
230// include-fixer supports multiple headers insertion.
231TEST(IncludeFixer, InsertAndSortSingleHeader) {
232 // Insert one header.
233 std::string Code = "#include \"a.h\"\n"
234 "#include \"foo.h\"\n"
235 "\n"
Haojian Wu62aee522016-07-21 13:47:09 +0000236 "namespace a {\nb::bar b;\n}\n";
Eric Liu702cfd12016-05-19 08:21:09 +0000237 std::string Expected = "#include \"a.h\"\n"
238 "#include \"bar.h\"\n"
239 "#include \"foo.h\"\n"
240 "\n"
Haojian Wu62aee522016-07-21 13:47:09 +0000241 "namespace a {\nb::bar b;\n}\n";
Eric Liu702cfd12016-05-19 08:21:09 +0000242 EXPECT_EQ(Expected, runIncludeFixer(Code));
243}
244
Eric Liua4be83a2016-06-13 19:05:07 +0000245TEST(IncludeFixer, DoNotDeleteMatchedSymbol) {
246 EXPECT_EQ("#include \"Vector.h\"\na::Vector v;",
247 runIncludeFixer("a::Vector v;"));
248}
249
Haojian Wu627ca962016-07-08 09:10:29 +0000250TEST(IncludeFixer, FixNamespaceQualifiers) {
251 EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
252 runIncludeFixer("b::bar b;\n"));
253 EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
254 runIncludeFixer("a::b::bar b;\n"));
255 EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
256 runIncludeFixer("bar b;\n"));
257 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
258 runIncludeFixer("namespace a {\nb::bar b;\n}\n"));
259 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
260 runIncludeFixer("namespace a {\nbar b;\n}\n"));
261 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nnamespace b{\nbar b;\n}\n}\n",
262 runIncludeFixer("namespace a {\nnamespace b{\nbar b;\n}\n}\n"));
263 EXPECT_EQ("c::b::bar b;\n",
264 runIncludeFixer("c::b::bar b;\n"));
Haojian Wu0c05e2e2016-07-14 09:39:12 +0000265 EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar b;\n}\n",
266 runIncludeFixer("namespace d {\nbar b;\n}\n"));
267 EXPECT_EQ("#include \"bar2.h\"\nnamespace c {\na::c::bar b;\n}\n",
Haojian Wu627ca962016-07-08 09:10:29 +0000268 runIncludeFixer("namespace c {\nbar b;\n}\n"));
269
Haojian Wu39a718c2016-07-15 08:12:48 +0000270 // Test common qualifers reduction.
271 EXPECT_EQ(
272 "#include \"bar.h\"\nnamespace a {\nnamespace d {\nb::bar b;\n}\n}\n",
273 runIncludeFixer("namespace a {\nnamespace d {\nbar b;\n}\n}\n"));
274 EXPECT_EQ(
275 "#include \"bar.h\"\nnamespace d {\nnamespace a {\na::b::bar b;\n}\n}\n",
276 runIncludeFixer("namespace d {\nnamespace a {\nbar b;\n}\n}\n"));
277
Haojian Wu627ca962016-07-08 09:10:29 +0000278 // Test nested classes.
Haojian Wu0c05e2e2016-07-14 09:39:12 +0000279 EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar::t b;\n}\n",
280 runIncludeFixer("namespace d {\nbar::t b;\n}\n"));
Haojian Wuadedac62016-08-02 10:43:10 +0000281 EXPECT_EQ("#include \"bar.h\"\nnamespace c {\na::b::bar::t b;\n}\n",
Haojian Wu627ca962016-07-08 09:10:29 +0000282 runIncludeFixer("namespace c {\nbar::t b;\n}\n"));
283 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar::t b;\n}\n",
284 runIncludeFixer("namespace a {\nbar::t b;\n}\n"));
285
Haojian Wu5d9482d2016-07-08 14:28:43 +0000286 EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
287 runIncludeFixer("int test = Green;\n"));
Haojian Wu627ca962016-07-08 09:10:29 +0000288 EXPECT_EQ("#include \"color.h\"\nnamespace d {\nint test = a::b::Green;\n}\n",
289 runIncludeFixer("namespace d {\nint test = Green;\n}\n"));
290 EXPECT_EQ("#include \"color.h\"\nnamespace a {\nint test = b::Green;\n}\n",
291 runIncludeFixer("namespace a {\nint test = Green;\n}\n"));
292
Haojian Wu5d9482d2016-07-08 14:28:43 +0000293 // Test global scope operator.
294 EXPECT_EQ("#include \"bar.h\"\n::a::b::bar b;\n",
295 runIncludeFixer("::a::b::bar b;\n"));
296 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\n::a::b::bar b;\n}\n",
297 runIncludeFixer("namespace a {\n::a::b::bar b;\n}\n"));
Haojian Wu627ca962016-07-08 09:10:29 +0000298}
299
Haojian Wu62aee522016-07-21 13:47:09 +0000300TEST(IncludeFixer, FixNamespaceQualifiersForAllInstances) {
301 const char TestCode[] = R"(
302namespace a {
303bar b;
304int func1() {
305 bar a;
306 bar *p = new bar();
307 return 0;
308}
309} // namespace a
310
311namespace a {
312bar func2() {
313 bar f;
314 return f;
315}
316} // namespace a
317
318// Non-fixed cases:
319void f() {
320 bar b;
321}
322
323namespace a {
324namespace c {
325 bar b;
326} // namespace c
327} // namespace a
328)";
329
330 const char ExpectedCode[] = R"(
331#include "bar.h"
332namespace a {
333b::bar b;
334int func1() {
335 b::bar a;
336 b::bar *p = new b::bar();
337 return 0;
338}
339} // namespace a
340
341namespace a {
342b::bar func2() {
343 b::bar f;
344 return f;
345}
346} // namespace a
347
348// Non-fixed cases:
349void f() {
350 bar b;
351}
352
353namespace a {
354namespace c {
355 bar b;
356} // namespace c
357} // namespace a
358)";
359
360 EXPECT_EQ(ExpectedCode, runIncludeFixer(TestCode));
361}
362
Haojian Wu56446182016-07-26 16:32:42 +0000363TEST(IncludeFixer, DontAddQualifiersForMissingCompleteType) {
364 EXPECT_EQ("#include \"bar.h\"\nclass bar;\nvoid f() {\nbar* b;\nb->f();\n}",
365 runIncludeFixer("class bar;\nvoid f() {\nbar* b;\nb->f();\n}"));
366}
367
Benjamin Kramer6b236262016-04-20 12:43:43 +0000368} // namespace
369} // namespace include_fixer
370} // namespace clang