//===-- IncludeFixerTest.cpp - Include fixer unit tests -------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "../../../../unittests/Tooling/RewriterTestContext.h" #include "InMemoryXrefsDB.h" #include "IncludeFixer.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" using namespace clang; namespace clang { namespace include_fixer { namespace { static bool runOnCode(tooling::ToolAction *ToolAction, StringRef Code, StringRef FileName) { llvm::IntrusiveRefCntPtr InMemoryFileSystem( new vfs::InMemoryFileSystem); llvm::IntrusiveRefCntPtr Files( new FileManager(FileSystemOptions(), InMemoryFileSystem)); tooling::ToolInvocation Invocation( {std::string("include_fixer"), std::string("-fsyntax-only"), FileName.str()}, ToolAction, Files.get(), std::make_shared()); InMemoryFileSystem->addFile(FileName, 0, llvm::MemoryBuffer::getMemBuffer(Code)); InMemoryFileSystem->addFile("foo.h", 0, llvm::MemoryBuffer::getMemBuffer("\n")); InMemoryFileSystem->addFile("bar.h", 0, llvm::MemoryBuffer::getMemBuffer("\n")); return Invocation.run(); } static std::string runIncludeFixer(StringRef Code) { std::map> XrefsMap = { {"std::string", {""}}, {"std::string::size_type", {""}}}; auto XrefsDB = llvm::make_unique(std::move(XrefsMap)); std::vector Replacements; IncludeFixerActionFactory Factory(*XrefsDB, Replacements); runOnCode(&Factory, Code, "input.cc"); clang::RewriterTestContext Context; clang::FileID ID = Context.createInMemoryFile("input.cc", Code); clang::tooling::applyAllReplacements(Replacements, Context.Rewrite); return Context.getRewrittenText(ID); } TEST(IncludeFixer, Typo) { EXPECT_EQ("#include \nstd::string foo;\n", runIncludeFixer("std::string foo;\n")); EXPECT_EQ( "// comment\n#include \n#include \"foo.h\"\nstd::string foo;\n" "#include \"bar.h\"\n", runIncludeFixer("// comment\n#include \"foo.h\"\nstd::string foo;\n" "#include \"bar.h\"\n")); EXPECT_EQ("#include \n#include \"foo.h\"\nstd::string foo;\n", runIncludeFixer("#include \"foo.h\"\nstd::string foo;\n")); EXPECT_EQ( "#include \n#include \"foo.h\"\nstd::string::size_type foo;\n", runIncludeFixer("#include \"foo.h\"\nstd::string::size_type foo;\n")); // The fixed xrefs db doesn't know how to handle string without std::. EXPECT_EQ("string foo;\n", runIncludeFixer("string foo;\n")); } TEST(IncludeFixer, IncompleteType) { EXPECT_EQ( "#include \n#include \"foo.h\"\n" "namespace std {\nclass string;\n}\nstring foo;\n", runIncludeFixer("#include \"foo.h\"\n" "namespace std {\nclass string;\n}\nstring foo;\n")); } } // namespace } // namespace include_fixer } // namespace clang