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, RootQueryDb,
64 SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, query_group,
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 db.set_all_crates(Arc::new(Box::new([])));
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
255#[query_group::query_group]
256pub trait LineIndexDatabase: base_db::RootQueryDb {
257 #[salsa::invoke_interned(line_index)]
258 fn line_index(&self, file_id: FileId) -> Arc<LineIndex>;
259}
260
261fn line_index(db: &dyn LineIndexDatabase, file_id: FileId) -> Arc<LineIndex> {
262 let text = db.file_text(file_id).text(db);
263 Arc::new(LineIndex::new(text))
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
267pub enum SymbolKind {
268 Attribute,
269 BuiltinAttr,
270 Const,
271 ConstParam,
272 CrateRoot,
273 Derive,
274 DeriveHelper,
275 Enum,
276 Field,
277 Function,
278 Method,
279 Impl,
280 InlineAsmRegOrRegClass,
281 Label,
282 LifetimeParam,
283 Local,
284 Macro,
285 ProcMacro,
286 Module,
287 SelfParam,
288 SelfType,
289 Static,
290 Struct,
291 ToolModule,
292 Trait,
293 TypeAlias,
294 TypeParam,
295 Union,
296 ValueParam,
297 Variant,
298}
299
300impl From<hir::MacroKind> for SymbolKind {
301 fn from(it: hir::MacroKind) -> Self {
302 match it {
303 hir::MacroKind::Declarative | hir::MacroKind::DeclarativeBuiltIn => SymbolKind::Macro,
304 hir::MacroKind::ProcMacro => SymbolKind::ProcMacro,
305 hir::MacroKind::Derive | hir::MacroKind::DeriveBuiltIn => SymbolKind::Derive,
306 hir::MacroKind::Attr | hir::MacroKind::AttrBuiltIn => SymbolKind::Attribute,
307 }
308 }
309}
310
311impl SymbolKind {
312 pub fn from_module_def(db: &dyn HirDatabase, it: hir::ModuleDef) -> Self {
313 match it {
314 hir::ModuleDef::Const(..) => SymbolKind::Const,
315 hir::ModuleDef::Variant(..) => SymbolKind::Variant,
316 hir::ModuleDef::Function(..) => SymbolKind::Function,
317 hir::ModuleDef::Macro(mac) if mac.is_proc_macro() => SymbolKind::ProcMacro,
318 hir::ModuleDef::Macro(..) => SymbolKind::Macro,
319 hir::ModuleDef::Module(m) if m.is_crate_root(db) => SymbolKind::CrateRoot,
320 hir::ModuleDef::Module(..) => SymbolKind::Module,
321 hir::ModuleDef::Static(..) => SymbolKind::Static,
322 hir::ModuleDef::Adt(hir::Adt::Struct(..)) => SymbolKind::Struct,
323 hir::ModuleDef::Adt(hir::Adt::Enum(..)) => SymbolKind::Enum,
324 hir::ModuleDef::Adt(hir::Adt::Union(..)) => SymbolKind::Union,
325 hir::ModuleDef::Trait(..) => SymbolKind::Trait,
326 hir::ModuleDef::TypeAlias(..) => SymbolKind::TypeAlias,
327 hir::ModuleDef::BuiltinType(..) => SymbolKind::TypeAlias,
328 }
329 }
330}
331
332#[derive(Clone, Copy, Debug, PartialEq, Eq)]
333pub struct SnippetCap {
334 _private: (),
335}
336
337impl SnippetCap {
338 pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
339 if allow_snippets { Some(SnippetCap { _private: () }) } else { None }
340 }
341}
342
343pub struct Ranker<'a> {
344 pub kind: parser::SyntaxKind,
345 pub text: &'a str,
346 pub ident_kind: bool,
347}
348
349impl<'a> Ranker<'a> {
350 pub const MAX_RANK: usize = 0b1110;
351
352 pub fn from_token(token: &'a syntax::SyntaxToken) -> Self {
353 let kind = token.kind();
354 Ranker { kind, text: token.text(), ident_kind: kind.is_any_identifier() }
355 }
356
357 pub fn rank_token(&self, tok: &syntax::SyntaxToken) -> usize {
360 let tok_kind = tok.kind();
361
362 let exact_same_kind = tok_kind == self.kind;
363 let both_idents = exact_same_kind || (tok_kind.is_any_identifier() && self.ident_kind);
364 let same_text = tok.text() == self.text;
365 let no_tt_parent =
367 tok.parent().is_some_and(|it| it.kind() != parser::SyntaxKind::TOKEN_TREE);
368 (both_idents as usize)
369 | ((exact_same_kind as usize) << 1)
370 | ((same_text as usize) << 2)
371 | ((no_tt_parent as usize) << 3)
372 }
373}
374
375#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
376pub enum Severity {
377 Error,
378 Warning,
379 WeakWarning,
380 Allow,
381}
382
383#[derive(Debug, Clone, Copy)]
384pub struct MiniCore<'a>(&'a str);
385
386impl<'a> MiniCore<'a> {
387 #[inline]
388 pub fn new(minicore: &'a str) -> Self {
389 Self(minicore)
390 }
391
392 #[inline]
393 pub const fn default() -> Self {
394 Self(test_utils::MiniCore::RAW_SOURCE)
395 }
396}
397
398impl<'a> Default for MiniCore<'a> {
399 #[inline]
400 fn default() -> Self {
401 Self::default()
402 }
403}