clang-tools  7.0.0
FileIndex.cpp
Go to the documentation of this file.
1 //===--- FileIndex.cpp - Indexes for files. ------------------------ 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 
10 #include "FileIndex.h"
11 #include "SymbolCollector.h"
12 #include "clang/Index/IndexingAction.h"
13 #include "clang/Lex/Preprocessor.h"
14 
15 namespace clang {
16 namespace clangd {
17 
18 SymbolSlab indexAST(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
19  llvm::ArrayRef<std::string> URISchemes) {
20  SymbolCollector::Options CollectorOpts;
21  // FIXME(ioeric): we might also want to collect include headers. We would need
22  // to make sure all includes are canonicalized (with CanonicalIncludes), which
23  // is not trivial given the current way of collecting symbols: we only have
24  // AST at this point, but we also need preprocessor callbacks (e.g.
25  // CommentHandler for IWYU pragma) to canonicalize includes.
26  CollectorOpts.CollectIncludePath = false;
27  CollectorOpts.CountReferences = false;
28  if (!URISchemes.empty())
29  CollectorOpts.URISchemes = URISchemes;
30  CollectorOpts.Origin = SymbolOrigin::Dynamic;
31 
32  SymbolCollector Collector(std::move(CollectorOpts));
33  Collector.setPreprocessor(PP);
34  index::IndexingOptions IndexOpts;
35  // We only need declarations, because we don't count references.
36  IndexOpts.SystemSymbolFilter =
37  index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
38  IndexOpts.IndexFunctionLocals = false;
39 
40  std::vector<const Decl *> TopLevelDecls(
41  AST.getTranslationUnitDecl()->decls().begin(),
42  AST.getTranslationUnitDecl()->decls().end());
43  index::indexTopLevelDecls(AST, TopLevelDecls, Collector, IndexOpts);
44 
45  return Collector.takeSymbols();
46 }
47 
48 FileIndex::FileIndex(std::vector<std::string> URISchemes)
49  : URISchemes(std::move(URISchemes)) {}
50 
51 void FileSymbols::update(PathRef Path, std::unique_ptr<SymbolSlab> Slab) {
52  std::lock_guard<std::mutex> Lock(Mutex);
53  if (!Slab)
54  FileToSlabs.erase(Path);
55  else
56  FileToSlabs[Path] = std::move(Slab);
57 }
58 
59 std::shared_ptr<std::vector<const Symbol *>> FileSymbols::allSymbols() {
60  // The snapshot manages life time of symbol slabs and provides pointers of all
61  // symbols in all slabs.
62  struct Snapshot {
63  std::vector<const Symbol *> Pointers;
64  std::vector<std::shared_ptr<SymbolSlab>> KeepAlive;
65  };
66  auto Snap = std::make_shared<Snapshot>();
67  {
68  std::lock_guard<std::mutex> Lock(Mutex);
69 
70  for (const auto &FileAndSlab : FileToSlabs) {
71  Snap->KeepAlive.push_back(FileAndSlab.second);
72  for (const auto &Iter : *FileAndSlab.second)
73  Snap->Pointers.push_back(&Iter);
74  }
75  }
76  auto *Pointers = &Snap->Pointers;
77  // Use aliasing constructor to keep the snapshot alive along with the
78  // pointers.
79  return {std::move(Snap), Pointers};
80 }
81 
82 void FileIndex::update(PathRef Path, ASTContext *AST,
83  std::shared_ptr<Preprocessor> PP) {
84  if (!AST) {
85  FSymbols.update(Path, nullptr);
86  } else {
87  assert(PP);
88  auto Slab = llvm::make_unique<SymbolSlab>();
89  *Slab = indexAST(*AST, PP, URISchemes);
90  FSymbols.update(Path, std::move(Slab));
91  }
92  auto Symbols = FSymbols.allSymbols();
93  Index.build(std::move(Symbols));
94 }
95 
97  const FuzzyFindRequest &Req,
98  llvm::function_ref<void(const Symbol &)> Callback) const {
99  return Index.fuzzyFind(Req, Callback);
100 }
101 
103  const LookupRequest &Req,
104  llvm::function_ref<void(const Symbol &)> Callback) const {
105  Index.lookup(Req, Callback);
106 }
107 
108 } // namespace clangd
109 } // namespace clang
SymbolSlab indexAST(ASTContext &AST, std::shared_ptr< Preprocessor > PP, llvm::ArrayRef< std::string > URISchemes)
Retrieves namespace and class level symbols in AST.
Definition: FileIndex.cpp:18
FileIndex(std::vector< std::string > URISchemes={})
If URISchemes is empty, the default schemes in SymbolCollector will be used.
Definition: FileIndex.cpp:48
std::vector< std::string > URISchemes
Specifies URI schemes that can be used to generate URIs for file paths in symbols.
std::shared_ptr< std::vector< const Symbol * > > allSymbols()
Definition: FileIndex.cpp:59
void update(PathRef Path, std::unique_ptr< SymbolSlab > Slab)
Updates all symbols in a file.
Definition: FileIndex.cpp:51
Collect declarations (symbols) from an AST.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:24
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
std::string Path
A typedef to represent a file path.
Definition: Path.h:21
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
void setPreprocessor(std::shared_ptr< Preprocessor > PP) override
void update(PathRef Path, ASTContext *AST, std::shared_ptr< Preprocessor > PP)
Update symbols in Path with symbols in AST.
Definition: FileIndex.cpp:82
void lookup(const LookupRequest &Req, llvm::function_ref< void(const Symbol &)> Callback) const override
Looks up symbols with any of the given symbol IDs and applies Callback on each matched symbol...
Definition: FileIndex.cpp:102
bool fuzzyFind(const FuzzyFindRequest &Req, llvm::function_ref< void(const Symbol &)> Callback) const override
Matches symbols in the index fuzzily and applies Callback on each matched symbol before returning...
Definition: FileIndex.cpp:96