1#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
6
7#[cfg(feature = "in-rust-tree")]
8extern crate rustc_driver as _;
9
10extern crate self as ide_db;
11
12mod apply_change;
13
14pub mod active_parameter;
15pub mod assists;
16pub mod defs;
17pub mod documentation;
18pub mod famous_defs;
19pub mod helpers;
20pub mod items_locator;
21pub mod label;
22pub mod path_transform;
23pub mod prime_caches;
24pub mod ra_fixture;
25pub mod range_mapper;
26pub mod rename;
27pub mod rust_doc;
28pub mod search;
29pub mod source_change;
30pub mod symbol_index;
31pub mod text_edit;
32pub mod traits;
33pub mod ty_filter;
34pub mod use_trivial_constructor;
35
36pub mod imports {
37 pub mod import_assets;
38 pub mod insert_use;
39 pub mod merge_imports;
40}
41
42pub mod generated {
43 pub mod lints;
44}
45
46pub mod syntax_helpers {
47 pub mod format_string;
48 pub mod format_string_exprs;
49 pub mod tree_diff;
50 pub use hir::prettify_macro_expansion;
51 pub mod node_ext;
52 pub mod suggest_name;
53
54 pub use parser::LexedStr;
55}
56
57pub use hir::{ChangeWithProcMacros, EditionedFileId};
58use salsa::Durability;
59
60use std::{fmt, mem::ManuallyDrop};
61
62use base_db::{
63 CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, Nonce, SourceDatabase,
64 SourceRoot, SourceRootId, SourceRootInput, set_all_crates_with_durability,
65};
66use hir::{
67 FilePositionWrapper, FileRangeWrapper,
68 db::{DefDatabase, ExpandDatabase, HirDatabase},
69};
70use triomphe::Arc;
71
72use crate::line_index::LineIndex;
73pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
74
75pub use ::line_index;
76
77pub use base_db::{self, FxIndexMap, FxIndexSet, LibraryRoots, LocalRoots};
79pub use span::{self, FileId};
80
81pub type FilePosition = FilePositionWrapper<FileId>;
82pub type FileRange = FileRangeWrapper<FileId>;
83
84#[salsa_macros::db]
85pub struct RootDatabase {
86 storage: ManuallyDrop<salsa::Storage<Self>>,
93 files: Arc<Files>,
94 crates_map: Arc<CratesMap>,
95 nonce: Nonce,
96}
97
98impl std::panic::RefUnwindSafe for RootDatabase {}
99
100#[salsa_macros::db]
101impl salsa::Database for RootDatabase {}
102
103impl Drop for RootDatabase {
104 fn drop(&mut self) {
105 unsafe { ManuallyDrop::drop(&mut self.storage) };
106 }
107}
108
109impl Clone for RootDatabase {
110 fn clone(&self) -> Self {
111 Self {
112 storage: self.storage.clone(),
113 files: self.files.clone(),
114 crates_map: self.crates_map.clone(),
115 nonce: Nonce::new(),
116 }
117 }
118}
119
120impl fmt::Debug for RootDatabase {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 f.debug_struct("RootDatabase").finish()
123 }
124}
125
126#[salsa_macros::db]
127impl SourceDatabase for RootDatabase {
128 fn file_text(&self, file_id: vfs::FileId) -> FileText {
129 self.files.file_text(file_id)
130 }
131
132 fn set_file_text(&mut self, file_id: vfs::FileId, text: &str) {
133 let files = Arc::clone(&self.files);
134 files.set_file_text(self, file_id, text);
135 }
136
137 fn set_file_text_with_durability(
138 &mut self,
139 file_id: vfs::FileId,
140 text: &str,
141 durability: Durability,
142 ) {
143 let files = Arc::clone(&self.files);
144 files.set_file_text_with_durability(self, file_id, text, durability);
145 }
146
147 fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput {
149 self.files.source_root(source_root_id)
150 }
151
152 fn set_source_root_with_durability(
153 &mut self,
154 source_root_id: SourceRootId,
155 source_root: Arc<SourceRoot>,
156 durability: Durability,
157 ) {
158 let files = Arc::clone(&self.files);
159 files.set_source_root_with_durability(self, source_root_id, source_root, durability);
160 }
161
162 fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput {
163 self.files.file_source_root(id)
164 }
165
166 fn set_file_source_root_with_durability(
167 &mut self,
168 id: vfs::FileId,
169 source_root_id: SourceRootId,
170 durability: Durability,
171 ) {
172 let files = Arc::clone(&self.files);
173 files.set_file_source_root_with_durability(self, id, source_root_id, durability);
174 }
175
176 fn crates_map(&self) -> Arc<CratesMap> {
177 self.crates_map.clone()
178 }
179
180 fn nonce_and_revision(&self) -> (Nonce, salsa::Revision) {
181 (self.nonce, salsa::plumbing::ZalsaDatabase::zalsa(self).current_revision())
182 }
183}
184
185impl Default for RootDatabase {
186 fn default() -> RootDatabase {
187 RootDatabase::new(None)
188 }
189}
190
191impl RootDatabase {
192 pub fn new(lru_capacity: Option<u16>) -> RootDatabase {
193 let mut db = RootDatabase {
194 storage: ManuallyDrop::new(salsa::Storage::default()),
195 files: Default::default(),
196 crates_map: Default::default(),
197 nonce: Nonce::new(),
198 };
199 set_all_crates_with_durability(&mut db, std::iter::empty(), Durability::HIGH);
201 CrateGraphBuilder::default().set_in_db(&mut db);
202 db.set_proc_macros_with_durability(Default::default(), Durability::MEDIUM);
203 _ = base_db::LibraryRoots::builder(Default::default())
204 .durability(Durability::MEDIUM)
205 .new(&db);
206 _ = base_db::LocalRoots::builder(Default::default())
207 .durability(Durability::MEDIUM)
208 .new(&db);
209 db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH);
210 db.update_base_query_lru_capacities(lru_capacity);
211 db
212 }
213
214 pub fn enable_proc_attr_macros(&mut self) {
215 self.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
216 }
217
218 pub fn update_base_query_lru_capacities(&mut self, _lru_capacity: Option<u16>) {
219 }
227
228 pub fn update_lru_capacities(&mut self, _lru_capacities: &FxHashMap<Box<str>, u16>) {
229 }
253}
254
255pub fn line_index(db: &dyn SourceDatabase, file_id: FileId) -> &Arc<LineIndex> {
256 #[salsa::interned]
257 pub struct InternedFileId {
258 id: FileId,
259 }
260 #[salsa::tracked(returns(ref))]
261 fn line_index<'db>(
262 db: &'db dyn SourceDatabase,
263 file_id: InternedFileId<'db>,
264 ) -> Arc<LineIndex> {
265 let text = db.file_text(file_id.id(db)).text(db);
266 Arc::new(LineIndex::new(text))
267 }
268 line_index(db, InternedFileId::new(db, file_id))
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
272pub enum SymbolKind {
273 Attribute,
274 BuiltinAttr,
275 Const,
276 ConstParam,
277 CrateRoot,
278 Derive,
279 DeriveHelper,
280 Enum,
281 Field,
282 Function,
283 Method,
284 Impl,
285 InlineAsmRegOrRegClass,
286 Label,
287 LifetimeParam,
288 Local,
289 Macro,
290 ProcMacro,
291 Module,
292 SelfParam,
293 SelfType,
294 Static,
295 Struct,
296 ToolModule,
297 Trait,
298 TypeAlias,
299 TypeParam,
300 Union,
301 ValueParam,
302 Variant,
303}
304
305impl From<hir::MacroKind> for SymbolKind {
306 fn from(it: hir::MacroKind) -> Self {
307 match it {
308 hir::MacroKind::Declarative | hir::MacroKind::DeclarativeBuiltIn => SymbolKind::Macro,
309 hir::MacroKind::ProcMacro => SymbolKind::ProcMacro,
310 hir::MacroKind::Derive | hir::MacroKind::DeriveBuiltIn => SymbolKind::Derive,
311 hir::MacroKind::Attr | hir::MacroKind::AttrBuiltIn => SymbolKind::Attribute,
312 }
313 }
314}
315
316impl SymbolKind {
317 pub fn from_module_def(db: &dyn HirDatabase, it: hir::ModuleDef) -> Self {
318 match it {
319 hir::ModuleDef::Const(..) => SymbolKind::Const,
320 hir::ModuleDef::EnumVariant(..) => SymbolKind::Variant,
321 hir::ModuleDef::Function(..) => SymbolKind::Function,
322 hir::ModuleDef::Macro(mac) if mac.is_proc_macro() => SymbolKind::ProcMacro,
323 hir::ModuleDef::Macro(..) => SymbolKind::Macro,
324 hir::ModuleDef::Module(m) if m.is_crate_root(db) => SymbolKind::CrateRoot,
325 hir::ModuleDef::Module(..) => SymbolKind::Module,
326 hir::ModuleDef::Static(..) => SymbolKind::Static,
327 hir::ModuleDef::Adt(hir::Adt::Struct(..)) => SymbolKind::Struct,
328 hir::ModuleDef::Adt(hir::Adt::Enum(..)) => SymbolKind::Enum,
329 hir::ModuleDef::Adt(hir::Adt::Union(..)) => SymbolKind::Union,
330 hir::ModuleDef::Trait(..) => SymbolKind::Trait,
331 hir::ModuleDef::TypeAlias(..) => SymbolKind::TypeAlias,
332 hir::ModuleDef::BuiltinType(..) => SymbolKind::TypeAlias,
333 }
334 }
335}
336
337#[derive(Clone, Copy, Debug, PartialEq, Eq)]
338pub struct SnippetCap {
339 _private: (),
340}
341
342impl SnippetCap {
343 pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
344 if allow_snippets { Some(SnippetCap { _private: () }) } else { None }
345 }
346}
347
348pub struct Ranker<'a> {
349 pub kind: parser::SyntaxKind,
350 pub text: &'a str,
351 pub ident_kind: bool,
352}
353
354impl<'a> Ranker<'a> {
355 pub const MAX_RANK: usize = 0b1110;
356
357 pub fn from_token(token: &'a syntax::SyntaxToken) -> Self {
358 let kind = token.kind();
359 Ranker { kind, text: token.text(), ident_kind: kind.is_any_identifier() }
360 }
361
362 pub fn rank_token(&self, tok: &syntax::SyntaxToken) -> usize {
365 let tok_kind = tok.kind();
366
367 let exact_same_kind = tok_kind == self.kind;
368 let both_idents = exact_same_kind || (tok_kind.is_any_identifier() && self.ident_kind);
369 let same_text = tok.text() == self.text;
370 let no_tt_parent =
372 tok.parent().is_some_and(|it| it.kind() != parser::SyntaxKind::TOKEN_TREE);
373 (both_idents as usize)
374 | ((exact_same_kind as usize) << 1)
375 | ((same_text as usize) << 2)
376 | ((no_tt_parent as usize) << 3)
377 }
378}
379
380#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
381pub enum Severity {
382 Error,
383 Warning,
384 WeakWarning,
385 Allow,
386}
387
388#[derive(Clone, Copy)]
389pub struct MiniCore<'a>(&'a str);
390
391impl<'a> MiniCore<'a> {
392 #[inline]
393 pub fn new(minicore: &'a str) -> Self {
394 Self(minicore)
395 }
396
397 #[inline]
398 pub const fn default() -> Self {
399 Self(test_utils::MiniCore::RAW_SOURCE)
400 }
401}
402
403impl std::fmt::Debug for MiniCore<'_> {
404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405 f.debug_tuple("MiniCore")
406 .field(if self.0 == test_utils::MiniCore::RAW_SOURCE { &"<default>" } else { &self.0 })
408 .finish()
409 }
410}
411
412impl<'a> Default for MiniCore<'a> {
413 #[inline]
414 fn default() -> Self {
415 Self::default()
416 }
417}