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::{FilePositionWrapper, FileRangeWrapper, db::HirDatabase};
67use triomphe::Arc;
68
69use crate::line_index::LineIndex;
70pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
71
72pub use ::line_index;
73
74pub use base_db::{self, FxIndexMap, FxIndexSet, LibraryRoots, LocalRoots};
76pub use span::{self, FileId};
77
78pub type FilePosition = FilePositionWrapper<FileId>;
79pub type FileRange = FileRangeWrapper<FileId>;
80
81#[salsa::db]
82pub struct RootDatabase {
83 storage: ManuallyDrop<salsa::Storage<Self>>,
90 files: Arc<Files>,
91 crates_map: Arc<CratesMap>,
92 nonce: Nonce,
93}
94
95impl std::panic::RefUnwindSafe for RootDatabase {}
96
97#[salsa::db]
98impl salsa::Database for RootDatabase {}
99
100impl Drop for RootDatabase {
101 fn drop(&mut self) {
102 unsafe { ManuallyDrop::drop(&mut self.storage) };
103 }
104}
105
106impl Clone for RootDatabase {
107 fn clone(&self) -> Self {
108 Self {
109 storage: self.storage.clone(),
110 files: self.files.clone(),
111 crates_map: self.crates_map.clone(),
112 nonce: self.nonce,
113 }
114 }
115}
116
117impl fmt::Debug for RootDatabase {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 f.debug_struct("RootDatabase").finish()
120 }
121}
122
123#[salsa::db]
124impl SourceDatabase for RootDatabase {
125 fn file_text(&self, file_id: vfs::FileId) -> FileText {
126 self.files.file_text(file_id)
127 }
128
129 fn set_file_text(&mut self, file_id: vfs::FileId, text: &str) {
130 let files = Arc::clone(&self.files);
131 files.set_file_text(self, file_id, text);
132 }
133
134 fn set_file_text_with_durability(
135 &mut self,
136 file_id: vfs::FileId,
137 text: &str,
138 durability: Durability,
139 ) {
140 let files = Arc::clone(&self.files);
141 files.set_file_text_with_durability(self, file_id, text, durability);
142 }
143
144 fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput {
146 self.files.source_root(source_root_id)
147 }
148
149 fn set_source_root_with_durability(
150 &mut self,
151 source_root_id: SourceRootId,
152 source_root: Arc<SourceRoot>,
153 durability: Durability,
154 ) {
155 let files = Arc::clone(&self.files);
156 files.set_source_root_with_durability(self, source_root_id, source_root, durability);
157 }
158
159 fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput {
160 self.files.file_source_root(self, id)
161 }
162
163 fn set_file_source_root_with_durability(
164 &mut self,
165 id: vfs::FileId,
166 source_root_id: SourceRootId,
167 durability: Durability,
168 ) {
169 let files = Arc::clone(&self.files);
170 files.set_file_source_root_with_durability(self, id, source_root_id, durability);
171 }
172
173 fn crates_map(&self) -> Arc<CratesMap> {
174 self.crates_map.clone()
175 }
176
177 fn nonce_and_revision(&self) -> (Nonce, salsa::Revision) {
178 (self.nonce, salsa::plumbing::ZalsaDatabase::zalsa(self).current_revision())
179 }
180
181 fn line_column(&self, file: FileId, offset: syntax::TextSize) -> Result<(u32, u32), ()> {
182 line_index(self, file).try_line_col(offset).map(|lc| (lc.line, lc.col)).ok_or(())
183 }
184}
185
186hir::impl_hir_database!(RootDatabase);
187
188impl Default for RootDatabase {
189 fn default() -> RootDatabase {
190 RootDatabase::new(None)
191 }
192}
193
194impl RootDatabase {
195 pub fn new(lru_capacity: Option<u16>) -> RootDatabase {
196 let mut db = RootDatabase {
197 storage: ManuallyDrop::new(salsa::Storage::default()),
198 files: Default::default(),
199 crates_map: Default::default(),
200 nonce: Nonce::new(),
201 };
202 set_all_crates_with_durability(&mut db, std::iter::empty(), Durability::HIGH);
204 CrateGraphBuilder::default().set_in_db(&mut db);
205 hir::ProcMacros::init_default(&db, Durability::MEDIUM);
206 _ = base_db::LibraryRoots::builder(Default::default())
207 .durability(Durability::MEDIUM)
208 .new(&db);
209 _ = base_db::LocalRoots::builder(Default::default())
210 .durability(Durability::MEDIUM)
211 .new(&db);
212 hir::db::set_expand_proc_attr_macros(&mut db, false);
213 db.update_base_query_lru_capacities(lru_capacity);
214 db
215 }
216
217 pub fn enable_proc_attr_macros(&mut self) {
218 hir::db::set_expand_proc_attr_macros(self, true);
219 }
220
221 pub fn update_base_query_lru_capacities(&mut self, _lru_capacity: Option<u16>) {
222 }
230
231 pub fn update_lru_capacities(&mut self, _lru_capacities: &FxHashMap<Box<str>, u16>) {
232 }
256}
257
258pub fn line_index(db: &dyn SourceDatabase, file_id: FileId) -> &Arc<LineIndex> {
259 #[salsa::interned]
260 pub struct InternedFileId {
261 #[returns(copy)]
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}