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