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