143356f56SNico Weber //===-- IncludeFixerTest.cpp - Include fixer unit tests -------------------===//
243356f56SNico Weber //
343356f56SNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
443356f56SNico Weber // See https://llvm.org/LICENSE.txt for license information.
543356f56SNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
643356f56SNico Weber //
743356f56SNico Weber //===----------------------------------------------------------------------===//
843356f56SNico Weber
943356f56SNico Weber #include "InMemorySymbolIndex.h"
1043356f56SNico Weber #include "IncludeFixer.h"
1143356f56SNico Weber #include "SymbolIndexManager.h"
1243356f56SNico Weber #include "unittests/Tooling/RewriterTestContext.h"
1343356f56SNico Weber #include "clang/Tooling/Tooling.h"
1443356f56SNico Weber #include "gtest/gtest.h"
1543356f56SNico Weber
1643356f56SNico Weber namespace clang {
1743356f56SNico Weber namespace include_fixer {
1843356f56SNico Weber namespace {
1943356f56SNico Weber
2043356f56SNico Weber using find_all_symbols::SymbolInfo;
2143356f56SNico Weber using find_all_symbols::SymbolAndSignals;
2243356f56SNico Weber
runOnCode(tooling::ToolAction * ToolAction,StringRef Code,StringRef FileName,const std::vector<std::string> & ExtraArgs)2343356f56SNico Weber static bool runOnCode(tooling::ToolAction *ToolAction, StringRef Code,
2443356f56SNico Weber StringRef FileName,
2543356f56SNico Weber const std::vector<std::string> &ExtraArgs) {
2643356f56SNico Weber llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
2743356f56SNico Weber new llvm::vfs::InMemoryFileSystem);
2843356f56SNico Weber llvm::IntrusiveRefCntPtr<FileManager> Files(
2943356f56SNico Weber new FileManager(FileSystemOptions(), InMemoryFileSystem));
3043356f56SNico Weber // FIXME: Investigate why -fms-compatibility breaks tests.
3143356f56SNico Weber std::vector<std::string> Args = {"include_fixer", "-fsyntax-only",
32adcd0268SBenjamin Kramer "-fno-ms-compatibility",
33adcd0268SBenjamin Kramer std::string(FileName)};
3443356f56SNico Weber Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
3543356f56SNico Weber tooling::ToolInvocation Invocation(
3643356f56SNico Weber Args, ToolAction, Files.get(),
3743356f56SNico Weber std::make_shared<PCHContainerOperations>());
3843356f56SNico Weber
3943356f56SNico Weber InMemoryFileSystem->addFile(FileName, 0,
4043356f56SNico Weber llvm::MemoryBuffer::getMemBuffer(Code));
4143356f56SNico Weber
4243356f56SNico Weber InMemoryFileSystem->addFile("foo.h", 0,
4343356f56SNico Weber llvm::MemoryBuffer::getMemBuffer("\n"));
4443356f56SNico Weber InMemoryFileSystem->addFile("dir/bar.h", 0,
4543356f56SNico Weber llvm::MemoryBuffer::getMemBuffer("\n"));
4643356f56SNico Weber InMemoryFileSystem->addFile("dir/otherdir/qux.h", 0,
4743356f56SNico Weber llvm::MemoryBuffer::getMemBuffer("\n"));
4843356f56SNico Weber InMemoryFileSystem->addFile("header.h", 0,
4943356f56SNico Weber llvm::MemoryBuffer::getMemBuffer("bar b;"));
5043356f56SNico Weber return Invocation.run();
5143356f56SNico Weber }
5243356f56SNico Weber
runIncludeFixer(StringRef Code,const std::vector<std::string> & ExtraArgs=std::vector<std::string> ())5343356f56SNico Weber static std::string runIncludeFixer(
5443356f56SNico Weber StringRef Code,
5543356f56SNico Weber const std::vector<std::string> &ExtraArgs = std::vector<std::string>()) {
5643356f56SNico Weber std::vector<SymbolAndSignals> Symbols = {
5743356f56SNico Weber {SymbolInfo("string", SymbolInfo::SymbolKind::Class, "<string>",
5843356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "std"}}),
5943356f56SNico Weber SymbolInfo::Signals{}},
6043356f56SNico Weber {SymbolInfo("sting", SymbolInfo::SymbolKind::Class, "\"sting\"",
6143356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "std"}}),
6243356f56SNico Weber SymbolInfo::Signals{}},
6343356f56SNico Weber {SymbolInfo("foo", SymbolInfo::SymbolKind::Class,
6443356f56SNico Weber "\"dir/otherdir/qux.h\"",
6543356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "b"},
6643356f56SNico Weber {SymbolInfo::ContextType::Namespace, "a"}}),
6743356f56SNico Weber SymbolInfo::Signals{}},
6843356f56SNico Weber {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar.h\"",
6943356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "b"},
7043356f56SNico Weber {SymbolInfo::ContextType::Namespace, "a"}}),
7143356f56SNico Weber SymbolInfo::Signals{}},
7243356f56SNico Weber {SymbolInfo("bar", SymbolInfo::SymbolKind::Class, "\"bar2.h\"",
7343356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "c"},
7443356f56SNico Weber {SymbolInfo::ContextType::Namespace, "a"}}),
7543356f56SNico Weber SymbolInfo::Signals{}},
7643356f56SNico Weber {SymbolInfo("Green", SymbolInfo::SymbolKind::Class, "\"color.h\"",
7743356f56SNico Weber {{SymbolInfo::ContextType::EnumDecl, "Color"},
7843356f56SNico Weber {SymbolInfo::ContextType::Namespace, "b"},
7943356f56SNico Weber {SymbolInfo::ContextType::Namespace, "a"}}),
8043356f56SNico Weber SymbolInfo::Signals{}},
8143356f56SNico Weber {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"",
8243356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "__a"},
8343356f56SNico Weber {SymbolInfo::ContextType::Namespace, "a"}}),
8443356f56SNico Weber SymbolInfo::Signals{/*Seen=*/2, 0}},
8543356f56SNico Weber {SymbolInfo("Vector", SymbolInfo::SymbolKind::Class, "\"Vector.h\"",
8643356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "a"}}),
8743356f56SNico Weber SymbolInfo::Signals{/*Seen=*/2, 0}},
8843356f56SNico Weber {SymbolInfo("StrCat", SymbolInfo::SymbolKind::Class, "\"strcat.h\"",
8943356f56SNico Weber {{SymbolInfo::ContextType::Namespace, "str"}}),
9043356f56SNico Weber SymbolInfo::Signals{}},
9143356f56SNico Weber {SymbolInfo("str", SymbolInfo::SymbolKind::Class, "\"str.h\"", {}),
9243356f56SNico Weber SymbolInfo::Signals{}},
9343356f56SNico Weber {SymbolInfo("foo2", SymbolInfo::SymbolKind::Class, "\"foo2.h\"", {}),
9443356f56SNico Weber SymbolInfo::Signals{}},
9543356f56SNico Weber };
961c705d9cSJonas Devlieghere auto SymbolIndexMgr = std::make_unique<SymbolIndexManager>();
9743356f56SNico Weber SymbolIndexMgr->addSymbolIndex(
981c705d9cSJonas Devlieghere [=]() { return std::make_unique<InMemorySymbolIndex>(Symbols); });
9943356f56SNico Weber
10043356f56SNico Weber std::vector<IncludeFixerContext> FixerContexts;
10143356f56SNico Weber IncludeFixerActionFactory Factory(*SymbolIndexMgr, FixerContexts, "llvm");
10243356f56SNico Weber std::string FakeFileName = "input.cc";
10343356f56SNico Weber runOnCode(&Factory, Code, FakeFileName, ExtraArgs);
10443356f56SNico Weber assert(FixerContexts.size() == 1);
10543356f56SNico Weber if (FixerContexts.front().getHeaderInfos().empty())
106adcd0268SBenjamin Kramer return std::string(Code);
10743356f56SNico Weber auto Replaces = createIncludeFixerReplacements(Code, FixerContexts.front());
10843356f56SNico Weber EXPECT_TRUE(static_cast<bool>(Replaces))
10943356f56SNico Weber << llvm::toString(Replaces.takeError()) << "\n";
11043356f56SNico Weber if (!Replaces)
11143356f56SNico Weber return "";
11243356f56SNico Weber RewriterTestContext Context;
11343356f56SNico Weber FileID ID = Context.createInMemoryFile(FakeFileName, Code);
11443356f56SNico Weber tooling::applyAllReplacements(*Replaces, Context.Rewrite);
11543356f56SNico Weber return Context.getRewrittenText(ID);
11643356f56SNico Weber }
11743356f56SNico Weber
TEST(IncludeFixer,Typo)11843356f56SNico Weber TEST(IncludeFixer, Typo) {
11943356f56SNico Weber EXPECT_EQ("#include <string>\nstd::string foo;\n",
12043356f56SNico Weber runIncludeFixer("std::string foo;\n"));
12143356f56SNico Weber
12243356f56SNico Weber EXPECT_EQ("// comment\n#include \"foo.h\"\n#include <string>\n"
12343356f56SNico Weber "std::string foo;\n#include \"dir/bar.h\"\n",
12443356f56SNico Weber runIncludeFixer("// comment\n#include \"foo.h\"\nstd::string foo;\n"
12543356f56SNico Weber "#include \"dir/bar.h\"\n"));
12643356f56SNico Weber
12743356f56SNico Weber EXPECT_EQ("#include \"foo.h\"\n#include <string>\nstd::string foo;\n",
12843356f56SNico Weber runIncludeFixer("#include \"foo.h\"\nstd::string foo;\n"));
12943356f56SNico Weber
13043356f56SNico Weber EXPECT_EQ(
13143356f56SNico Weber "#include \"foo.h\"\n#include <string>\nstd::string::size_type foo;\n",
13243356f56SNico Weber runIncludeFixer("#include \"foo.h\"\nstd::string::size_type foo;\n"));
13343356f56SNico Weber
13443356f56SNico Weber EXPECT_EQ("#include <string>\nstd::string foo;\n",
13543356f56SNico Weber runIncludeFixer("string foo;\n"));
13643356f56SNico Weber
13743356f56SNico Weber // Should not match std::string.
13843356f56SNico Weber EXPECT_EQ("::string foo;\n", runIncludeFixer("::string foo;\n"));
13943356f56SNico Weber }
14043356f56SNico Weber
TEST(IncludeFixer,IncompleteType)14143356f56SNico Weber TEST(IncludeFixer, IncompleteType) {
14243356f56SNico Weber EXPECT_EQ(
14343356f56SNico Weber "#include \"foo.h\"\n#include <string>\n"
14443356f56SNico Weber "namespace std {\nclass string;\n}\nstd::string foo;\n",
14543356f56SNico Weber runIncludeFixer("#include \"foo.h\"\n"
14643356f56SNico Weber "namespace std {\nclass string;\n}\nstring foo;\n"));
14743356f56SNico Weber
14843356f56SNico Weber EXPECT_EQ("#include <string>\n"
14943356f56SNico Weber "class string;\ntypedef string foo;\nfoo f;\n",
15043356f56SNico Weber runIncludeFixer("class string;\ntypedef string foo;\nfoo f;\n"));
15143356f56SNico Weber }
15243356f56SNico Weber
TEST(IncludeFixer,MinimizeInclude)15343356f56SNico Weber TEST(IncludeFixer, MinimizeInclude) {
15443356f56SNico Weber std::vector<std::string> IncludePath = {"-Idir/"};
15543356f56SNico Weber EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
15643356f56SNico Weber runIncludeFixer("a::b::foo bar;\n", IncludePath));
15743356f56SNico Weber
15843356f56SNico Weber IncludePath = {"-isystemdir"};
15943356f56SNico Weber EXPECT_EQ("#include <otherdir/qux.h>\na::b::foo bar;\n",
16043356f56SNico Weber runIncludeFixer("a::b::foo bar;\n", IncludePath));
16143356f56SNico Weber
16243356f56SNico Weber IncludePath = {"-iquotedir"};
16343356f56SNico Weber EXPECT_EQ("#include \"otherdir/qux.h\"\na::b::foo bar;\n",
16443356f56SNico Weber runIncludeFixer("a::b::foo bar;\n", IncludePath));
16543356f56SNico Weber
16643356f56SNico Weber IncludePath = {"-Idir", "-Idir/otherdir"};
16743356f56SNico Weber EXPECT_EQ("#include \"qux.h\"\na::b::foo bar;\n",
16843356f56SNico Weber runIncludeFixer("a::b::foo bar;\n", IncludePath));
16943356f56SNico Weber }
17043356f56SNico Weber
TEST(IncludeFixer,NestedName)17143356f56SNico Weber TEST(IncludeFixer, NestedName) {
17243356f56SNico Weber EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
17343356f56SNico Weber "int x = a::b::foo(0);\n",
17443356f56SNico Weber runIncludeFixer("int x = a::b::foo(0);\n"));
17543356f56SNico Weber
17643356f56SNico Weber // FIXME: Handle simple macros.
17743356f56SNico Weber EXPECT_EQ("#define FOO a::b::foo\nint x = FOO;\n",
17843356f56SNico Weber runIncludeFixer("#define FOO a::b::foo\nint x = FOO;\n"));
17943356f56SNico Weber EXPECT_EQ("#define FOO(x) a::##x\nint x = FOO(b::foo);\n",
18043356f56SNico Weber runIncludeFixer("#define FOO(x) a::##x\nint x = FOO(b::foo);\n"));
18143356f56SNico Weber
18243356f56SNico Weber // The empty namespace is cleaned up by clang-format after clang-include-fixer
18343356f56SNico Weber // finishes.
18443356f56SNico Weber EXPECT_EQ("#include \"dir/otherdir/qux.h\"\n"
18543356f56SNico Weber "\nint a = a::b::foo(0);\n",
18643356f56SNico Weber runIncludeFixer("namespace a {}\nint a = a::b::foo(0);\n"));
18743356f56SNico Weber }
18843356f56SNico Weber
TEST(IncludeFixer,MultipleMissingSymbols)18943356f56SNico Weber TEST(IncludeFixer, MultipleMissingSymbols) {
19043356f56SNico Weber EXPECT_EQ("#include <string>\nstd::string bar;\nstd::sting foo;\n",
19143356f56SNico Weber runIncludeFixer("std::string bar;\nstd::sting foo;\n"));
19243356f56SNico Weber }
19343356f56SNico Weber
TEST(IncludeFixer,ScopedNamespaceSymbols)19443356f56SNico Weber TEST(IncludeFixer, ScopedNamespaceSymbols) {
19543356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}",
19643356f56SNico Weber runIncludeFixer("namespace a {\nb::bar b;\n}"));
19743356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
19843356f56SNico Weber runIncludeFixer("namespace A {\na::b::bar b;\n}"));
19943356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nvoid func() { b::bar b; }\n} "
20043356f56SNico Weber "// namespace a",
20143356f56SNico Weber runIncludeFixer("namespace a {\nvoid func() { b::bar b; }\n}"));
20243356f56SNico Weber EXPECT_EQ("namespace A { c::b::bar b; }\n",
20343356f56SNico Weber runIncludeFixer("namespace A { c::b::bar b; }\n"));
20443356f56SNico Weber // FIXME: The header should not be added here. Remove this after we support
20543356f56SNico Weber // full match.
20643356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace A {\na::b::bar b;\n}",
20743356f56SNico Weber runIncludeFixer("namespace A {\nb::bar b;\n}"));
20843356f56SNico Weber
20943356f56SNico Weber // Finds candidates for "str::StrCat".
21043356f56SNico Weber EXPECT_EQ("#include \"strcat.h\"\nnamespace foo2 {\nstr::StrCat b;\n}",
21143356f56SNico Weber runIncludeFixer("namespace foo2 {\nstr::StrCat b;\n}"));
21243356f56SNico Weber // str::StrCat2 doesn't exist.
21343356f56SNico Weber // In these two cases, StrCat2 is a nested class of class str.
21443356f56SNico Weber EXPECT_EQ("#include \"str.h\"\nnamespace foo2 {\nstr::StrCat2 b;\n}",
21543356f56SNico Weber runIncludeFixer("namespace foo2 {\nstr::StrCat2 b;\n}"));
21643356f56SNico Weber EXPECT_EQ("#include \"str.h\"\nnamespace ns {\nstr::StrCat2 b;\n}",
21743356f56SNico Weber runIncludeFixer("namespace ns {\nstr::StrCat2 b;\n}"));
21843356f56SNico Weber }
21943356f56SNico Weber
TEST(IncludeFixer,EnumConstantSymbols)22043356f56SNico Weber TEST(IncludeFixer, EnumConstantSymbols) {
22143356f56SNico Weber EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
22243356f56SNico Weber runIncludeFixer("int test = a::b::Green;\n"));
22343356f56SNico Weber }
22443356f56SNico Weber
TEST(IncludeFixer,IgnoreSymbolFromHeader)22543356f56SNico Weber TEST(IncludeFixer, IgnoreSymbolFromHeader) {
22643356f56SNico Weber std::string Code = "#include \"header.h\"";
22743356f56SNico Weber EXPECT_EQ(Code, runIncludeFixer(Code));
22843356f56SNico Weber }
22943356f56SNico Weber
23043356f56SNico Weber // FIXME: add test cases for inserting and sorting multiple headers when
23143356f56SNico Weber // clang-include-fixer supports multiple headers insertion.
TEST(IncludeFixer,InsertAndSortSingleHeader)23243356f56SNico Weber TEST(IncludeFixer, InsertAndSortSingleHeader) {
23343356f56SNico Weber // Insert one header.
23443356f56SNico Weber std::string Code = "#include \"a.h\"\n"
23543356f56SNico Weber "#include \"foo.h\"\n"
23643356f56SNico Weber "\n"
23743356f56SNico Weber "namespace a {\nb::bar b;\n}\n";
23843356f56SNico Weber std::string Expected = "#include \"a.h\"\n"
23943356f56SNico Weber "#include \"bar.h\"\n"
24043356f56SNico Weber "#include \"foo.h\"\n"
24143356f56SNico Weber "\n"
24243356f56SNico Weber "namespace a {\nb::bar b;\n}\n";
24343356f56SNico Weber EXPECT_EQ(Expected, runIncludeFixer(Code));
24443356f56SNico Weber }
24543356f56SNico Weber
TEST(IncludeFixer,DoNotDeleteMatchedSymbol)24643356f56SNico Weber TEST(IncludeFixer, DoNotDeleteMatchedSymbol) {
24743356f56SNico Weber EXPECT_EQ("#include \"Vector.h\"\na::Vector v;",
24843356f56SNico Weber runIncludeFixer("a::Vector v;"));
24943356f56SNico Weber }
25043356f56SNico Weber
TEST(IncludeFixer,FixNamespaceQualifiers)25143356f56SNico Weber TEST(IncludeFixer, FixNamespaceQualifiers) {
25243356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
25343356f56SNico Weber runIncludeFixer("b::bar b;\n"));
25443356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
25543356f56SNico Weber runIncludeFixer("a::b::bar b;\n"));
25643356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\na::b::bar b;\n",
25743356f56SNico Weber runIncludeFixer("bar b;\n"));
25843356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
25943356f56SNico Weber runIncludeFixer("namespace a {\nb::bar b;\n}\n"));
26043356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar b;\n}\n",
26143356f56SNico Weber runIncludeFixer("namespace a {\nbar b;\n}\n"));
26243356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nnamespace b{\nbar b;\n}\n} "
26343356f56SNico Weber "// namespace a\n",
26443356f56SNico Weber runIncludeFixer("namespace a {\nnamespace b{\nbar b;\n}\n}\n"));
26543356f56SNico Weber EXPECT_EQ("c::b::bar b;\n",
26643356f56SNico Weber runIncludeFixer("c::b::bar b;\n"));
26743356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar b;\n}\n",
26843356f56SNico Weber runIncludeFixer("namespace d {\nbar b;\n}\n"));
26943356f56SNico Weber EXPECT_EQ("#include \"bar2.h\"\nnamespace c {\na::c::bar b;\n}\n",
27043356f56SNico Weber runIncludeFixer("namespace c {\nbar b;\n}\n"));
27143356f56SNico Weber
272*dd5571d5SKazuaki Ishizaki // Test common qualifiers reduction.
27343356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nnamespace d {\nb::bar b;\n}\n} "
27443356f56SNico Weber "// namespace a\n",
27543356f56SNico Weber runIncludeFixer("namespace a {\nnamespace d {\nbar b;\n}\n}\n"));
27643356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace d {\nnamespace a {\na::b::bar "
27743356f56SNico Weber "b;\n}\n} // namespace d\n",
27843356f56SNico Weber runIncludeFixer("namespace d {\nnamespace a {\nbar b;\n}\n}\n"));
27943356f56SNico Weber
28043356f56SNico Weber // Test nested classes.
28143356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace d {\na::b::bar::t b;\n}\n",
28243356f56SNico Weber runIncludeFixer("namespace d {\nbar::t b;\n}\n"));
28343356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace c {\na::b::bar::t b;\n}\n",
28443356f56SNico Weber runIncludeFixer("namespace c {\nbar::t b;\n}\n"));
28543356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\nb::bar::t b;\n}\n",
28643356f56SNico Weber runIncludeFixer("namespace a {\nbar::t b;\n}\n"));
28743356f56SNico Weber
28843356f56SNico Weber EXPECT_EQ("#include \"color.h\"\nint test = a::b::Green;\n",
28943356f56SNico Weber runIncludeFixer("int test = Green;\n"));
29043356f56SNico Weber EXPECT_EQ("#include \"color.h\"\nnamespace d {\nint test = a::b::Green;\n}\n",
29143356f56SNico Weber runIncludeFixer("namespace d {\nint test = Green;\n}\n"));
29243356f56SNico Weber EXPECT_EQ("#include \"color.h\"\nnamespace a {\nint test = b::Green;\n}\n",
29343356f56SNico Weber runIncludeFixer("namespace a {\nint test = Green;\n}\n"));
29443356f56SNico Weber
29543356f56SNico Weber // Test global scope operator.
29643356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\n::a::b::bar b;\n",
29743356f56SNico Weber runIncludeFixer("::a::b::bar b;\n"));
29843356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nnamespace a {\n::a::b::bar b;\n}\n",
29943356f56SNico Weber runIncludeFixer("namespace a {\n::a::b::bar b;\n}\n"));
30043356f56SNico Weber }
30143356f56SNico Weber
TEST(IncludeFixer,FixNamespaceQualifiersForAllInstances)30243356f56SNico Weber TEST(IncludeFixer, FixNamespaceQualifiersForAllInstances) {
30343356f56SNico Weber const char TestCode[] = R"(
30443356f56SNico Weber namespace a {
30543356f56SNico Weber bar b;
30643356f56SNico Weber int func1() {
30743356f56SNico Weber bar a;
30843356f56SNico Weber bar *p = new bar();
30943356f56SNico Weber return 0;
31043356f56SNico Weber }
31143356f56SNico Weber } // namespace a
31243356f56SNico Weber
31343356f56SNico Weber namespace a {
31443356f56SNico Weber bar func2() {
31543356f56SNico Weber bar f;
31643356f56SNico Weber return f;
31743356f56SNico Weber }
31843356f56SNico Weber } // namespace a
31943356f56SNico Weber
32043356f56SNico Weber // Non-fixed cases:
32143356f56SNico Weber void f() {
32243356f56SNico Weber bar b;
32343356f56SNico Weber }
32443356f56SNico Weber
32543356f56SNico Weber namespace a {
32643356f56SNico Weber namespace c {
32743356f56SNico Weber bar b;
32843356f56SNico Weber } // namespace c
32943356f56SNico Weber } // namespace a
33043356f56SNico Weber )";
33143356f56SNico Weber
33243356f56SNico Weber const char ExpectedCode[] = R"(
33343356f56SNico Weber #include "bar.h"
33443356f56SNico Weber namespace a {
33543356f56SNico Weber b::bar b;
33643356f56SNico Weber int func1() {
33743356f56SNico Weber b::bar a;
33843356f56SNico Weber b::bar *p = new b::bar();
33943356f56SNico Weber return 0;
34043356f56SNico Weber }
34143356f56SNico Weber } // namespace a
34243356f56SNico Weber
34343356f56SNico Weber namespace a {
34443356f56SNico Weber b::bar func2() {
34543356f56SNico Weber b::bar f;
34643356f56SNico Weber return f;
34743356f56SNico Weber }
34843356f56SNico Weber } // namespace a
34943356f56SNico Weber
35043356f56SNico Weber // Non-fixed cases:
35143356f56SNico Weber void f() {
35243356f56SNico Weber bar b;
35343356f56SNico Weber }
35443356f56SNico Weber
35543356f56SNico Weber namespace a {
35643356f56SNico Weber namespace c {
35743356f56SNico Weber bar b;
35843356f56SNico Weber } // namespace c
35943356f56SNico Weber } // namespace a
36043356f56SNico Weber )";
36143356f56SNico Weber
36243356f56SNico Weber EXPECT_EQ(ExpectedCode, runIncludeFixer(TestCode));
36343356f56SNico Weber }
36443356f56SNico Weber
TEST(IncludeFixer,DontAddQualifiersForMissingCompleteType)36543356f56SNico Weber TEST(IncludeFixer, DontAddQualifiersForMissingCompleteType) {
36643356f56SNico Weber EXPECT_EQ("#include \"bar.h\"\nclass bar;\nvoid f() {\nbar* b;\nb->f();\n}",
36743356f56SNico Weber runIncludeFixer("class bar;\nvoid f() {\nbar* b;\nb->f();\n}"));
36843356f56SNico Weber }
36943356f56SNico Weber
37043356f56SNico Weber } // namespace
37143356f56SNico Weber } // namespace include_fixer
37243356f56SNico Weber } // namespace clang
373