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 path_transform;
17 pub mod rename;
18 pub mod rust_doc;
19 pub mod search;
20 pub mod source_change;
21 pub mod symbol_index;
22 pub mod traits;
23 pub mod ty_filter;
24 pub mod use_trivial_constructor;
25
26 pub mod imports {
27 pub mod import_assets;
28 pub mod insert_use;
29 pub mod merge_imports;
30 }
31
32 pub mod generated {
33 pub mod lints;
34 }
35
36 pub mod syntax_helpers {
37 pub mod node_ext;
38 pub mod insert_whitespace_into_node;
39 pub mod format_string;
40 pub mod format_string_exprs;
41
42 pub use parser::LexedStr;
43 }
44
45 use std::{fmt, mem::ManuallyDrop};
46
47 use base_db::{
48 salsa::{self, Durability},
49 AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast,
50 };
51 use hir::db::{DefDatabase, ExpandDatabase, HirDatabase};
52 use triomphe::Arc;
53
54 use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
55 pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
56
57 pub use ::line_index;
58
59 /// `base_db` is normally also needed in places where `ide_db` is used, so this re-export is for convenience.
60 pub use base_db;
61
62 pub type FxIndexSet<T> = indexmap::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
63 pub type FxIndexMap<K, V> =
64 indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
65
66 #[salsa::database(
67 base_db::SourceDatabaseExtStorage,
68 base_db::SourceDatabaseStorage,
69 hir::db::ExpandDatabaseStorage,
70 hir::db::DefDatabaseStorage,
71 hir::db::HirDatabaseStorage,
72 hir::db::InternDatabaseStorage,
73 LineIndexDatabaseStorage,
74 symbol_index::SymbolsDatabaseStorage
75 )]
76 pub struct RootDatabase {
77 // We use `ManuallyDrop` here because every codegen unit that contains a
78 // `&RootDatabase -> &dyn OtherDatabase` cast will instantiate its drop glue in the vtable,
79 // which duplicates `Weak::drop` and `Arc::drop` tens of thousands of times, which makes
80 // compile times of all `ide_*` and downstream crates suffer greatly.
81 storage: ManuallyDrop<salsa::Storage<RootDatabase>>,
82 }
83
84 impl Drop for RootDatabase {
drop(&mut self)85 fn drop(&mut self) {
86 unsafe { ManuallyDrop::drop(&mut self.storage) };
87 }
88 }
89
90 impl fmt::Debug for RootDatabase {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 f.debug_struct("RootDatabase").finish()
93 }
94 }
95
96 impl Upcast<dyn ExpandDatabase> for RootDatabase {
upcast(&self) -> &(dyn ExpandDatabase + 'static)97 fn upcast(&self) -> &(dyn ExpandDatabase + 'static) {
98 &*self
99 }
100 }
101
102 impl Upcast<dyn DefDatabase> for RootDatabase {
upcast(&self) -> &(dyn DefDatabase + 'static)103 fn upcast(&self) -> &(dyn DefDatabase + 'static) {
104 &*self
105 }
106 }
107
108 impl Upcast<dyn HirDatabase> for RootDatabase {
upcast(&self) -> &(dyn HirDatabase + 'static)109 fn upcast(&self) -> &(dyn HirDatabase + 'static) {
110 &*self
111 }
112 }
113
114 impl FileLoader for RootDatabase {
file_text(&self, file_id: FileId) -> Arc<str>115 fn file_text(&self, file_id: FileId) -> Arc<str> {
116 FileLoaderDelegate(self).file_text(file_id)
117 }
resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId>118 fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
119 FileLoaderDelegate(self).resolve_path(path)
120 }
relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>121 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
122 FileLoaderDelegate(self).relevant_crates(file_id)
123 }
124 }
125
126 impl salsa::Database for RootDatabase {}
127
128 impl Default for RootDatabase {
default() -> RootDatabase129 fn default() -> RootDatabase {
130 RootDatabase::new(None)
131 }
132 }
133
134 impl RootDatabase {
new(lru_capacity: Option<usize>) -> RootDatabase135 pub fn new(lru_capacity: Option<usize>) -> RootDatabase {
136 let mut db = RootDatabase { storage: ManuallyDrop::new(salsa::Storage::default()) };
137 db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
138 db.set_proc_macros_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_expand_proc_attr_macros_with_durability(false, Durability::HIGH);
142 db.update_parse_query_lru_capacity(lru_capacity);
143 db
144 }
145
enable_proc_attr_macros(&mut self)146 pub fn enable_proc_attr_macros(&mut self) {
147 self.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
148 }
149
update_parse_query_lru_capacity(&mut self, lru_capacity: Option<usize>)150 pub fn update_parse_query_lru_capacity(&mut self, lru_capacity: Option<usize>) {
151 let lru_capacity = lru_capacity.unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP);
152 base_db::ParseQuery.in_db_mut(self).set_lru_capacity(lru_capacity);
153 // macro expansions are usually rather small, so we can afford to keep more of them alive
154 hir::db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(4 * lru_capacity);
155 hir::db::MacroExpandQuery.in_db_mut(self).set_lru_capacity(4 * lru_capacity);
156 }
157
update_lru_capacities(&mut self, lru_capacities: &FxHashMap<Box<str>, usize>)158 pub fn update_lru_capacities(&mut self, lru_capacities: &FxHashMap<Box<str>, usize>) {
159 use hir::db as hir_db;
160
161 base_db::ParseQuery.in_db_mut(self).set_lru_capacity(
162 lru_capacities
163 .get(stringify!(ParseQuery))
164 .copied()
165 .unwrap_or(base_db::DEFAULT_PARSE_LRU_CAP),
166 );
167 hir_db::ParseMacroExpansionQuery.in_db_mut(self).set_lru_capacity(
168 lru_capacities
169 .get(stringify!(ParseMacroExpansionQuery))
170 .copied()
171 .unwrap_or(4 * base_db::DEFAULT_PARSE_LRU_CAP),
172 );
173 hir_db::MacroExpandQuery.in_db_mut(self).set_lru_capacity(
174 lru_capacities
175 .get(stringify!(MacroExpandQuery))
176 .copied()
177 .unwrap_or(4 * base_db::DEFAULT_PARSE_LRU_CAP),
178 );
179
180 macro_rules! update_lru_capacity_per_query {
181 ($( $module:ident :: $query:ident )*) => {$(
182 if let Some(&cap) = lru_capacities.get(stringify!($query)) {
183 $module::$query.in_db_mut(self).set_lru_capacity(cap);
184 }
185 )*}
186 }
187 update_lru_capacity_per_query![
188 // SourceDatabase
189 // base_db::ParseQuery
190 // base_db::CrateGraphQuery
191 // base_db::ProcMacrosQuery
192
193 // SourceDatabaseExt
194 // base_db::FileTextQuery
195 // base_db::FileSourceRootQuery
196 // base_db::SourceRootQuery
197 base_db::SourceRootCratesQuery
198
199 // ExpandDatabase
200 hir_db::AstIdMapQuery
201 // hir_db::ParseMacroExpansionQuery
202 // hir_db::InternMacroCallQuery
203 hir_db::MacroArgTextQuery
204 hir_db::MacroDefQuery
205 // hir_db::MacroExpandQuery
206 hir_db::ExpandProcMacroQuery
207 hir_db::HygieneFrameQuery
208 hir_db::ParseMacroExpansionErrorQuery
209
210 // DefDatabase
211 hir_db::FileItemTreeQuery
212 hir_db::CrateDefMapQueryQuery
213 hir_db::BlockDefMapQuery
214 hir_db::StructDataQuery
215 hir_db::StructDataWithDiagnosticsQuery
216 hir_db::UnionDataQuery
217 hir_db::UnionDataWithDiagnosticsQuery
218 hir_db::EnumDataQuery
219 hir_db::EnumDataWithDiagnosticsQuery
220 hir_db::ImplDataQuery
221 hir_db::ImplDataWithDiagnosticsQuery
222 hir_db::TraitDataQuery
223 hir_db::TraitDataWithDiagnosticsQuery
224 hir_db::TraitAliasDataQuery
225 hir_db::TypeAliasDataQuery
226 hir_db::FunctionDataQuery
227 hir_db::ConstDataQuery
228 hir_db::StaticDataQuery
229 hir_db::Macro2DataQuery
230 hir_db::MacroRulesDataQuery
231 hir_db::ProcMacroDataQuery
232 hir_db::BodyWithSourceMapQuery
233 hir_db::BodyQuery
234 hir_db::ExprScopesQuery
235 hir_db::GenericParamsQuery
236 hir_db::VariantsAttrsQuery
237 hir_db::FieldsAttrsQuery
238 hir_db::VariantsAttrsSourceMapQuery
239 hir_db::FieldsAttrsSourceMapQuery
240 hir_db::AttrsQuery
241 hir_db::CrateLangItemsQuery
242 hir_db::LangItemQuery
243 hir_db::ImportMapQuery
244 hir_db::FieldVisibilitiesQuery
245 hir_db::FunctionVisibilityQuery
246 hir_db::ConstVisibilityQuery
247 hir_db::CrateSupportsNoStdQuery
248
249 // HirDatabase
250 hir_db::InferQueryQuery
251 hir_db::MirBodyQuery
252 hir_db::BorrowckQuery
253 hir_db::TyQuery
254 hir_db::ValueTyQuery
255 hir_db::ImplSelfTyQuery
256 hir_db::ConstParamTyQuery
257 hir_db::ConstEvalQuery
258 hir_db::ConstEvalDiscriminantQuery
259 hir_db::ImplTraitQuery
260 hir_db::FieldTypesQuery
261 hir_db::LayoutOfAdtQuery
262 hir_db::TargetDataLayoutQuery
263 hir_db::CallableItemSignatureQuery
264 hir_db::ReturnTypeImplTraitsQuery
265 hir_db::GenericPredicatesForParamQuery
266 hir_db::GenericPredicatesQuery
267 hir_db::TraitEnvironmentQuery
268 hir_db::GenericDefaultsQuery
269 hir_db::InherentImplsInCrateQuery
270 hir_db::InherentImplsInBlockQuery
271 hir_db::IncoherentInherentImplCratesQuery
272 hir_db::TraitImplsInCrateQuery
273 hir_db::TraitImplsInBlockQuery
274 hir_db::TraitImplsInDepsQuery
275 // hir_db::InternCallableDefQuery
276 // hir_db::InternLifetimeParamIdQuery
277 // hir_db::InternImplTraitIdQuery
278 // hir_db::InternTypeOrConstParamIdQuery
279 // hir_db::InternClosureQuery
280 // hir_db::InternGeneratorQuery
281 hir_db::AssociatedTyDataQuery
282 hir_db::TraitDatumQuery
283 hir_db::StructDatumQuery
284 hir_db::ImplDatumQuery
285 hir_db::FnDefDatumQuery
286 hir_db::FnDefVarianceQuery
287 hir_db::AdtVarianceQuery
288 hir_db::AssociatedTyValueQuery
289 hir_db::TraitSolveQueryQuery
290 hir_db::ProgramClausesForChalkEnvQuery
291
292 // SymbolsDatabase
293 symbol_index::ModuleSymbolsQuery
294 symbol_index::LibrarySymbolsQuery
295 // symbol_index::LocalRootsQuery
296 // symbol_index::LibraryRootsQuery
297
298 // LineIndexDatabase
299 crate::LineIndexQuery
300
301 // InternDatabase
302 // hir_db::InternFunctionQuery
303 // hir_db::InternStructQuery
304 // hir_db::InternUnionQuery
305 // hir_db::InternEnumQuery
306 // hir_db::InternConstQuery
307 // hir_db::InternStaticQuery
308 // hir_db::InternTraitQuery
309 // hir_db::InternTraitAliasQuery
310 // hir_db::InternTypeAliasQuery
311 // hir_db::InternImplQuery
312 // hir_db::InternExternBlockQuery
313 // hir_db::InternBlockQuery
314 // hir_db::InternMacro2Query
315 // hir_db::InternProcMacroQuery
316 // hir_db::InternMacroRulesQuery
317 ];
318 }
319 }
320
321 impl salsa::ParallelDatabase for RootDatabase {
snapshot(&self) -> salsa::Snapshot<RootDatabase>322 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
323 salsa::Snapshot::new(RootDatabase { storage: ManuallyDrop::new(self.storage.snapshot()) })
324 }
325 }
326
327 #[salsa::query_group(LineIndexDatabaseStorage)]
328 pub trait LineIndexDatabase: base_db::SourceDatabase {
line_index(&self, file_id: FileId) -> Arc<LineIndex>329 fn line_index(&self, file_id: FileId) -> Arc<LineIndex>;
330 }
331
line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex>332 fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> {
333 let text = db.file_text(file_id);
334 Arc::new(LineIndex::new(&text))
335 }
336
337 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
338 pub enum SymbolKind {
339 Attribute,
340 BuiltinAttr,
341 Const,
342 ConstParam,
343 Derive,
344 DeriveHelper,
345 Enum,
346 Field,
347 Function,
348 Impl,
349 Label,
350 LifetimeParam,
351 Local,
352 Macro,
353 Module,
354 SelfParam,
355 SelfType,
356 Static,
357 Struct,
358 ToolModule,
359 Trait,
360 TraitAlias,
361 TypeAlias,
362 TypeParam,
363 Union,
364 ValueParam,
365 Variant,
366 }
367
368 impl From<hir::MacroKind> for SymbolKind {
from(it: hir::MacroKind) -> Self369 fn from(it: hir::MacroKind) -> Self {
370 match it {
371 hir::MacroKind::Declarative | hir::MacroKind::BuiltIn | hir::MacroKind::ProcMacro => {
372 SymbolKind::Macro
373 }
374 hir::MacroKind::Derive => SymbolKind::Derive,
375 hir::MacroKind::Attr => SymbolKind::Attribute,
376 }
377 }
378 }
379
380 impl From<hir::ModuleDefId> for SymbolKind {
from(it: hir::ModuleDefId) -> Self381 fn from(it: hir::ModuleDefId) -> Self {
382 match it {
383 hir::ModuleDefId::ConstId(..) => SymbolKind::Const,
384 hir::ModuleDefId::EnumVariantId(..) => SymbolKind::Variant,
385 hir::ModuleDefId::FunctionId(..) => SymbolKind::Function,
386 hir::ModuleDefId::MacroId(..) => SymbolKind::Macro,
387 hir::ModuleDefId::ModuleId(..) => SymbolKind::Module,
388 hir::ModuleDefId::StaticId(..) => SymbolKind::Static,
389 hir::ModuleDefId::AdtId(hir::AdtId::StructId(..)) => SymbolKind::Struct,
390 hir::ModuleDefId::AdtId(hir::AdtId::EnumId(..)) => SymbolKind::Enum,
391 hir::ModuleDefId::AdtId(hir::AdtId::UnionId(..)) => SymbolKind::Union,
392 hir::ModuleDefId::TraitId(..) => SymbolKind::Trait,
393 hir::ModuleDefId::TraitAliasId(..) => SymbolKind::TraitAlias,
394 hir::ModuleDefId::TypeAliasId(..) => SymbolKind::TypeAlias,
395 hir::ModuleDefId::BuiltinType(..) => SymbolKind::TypeAlias,
396 }
397 }
398 }
399
400 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
401 pub struct SnippetCap {
402 _private: (),
403 }
404
405 impl SnippetCap {
new(allow_snippets: bool) -> Option<SnippetCap>406 pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
407 if allow_snippets {
408 Some(SnippetCap { _private: () })
409 } else {
410 None
411 }
412 }
413 }
414
415 #[cfg(test)]
416 mod tests {
417 mod sourcegen_lints;
418 mod line_index;
419 }
420