xref: /llvm-project/clang-tools-extra/clangd/index/Ref.cpp (revision d19265b31e65c84ad908abce6e7f6e6d15c22258)
1cb83ea62SDmitri Gribenko //===--- Ref.cpp -------------------------------------------------*- C++-*-===//
2cb83ea62SDmitri Gribenko //
3cb83ea62SDmitri Gribenko // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4cb83ea62SDmitri Gribenko // See https://llvm.org/LICENSE.txt for license information.
5cb83ea62SDmitri Gribenko // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6cb83ea62SDmitri Gribenko //
7cb83ea62SDmitri Gribenko //===----------------------------------------------------------------------===//
8cb83ea62SDmitri Gribenko 
9cb83ea62SDmitri Gribenko #include "Ref.h"
10*d19265b3SSam McCall #include "llvm/ADT/STLExtras.h"
11cb83ea62SDmitri Gribenko 
12cb83ea62SDmitri Gribenko namespace clang {
13cb83ea62SDmitri Gribenko namespace clangd {
14cb83ea62SDmitri Gribenko 
operator <<(llvm::raw_ostream & OS,RefKind K)15cb83ea62SDmitri Gribenko llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, RefKind K) {
16cb83ea62SDmitri Gribenko   if (K == RefKind::Unknown)
17cb83ea62SDmitri Gribenko     return OS << "Unknown";
18b1309a18SHaojian Wu   static constexpr std::array<const char *, 4> Messages = {"Decl", "Def", "Ref",
19b1309a18SHaojian Wu                                                            "Spelled"};
20cb83ea62SDmitri Gribenko   bool VisitedOnce = false;
21cb83ea62SDmitri Gribenko   for (unsigned I = 0; I < Messages.size(); ++I) {
22cb83ea62SDmitri Gribenko     if (static_cast<uint8_t>(K) & 1u << I) {
23cb83ea62SDmitri Gribenko       if (VisitedOnce)
24cb83ea62SDmitri Gribenko         OS << ", ";
25cb83ea62SDmitri Gribenko       OS << Messages[I];
26cb83ea62SDmitri Gribenko       VisitedOnce = true;
27cb83ea62SDmitri Gribenko     }
28cb83ea62SDmitri Gribenko   }
29cb83ea62SDmitri Gribenko   return OS;
30cb83ea62SDmitri Gribenko }
31cb83ea62SDmitri Gribenko 
operator <<(llvm::raw_ostream & OS,const Ref & R)32cb83ea62SDmitri Gribenko llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Ref &R) {
33cb83ea62SDmitri Gribenko   return OS << R.Location << ":" << R.Kind;
34cb83ea62SDmitri Gribenko }
35cb83ea62SDmitri Gribenko 
insert(const SymbolID & ID,const Ref & S)36cb83ea62SDmitri Gribenko void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
37*d19265b3SSam McCall   Entry E = {ID, S};
38*d19265b3SSam McCall   E.Reference.Location.FileURI = UniqueStrings.save(S.Location.FileURI).data();
39*d19265b3SSam McCall   Entries.insert(std::move(E));
40cb83ea62SDmitri Gribenko }
41cb83ea62SDmitri Gribenko 
build()42cb83ea62SDmitri Gribenko RefSlab RefSlab::Builder::build() && {
43cb83ea62SDmitri Gribenko   std::vector<std::pair<SymbolID, llvm::ArrayRef<Ref>>> Result;
44*d19265b3SSam McCall   // We'll reuse the arena, as it only has unique strings and we need them all.
45*d19265b3SSam McCall   // We need to group refs by symbol and form contiguous arrays on the arena.
46*d19265b3SSam McCall   std::vector<std::pair<SymbolID, const Ref *>> Flat;
47*d19265b3SSam McCall   Flat.reserve(Entries.size());
48*d19265b3SSam McCall   for (const Entry &E : Entries)
49*d19265b3SSam McCall     Flat.emplace_back(E.Symbol, &E.Reference);
50*d19265b3SSam McCall   // Group by SymbolID.
51*d19265b3SSam McCall   llvm::sort(Flat, llvm::less_first());
52*d19265b3SSam McCall   std::vector<Ref> Refs;
53*d19265b3SSam McCall   // Loop over symbols, copying refs for each onto the arena.
54*d19265b3SSam McCall   for (auto I = Flat.begin(), End = Flat.end(); I != End;) {
55*d19265b3SSam McCall     SymbolID Sym = I->first;
56*d19265b3SSam McCall     Refs.clear();
57*d19265b3SSam McCall     do {
58*d19265b3SSam McCall       Refs.push_back(*I->second);
59*d19265b3SSam McCall       ++I;
60*d19265b3SSam McCall     } while (I != End && I->first == Sym);
61*d19265b3SSam McCall     llvm::sort(Refs); // By file, affects xrefs display order.
62*d19265b3SSam McCall     Result.emplace_back(Sym, llvm::ArrayRef<Ref>(Refs).copy(Arena));
63cb83ea62SDmitri Gribenko   }
64*d19265b3SSam McCall   return RefSlab(std::move(Result), std::move(Arena), Entries.size());
65cb83ea62SDmitri Gribenko }
66cb83ea62SDmitri Gribenko 
67cb83ea62SDmitri Gribenko } // namespace clangd
68cb83ea62SDmitri Gribenko } // namespace clang
69