//===--- MemIndex.cpp - Dynamic in-memory symbol index. ----------*- C++-*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===-------------------------------------------------------------------===// #include "MemIndex.h" #include "FuzzyMatch.h" #include "Logger.h" #include "Quality.h" #include "Trace.h" using namespace llvm; namespace clang { namespace clangd { std::unique_ptr MemIndex::build(SymbolSlab Slab, RefSlab Refs) { // Store Slab size before it is moved. const auto BackingDataSize = Slab.bytes() + Refs.bytes(); auto Data = std::make_pair(std::move(Slab), std::move(Refs)); return llvm::make_unique(Data.first, Data.second, std::move(Data), BackingDataSize); } bool MemIndex::fuzzyFind(const FuzzyFindRequest &Req, function_ref Callback) const { assert(!StringRef(Req.Query).contains("::") && "There must be no :: in query."); trace::Span Tracer("MemIndex fuzzyFind"); TopN> Top( Req.Limit ? *Req.Limit : std::numeric_limits::max()); FuzzyMatcher Filter(Req.Query); bool More = false; for (const auto Pair : Index) { const Symbol *Sym = Pair.second; // Exact match against all possible scopes. if (!Req.AnyScope && !is_contained(Req.Scopes, Sym->Scope)) continue; if (Req.RestrictForCodeCompletion && !(Sym->Flags & Symbol::IndexedForCodeCompletion)) continue; if (auto Score = Filter.match(Sym->Name)) if (Top.push({*Score * quality(*Sym), Sym})) More = true; // An element with smallest score was discarded. } auto Results = std::move(Top).items(); SPAN_ATTACH(Tracer, "results", static_cast(Results.size())); for (const auto &Item : Results) Callback(*Item.second); return More; } void MemIndex::lookup(const LookupRequest &Req, function_ref Callback) const { trace::Span Tracer("MemIndex lookup"); for (const auto &ID : Req.IDs) { auto I = Index.find(ID); if (I != Index.end()) Callback(*I->second); } } void MemIndex::refs(const RefsRequest &Req, function_ref Callback) const { trace::Span Tracer("MemIndex refs"); for (const auto &ReqID : Req.IDs) { auto SymRefs = Refs.find(ReqID); if (SymRefs == Refs.end()) continue; for (const auto &O : SymRefs->second) if (static_cast(Req.Filter & O.Kind)) Callback(O); } } size_t MemIndex::estimateMemoryUsage() const { return Index.getMemorySize() + Refs.getMemorySize() + BackingDataSize; } } // namespace clangd } // namespace clang