]> git.lizzy.rs Git - rust.git/blob - crates/ide_db/src/lib.rs
99b64821fc3aaea357e444e9e1e798132953bc6b
[rust.git] / 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 mod apply_change;
6
7 pub mod assists;
8 pub mod label;
9 pub mod line_index;
10 pub mod symbol_index;
11 pub mod defs;
12 pub mod items_locator;
13 pub mod source_change;
14 pub mod ty_filter;
15 pub mod traits;
16 pub mod helpers;
17 pub mod path_transform;
18
19 pub mod search;
20 pub mod rename;
21 pub mod active_parameter;
22
23 use std::{fmt, mem::ManuallyDrop, sync::Arc};
24
25 use base_db::{
26     salsa::{self, Durability},
27     AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast,
28 };
29 use hir::db::{AstDatabase, DefDatabase, HirDatabase};
30 use rustc_hash::FxHashSet;
31
32 use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
33
34 /// `base_db` is normally also needed in places where `ide_db` is used, so this re-export is for convenience.
35 pub use base_db;
36
37 pub type FxIndexSet<T> = indexmap::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
38 pub type FxIndexMap<K, V> =
39     indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
40
41 #[salsa::database(
42     base_db::SourceDatabaseStorage,
43     base_db::SourceDatabaseExtStorage,
44     LineIndexDatabaseStorage,
45     symbol_index::SymbolsDatabaseStorage,
46     hir::db::InternDatabaseStorage,
47     hir::db::AstDatabaseStorage,
48     hir::db::DefDatabaseStorage,
49     hir::db::HirDatabaseStorage
50 )]
51 pub struct RootDatabase {
52     // We use `ManuallyDrop` here because every codegen unit that contains a
53     // `&RootDatabase -> &dyn OtherDatabase` cast will instantiate its drop glue in the vtable,
54     // which duplicates `Weak::drop` and `Arc::drop` tens of thousands of times, which makes
55     // compile times of all `ide_*` and downstream crates suffer greatly.
56     storage: ManuallyDrop<salsa::Storage<RootDatabase>>,
57 }
58
59 impl Drop for RootDatabase {
60     fn drop(&mut self) {
61         unsafe {
62             ManuallyDrop::drop(&mut self.storage);
63         }
64     }
65 }
66
67 impl fmt::Debug for RootDatabase {
68     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69         f.debug_struct("RootDatabase").finish()
70     }
71 }
72
73 impl Upcast<dyn AstDatabase> for RootDatabase {
74     fn upcast(&self) -> &(dyn AstDatabase + 'static) {
75         &*self
76     }
77 }
78
79 impl Upcast<dyn DefDatabase> for RootDatabase {
80     fn upcast(&self) -> &(dyn DefDatabase + 'static) {
81         &*self
82     }
83 }
84
85 impl Upcast<dyn HirDatabase> for RootDatabase {
86     fn upcast(&self) -> &(dyn HirDatabase + 'static) {
87         &*self
88     }
89 }
90
91 impl FileLoader for RootDatabase {
92     fn file_text(&self, file_id: FileId) -> Arc<String> {
93         FileLoaderDelegate(self).file_text(file_id)
94     }
95     fn resolve_path(&self, path: AnchoredPath) -> Option<FileId> {
96         FileLoaderDelegate(self).resolve_path(path)
97     }
98     fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
99         FileLoaderDelegate(self).relevant_crates(file_id)
100     }
101 }
102
103 impl salsa::Database for RootDatabase {}
104
105 impl Default for RootDatabase {
106     fn default() -> RootDatabase {
107         RootDatabase::new(None)
108     }
109 }
110
111 impl RootDatabase {
112     pub fn new(lru_capacity: Option<usize>) -> RootDatabase {
113         let mut db = RootDatabase { storage: ManuallyDrop::new(salsa::Storage::default()) };
114         db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
115         db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
116         db.set_library_roots_with_durability(Default::default(), Durability::HIGH);
117         db.set_enable_proc_attr_macros(Default::default());
118         db.update_lru_capacity(lru_capacity);
119         db
120     }
121
122     pub fn update_lru_capacity(&mut self, lru_capacity: Option<usize>) {
123         let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_LRU_CAP);
124         base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
125         hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
126         hir::db::MacroExpandQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
127     }
128 }
129
130 impl salsa::ParallelDatabase for RootDatabase {
131     fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
132         salsa::Snapshot::new(RootDatabase { storage: ManuallyDrop::new(self.storage.snapshot()) })
133     }
134 }
135
136 #[salsa::query_group(LineIndexDatabaseStorage)]
137 pub trait LineIndexDatabase: base_db::SourceDatabase {
138     fn line_index(&self, file_id: FileId) -> Arc<LineIndex>;
139 }
140
141 fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> {
142     let text = db.file_text(file_id);
143     Arc::new(LineIndex::new(&*text))
144 }
145
146 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
147 pub enum SymbolKind {
148     Attribute,
149     BuiltinAttr,
150     Const,
151     ConstParam,
152     Enum,
153     Field,
154     Function,
155     Impl,
156     Label,
157     LifetimeParam,
158     Local,
159     Macro,
160     Module,
161     SelfParam,
162     Static,
163     Struct,
164     ToolModule,
165     Trait,
166     TypeAlias,
167     TypeParam,
168     Union,
169     ValueParam,
170     Variant,
171 }
172
173 #[cfg(test)]
174 mod tests {
175     mod sourcegen_lints;
176 }