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/D41232
Files:
clangd/CMakeLists.txt
clangd/index/FileSymbols.cpp
clangd/index/FileSymbols.h
unittests/clangd/IndexTests.cpp
Index: unittests/clangd/IndexTests.cpp
===================================================================
--- unittests/clangd/IndexTests.cpp
+++ unittests/clangd/IndexTests.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "index/FileSymbols.h"
#include "index/Index.h"
#include "index/MemIndex.h"
#include "gmock/gmock.h"
@@ -31,6 +32,11 @@
std::vector<const Symbol *> Pointers;
};
+void addNumSymbolsToSlab(int Begin, int End, SymbolSlab *Slab) {
+ for (int i = Begin; i <= End; i++)
+ Slab->insert(symbol(std::to_string(i)));
+}
+
// Create a slab of symbols with IDs and names [Begin, End]. The life time of
// the slab is managed by the returned shared pointer. If \p WeakSymbols is
// provided, it will be pointed to the managed object in the returned shared
@@ -42,9 +48,7 @@
if (WeakSymbols)
*WeakSymbols = Slab;
- for (int i = Begin; i <= End; i++)
- Slab->Slab.insert(symbol(std::to_string(i)));
-
+ addNumSymbolsToSlab(Begin, End, &Slab->Slab);
for (const auto &Sym : Slab->Slab)
Slab->Pointers.push_back(&Sym.second);
@@ -61,6 +65,13 @@
return Matches;
}
+std::vector<std::string> getSymbolNames(const std::vector<const Symbol *> &Symbols) {
+ std::vector<std::string> Names;
+ for (const Symbol *Sym : Symbols)
+ Names.push_back(Sym->QualifiedName);
+ return Names;
+}
+
TEST(MemIndexTest, MemIndexSymbolsRecycled) {
MemIndex I;
std::weak_ptr<SlabAndPointers> Symbols;
@@ -110,6 +121,53 @@
EXPECT_EQ(Matches.size(), Req.MaxCandidateCount);
}
+TEST(FileSymbolsTest, UpdateAndGet) {
+ FileSymbols FS;
+ EXPECT_THAT(getSymbolNames(*FS.allSymbols()), UnorderedElementsAre());
+
+ auto Slab = llvm::make_unique<SymbolSlab>();
+ addNumSymbolsToSlab(1, 3, Slab.get());
+
+ FS.update("f1", std::move(Slab));
+
+ EXPECT_THAT(getSymbolNames(*FS.allSymbols()),
+ UnorderedElementsAre("1", "2", "3"));
+}
+
+TEST(FileSymbolsTest, Overlap) {
+ FileSymbols FS;
+
+ auto Slab = llvm::make_unique<SymbolSlab>();
+ addNumSymbolsToSlab(1, 3, Slab.get());
+
+ FS.update("f1", std::move(Slab));
+
+ Slab = llvm::make_unique<SymbolSlab>();
+ addNumSymbolsToSlab(3, 5, Slab.get());
+
+ FS.update("f2", std::move(Slab));
+
+ EXPECT_THAT(getSymbolNames(*FS.allSymbols()),
+ UnorderedElementsAre("1", "2", "3", "3", "4", "5"));
+}
+
+TEST(FileSymbolsTest, SnapshotAliveAfterRemove) {
+ FileSymbols FS;
+
+ auto Slab = llvm::make_unique<SymbolSlab>();
+ addNumSymbolsToSlab(1, 3, Slab.get());
+
+ FS.update("f1", std::move(Slab));
+
+ auto Symbols = FS.allSymbols();
+ EXPECT_THAT(getSymbolNames(*Symbols), UnorderedElementsAre("1", "2", "3"));
+
+ FS.remove("f1");
+ EXPECT_THAT(getSymbolNames(*FS.allSymbols()), UnorderedElementsAre());
+
+ EXPECT_THAT(getSymbolNames(*Symbols), UnorderedElementsAre("1", "2", "3"));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
Index: clangd/index/FileSymbols.h
===================================================================
--- /dev/null
+++ clangd/index/FileSymbols.h
@@ -0,0 +1,55 @@
+//===--- FileSymbols.h - Symbols from 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_FILEINDEX_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
+
+#include "../Path.h"
+#include "Index.h"
+#include "llvm/ADT/StringMap.h"
+#include <mutex>
+
+namespace clang {
+namespace clangd {
+
+/// \brief A container of Symbols from several source files. It can be updated
+/// at source-file granularity, replacing all symbols from one file with a new
+/// set.
+///
+/// This implements a snapshot semantics for symbols in a file. Each update to a
+/// file will create a new snapshot for all symbols in the file. Snapshots are
+/// managed with shared pointers that are shared between this class and the
+/// users. For each file, this class only stores a pointer pointing to the
+/// newest snapshot, and an outdated snapshot is deleted by the last owner of
+/// the snapshot, either this class or the symbol index.
+///
+/// The snapshot semantics keeps critical sections minimal since we only need
+/// locking when we swap or obtain refereces to snapshots.
+class FileSymbols {
+public:
+ /// \brief Updates all symbols in a file.
+ void update(PathRef Path, std::unique_ptr<SymbolSlab> Slab);
+
+ /// \brief Removes snapshots of \p Path.
+ void remove(PathRef Path);
+
+ // The shared_ptr keeps the symbols alive
+ std::shared_ptr<std::vector<const Symbol *>> allSymbols();
+
+private:
+ mutable std::mutex Mutex;
+
+ /// \brief Stores the latest snapshots for all active files.
+ llvm::StringMap<std::shared_ptr<SymbolSlab>> FileToSlabs;
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
Index: clangd/index/FileSymbols.cpp
===================================================================
--- /dev/null
+++ clangd/index/FileSymbols.cpp
@@ -0,0 +1,50 @@
+//===--- FileSymbols.cpp - Symbols from files. ------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FileSymbols.h"
+#include "clang/Index/IndexingAction.h"
+
+namespace clang {
+namespace clangd {
+
+void FileSymbols::update(PathRef Path, std::unique_ptr<SymbolSlab> Slab) {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ FileToSlabs[Path] = std::shared_ptr<SymbolSlab>(Slab.release());
+}
+
+void FileSymbols::remove(PathRef Path) {
+ std::lock_guard<std::mutex> Lock(Mutex);
+ FileToSlabs.erase(Path);
+}
+
+std::shared_ptr<std::vector<const Symbol *>> FileSymbols::allSymbols() {
+ // The snapshot manages life time of symbol slabs and provides pointers of all
+ // symbols in all slabs.
+ struct Snapshot {
+ std::vector<const Symbol *> Pointers;
+ std::vector<std::shared_ptr<SymbolSlab>> KeepAlive;
+ };
+ auto Snap = std::make_shared<Snapshot>();
+ {
+ std::lock_guard<std::mutex> Lock(Mutex);
+
+ for (const auto &FileAndSlab : FileToSlabs) {
+ Snap->KeepAlive.push_back(FileAndSlab.second);
+ for (const auto &Iter : *FileAndSlab.second)
+ Snap->Pointers.push_back(&Iter.second);
+ }
+ }
+ auto *Pointers = &Snap->Pointers;
+ // Use aliasing constructor to keep the snapshot alive along with the
+ // pointers.
+ return {std::move(Snap), Pointers};
+}
+
+} // namespace clangd
+} // namespace clang
Index: clangd/CMakeLists.txt
===================================================================
--- clangd/CMakeLists.txt
+++ clangd/CMakeLists.txt
@@ -19,8 +19,9 @@
Protocol.cpp
ProtocolHandlers.cpp
Trace.cpp
- index/MemIndex.cpp
+ index/FileSymbols.cpp
index/Index.cpp
+ index/MemIndex.cpp
index/SymbolCollector.cpp
index/SymbolYAML.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits