//===--- IndexTests.cpp - Test indexing actions -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" #include "clang/AST/Decl.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/IndexSymbol.h" #include "clang/Index/IndexingAction.h" #include "clang/Lex/Preprocessor.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/VirtualFileSystem.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include namespace clang { namespace index { struct TestSymbol { std::string QName; // FIXME: add more information. }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) { return OS << S.QName; } namespace { class Indexer : public IndexDataConsumer { public: bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef, SourceLocation, ASTNodeInfo) override { const auto *ND = llvm::dyn_cast(D); if (!ND) return true; TestSymbol S; S.QName = ND->getQualifiedNameAsString(); Symbols.push_back(std::move(S)); return true; } bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *, SymbolRoleSet, SourceLocation) override { TestSymbol S; S.QName = Name->getName(); Symbols.push_back(std::move(S)); return true; } std::vector Symbols; }; class IndexAction : public ASTFrontendAction { public: IndexAction(std::shared_ptr Index, IndexingOptions Opts = IndexingOptions()) : Index(std::move(Index)), Opts(Opts) {} protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { class Consumer : public ASTConsumer { std::shared_ptr Index; std::shared_ptr PP; IndexingOptions Opts; public: Consumer(std::shared_ptr Index, std::shared_ptr PP, IndexingOptions Opts) : Index(std::move(Index)), PP(std::move(PP)), Opts(Opts) {} void HandleTranslationUnit(ASTContext &Ctx) override { std::vector DeclsToIndex( Ctx.getTranslationUnitDecl()->decls().begin(), Ctx.getTranslationUnitDecl()->decls().end()); indexTopLevelDecls(Ctx, *PP, DeclsToIndex, *Index, Opts); } }; return llvm::make_unique(Index, CI.getPreprocessorPtr(), Opts); } private: std::shared_ptr Index; IndexingOptions Opts; }; using testing::Contains; using testing::Not; using testing::UnorderedElementsAre; MATCHER_P(QName, Name, "") { return arg.QName == Name; } TEST(IndexTest, Simple) { auto Index = std::make_shared(); tooling::runToolOnCode(new IndexAction(Index), "class X {}; void f() {}"); EXPECT_THAT(Index->Symbols, UnorderedElementsAre(QName("X"), QName("f"))); } TEST(IndexTest, IndexPreprocessorMacros) { std::string Code = "#define INDEX_MAC 1"; auto Index = std::make_shared(); IndexingOptions Opts; Opts.IndexMacrosInPreprocessor = true; tooling::runToolOnCode(new IndexAction(Index, Opts), Code); EXPECT_THAT(Index->Symbols, Contains(QName("INDEX_MAC"))); Opts.IndexMacrosInPreprocessor = false; Index->Symbols.clear(); tooling::runToolOnCode(new IndexAction(Index, Opts), Code); EXPECT_THAT(Index->Symbols, UnorderedElementsAre()); } } // namespace } // namespace index } // namespace clang