108b49b53SDmitri Gribenko //===--- Symbol.cpp ----------------------------------------------*- C++-*-===//
208b49b53SDmitri Gribenko //
308b49b53SDmitri Gribenko // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
408b49b53SDmitri Gribenko // See https://llvm.org/LICENSE.txt for license information.
508b49b53SDmitri Gribenko // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
608b49b53SDmitri Gribenko //
708b49b53SDmitri Gribenko //===----------------------------------------------------------------------===//
808b49b53SDmitri Gribenko
908b49b53SDmitri Gribenko #include "Symbol.h"
1008b49b53SDmitri Gribenko
11d4a6513aSNico Weber #include <cmath>
12d4a6513aSNico Weber
1308b49b53SDmitri Gribenko namespace clang {
1408b49b53SDmitri Gribenko namespace clangd {
1508b49b53SDmitri Gribenko
operator <<(llvm::raw_ostream & OS,Symbol::SymbolFlag F)1608b49b53SDmitri Gribenko llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag F) {
1708b49b53SDmitri Gribenko if (F == Symbol::None)
1808b49b53SDmitri Gribenko return OS << "None";
1908b49b53SDmitri Gribenko std::string S;
2008b49b53SDmitri Gribenko if (F & Symbol::Deprecated)
2108b49b53SDmitri Gribenko S += "deprecated|";
2208b49b53SDmitri Gribenko if (F & Symbol::IndexedForCodeCompletion)
2308b49b53SDmitri Gribenko S += "completion|";
2408b49b53SDmitri Gribenko return OS << llvm::StringRef(S).rtrim('|');
2508b49b53SDmitri Gribenko }
2608b49b53SDmitri Gribenko
operator <<(llvm::raw_ostream & OS,const Symbol & S)2708b49b53SDmitri Gribenko llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
2808b49b53SDmitri Gribenko return OS << S.Scope << S.Name;
2908b49b53SDmitri Gribenko }
3008b49b53SDmitri Gribenko
quality(const Symbol & S)3108b49b53SDmitri Gribenko float quality(const Symbol &S) {
3208b49b53SDmitri Gribenko // This avoids a sharp gradient for tail symbols, and also neatly avoids the
3308b49b53SDmitri Gribenko // question of whether 0 references means a bad symbol or missing data.
3408b49b53SDmitri Gribenko if (S.References < 3)
3508b49b53SDmitri Gribenko return 1;
3608b49b53SDmitri Gribenko return std::log(S.References);
3708b49b53SDmitri Gribenko }
3808b49b53SDmitri Gribenko
find(const SymbolID & ID) const3908b49b53SDmitri Gribenko SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
4078ee2fbfSFangrui Song auto It = llvm::partition_point(Symbols,
4178ee2fbfSFangrui Song [&](const Symbol &S) { return S.ID < ID; });
4208b49b53SDmitri Gribenko if (It != Symbols.end() && It->ID == ID)
4308b49b53SDmitri Gribenko return It;
4408b49b53SDmitri Gribenko return Symbols.end();
4508b49b53SDmitri Gribenko }
4608b49b53SDmitri Gribenko
4708b49b53SDmitri Gribenko // Copy the underlying data of the symbol into the owned arena.
own(Symbol & S,llvm::UniqueStringSaver & Strings)4808b49b53SDmitri Gribenko static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
4908b49b53SDmitri Gribenko visitStrings(S, [&](llvm::StringRef &V) { V = Strings.save(V); });
5008b49b53SDmitri Gribenko }
5108b49b53SDmitri Gribenko
insert(const Symbol & S)5208b49b53SDmitri Gribenko void SymbolSlab::Builder::insert(const Symbol &S) {
53ec026532SSam McCall own(Symbols[S.ID] = S, UniqueStrings);
5408b49b53SDmitri Gribenko }
5508b49b53SDmitri Gribenko
build()5608b49b53SDmitri Gribenko SymbolSlab SymbolSlab::Builder::build() && {
57ec026532SSam McCall // Sort symbols into vector so the slab can binary search over them.
58ec026532SSam McCall std::vector<Symbol> SortedSymbols;
59ec026532SSam McCall SortedSymbols.reserve(Symbols.size());
60ec026532SSam McCall for (auto &Entry : Symbols)
61ec026532SSam McCall SortedSymbols.push_back(std::move(Entry.second));
62ec026532SSam McCall llvm::sort(SortedSymbols,
6308b49b53SDmitri Gribenko [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
64*6ea83fc9SSam McCall // We may have unused strings from overwritten symbols.
65*6ea83fc9SSam McCall // In practice, these are extremely small, it's not worth compacting.
66*6ea83fc9SSam McCall return SymbolSlab(std::move(Arena), std::move(SortedSymbols));
6708b49b53SDmitri Gribenko }
6808b49b53SDmitri Gribenko
operator <<(llvm::raw_ostream & OS,const SymbolSlab & Slab)694728aca9SKadir Cetinkaya llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolSlab &Slab) {
704728aca9SKadir Cetinkaya OS << "{";
714728aca9SKadir Cetinkaya llvm::StringRef Sep = "";
724728aca9SKadir Cetinkaya for (const auto &S : Slab) {
734728aca9SKadir Cetinkaya OS << Sep << S;
744728aca9SKadir Cetinkaya Sep = ", ";
754728aca9SKadir Cetinkaya }
764728aca9SKadir Cetinkaya OS << "}";
774728aca9SKadir Cetinkaya return OS;
784728aca9SKadir Cetinkaya }
7908b49b53SDmitri Gribenko } // namespace clangd
8008b49b53SDmitri Gribenko } // namespace clang
81