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