File: ProjectAware.cpp

package info (click to toggle)
llvm-toolchain-14 1%3A14.0.6-16
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,496,368 kB
  • sloc: cpp: 5,593,980; ansic: 986,873; asm: 585,869; python: 184,223; objc: 72,530; lisp: 31,119; f90: 27,793; javascript: 9,780; pascal: 9,762; sh: 9,482; perl: 7,468; ml: 5,432; awk: 3,523; makefile: 2,547; xml: 953; cs: 573; fortran: 567
file content (148 lines) | stat: -rw-r--r-- 4,821 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//===--- ProjectAware.h ------------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ProjectAware.h"
#include "Config.h"
#include "index/Index.h"
#include "index/MemIndex.h"
#include "index/Merge.h"
#include "index/Ref.h"
#include "index/Serialization.h"
#include "index/Symbol.h"
#include "index/SymbolID.h"
#include "support/Logger.h"
#include "support/Threading.h"
#include "support/Trace.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <map>
#include <memory>
#include <mutex>
#include <tuple>

namespace clang {
namespace clangd {
namespace {
class ProjectAwareIndex : public SymbolIndex {
public:
  size_t estimateMemoryUsage() const override;

  /// Only queries the associated index with the current context.
  void lookup(const LookupRequest &Req,
              llvm::function_ref<void(const Symbol &)> Callback) const override;

  /// Query all indexes while prioritizing the associated one (if any).
  bool refs(const RefsRequest &Req,
            llvm::function_ref<void(const Ref &)> Callback) const override;

  /// Queries only the associates index when Req.RestrictForCodeCompletion is
  /// set, otherwise queries all.
  bool
  fuzzyFind(const FuzzyFindRequest &Req,
            llvm::function_ref<void(const Symbol &)> Callback) const override;

  /// Query all indexes while prioritizing the associated one (if any).
  void relations(const RelationsRequest &Req,
                 llvm::function_ref<void(const SymbolID &, const Symbol &)>
                     Callback) const override;

  llvm::unique_function<IndexContents(llvm::StringRef) const>
  indexedFiles() const override;

  ProjectAwareIndex(IndexFactory Gen, bool Sync) : Gen(std::move(Gen)) {
    if (!Sync)
      Tasks = std::make_unique<AsyncTaskRunner>();
  }

private:
  // Returns the index associated with current context, if any.
  SymbolIndex *getIndex() const;

  // Storage for all the external indexes.
  mutable std::mutex Mu;
  mutable llvm::DenseMap<Config::ExternalIndexSpec,
                         std::unique_ptr<SymbolIndex>>
      IndexForSpec;
  mutable std::unique_ptr<AsyncTaskRunner> Tasks;

  const IndexFactory Gen;
};

size_t ProjectAwareIndex::estimateMemoryUsage() const {
  size_t Total = 0;
  std::lock_guard<std::mutex> Lock(Mu);
  for (auto &Entry : IndexForSpec)
    Total += Entry.second->estimateMemoryUsage();
  return Total;
}

void ProjectAwareIndex::lookup(
    const LookupRequest &Req,
    llvm::function_ref<void(const Symbol &)> Callback) const {
  trace::Span Tracer("ProjectAwareIndex::lookup");
  if (auto *Idx = getIndex())
    Idx->lookup(Req, Callback);
}

bool ProjectAwareIndex::refs(
    const RefsRequest &Req,
    llvm::function_ref<void(const Ref &)> Callback) const {
  trace::Span Tracer("ProjectAwareIndex::refs");
  if (auto *Idx = getIndex())
    return Idx->refs(Req, Callback);
  return false;
}

bool ProjectAwareIndex::fuzzyFind(
    const FuzzyFindRequest &Req,
    llvm::function_ref<void(const Symbol &)> Callback) const {
  trace::Span Tracer("ProjectAwareIndex::fuzzyFind");
  if (auto *Idx = getIndex())
    return Idx->fuzzyFind(Req, Callback);
  return false;
}

void ProjectAwareIndex::relations(
    const RelationsRequest &Req,
    llvm::function_ref<void(const SymbolID &, const Symbol &)> Callback) const {
  trace::Span Tracer("ProjectAwareIndex::relations");
  if (auto *Idx = getIndex())
    return Idx->relations(Req, Callback);
}

llvm::unique_function<IndexContents(llvm::StringRef) const>
ProjectAwareIndex::indexedFiles() const {
  trace::Span Tracer("ProjectAwareIndex::indexedFiles");
  if (auto *Idx = getIndex())
    return Idx->indexedFiles();
  return [](llvm::StringRef) { return IndexContents::None; };
}

SymbolIndex *ProjectAwareIndex::getIndex() const {
  const auto &C = Config::current();
  if (C.Index.External.Kind == Config::ExternalIndexSpec::None)
    return nullptr;
  const auto &External = C.Index.External;
  std::lock_guard<std::mutex> Lock(Mu);
  auto Entry = IndexForSpec.try_emplace(External, nullptr);
  if (Entry.second)
    Entry.first->getSecond() = Gen(External, Tasks.get());
  return Entry.first->second.get();
}
} // namespace

std::unique_ptr<SymbolIndex> createProjectAwareIndex(IndexFactory Gen,
                                                     bool Sync) {
  assert(Gen);
  return std::make_unique<ProjectAwareIndex>(std::move(Gen), Sync);
}
} // namespace clangd
} // namespace clang