12 #include "clang/Tooling/Tooling.h" 13 #include "gmock/gmock.h" 14 #include "gtest/gtest.h" 20 using ::testing::AllOf;
21 using ::testing::ElementsAre;
23 using ::testing::Pair;
24 using ::testing::UnorderedElementsAre;
25 using ::testing::UnorderedPointwise;
27 std::string toUri(llvm::StringRef
Path) {
return URI::create(Path).toString(); }
31 MATCHER_P(HasDigest, Digest,
"") {
return arg.Digest == Digest; }
36 llvm::StringRef URI = ::testing::get<0>(arg);
37 const std::string &Path = ::testing::get<1>(arg);
38 return toUri(Path) == URI;
41 ::testing::Matcher<const IncludeGraphNode &>
42 IncludesAre(
const std::vector<std::string> &Includes) {
44 UnorderedPointwise(HasSameURI(), Includes));
47 void checkNodesAreInitialized(
const IndexFileIn &IndexFile,
48 const std::vector<std::string> &Paths) {
49 ASSERT_TRUE(IndexFile.Sources);
50 EXPECT_THAT(Paths.size(), IndexFile.Sources->size());
51 for (llvm::StringRef Path : Paths) {
52 auto URI = toUri(Path);
53 const auto &Node = IndexFile.Sources->lookup(URI);
55 EXPECT_EQ(Node.URI.data(), IndexFile.Sources->find(URI)->getKeyData());
59 std::map<std::string, const IncludeGraphNode &> toMap(
const IncludeGraph &IG) {
60 std::map<std::string, const IncludeGraphNode &> Nodes;
62 Nodes.emplace(I.getKey(), I.getValue());
66 class IndexActionTest :
public ::testing::Test {
71 runIndexingAction(llvm::StringRef MainFilePath,
72 const std::vector<std::string> &ExtraArgs = {}) {
73 IndexFileIn IndexFile;
74 llvm::IntrusiveRefCntPtr<FileManager>
Files(
78 SymbolCollector::Options(),
79 [&](SymbolSlab S) { IndexFile.Symbols = std::move(S); },
80 [&](RefSlab R) { IndexFile.Refs = std::move(R); },
81 [&](RelationSlab R) { IndexFile.Relations = std::move(R); },
82 [&](
IncludeGraph IG) { IndexFile.Sources = std::move(IG); });
84 std::vector<std::string> Args = {
"index_action",
"-fsyntax-only",
85 "-xc++",
"-std=c++11",
87 Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
88 Args.push_back(MainFilePath);
90 tooling::ToolInvocation Invocation(
92 std::make_shared<PCHContainerOperations>());
96 checkNodesAreInitialized(IndexFile,
FilePaths);
100 void addFile(llvm::StringRef Path, llvm::StringRef Content) {
102 llvm::MemoryBuffer::getMemBuffer(Content));
111 TEST_F(IndexActionTest, CollectIncludeGraph) {
112 std::string MainFilePath =
testPath(
"main.cpp");
113 std::string MainCode =
"#include \"level1.h\"";
114 std::string Level1HeaderPath =
testPath(
"level1.h");
115 std::string Level1HeaderCode =
"#include \"level2.h\"";
116 std::string Level2HeaderPath =
testPath(
"level2.h");
117 std::string Level2HeaderCode =
"";
119 addFile(MainFilePath, MainCode);
120 addFile(Level1HeaderPath, Level1HeaderCode);
121 addFile(Level2HeaderPath, Level2HeaderCode);
123 IndexFileIn IndexFile = runIndexingAction(MainFilePath);
124 auto Nodes = toMap(*IndexFile.Sources);
127 UnorderedElementsAre(
128 Pair(toUri(MainFilePath),
129 AllOf(IsTU(), IncludesAre({Level1HeaderPath}),
130 HasDigest(
digest(MainCode)))),
131 Pair(toUri(Level1HeaderPath),
132 AllOf(Not(IsTU()), IncludesAre({Level2HeaderPath}),
133 HasDigest(
digest(Level1HeaderCode)))),
134 Pair(toUri(Level2HeaderPath),
135 AllOf(Not(IsTU()), IncludesAre({}),
136 HasDigest(
digest(Level2HeaderCode))))));
139 TEST_F(IndexActionTest, IncludeGraphSelfInclude) {
140 std::string MainFilePath =
testPath(
"main.cpp");
141 std::string MainCode =
"#include \"header.h\"";
142 std::string HeaderPath =
testPath(
"header.h");
143 std::string HeaderCode = R
"cpp( 149 addFile(MainFilePath, MainCode); 150 addFile(HeaderPath, HeaderCode); 152 IndexFileIn IndexFile = runIndexingAction(MainFilePath); 153 auto Nodes = toMap(*IndexFile.Sources);
157 UnorderedElementsAre(
158 Pair(toUri(MainFilePath), AllOf(IsTU(), IncludesAre({HeaderPath}),
159 HasDigest(
digest(MainCode)))),
160 Pair(toUri(HeaderPath), AllOf(Not(IsTU()), IncludesAre({HeaderPath}),
161 HasDigest(
digest(HeaderCode))))));
164 TEST_F(IndexActionTest, IncludeGraphSkippedFile) {
165 std::string MainFilePath =
testPath(
"main.cpp");
166 std::string MainCode = R
"cpp( 171 std::string CommonHeaderPath = testPath("common.h");
172 std::string CommonHeaderCode = R
"cpp( 178 std::string HeaderPath = testPath("header.h");
179 std::string HeaderCode = R
"cpp( 183 addFile(MainFilePath, MainCode); 184 addFile(HeaderPath, HeaderCode); 185 addFile(CommonHeaderPath, CommonHeaderCode); 187 IndexFileIn IndexFile = runIndexingAction(MainFilePath); 188 auto Nodes = toMap(*IndexFile.Sources);
191 Nodes, UnorderedElementsAre(
192 Pair(toUri(MainFilePath),
193 AllOf(IsTU(), IncludesAre({HeaderPath, CommonHeaderPath}),
194 HasDigest(
digest(MainCode)))),
195 Pair(toUri(HeaderPath),
196 AllOf(Not(IsTU()), IncludesAre({CommonHeaderPath}),
197 HasDigest(
digest(HeaderCode)))),
198 Pair(toUri(CommonHeaderPath),
199 AllOf(Not(IsTU()), IncludesAre({}),
200 HasDigest(
digest(CommonHeaderCode))))));
203 TEST_F(IndexActionTest, IncludeGraphDynamicInclude) {
204 std::string MainFilePath =
testPath(
"main.cpp");
205 std::string MainCode = R
"cpp( 207 #define FOO "main.cpp" 209 #define FOO "header.h" 213 std::string HeaderPath = testPath("header.h");
214 std::string HeaderCode =
"";
216 addFile(MainFilePath, MainCode);
217 addFile(HeaderPath, HeaderCode);
219 IndexFileIn IndexFile = runIndexingAction(MainFilePath);
220 auto Nodes = toMap(*IndexFile.Sources);
224 UnorderedElementsAre(
225 Pair(toUri(MainFilePath),
226 AllOf(IsTU(), IncludesAre({MainFilePath, HeaderPath}),
227 HasDigest(
digest(MainCode)))),
228 Pair(toUri(HeaderPath), AllOf(Not(IsTU()), IncludesAre({}),
229 HasDigest(
digest(HeaderCode))))));
232 TEST_F(IndexActionTest, NoWarnings) {
233 std::string MainFilePath =
testPath(
"main.cpp");
234 std::string MainCode = R
"cpp( 236 if (x = 1) // -Wparentheses 238 if (x = 1) // -Wparentheses 243 addFile(MainFilePath, MainCode); 246 IndexFileIn IndexFile = runIndexingAction(
247 MainFilePath, {
"-ferror-limit=1",
"-Wparentheses",
"-Werror"});
248 ASSERT_TRUE(IndexFile.Sources);
249 ASSERT_NE(0u, IndexFile.Sources->size());
250 EXPECT_THAT(*IndexFile.Symbols, ElementsAre(HasName(
"foo"), HasName(
"bar")));
Some operations such as code completion produce a set of candidates.
llvm::IntrusiveRefCntPtr< llvm::vfs::InMemoryFileSystem > InMemoryFileSystem
std::vector< llvm::StringRef > DirectIncludes
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
llvm::StringMap< IncludeGraphNode > IncludeGraph
std::string testPath(PathRef File)
llvm::unique_function< void()> Action
std::string Path
A typedef to represent a file path.
static constexpr llvm::StringLiteral Name
std::vector< std::string > FilePaths
FileDigest digest(llvm::StringRef Content)
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< FrontendAction > createStaticIndexingAction(SymbolCollector::Options Opts, std::function< void(SymbolSlab)> SymbolsCallback, std::function< void(RefSlab)> RefsCallback, std::function< void(RelationSlab)> RelationsCallback, std::function< void(IncludeGraph)> IncludeGraphCallback)
llvm::StringMap< std::string > Files