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