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: self.nonce,
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 fn line_column(&self, file: FileId, offset: syntax::TextSize) -> Result<(u32, u32), ()> {
185 line_index(self, file).try_line_col(offset).map(|lc| (lc.line, lc.col)).ok_or(())
186 }
187}
188
189impl Default for RootDatabase {
190 fn default() -> RootDatabase {
191 RootDatabase::new(None)
192 }
193}
194
195impl RootDatabase {
196 pub fn new(lru_capacity: Option<u16>) -> RootDatabase {
197 let mut db = RootDatabase {
198 storage: ManuallyDrop::new(salsa::Storage::default()),
199 files: Default::default(),
200 crates_map: Default::default(),
201 nonce: Nonce::new(),
202 };
203 set_all_crates_with_durability(&mut db, std::iter::empty(), Durability::HIGH);
205 CrateGraphBuilder::default().set_in_db(&mut db);
206 db.set_proc_macros_with_durability(Default::default(), Durability::MEDIUM);
207 _ = base_db::LibraryRoots::builder(Default::default())
208 .durability(Durability::MEDIUM)
209 .new(&db);
210 _ = base_db::LocalRoots::builder(Default::default())
211 .durability(Durability::MEDIUM)
212 .new(&db);
213 db.set_expand_proc_attr_macros_with_durability(false, Durability::HIGH);
214 db.update_base_query_lru_capacities(lru_capacity);
215 db
216 }
217
218 pub fn enable_proc_attr_macros(&mut self) {
219 self.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
220 }
221
222 pub fn update_base_query_lru_capacities(&mut self, _lru_capacity: Option<u16>) {
223 }
231
232 pub fn update_lru_capacities(&mut self, _lru_capacities: &FxHashMap<Box<str>, u16>) {
233 }
257}
258
259pub fn line_index(db: &dyn SourceDatabase, file_id: FileId) -> &Arc<LineIndex> {
260 #[salsa::interned]
261 pub struct InternedFileId {
262 id: FileId,
263 }
264 #[salsa::tracked(returns(ref))]
265 fn line_index<'db>(
266 db: &'db dyn SourceDatabase,
267 file_id: InternedFileId<'db>,
268 ) -> Arc<LineIndex> {
269 let text = db.file_text(file_id.id(db)).text(db);
270 Arc::new(LineIndex::new(text))
271 }
272 line_index(db, InternedFileId::new(db, file_id))
273}
274
275#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
276pub enum SymbolKind {
277 Attribute,
278 BuiltinAttr,
279 Const,
280 ConstParam,
281 CrateRoot,
282 Derive,
283 DeriveHelper,
284 Enum,
285 Field,
286 Function,
287 Method,
288 Impl,
289 InlineAsmRegOrRegClass,
290 Label,
291 LifetimeParam,
292 Local,
293 Macro,
294 ProcMacro,
295 Module,
296 SelfParam,
297 SelfType,
298 Static,
299 Struct,
300 ToolModule,
301 Trait,
302 TypeAlias,
303 TypeParam,
304 Union,
305 ValueParam,
306 Variant,
307}
308
309impl From<hir::MacroKind> for SymbolKind {
310 fn from(it: hir::MacroKind) -> Self {
311 match it {
312 hir::MacroKind::Declarative | hir::MacroKind::DeclarativeBuiltIn => SymbolKind::Macro,
313 hir::MacroKind::ProcMacro => SymbolKind::ProcMacro,
314 hir::MacroKind::Derive | hir::MacroKind::DeriveBuiltIn => SymbolKind::Derive,
315 hir::MacroKind::Attr | hir::MacroKind::AttrBuiltIn => SymbolKind::Attribute,
316 }
317 }
318}
319
320impl SymbolKind {
321 pub fn from_module_def(db: &dyn HirDatabase, it: hir::ModuleDef) -> Self {
322 match it {
323 hir::ModuleDef::Const(..) => SymbolKind::Const,
324 hir::ModuleDef::EnumVariant(..) => SymbolKind::Variant,
325 hir::ModuleDef::Function(..) => SymbolKind::Function,
326 hir::ModuleDef::Macro(mac) if mac.is_proc_macro() => SymbolKind::ProcMacro,
327 hir::ModuleDef::Macro(..) => SymbolKind::Macro,
328 hir::ModuleDef::Module(m) if m.is_crate_root(db) => SymbolKind::CrateRoot,
329 hir::ModuleDef::Module(..) => SymbolKind::Module,
330 hir::ModuleDef::Static(..) => SymbolKind::Static,
331 hir::ModuleDef::Adt(hir::Adt::Struct(..)) => SymbolKind::Struct,
332 hir::ModuleDef::Adt(hir::Adt::Enum(..)) => SymbolKind::Enum,
333 hir::ModuleDef::Adt(hir::Adt::Union(..)) => SymbolKind::Union,
334 hir::ModuleDef::Trait(..) => SymbolKind::Trait,
335 hir::ModuleDef::TypeAlias(..) => SymbolKind::TypeAlias,
336 hir::ModuleDef::BuiltinType(..) => SymbolKind::TypeAlias,
337 }
338 }
339}
340
341#[derive(Clone, Copy, Debug, PartialEq, Eq)]
342pub struct SnippetCap {
343 _private: (),
344}
345
346impl SnippetCap {
347 pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
348 if allow_snippets { Some(SnippetCap { _private: () }) } else { None }
349 }
350}
351
352pub struct Ranker<'a> {
353 pub kind: parser::SyntaxKind,
354 pub text: &'a str,
355 pub ident_kind: bool,
356}
357
358impl<'a> Ranker<'a> {
359 pub const MAX_RANK: usize = 0b1110;
360
361 pub fn from_token(token: &'a syntax::SyntaxToken) -> Self {
362 let kind = token.kind();
363 Ranker { kind, text: token.text(), ident_kind: kind.is_any_identifier() }
364 }
365
366 pub fn rank_token(&self, tok: &syntax::SyntaxToken) -> usize {
369 let tok_kind = tok.kind();
370
371 let exact_same_kind = tok_kind == self.kind;
372 let both_idents = exact_same_kind || (tok_kind.is_any_identifier() && self.ident_kind);
373 let same_text = tok.text() == self.text;
374 let no_tt_parent =
376 tok.parent().is_some_and(|it| it.kind() != parser::SyntaxKind::TOKEN_TREE);
377 (both_idents as usize)
378 | ((exact_same_kind as usize) << 1)
379 | ((same_text as usize) << 2)
380 | ((no_tt_parent as usize) << 3)
381 }
382}
383
384#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
385pub enum Severity {
386 Error,
387 Warning,
388 WeakWarning,
389 Allow,
390}
391
392#[derive(Clone, Copy)]
393pub struct MiniCore<'a>(&'a str);
394
395impl<'a> MiniCore<'a> {
396 #[inline]
397 pub fn new(minicore: &'a str) -> Self {
398 Self(minicore)
399 }
400
401 #[inline]
402 pub const fn default() -> Self {
403 Self(test_utils::MiniCore::RAW_SOURCE)
404 }
405}
406
407impl std::fmt::Debug for MiniCore<'_> {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 let mut d = f.debug_tuple("MiniCore");
410 if self.0 == test_utils::MiniCore::RAW_SOURCE {
411 d.field(&format_args!("<default>"));
415 } else {
416 d.field(&self.0);
417 };
418 d.finish()
419 }
420}
421
422impl<'a> Default for MiniCore<'a> {
423 #[inline]
424 fn default() -> Self {
425 Self::default()
426 }
427}