blob: 12759761b195d770c6dc1b10145b5cec99e52c92 [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
NAKAMURA Takumif2c717b2016-04-20 14:14:16 +000010#include "unittests/Tooling/RewriterTestContext.h"
Benjamin Kramer6b236262016-04-20 12:43:43 +000011#include "InMemoryXrefsDB.h"
12#include "IncludeFixer.h"
13#include "clang/Tooling/Tooling.h"
14#include "gtest/gtest.h"
15using namespace clang;
16
17namespace clang {
18namespace include_fixer {
19namespace {
20
21static bool runOnCode(tooling::ToolAction *ToolAction, StringRef Code,
22 StringRef FileName) {
23 llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
24 new vfs::InMemoryFileSystem);
25 llvm::IntrusiveRefCntPtr<FileManager> Files(
26 new FileManager(FileSystemOptions(), InMemoryFileSystem));
27 tooling::ToolInvocation Invocation(
28 {std::string("include_fixer"), std::string("-fsyntax-only"),
29 FileName.str()},
30 ToolAction, Files.get(), std::make_shared<PCHContainerOperations>());
31
32 InMemoryFileSystem->addFile(FileName, 0,
33 llvm::MemoryBuffer::getMemBuffer(Code));
34
35 InMemoryFileSystem->addFile("foo.h", 0,
36 llvm::MemoryBuffer::getMemBuffer("\n"));
37 InMemoryFileSystem->addFile("bar.h", 0,
38 llvm::MemoryBuffer::getMemBuffer("\n"));
39 return Invocation.run();
40}
41
42static std::string runIncludeFixer(StringRef Code) {
43 std::map<std::string, std::vector<std::string>> XrefsMap = {
44 {"std::string", {"<string>"}}, {"std::string::size_type", {"<string>"}}};
45 auto XrefsDB =
46 llvm::make_unique<include_fixer::InMemoryXrefsDB>(std::move(XrefsMap));
47 std::vector<clang::tooling::Replacement> Replacements;
48 IncludeFixerActionFactory Factory(*XrefsDB, Replacements);
49 runOnCode(&Factory, Code, "input.cc");
50 clang::RewriterTestContext Context;
51 clang::FileID ID = Context.createInMemoryFile("input.cc", Code);
52 clang::tooling::applyAllReplacements(Replacements, Context.Rewrite);
53 return Context.getRewrittenText(ID);
54}
55
56TEST(IncludeFixer, Typo) {
57 EXPECT_EQ("#include <string>\nstd::string foo;\n",
58 runIncludeFixer("std::string foo;\n"));
59
60 EXPECT_EQ(
61 "// comment\n#include <string>\n#include \"foo.h\"\nstd::string foo;\n"
62 "#include \"bar.h\"\n",
63 runIncludeFixer("// comment\n#include \"foo.h\"\nstd::string foo;\n"
64 "#include \"bar.h\"\n"));
65
66 EXPECT_EQ("#include <string>\n#include \"foo.h\"\nstd::string foo;\n",
67 runIncludeFixer("#include \"foo.h\"\nstd::string foo;\n"));
68
69 EXPECT_EQ(
70 "#include <string>\n#include \"foo.h\"\nstd::string::size_type foo;\n",
71 runIncludeFixer("#include \"foo.h\"\nstd::string::size_type foo;\n"));
72
73 // The fixed xrefs db doesn't know how to handle string without std::.
74 EXPECT_EQ("string foo;\n", runIncludeFixer("string foo;\n"));
75}
76
77TEST(IncludeFixer, IncompleteType) {
78 EXPECT_EQ(
79 "#include <string>\n#include \"foo.h\"\n"
80 "namespace std {\nclass string;\n}\nstring foo;\n",
81 runIncludeFixer("#include \"foo.h\"\n"
82 "namespace std {\nclass string;\n}\nstring foo;\n"));
83}
84
85} // namespace
86} // namespace include_fixer
87} // namespace clang