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