Line data Source code
1 : //===--- FileIndex.h - Index 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 : // FileIndex implements SymbolIndex for symbols from a set of files. Symbols are
11 : // maintained at source-file granuality (e.g. with ASTs), and files can be
12 : // updated dynamically.
13 : //
14 : //===----------------------------------------------------------------------===//
15 :
16 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
17 : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
18 :
19 : #include "ClangdUnit.h"
20 : #include "Index.h"
21 : #include "MemIndex.h"
22 : #include "Merge.h"
23 : #include "clang/Lex/Preprocessor.h"
24 : #include <memory>
25 :
26 : namespace clang {
27 : namespace clangd {
28 :
29 : /// Select between in-memory index implementations, which have tradeoffs.
30 : enum class IndexType {
31 : // MemIndex is trivially cheap to build, but has poor query performance.
32 : Light,
33 : // Dex is relatively expensive to build and uses more memory, but is fast.
34 : Heavy,
35 : };
36 :
37 : /// A container of Symbols from several source files. It can be updated
38 : /// at source-file granularity, replacing all symbols from one file with a new
39 : /// set.
40 : ///
41 : /// This implements a snapshot semantics for symbols in a file. Each update to a
42 : /// file will create a new snapshot for all symbols in the file. Snapshots are
43 : /// managed with shared pointers that are shared between this class and the
44 : /// users. For each file, this class only stores a pointer pointing to the
45 : /// newest snapshot, and an outdated snapshot is deleted by the last owner of
46 : /// the snapshot, either this class or the symbol index.
47 : ///
48 : /// The snapshot semantics keeps critical sections minimal since we only need
49 : /// locking when we swap or obtain references to snapshots.
50 0 : class FileSymbols {
51 : public:
52 : /// Updates all symbols and refs in a file.
53 : /// If either is nullptr, corresponding data for \p Path will be removed.
54 : void update(PathRef Path, std::unique_ptr<SymbolSlab> Slab,
55 : std::unique_ptr<RefSlab> Refs);
56 :
57 : // The index keeps the symbols alive.
58 : std::unique_ptr<SymbolIndex>
59 : buildIndex(IndexType, ArrayRef<std::string> URISchemes = {});
60 :
61 : private:
62 : mutable std::mutex Mutex;
63 :
64 : /// Stores the latest symbol snapshots for all active files.
65 : llvm::StringMap<std::shared_ptr<SymbolSlab>> FileToSymbols;
66 : /// Stores the latest ref snapshots for all active files.
67 : llvm::StringMap<std::shared_ptr<RefSlab>> FileToRefs;
68 : };
69 :
70 : /// This manages symbols from files and an in-memory index on all symbols.
71 : /// FIXME: Expose an interface to remove files that are closed.
72 : class FileIndex : public MergedIndex {
73 : public:
74 : /// If URISchemes is empty, the default schemes in SymbolCollector will be
75 : /// used.
76 : FileIndex(std::vector<std::string> URISchemes = {}, bool UseDex = true);
77 :
78 : /// Update preamble symbols of file \p Path with all declarations in \p AST
79 : /// and macros in \p PP.
80 : void updatePreamble(PathRef Path, ASTContext &AST,
81 : std::shared_ptr<Preprocessor> PP);
82 :
83 : /// Update symbols and references from main file \p Path with
84 : /// `indexMainDecls`.
85 : void updateMain(PathRef Path, ParsedAST &AST);
86 :
87 : private:
88 : bool UseDex; // FIXME: this should be always on.
89 : std::vector<std::string> URISchemes;
90 :
91 : // Contains information from each file's preamble only.
92 : // These are large, but update fairly infrequently (preambles are stable).
93 : // Missing information:
94 : // - symbol refs (these are always "from the main file")
95 : // - definition locations in the main file
96 : //
97 : // FIXME: Because the preambles for different TUs have large overlap and
98 : // FileIndex doesn't deduplicate, this uses lots of extra RAM.
99 : // The biggest obstacle in fixing this: the obvious approach of partitioning
100 : // by declaring file (rather than main file) fails if headers provide
101 : // different symbols based on preprocessor state.
102 : FileSymbols PreambleSymbols;
103 : SwapIndex PreambleIndex;
104 :
105 : // Contains information from each file's main AST.
106 : // These are updated frequently (on file change), but are relatively small.
107 : // Mostly contains:
108 : // - refs to symbols declared in the preamble and referenced from main
109 : // - symbols declared both in the main file and the preamble
110 : // (Note that symbols *only* in the main file are not indexed).
111 : FileSymbols MainFileSymbols;
112 : SwapIndex MainFileIndex;
113 : };
114 :
115 : /// Retrieves symbols and refs of local top level decls in \p AST (i.e.
116 : /// `AST.getLocalTopLevelDecls()`).
117 : /// Exposed to assist in unit tests.
118 : /// If URISchemes is empty, the default schemes in SymbolCollector will be used.
119 : std::pair<SymbolSlab, RefSlab>
120 : indexMainDecls(ParsedAST &AST, llvm::ArrayRef<std::string> URISchemes = {});
121 :
122 : /// Idex declarations from \p AST and macros from \p PP that are declared in
123 : /// included headers.
124 : /// If URISchemes is empty, the default schemes in SymbolCollector will be used.
125 : SymbolSlab indexHeaderSymbols(ASTContext &AST, std::shared_ptr<Preprocessor> PP,
126 : llvm::ArrayRef<std::string> URISchemes = {});
127 :
128 : } // namespace clangd
129 : } // namespace clang
130 :
131 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
|