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