• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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