]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-db/src/lib.rs
Rollup merge of #102567 - compiler-errors:issue-102561, r=davidtwco
[rust.git] / src / tools / rust-analyzer / crates / ide-db / src / lib.rs
1 //! This crate defines the core datastructure representing IDE state -- `RootDatabase`.
2 //!
3 //! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
4
5 #![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
6
7 mod apply_change;
8
9 pub mod active_parameter;
10 pub mod assists;
11 pub mod defs;
12 pub mod famous_defs;
13 pub mod helpers;
14 pub mod items_locator;
15 pub mod label;
16 pub mod line_index;
17 pub mod path_transform;
18 pub mod rename;
19 pub mod rust_doc;
20 pub mod search;
21 pub mod source_change;
22 pub mod symbol_index;
23 pub mod traits;
24 pub mod ty_filter;
25 pub mod use_trivial_contructor;
26
27 pub mod imports {
28     pub mod import_assets;
29     pub mod insert_use;
30     pub mod merge_imports;
31 }
32
33 pub mod generated {
34     pub mod lints;
35 }
36
37 pub mod syntax_helpers {
38     pub mod node_ext;
39     pub mod insert_whitespace_into_node;
40     pub mod format_string;
41     pub mod format_string_exprs;
42
43     pub use parser::LexedStr;
44 }
45
46 use std::{fmt, mem::ManuallyDrop, sync::Arc};
47
48 use base_db::{
49     salsa::{self, Durability},
50     AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast,
51 };
52 use hir::{
53     db::{AstDatabase, DefDatabase, HirDatabase},
54     symbols::FileSymbolKind,
55 };
56 use stdx::hash::NoHashHashSet;
57
58 use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
59 pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
60
61 /// `base_db` is normally also needed in places where `ide_db` is used, so this re-export is for convenience.
62 pub use base_db;
63
64 pub type FxIndexSet<T> = indexmap::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
65 pub type FxIndexMap<K, V> =
66     indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
67
68 #[salsa::database(
69     base_db::SourceDatabaseExtStorage,
70     base_db::SourceDatabaseStorage,
71     hir::db::AstDatabaseStorage,
72     hir::db::DefDatabaseStorage,
73     hir::db::HirDatabaseStorage,
74     hir::db::InternDatabaseStorage,
75     LineIndexDatabaseStorage,
76     symbol_index::SymbolsDatabaseStorage
77 )]
78 pub struct RootDatabase {
79     // We use `ManuallyDrop` here because every codegen unit that contains a
80     // `&RootDatabase -> &dyn OtherDatabase` cast will instantiate its drop glue in the vtable,
81     // which duplicates `Weak::drop` and `Arc::drop` tens of thousands of times, which makes
82     // compile times of all `ide_*` and downstream crates suffer greatly.
83     storage: ManuallyDrop<salsa::Storage<RootDatabase>>,
84 }
85
86 impl Drop for RootDatabase {
87     fn drop(&mut self) {
88         unsafe { ManuallyDrop::drop(&mut self.storage) };
89     }
90 }
91
92 impl fmt::Debug for RootDatabase {
93     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94         f.debug_struct("RootDatabase").finish()
95     }
96 }
97
98 impl Upcast<dyn AstDatabase> for RootDatabase {
99     fn upcast(&self) -> &(dyn AstDatabase + 'static) {
100         &*self
101     }
102 }
103
104 impl Upcast<dyn DefDatabase> for RootDatabase {
105     fn upcast(&self) -> &(dyn DefDatabase + 'static) {
106         &*self
107     }
108 }
109
110 impl Upcast<dyn HirDatabase> for RootDatabase {
111     fn upcast(&self) -> &(dyn HirDatabase + 'static) {
112         &*self
113     }
114 }
115
116 impl FileLoader for RootDatabase {
117     fn file_text(&self, file_id: FileId) -> Arc<String> {
118         FileLoaderDelegate(self).file_text(file_id)
119     }
120     fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
121         FileLoaderDelegate(self).resolve_path(path)
122     }
123     fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
124         FileLoaderDelegate(self).relevant_crates(file_id)
125     }
126 }
127
128 impl salsa::Database for RootDatabase {}
129
130 impl Default for RootDatabase {
131     fn default() -> RootDatabase {
132         RootDatabase::new(None)
133     }
134 }
135
136 impl RootDatabase {
137     pub fn new(lru_capacity: Option<usize>) -> RootDatabase {
138         let mut db = RootDatabase { storage: ManuallyDrop::new(salsa::Storage::default()) };
139         db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
140         db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
141         db.set_library_roots_with_durability(Default::default(), Durability::HIGH);
142         db.set_enable_proc_attr_macros(false);
143         db.update_lru_capacity(lru_capacity);
144         db
145     }
146
147     pub fn update_lru_capacity(&mut self, lru_capacity: Option<usize>) {
148         let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_LRU_CAP);
149         base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
150         hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
151         hir::db::MacroExpandQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
152     }
153 }
154
155 impl salsa::ParallelDatabase for RootDatabase {
156     fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
157         salsa::Snapshot::new(RootDatabase { storage: ManuallyDrop::new(self.storage.snapshot()) })
158     }
159 }
160
161 #[salsa::query_group(LineIndexDatabaseStorage)]
162 pub trait LineIndexDatabase: base_db::SourceDatabase {
163     fn line_index(&self, file_id: FileId) -> Arc<LineIndex>;
164 }
165
166 fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> {
167     let text = db.file_text(file_id);
168     Arc::new(LineIndex::new(&*text))
169 }
170
171 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
172 pub enum SymbolKind {
173     Attribute,
174     BuiltinAttr,
175     Const,
176     ConstParam,
177     Derive,
178     DeriveHelper,
179     Enum,
180     Field,
181     Function,
182     Impl,
183     Label,
184     LifetimeParam,
185     Local,
186     Macro,
187     Module,
188     SelfParam,
189     SelfType,
190     Static,
191     Struct,
192     ToolModule,
193     Trait,
194     TypeAlias,
195     TypeParam,
196     Union,
197     ValueParam,
198     Variant,
199 }
200
201 impl From<hir::MacroKind> for SymbolKind {
202     fn from(it: hir::MacroKind) -> Self {
203         match it {
204             hir::MacroKind::Declarative | hir::MacroKind::BuiltIn | hir::MacroKind::ProcMacro => {
205                 SymbolKind::Macro
206             }
207             hir::MacroKind::Derive => SymbolKind::Derive,
208             hir::MacroKind::Attr => SymbolKind::Attribute,
209         }
210     }
211 }
212
213 impl From<FileSymbolKind> for SymbolKind {
214     fn from(it: FileSymbolKind) -> Self {
215         match it {
216             FileSymbolKind::Const => SymbolKind::Const,
217             FileSymbolKind::Enum => SymbolKind::Enum,
218             FileSymbolKind::Function => SymbolKind::Function,
219             FileSymbolKind::Macro => SymbolKind::Macro,
220             FileSymbolKind::Module => SymbolKind::Module,
221             FileSymbolKind::Static => SymbolKind::Static,
222             FileSymbolKind::Struct => SymbolKind::Struct,
223             FileSymbolKind::Trait => SymbolKind::Trait,
224             FileSymbolKind::TypeAlias => SymbolKind::TypeAlias,
225             FileSymbolKind::Union => SymbolKind::Union,
226         }
227     }
228 }
229
230 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
231 pub struct SnippetCap {
232     _private: (),
233 }
234
235 impl SnippetCap {
236     pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
237         if allow_snippets {
238             Some(SnippetCap { _private: () })
239         } else {
240             None
241         }
242     }
243 }
244
245 #[cfg(test)]
246 mod tests {
247     mod sourcegen_lints;
248 }