clang-tools  7.0.0
Merge.cpp
Go to the documentation of this file.
1 //===--- Merge.h ------------------------------------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===---------------------------------------------------------------------===//
9 #include "Merge.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/Support/raw_ostream.h"
12 namespace clang {
13 namespace clangd {
14 namespace {
15 using namespace llvm;
16 
17 class MergedIndex : public SymbolIndex {
18  public:
19  MergedIndex(const SymbolIndex *Dynamic, const SymbolIndex *Static)
20  : Dynamic(Dynamic), Static(Static) {}
21 
22  // FIXME: Deleted symbols in dirty files are still returned (from Static).
23  // To identify these eliminate these, we should:
24  // - find the generating file from each Symbol which is Static-only
25  // - ask Dynamic if it has that file (needs new SymbolIndex method)
26  // - if so, drop the Symbol.
27  bool fuzzyFind(const FuzzyFindRequest &Req,
28  function_ref<void(const Symbol &)> Callback) const override {
29  // We can't step through both sources in parallel. So:
30  // 1) query all dynamic symbols, slurping results into a slab
31  // 2) query the static symbols, for each one:
32  // a) if it's not in the dynamic slab, yield it directly
33  // b) if it's in the dynamic slab, merge it and yield the result
34  // 3) now yield all the dynamic symbols we haven't processed.
35  bool More = false; // We'll be incomplete if either source was.
36  SymbolSlab::Builder DynB;
37  More |= Dynamic->fuzzyFind(Req, [&](const Symbol &S) { DynB.insert(S); });
38  SymbolSlab Dyn = std::move(DynB).build();
39 
40  DenseSet<SymbolID> SeenDynamicSymbols;
41  Symbol::Details Scratch;
42  More |= Static->fuzzyFind(Req, [&](const Symbol &S) {
43  auto DynS = Dyn.find(S.ID);
44  if (DynS == Dyn.end())
45  return Callback(S);
46  SeenDynamicSymbols.insert(S.ID);
47  Callback(mergeSymbol(*DynS, S, &Scratch));
48  });
49  for (const Symbol &S : Dyn)
50  if (!SeenDynamicSymbols.count(S.ID))
51  Callback(S);
52  return More;
53  }
54 
55  void
56  lookup(const LookupRequest &Req,
57  llvm::function_ref<void(const Symbol &)> Callback) const override {
58  SymbolSlab::Builder B;
59 
60  Dynamic->lookup(Req, [&](const Symbol &S) { B.insert(S); });
61 
62  auto RemainingIDs = Req.IDs;
63  Symbol::Details Scratch;
64  Static->lookup(Req, [&](const Symbol &S) {
65  const Symbol *Sym = B.find(S.ID);
66  RemainingIDs.erase(S.ID);
67  if (!Sym)
68  Callback(S);
69  else
70  Callback(mergeSymbol(*Sym, S, &Scratch));
71  });
72  for (const auto &ID : RemainingIDs)
73  if (const Symbol *Sym = B.find(ID))
74  Callback(*Sym);
75  }
76 
77 private:
78  const SymbolIndex *Dynamic, *Static;
79 };
80 } // namespace
81 
82 Symbol
83 mergeSymbol(const Symbol &L, const Symbol &R, Symbol::Details *Scratch) {
84  assert(L.ID == R.ID);
85  // We prefer information from TUs that saw the definition.
86  // Classes: this is the def itself. Functions: hopefully the header decl.
87  // If both did (or both didn't), continue to prefer L over R.
88  bool PreferR = R.Definition && !L.Definition;
89  Symbol S = PreferR ? R : L; // The target symbol we're merging into.
90  const Symbol &O = PreferR ? L : R; // The "other" less-preferred symbol.
91 
92  // For each optional field, fill it from O if missing in S.
93  // (It might be missing in O too, but that's a no-op).
94  if (!S.Definition)
95  S.Definition = O.Definition;
96  if (!S.CanonicalDeclaration)
98  S.References += O.References;
99  if (S.Signature == "")
100  S.Signature = O.Signature;
101  if (S.CompletionSnippetSuffix == "")
103 
104  if (O.Detail) {
105  if (S.Detail) {
106  // Copy into scratch space so we can merge.
107  *Scratch = *S.Detail;
108  if (Scratch->Documentation == "")
109  Scratch->Documentation = O.Detail->Documentation;
110  if (Scratch->ReturnType == "")
111  Scratch->ReturnType = O.Detail->ReturnType;
112  if (Scratch->IncludeHeader == "")
113  Scratch->IncludeHeader = O.Detail->IncludeHeader;
114  S.Detail = Scratch;
115  } else
116  S.Detail = O.Detail;
117  }
118 
120  return S;
121 }
122 
123 std::unique_ptr<SymbolIndex> mergeIndex(const SymbolIndex *Dynamic,
124  const SymbolIndex *Static) {
125  return llvm::make_unique<MergedIndex>(Dynamic, Static);
126 }
127 } // namespace clangd
128 } // namespace clang
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
Definition: Index.h:208
Optional symbol details that are not required to be set.
Definition: Index.h:206
Some operations such as code completion produce a set of candidates.
llvm::StringRef IncludeHeader
This can be either a URI of the header to be #include&#39;d for this symbol, or a literal header quoted w...
Definition: Index.h:219
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:317
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
llvm::StringRef ReturnType
Type when this symbol is used in an expression.
Definition: Index.h:211
unsigned References
Definition: Index.h:187
SymbolLocation Definition
Definition: Index.h:175
llvm::StringRef Signature
A brief description of the symbol that can be appended in the completion candidate list...
Definition: Index.h:195
SymbolLocation CanonicalDeclaration
Definition: Index.h:184
Symbol mergeSymbol(const Symbol &L, const Symbol &R, Symbol::Details *Scratch)
Definition: Merge.cpp:83
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const Details * Detail
Definition: Index.h:223
llvm::StringRef CompletionSnippetSuffix
What to insert when completing this symbol, after the symbol name.
Definition: Index.h:199
SymbolOrigin Origin
Where this symbol came from. Usually an index provides a constant value.
Definition: Index.h:192
std::unique_ptr< SymbolIndex > mergeIndex(const SymbolIndex *Dynamic, const SymbolIndex *Static)
Definition: Merge.cpp:123