blob: 47e7d0417034de5e590852ac5b5901b92aed5c87 [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;
22
Benjamin Kramer6b236262016-04-20 12:43:43 +000023static bool runOnCode(tooling::ToolAction *ToolAction, StringRef Code,
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000024 StringRef FileName,
25 const std::vector<std::string> &ExtraArgs) {
Benjamin Kramer6b236262016-04-20 12:43:43 +000026 llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
27 new vfs::InMemoryFileSystem);
28 llvm::IntrusiveRefCntPtr<FileManager> Files(
29 new FileManager(FileSystemOptions(), InMemoryFileSystem));
Benjamin Kramer2ecd0902016-05-18 09:28:45 +000030 // FIXME: Investigate why -fms-compatibility breaks tests.
31 std::vector<std::string> Args = {"include_fixer", "-fsyntax-only",
32 "-fno-ms-compatibility", FileName};
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000033 Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
Benjamin Kramer6b236262016-04-20 12:43:43 +000034 tooling::ToolInvocation Invocation(
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000035 Args, ToolAction, Files.get(),
36 std::make_shared<PCHContainerOperations>());
Benjamin Kramer6b236262016-04-20 12:43:43 +000037
38 InMemoryFileSystem->addFile(FileName, 0,
39 llvm::MemoryBuffer::getMemBuffer(Code));
40
41 InMemoryFileSystem->addFile("foo.h", 0,
42 llvm::MemoryBuffer::getMemBuffer("\n"));
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000043 InMemoryFileSystem->addFile("dir/bar.h", 0,
44 llvm::MemoryBuffer::getMemBuffer("\n"));
45 InMemoryFileSystem->addFile("dir/otherdir/qux.h", 0,
Benjamin Kramer6b236262016-04-20 12:43:43 +000046 llvm::MemoryBuffer::getMemBuffer("\n"));
Haojian Wu9c6cb032016-06-03 11:26:02 +000047 InMemoryFileSystem->addFile("header.h", 0,
48 llvm::MemoryBuffer::getMemBuffer("bar b;"));
Benjamin Kramer6b236262016-04-20 12:43:43 +000049 return Invocation.run();
50}
51
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000052static std::string runIncludeFixer(
53 StringRef Code,
54 const std::vector<std::string> &ExtraArgs = std::vector<std::string>()) {
Haojian Wu631e5f22016-05-13 15:17:17 +000055 std::vector<SymbolInfo> Symbols = {
56 SymbolInfo("string", SymbolInfo::SymbolKind::Class, "<string>", 1,
57 {{SymbolInfo::ContextType::Namespace, "std"}}),
58 SymbolInfo("sting", SymbolInfo::SymbolKind::Class, "\"sting\"", 1,
59 {{SymbolInfo::ContextType::Namespace, "std"}}),
Haojian Wu631e5f22016-05-13 15:17:17 +000060 SymbolInfo("foo", SymbolInfo::SymbolKind::Class, "\"dir/otherdir/qux.h\"",
61 1, {{SymbolInfo::ContextType::Namespace, "b"},
62 {SymbolInfo::ContextType::Namespace, "a"}}),
Eric Liua4be83a2016-06-13 19:05:07 +000063 SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar.h\"", 1,
64 {{SymbolInfo::ContextType::Namespace, "b"},
65 {SymbolInfo::ContextType::Namespace, "a"}}),
Haojian Wu0c05e2e2016-07-14 09:39:12 +000066 SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar2.h\"", 1,
67 {{SymbolInfo::ContextType::Namespace, "c"},
68 {SymbolInfo::ContextType::Namespace, "a"}}),
Eric Liua4be83a2016-06-13 19:05:07 +000069 SymbolInfo("Green", SymbolInfo::SymbolKind::Class, "\"color.h\"", 1,
70 {{SymbolInfo::ContextType::EnumDecl, "Color"},
71 {SymbolInfo::ContextType::Namespace, "b"},
72 {SymbolInfo::ContextType::Namespace, "a"}}),
73 SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"", 1,
74 {{SymbolInfo::ContextType::Namespace, "__a"},
75 {SymbolInfo::ContextType::Namespace, "a"}},
76 /*num_occurrences=*/2),
77 SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"", 2,
78 {{SymbolInfo::ContextType::Namespace, "a"}},
79 /*num_occurrences=*/1),
Haojian Wuadedac62016-08-02 10:43:10 +000080 SymbolInfo("StrCat", SymbolInfo::SymbolKind::Class, "\"strcat.h\"",
81 1, {{SymbolInfo::ContextType::Namespace, "str"}}),
82 SymbolInfo("str", SymbolInfo::SymbolKind::Class, "\"str.h\"",
83 1, {}),
84 SymbolInfo("foo2", SymbolInfo::SymbolKind::Class, "\"foo2.h\"",
85 1, {}),
Benjamin Kramer3a45fab2016-04-28 11:21:29 +000086 };
Benjamin Kramera3d82332016-05-13 09:27:54 +000087 auto SymbolIndexMgr = llvm::make_unique<include_fixer::SymbolIndexManager>();
88 SymbolIndexMgr->addSymbolIndex(
Haojian Wu631e5f22016-05-13 15:17:17 +000089 llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols));
Eric Liu692aca62016-05-04 08:22:35 +000090
Haojian Wuc99f7282016-08-09 08:26:19 +000091 std::vector<IncludeFixerContext> FixerContexts;
92 IncludeFixerActionFactory Factory(*SymbolIndexMgr, FixerContexts, "llvm");
Haojian Wu627ca962016-07-08 09:10:29 +000093 std::string FakeFileName = "input.cc";
94 runOnCode(&Factory, Code, FakeFileName, ExtraArgs);
Haojian Wuc99f7282016-08-09 08:26:19 +000095 assert(FixerContexts.size() == 1);
96 if (FixerContexts.front().getHeaderInfos().empty())
Eric Liuf83187d2016-05-31 13:52:59 +000097 return Code;
Haojian Wu62aee522016-07-21 13:47:09 +000098 auto Replaces = clang::include_fixer::createIncludeFixerReplacements(
Haojian Wuc99f7282016-08-09 08:26:19 +000099 Code, FixerContexts.front());
Eric Liua452db42016-07-11 13:53:21 +0000100 EXPECT_TRUE(static_cast<bool>(Replaces))
101 << llvm::toString(Replaces.takeError()) << "\n";
102 if (!Replaces)
103 return "";
Benjamin Kramer6b236262016-04-20 12:43:43 +0000104 clang::RewriterTestContext Context;
Haojian Wu627ca962016-07-08 09:10:29 +0000105 clang::FileID ID = Context.createInMemoryFile(FakeFileName, Code);
Eric Liua452db42016-07-11 13:53:21 +0000106 clang::tooling::applyAllReplacements(*Replaces, Context.Rewrite);
Benjamin Kramer6b236262016-04-20 12:43:43 +0000107 return Context.getRewrittenText(ID);
108}
109
110TEST(IncludeFixer, Typo) {
Eric Liu516f18e2016-05-31 14:48:45 +0000111 EXPECT_EQ("#include <string>\nstd::string foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000112 runIncludeFixer("std::string foo;\n"));
113
Eric Liu516f18e2016-05-31 14:48:45 +0000114 // FIXME: the current version of include-fixer does not get this test case
115 // right - header should be inserted before definition.
Benjamin Kramer6b236262016-04-20 12:43:43 +0000116 EXPECT_EQ(
Eric Liu516f18e2016-05-31 14:48:45 +0000117 "// comment\n#include \"foo.h\"\nstd::string foo;\n"
118 "#include \"dir/bar.h\"\n#include <string>\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000119 runIncludeFixer("// comment\n#include \"foo.h\"\nstd::string foo;\n"
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000120 "#include \"dir/bar.h\"\n"));
Benjamin Kramer6b236262016-04-20 12:43:43 +0000121
Eric Liu702cfd12016-05-19 08:21:09 +0000122 EXPECT_EQ("#include \"foo.h\"\n#include <string>\nstd::string foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000123 runIncludeFixer("#include \"foo.h\"\nstd::string foo;\n"));
124
125 EXPECT_EQ(
Eric Liu702cfd12016-05-19 08:21:09 +0000126 "#include \"foo.h\"\n#include <string>\nstd::string::size_type foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000127 runIncludeFixer("#include \"foo.h\"\nstd::string::size_type foo;\n"));
128
Haojian Wu627ca962016-07-08 09:10:29 +0000129 EXPECT_EQ("#include <string>\nstd::string foo;\n",
Eric Liu692aca62016-05-04 08:22:35 +0000130 runIncludeFixer("string foo;\n"));
Benjamin Kramer9b15b6f2016-05-19 12:41:56 +0000131
Benjamin Kramer9b15b6f2016-05-19 12:41:56 +0000132 // Should not match std::string.
133 EXPECT_EQ("::string foo;\n", runIncludeFixer("::string foo;\n"));
Benjamin Kramer6b236262016-04-20 12:43:43 +0000134}
135
136TEST(IncludeFixer, IncompleteType) {
137 EXPECT_EQ(
Eric Liu702cfd12016-05-19 08:21:09 +0000138 "#include \"foo.h\"\n#include <string>\n"
Haojian Wu627ca962016-07-08 09:10:29 +0000139 "namespace std {\nclass string;\n}\nstd::string foo;\n",
Benjamin Kramer6b236262016-04-20 12:43:43 +0000140 runIncludeFixer("#include \"foo.h\"\n"
141 "namespace std {\nclass string;\n}\nstring foo;\n"));
142}
143
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000144TEST(IncludeFixer, MinimizeInclude) {
145 std::vector<std::string> IncludePath = {"-Idir/"};
Eric Liu516f18e2016-05-31 14:48:45 +0000146 EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000147 runIncludeFixer("a::b::foo bar;\n", IncludePath));
148
149 IncludePath = {"-isystemdir"};
Eric Liu516f18e2016-05-31 14:48:45 +0000150 EXPECT_EQ("#include <otherdir/qux.h>\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000151 runIncludeFixer("a::b::foo bar;\n", IncludePath));
152
153 IncludePath = {"-iquotedir"};
Eric Liu516f18e2016-05-31 14:48:45 +0000154 EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000155 runIncludeFixer("a::b::foo bar;\n", IncludePath));
156
157 IncludePath = {"-Idir", "-Idir/otherdir"};
Eric Liu516f18e2016-05-31 14:48:45 +0000158 EXPECT_EQ("#include \"qux.h\"\na::b::foo bar;\n",
Benjamin Kramer3a45fab2016-04-28 11:21:29 +0000159 runIncludeFixer("a::b::foo bar;\n", IncludePath));
160}
161
Benjamin Kramerad935002016-05-10 08:25:31 +0000162TEST(IncludeFixer, NestedName) {
Eric Liu516f18e2016-05-31 14:48:45 +0000163 EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
Benjamin Krameraf34e062016-05-17 12:35:18 +0000164 "int x = a::b::foo(0);\n",
Benjamin Kramer04666a22016-05-19 11:39:56 +0000165 runIncludeFixer("int x = a::b::foo(0);\n"));
Benjamin Krameraf34e062016-05-17 12:35:18 +0000166
167 // FIXME: Handle simple macros.
168 EXPECT_EQ("#define FOO a::b::foo\nint x = FOO;\n",
169 runIncludeFixer("#define FOO a::b::foo\nint x = FOO;\n"));
170 EXPECT_EQ("#define FOO(x) a::##x\nint x = FOO(b::foo);\n",
171 runIncludeFixer("#define FOO(x) a::##x\nint x = FOO(b::foo);\n"));
172
Eric Liu516f18e2016-05-31 14:48:45 +0000173 // The empty namespace is cleaned up by clang-format after include-fixer
174 // finishes.
175 EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
176 "\nint a = a::b::foo(0);\n",
Benjamin Kramer04666a22016-05-19 11:39:56 +0000177 runIncludeFixer("namespace a {}\nint a = a::b::foo(0);\n"));
Benjamin Kramerad935002016-05-10 08:25:31 +0000178}
179
Benjamin Kramerc3459a52016-05-10 08:25:28 +0000180TEST(IncludeFixer, MultipleMissingSymbols) {
Eric Liu516f18e2016-05-31 14:48:45 +0000181 EXPECT_EQ("#include <string>\nstd::string bar;\nstd::sting foo;\n",
Benjamin Kramerc3459a52016-05-10 08:25:28 +0000182 runIncludeFixer("std::string bar;\nstd::sting foo;\n"));
183}
184
Haojian Wu57cdcb02016-05-13 15:44:16 +0000185TEST(IncludeFixer, ScopedNamespaceSymbols) {
Eric Liu516f18e2016-05-31 14:48:45 +0000186 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000187 runIncludeFixer("namespace a {\nb::bar b;\n}"));
Eric Liu516f18e2016-05-31 14:48:45 +0000188 EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000189 runIncludeFixer("namespace A {\na::b::bar b;\n}"));
Eric Liu516f18e2016-05-31 14:48:45 +0000190 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nvoid func() { b::bar b; }\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000191 runIncludeFixer("namespace a {\nvoid func() { b::bar b; }\n}"));
Haojian Wu57cdcb02016-05-13 15:44:16 +0000192 EXPECT_EQ("namespace A { c::b::bar b; }\n",
193 runIncludeFixer("namespace A { c::b::bar b; }\n"));
194 // FIXME: The header should not be added here. Remove this after we support
195 // full match.
Haojian Wu627ca962016-07-08 09:10:29 +0000196 EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
Eric Liu702cfd12016-05-19 08:21:09 +0000197 runIncludeFixer("namespace A {\nb::bar b;\n}"));
Haojian Wuadedac62016-08-02 10:43:10 +0000198
199 // Finds candidates for "str::StrCat".
200 EXPECT_EQ("#include \"strcat.h\"\nnamespace foo2 {\nstr::StrCat b;\n}",
201 runIncludeFixer("namespace foo2 {\nstr::StrCat b;\n}"));
202 // str::StrCat2 doesn't exist.
203 // In these two cases, StrCat2 is a nested class of class str.
204 EXPECT_EQ("#include \"str.h\"\nnamespace foo2 {\nstr::StrCat2 b;\n}",
205 runIncludeFixer("namespace foo2 {\nstr::StrCat2 b;\n}"));
206 EXPECT_EQ("#include \"str.h\"\nnamespace ns {\nstr::StrCat2 b;\n}",
207 runIncludeFixer("namespace ns {\nstr::StrCat2 b;\n}"));
Haojian Wu57cdcb02016-05-13 15:44:16 +0000208}
Haojian Wuff6d1952016-05-18 09:04:43 +0000209
210TEST(IncludeFixer, EnumConstantSymbols) {
Eric Liu516f18e2016-05-31 14:48:45 +0000211 EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
Haojian Wuff6d1952016-05-18 09:04:43 +0000212 runIncludeFixer("int test = a::b::Green;\n"));
213}
214
Haojian Wu9c6cb032016-06-03 11:26:02 +0000215TEST(IncludeFixer, IgnoreSymbolFromHeader) {
216 std::string Code = "#include \"header.h\"";
217 EXPECT_EQ(Code, runIncludeFixer(Code));
218}
219
Eric Liu702cfd12016-05-19 08:21:09 +0000220// FIXME: add test cases for inserting and sorting multiple headers when
221// include-fixer supports multiple headers insertion.
222TEST(IncludeFixer, InsertAndSortSingleHeader) {
223 // Insert one header.
224 std::string Code = "#include \"a.h\"\n"
225 "#include \"foo.h\"\n"
226 "\n"
Haojian Wu62aee522016-07-21 13:47:09 +0000227 "namespace a {\nb::bar b;\n}\n";
Eric Liu702cfd12016-05-19 08:21:09 +0000228 std::string Expected = "#include \"a.h\"\n"
229 "#include \"bar.h\"\n"
230 "#include \"foo.h\"\n"
231 "\n"
Haojian Wu62aee522016-07-21 13:47:09 +0000232 "namespace a {\nb::bar b;\n}\n";
Eric Liu702cfd12016-05-19 08:21:09 +0000233 EXPECT_EQ(Expected, runIncludeFixer(Code));
234}
235
Eric Liua4be83a2016-06-13 19:05:07 +0000236TEST(IncludeFixer, DoNotDeleteMatchedSymbol) {
237 EXPECT_EQ("#include \"Vector.h\"\na::Vector v;",
238 runIncludeFixer("a::Vector v;"));
239}
240
Haojian Wu627ca962016-07-08 09:10:29 +0000241TEST(IncludeFixer, FixNamespaceQualifiers) {
242 EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
243 runIncludeFixer("b::bar b;\n"));
244 EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
245 runIncludeFixer("a::b::bar b;\n"));
246 EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
247 runIncludeFixer("bar b;\n"));
248 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
249 runIncludeFixer("namespace a {\nb::bar b;\n}\n"));
250 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
251 runIncludeFixer("namespace a {\nbar b;\n}\n"));
252 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nnamespace b{\nbar b;\n}\n}\n",
253 runIncludeFixer("namespace a {\nnamespace b{\nbar b;\n}\n}\n"));
254 EXPECT_EQ("c::b::bar b;\n",
255 runIncludeFixer("c::b::bar b;\n"));
Haojian Wu0c05e2e2016-07-14 09:39:12 +0000256 EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar b;\n}\n",
257 runIncludeFixer("namespace d {\nbar b;\n}\n"));
258 EXPECT_EQ("#include \"bar2.h\"\nnamespace c {\na::c::bar b;\n}\n",
Haojian Wu627ca962016-07-08 09:10:29 +0000259 runIncludeFixer("namespace c {\nbar b;\n}\n"));
260
Haojian Wu39a718c2016-07-15 08:12:48 +0000261 // Test common qualifers reduction.
262 EXPECT_EQ(
263 "#include \"bar.h\"\nnamespace a {\nnamespace d {\nb::bar b;\n}\n}\n",
264 runIncludeFixer("namespace a {\nnamespace d {\nbar b;\n}\n}\n"));
265 EXPECT_EQ(
266 "#include \"bar.h\"\nnamespace d {\nnamespace a {\na::b::bar b;\n}\n}\n",
267 runIncludeFixer("namespace d {\nnamespace a {\nbar b;\n}\n}\n"));
268
Haojian Wu627ca962016-07-08 09:10:29 +0000269 // Test nested classes.
Haojian Wu0c05e2e2016-07-14 09:39:12 +0000270 EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar::t b;\n}\n",
271 runIncludeFixer("namespace d {\nbar::t b;\n}\n"));
Haojian Wuadedac62016-08-02 10:43:10 +0000272 EXPECT_EQ("#include \"bar.h\"\nnamespace c {\na::b::bar::t b;\n}\n",
Haojian Wu627ca962016-07-08 09:10:29 +0000273 runIncludeFixer("namespace c {\nbar::t b;\n}\n"));
274 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar::t b;\n}\n",
275 runIncludeFixer("namespace a {\nbar::t b;\n}\n"));
276
Haojian Wu5d9482d2016-07-08 14:28:43 +0000277 EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
278 runIncludeFixer("int test = Green;\n"));
Haojian Wu627ca962016-07-08 09:10:29 +0000279 EXPECT_EQ("#include \"color.h\"\nnamespace d {\nint test = a::b::Green;\n}\n",
280 runIncludeFixer("namespace d {\nint test = Green;\n}\n"));
281 EXPECT_EQ("#include \"color.h\"\nnamespace a {\nint test = b::Green;\n}\n",
282 runIncludeFixer("namespace a {\nint test = Green;\n}\n"));
283
Haojian Wu5d9482d2016-07-08 14:28:43 +0000284 // Test global scope operator.
285 EXPECT_EQ("#include \"bar.h\"\n::a::b::bar b;\n",
286 runIncludeFixer("::a::b::bar b;\n"));
287 EXPECT_EQ("#include \"bar.h\"\nnamespace a {\n::a::b::bar b;\n}\n",
288 runIncludeFixer("namespace a {\n::a::b::bar b;\n}\n"));
Haojian Wu627ca962016-07-08 09:10:29 +0000289}
290
Haojian Wu62aee522016-07-21 13:47:09 +0000291TEST(IncludeFixer, FixNamespaceQualifiersForAllInstances) {
292 const char TestCode[] = R"(
293namespace a {
294bar b;
295int func1() {
296 bar a;
297 bar *p = new bar();
298 return 0;
299}
300} // namespace a
301
302namespace a {
303bar func2() {
304 bar f;
305 return f;
306}
307} // namespace a
308
309// Non-fixed cases:
310void f() {
311 bar b;
312}
313
314namespace a {
315namespace c {
316 bar b;
317} // namespace c
318} // namespace a
319)";
320
321 const char ExpectedCode[] = R"(
322#include "bar.h"
323namespace a {
324b::bar b;
325int func1() {
326 b::bar a;
327 b::bar *p = new b::bar();
328 return 0;
329}
330} // namespace a
331
332namespace a {
333b::bar func2() {
334 b::bar f;
335 return f;
336}
337} // namespace a
338
339// Non-fixed cases:
340void f() {
341 bar b;
342}
343
344namespace a {
345namespace c {
346 bar b;
347} // namespace c
348} // namespace a
349)";
350
351 EXPECT_EQ(ExpectedCode, runIncludeFixer(TestCode));
352}
353
Haojian Wu56446182016-07-26 16:32:42 +0000354TEST(IncludeFixer, DontAddQualifiersForMissingCompleteType) {
355 EXPECT_EQ("#include \"bar.h\"\nclass bar;\nvoid f() {\nbar* b;\nb->f();\n}",
356 runIncludeFixer("class bar;\nvoid f() {\nbar* b;\nb->f();\n}"));
357}
358
Benjamin Kramer6b236262016-04-20 12:43:43 +0000359} // namespace
360} // namespace include_fixer
361} // namespace clang