ioeric created this revision.
ioeric added a reviewer: sammccall.
Herald added subscribers: cfe-commits, ilya-biryukov, mgorny, klimek.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D41276

Files:
  clangd/CMakeLists.txt
  clangd/index/FileMemIndexManager.cpp
  clangd/index/FileMemIndexManager.h
  unittests/clangd/IndexTests.cpp

Index: unittests/clangd/IndexTests.cpp
===================================================================
--- unittests/clangd/IndexTests.cpp
+++ unittests/clangd/IndexTests.cpp
@@ -7,8 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "index/FileMemIndexManager.h"
 #include "index/Index.h"
 #include "index/MemIndex.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PCHContainerOperations.h"
+#include "clang/Frontend/Utils.h"
+#include "llvm/ADT/Optional.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -110,6 +115,86 @@
   EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
 }
 
+/// Update symbols in \p Path to symbols from the AST of \p Code. If \p Code is
+/// empty, all symbols in \p Path are removed.
+void updateFile(std::string Path, llvm::StringRef Code,
+                FileMemIndexManager *M) {
+  Context Ctx = Context::empty();
+  if (Code.empty()) {
+    M->update(Ctx, Path, nullptr);
+    return;
+  }
+  const char *Args[] = {"clang", "-xc++", Path.c_str()};
+
+  auto CI = createInvocationFromCommandLine(Args);
+
+  auto Buf = llvm::MemoryBuffer::getMemBuffer(Code);
+  auto AST = ParsedAST::Build(Ctx, std::move(CI), nullptr, std::move(Buf),
+                              std::make_shared<PCHContainerOperations>(),
+                              vfs::getRealFileSystem());
+  assert(AST.hasValue());
+  M->update(Ctx, Path, AST.getPointer());
+}
+
+TEST(FileMemIndexTest, IndexAST) {
+  FileMemIndexManager M;
+  updateFile("f1", "namespace ns { void f() {} class X {}; }", &M);
+
+  FuzzyFindRequest Req;
+  Req.Query = "ns::";
+  EXPECT_THAT(match(M.index(), Req), UnorderedElementsAre("ns::f", "ns::X"));
+}
+
+TEST(FileMemIndexTest, NoLocal) {
+  FileMemIndexManager M;
+  updateFile("f1", "namespace ns { void f() { int local = 0; } class X {}; }",
+             &M);
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  EXPECT_THAT(match(M.index(), Req),
+              UnorderedElementsAre("ns", "ns::f", "ns::X"));
+}
+
+TEST(FileMemIndexTest, IndexMultiASTAndDeduplicate) {
+  FileMemIndexManager M;
+  updateFile("f1", "namespace ns { void f() {} class X {}; }", &M);
+  updateFile("f2", "namespace ns { void ff() {} class X {}; }", &M);
+
+  FuzzyFindRequest Req;
+  Req.Query = "ns::";
+  EXPECT_THAT(match(M.index(), Req),
+              UnorderedElementsAre("ns::f", "ns::X", "ns::ff"));
+}
+
+TEST(FileMemIndexTest, RemoveAST) {
+  FileMemIndexManager M;
+  updateFile("f1", "namespace ns { void f() {} class X {}; }", &M);
+
+  FuzzyFindRequest Req;
+  Req.Query = "ns::";
+  EXPECT_THAT(match(M.index(), Req), UnorderedElementsAre("ns::f", "ns::X"));
+
+  updateFile("f1", "", &M);
+  EXPECT_THAT(match(M.index(), Req), UnorderedElementsAre());
+}
+
+TEST(FileMemIndexTest, RemoveNonExisting) {
+  FileMemIndexManager M;
+  updateFile("no", "", &M);
+  EXPECT_THAT(match(M.index(), FuzzyFindRequest()), UnorderedElementsAre());
+}
+
+TEST(FileMemIndexTest, ClassMembers) {
+  FileMemIndexManager M;
+  updateFile("f1", "class X { static int m1; int m2;};", &M);
+
+  FuzzyFindRequest Req;
+  Req.Query = "";
+  EXPECT_THAT(match(M.index(), Req),
+              UnorderedElementsAre("X", "X::m1", "X::m2"));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/index/FileMemIndexManager.h
===================================================================
--- /dev/null
+++ clangd/index/FileMemIndexManager.h
@@ -0,0 +1,39 @@
+//===--- FileMemIndexManager.h - In-memory index for files. -------- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEMEMINDEXMANAGER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEMEMINDEXMANAGER_H
+
+#include "../ClangdUnit.h"
+#include "../Context.h"
+#include "FileSymbols.h"
+#include "MemIndex.h"
+
+namespace clang {
+namespace clangd {
+
+/// \brief This manages symbls from a set of files and an in-memory index on
+/// all symbols.
+class FileMemIndexManager {
+public:
+  /// \brief Update symbols in \p Path with symbols in \p AST. If \p AST is
+  /// nullptr, this removes all symbols from \p Path.
+  void update(Context &Ctx, PathRef Path, ParsedAST *AST);
+
+  MemIndex &index() { return Index; }
+
+private:
+  FileSymbols FSymbols;
+  MemIndex Index;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEMEMINDEXMANAGER_H
Index: clangd/index/FileMemIndexManager.cpp
===================================================================
--- /dev/null
+++ clangd/index/FileMemIndexManager.cpp
@@ -0,0 +1,48 @@
+//===--- FileMemIndexManager.cpp - In-memory index for files. ------ C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FileMemIndexManager.h"
+#include "SymbolCollector.h"
+#include "clang/Index/IndexingAction.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+/// Retrieves namespace and class level symbols in \p Decls.
+std::unique_ptr<SymbolSlab> indexAST(ASTContext &Ctx,
+                                     llvm::ArrayRef<const Decl *> Decls) {
+  auto Collector = std::make_shared<SymbolCollector>();
+  index::IndexingOptions IndexOpts;
+  IndexOpts.SystemSymbolFilter =
+      index::IndexingOptions::SystemSymbolFilterKind::All;
+  IndexOpts.IndexFunctionLocals = false;
+
+  index::indexTopLevelDecls(Ctx, Decls, Collector, IndexOpts);
+  auto Symbols = llvm::make_unique<SymbolSlab>();
+  *Symbols = Collector->takeSymbols();
+  return Symbols;
+}
+
+} // namespace
+
+void FileMemIndexManager::update(Context &Ctx, PathRef Path,
+                                 ParsedAST *AST) {
+  if (!AST) {
+    FSymbols.update(Path, nullptr);
+  } else {
+    auto Slab = indexAST(AST->getASTContext(), AST->getTopLevelDecls());
+    FSymbols.update(Path, std::move(Slab));
+  }
+  auto Symbols = FSymbols.allSymbols();
+  Index.build(std::move(Symbols));
+}
+
+} // namespace clangd
+} // namespace clang
Index: clangd/CMakeLists.txt
===================================================================
--- clangd/CMakeLists.txt
+++ clangd/CMakeLists.txt
@@ -21,6 +21,7 @@
   Trace.cpp
   index/FileSymbols.cpp
   index/Index.cpp
+  index/FileMemIndexManager.cpp
   index/MemIndex.cpp
   index/SymbolCollector.cpp
   index/SymbolYAML.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to