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