1use std::collections::VecDeque;
2use std::sync::Arc;
3
4use cairo_lang_diagnostics::{DiagnosticNote, Maybe, PluginFileDiagnosticNotes, ToMaybe};
5use cairo_lang_filesystem::ids::{CrateId, Directory, FileId, FileKind, FileLongId, VirtualFile};
6use cairo_lang_parser::db::ParserGroup;
7use cairo_lang_syntax::attribute::consts::{
8 ALLOW_ATTR, ALLOW_ATTR_ATTR, DEPRECATED_ATTR, FEATURE_ATTR, FMT_SKIP_ATTR,
9 IMPLICIT_PRECEDENCE_ATTR, INLINE_ATTR, INTERNAL_ATTR, MUST_USE_ATTR, PHANTOM_ATTR,
10 STARKNET_INTERFACE_ATTR, UNSTABLE_ATTR,
11};
12use cairo_lang_syntax::attribute::structured::AttributeStructurize;
13use cairo_lang_syntax::node::ast::MaybeModuleBody;
14use cairo_lang_syntax::node::db::SyntaxGroup;
15use cairo_lang_syntax::node::helpers::QueryAttrs;
16use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
17use cairo_lang_syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode, ast};
18use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
19use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
20use cairo_lang_utils::{Intern, LookupIntern};
21use itertools::{Itertools, chain};
22use salsa::InternKey;
23
24use crate::cache::{DefCacheLoadingData, load_cached_crate_modules};
25use crate::ids::*;
26use crate::plugin::{DynGeneratedFileAuxData, MacroPlugin, MacroPluginMetadata, PluginDiagnostic};
27use crate::plugin_utils::try_extract_unnamed_arg;
28
29#[salsa::query_group(DefsDatabase)]
32pub trait DefsGroup: ParserGroup {
33 #[salsa::interned]
34 fn intern_constant(&self, id: ConstantLongId) -> ConstantId;
35 #[salsa::interned]
36 fn intern_submodule(&self, id: SubmoduleLongId) -> SubmoduleId;
37 #[salsa::interned]
38 fn intern_use(&self, id: UseLongId) -> UseId;
39 #[salsa::interned]
40 fn intern_global_use(&self, id: GlobalUseLongId) -> GlobalUseId;
41 #[salsa::interned]
42 fn intern_free_function(&self, id: FreeFunctionLongId) -> FreeFunctionId;
43 #[salsa::interned]
44 fn intern_impl_type_def(&self, id: ImplTypeDefLongId) -> ImplTypeDefId;
45 #[salsa::interned]
46 fn intern_impl_constant_def(&self, id: ImplConstantDefLongId) -> ImplConstantDefId;
47 #[salsa::interned]
48 fn intern_impl_impl_def(&self, id: ImplImplDefLongId) -> ImplImplDefId;
49 #[salsa::interned]
50 fn intern_impl_function(&self, id: ImplFunctionLongId) -> ImplFunctionId;
51 #[salsa::interned]
52 fn intern_struct(&self, id: StructLongId) -> StructId;
53 #[salsa::interned]
54 fn intern_enum(&self, id: EnumLongId) -> EnumId;
55 #[salsa::interned]
56 fn intern_module_type_alias(&self, id: ModuleTypeAliasLongId) -> ModuleTypeAliasId;
57 #[salsa::interned]
58 fn intern_impl_alias(&self, id: ImplAliasLongId) -> ImplAliasId;
59 #[salsa::interned]
60 fn intern_member(&self, id: MemberLongId) -> MemberId;
61 #[salsa::interned]
62 fn intern_variant(&self, id: VariantLongId) -> VariantId;
63 #[salsa::interned]
64 fn intern_trait(&self, id: TraitLongId) -> TraitId;
65 #[salsa::interned]
66 fn intern_trait_type(&self, id: TraitTypeLongId) -> TraitTypeId;
67 #[salsa::interned]
68 fn intern_trait_constant(&self, id: TraitConstantLongId) -> TraitConstantId;
69 #[salsa::interned]
70 fn intern_trait_impl(&self, id: TraitImplLongId) -> TraitImplId;
71 #[salsa::interned]
72 fn intern_trait_function(&self, id: TraitFunctionLongId) -> TraitFunctionId;
73 #[salsa::interned]
74 fn intern_impl_def(&self, id: ImplDefLongId) -> ImplDefId;
75 #[salsa::interned]
76 fn intern_extern_type(&self, id: ExternTypeLongId) -> ExternTypeId;
77 #[salsa::interned]
78 fn intern_extern_function(&self, id: ExternFunctionLongId) -> ExternFunctionId;
79 #[salsa::interned]
80 fn intern_macro_declaration(&self, id: MacroDeclarationLongId) -> MacroDeclarationId;
81 #[salsa::interned]
82 fn intern_param(&self, id: ParamLongId) -> ParamId;
83 #[salsa::interned]
84 fn intern_generic_param(&self, id: GenericParamLongId) -> GenericParamId;
85 #[salsa::interned]
86 fn intern_local_var(&self, id: LocalVarLongId) -> LocalVarId;
87 #[salsa::interned]
88 fn intern_statement_const(&self, id: StatementConstLongId) -> StatementConstId;
89 #[salsa::interned]
90 fn intern_statement_use(&self, id: StatementUseLongId) -> StatementUseId;
91 #[salsa::interned]
92 fn intern_plugin_generated_file(&self, id: PluginGeneratedFileLongId) -> PluginGeneratedFileId;
93
94 #[salsa::input]
98 fn default_macro_plugins(&self) -> Arc<[MacroPluginId]>;
99
100 #[salsa::input]
101 fn macro_plugin_overrides(&self) -> Arc<OrderedHashMap<CrateId, Arc<[MacroPluginId]>>>;
102
103 #[salsa::interned]
104 fn intern_macro_plugin(&self, plugin: MacroPluginLongId) -> MacroPluginId;
105
106 fn crate_macro_plugins(&self, crate_id: CrateId) -> Arc<[MacroPluginId]>;
111
112 #[salsa::input]
113 fn default_inline_macro_plugins(&self) -> Arc<OrderedHashMap<String, InlineMacroExprPluginId>>;
114
115 #[salsa::input]
116 fn inline_macro_plugin_overrides(
117 &self,
118 ) -> Arc<OrderedHashMap<CrateId, Arc<OrderedHashMap<String, InlineMacroExprPluginId>>>>;
119
120 #[salsa::interned]
121 fn intern_inline_macro_plugin(
122 &self,
123 plugin: InlineMacroExprPluginLongId,
124 ) -> InlineMacroExprPluginId;
125
126 fn crate_inline_macro_plugins(
131 &self,
132 crate_id: CrateId,
133 ) -> Arc<OrderedHashMap<String, InlineMacroExprPluginId>>;
134
135 fn allowed_attributes(&self, crate_id: CrateId) -> Arc<OrderedHashSet<String>>;
138
139 fn allowed_statement_attributes(&self) -> Arc<OrderedHashSet<String>>;
142
143 fn declared_derives(&self, crate_id: CrateId) -> Arc<OrderedHashSet<String>>;
146
147 fn declared_phantom_type_attributes(&self, crate_id: CrateId) -> Arc<OrderedHashSet<String>>;
150
151 fn is_submodule_inline(&self, submodule_id: SubmoduleId) -> bool;
153
154 fn module_main_file(&self, module_id: ModuleId) -> Maybe<FileId>;
158 fn module_files(&self, module_id: ModuleId) -> Maybe<Arc<[FileId]>>;
160 fn module_file(&self, module_id: ModuleFileId) -> Maybe<FileId>;
162 fn module_dir(&self, module_id: ModuleId) -> Maybe<Directory>;
164
165 fn crate_modules(&self, crate_id: CrateId) -> Arc<[ModuleId]>;
167 fn priv_file_to_module_mapping(&self) -> Arc<OrderedHashMap<FileId, Vec<ModuleId>>>;
168 fn file_modules(&self, file_id: FileId) -> Maybe<Arc<[ModuleId]>>;
169
170 fn cached_crate_modules(&self, crate_id: CrateId) -> Option<ModuleDataCacheAndLoadingData>;
173 fn priv_module_data(&self, module_id: ModuleId) -> Maybe<ModuleData>;
175 fn priv_module_sub_files(
177 &self,
178 module_id: ModuleId,
179 file_id: FileId,
180 ) -> Maybe<Arc<PrivModuleSubFiles>>;
181 fn module_submodules(
182 &self,
183 module_id: ModuleId,
184 ) -> Maybe<Arc<OrderedHashMap<SubmoduleId, ast::ItemModule>>>;
185 fn module_submodules_ids(&self, module_id: ModuleId) -> Maybe<Arc<[SubmoduleId]>>;
186 fn module_constants(
187 &self,
188 module_id: ModuleId,
189 ) -> Maybe<Arc<OrderedHashMap<ConstantId, ast::ItemConstant>>>;
190 fn module_constants_ids(&self, module_id: ModuleId) -> Maybe<Arc<[ConstantId]>>;
191 fn module_constant_by_id(&self, constant_id: ConstantId) -> Maybe<Option<ast::ItemConstant>>;
192 fn module_free_functions(
193 &self,
194 module_id: ModuleId,
195 ) -> Maybe<Arc<OrderedHashMap<FreeFunctionId, ast::FunctionWithBody>>>;
196 fn module_free_functions_ids(&self, module_id: ModuleId) -> Maybe<Arc<[FreeFunctionId]>>;
197 fn module_free_function_by_id(
198 &self,
199 free_function_id: FreeFunctionId,
200 ) -> Maybe<Option<ast::FunctionWithBody>>;
201 fn module_items(&self, module_id: ModuleId) -> Maybe<Arc<[ModuleItemId]>>;
202 fn module_global_uses(
203 &self,
204 module_id: ModuleId,
205 ) -> Maybe<Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>>;
206 fn module_item_name_stable_ptr(
208 &self,
209 module_id: ModuleId,
210 item_id: ModuleItemId,
211 ) -> Maybe<SyntaxStablePtrId>;
212 fn module_uses(
213 &self,
214 module_id: ModuleId,
215 ) -> Maybe<Arc<OrderedHashMap<UseId, ast::UsePathLeaf>>>;
216 fn module_uses_ids(&self, module_id: ModuleId) -> Maybe<Arc<[UseId]>>;
217 fn module_use_by_id(&self, use_id: UseId) -> Maybe<Option<ast::UsePathLeaf>>;
218 fn module_global_use_by_id(
219 &self,
220 global_use_id: GlobalUseId,
221 ) -> Maybe<Option<ast::UsePathStar>>;
222 fn module_structs(
223 &self,
224 module_id: ModuleId,
225 ) -> Maybe<Arc<OrderedHashMap<StructId, ast::ItemStruct>>>;
226 fn module_structs_ids(&self, module_id: ModuleId) -> Maybe<Arc<[StructId]>>;
227 fn module_struct_by_id(&self, struct_id: StructId) -> Maybe<Option<ast::ItemStruct>>;
228 fn module_enums(
229 &self,
230 module_id: ModuleId,
231 ) -> Maybe<Arc<OrderedHashMap<EnumId, ast::ItemEnum>>>;
232 fn module_enums_ids(&self, module_id: ModuleId) -> Maybe<Arc<[EnumId]>>;
233 fn module_enum_by_id(&self, enum_id: EnumId) -> Maybe<Option<ast::ItemEnum>>;
234 fn module_type_aliases(
235 &self,
236 module_id: ModuleId,
237 ) -> Maybe<Arc<OrderedHashMap<ModuleTypeAliasId, ast::ItemTypeAlias>>>;
238 fn module_type_aliases_ids(&self, module_id: ModuleId) -> Maybe<Arc<[ModuleTypeAliasId]>>;
239 fn module_type_alias_by_id(
240 &self,
241 module_type_alias_id: ModuleTypeAliasId,
242 ) -> Maybe<Option<ast::ItemTypeAlias>>;
243 fn module_impl_aliases(
244 &self,
245 module_id: ModuleId,
246 ) -> Maybe<Arc<OrderedHashMap<ImplAliasId, ast::ItemImplAlias>>>;
247 fn module_impl_aliases_ids(&self, module_id: ModuleId) -> Maybe<Arc<[ImplAliasId]>>;
248 fn module_impl_alias_by_id(
249 &self,
250 impl_alias_id: ImplAliasId,
251 ) -> Maybe<Option<ast::ItemImplAlias>>;
252 fn module_traits(
253 &self,
254 module_id: ModuleId,
255 ) -> Maybe<Arc<OrderedHashMap<TraitId, ast::ItemTrait>>>;
256 fn module_traits_ids(&self, module_id: ModuleId) -> Maybe<Arc<[TraitId]>>;
257 fn module_trait_by_id(&self, trait_id: TraitId) -> Maybe<Option<ast::ItemTrait>>;
258 fn module_impls(
259 &self,
260 module_id: ModuleId,
261 ) -> Maybe<Arc<OrderedHashMap<ImplDefId, ast::ItemImpl>>>;
262 fn module_impls_ids(&self, module_id: ModuleId) -> Maybe<Arc<[ImplDefId]>>;
263 fn module_impl_by_id(&self, impl_id: ImplDefId) -> Maybe<Option<ast::ItemImpl>>;
264 fn module_extern_types(
265 &self,
266 module_id: ModuleId,
267 ) -> Maybe<Arc<OrderedHashMap<ExternTypeId, ast::ItemExternType>>>;
268 fn module_extern_types_ids(&self, module_id: ModuleId) -> Maybe<Arc<[ExternTypeId]>>;
269 fn module_extern_type_by_id(
270 &self,
271 extern_type_id: ExternTypeId,
272 ) -> Maybe<Option<ast::ItemExternType>>;
273 fn module_extern_functions(
274 &self,
275 module_id: ModuleId,
276 ) -> Maybe<Arc<OrderedHashMap<ExternFunctionId, ast::ItemExternFunction>>>;
277 fn module_extern_functions_ids(&self, module_id: ModuleId) -> Maybe<Arc<[ExternFunctionId]>>;
278 fn module_extern_function_by_id(
279 &self,
280 extern_function_id: ExternFunctionId,
281 ) -> Maybe<Option<ast::ItemExternFunction>>;
282 fn module_macro_declarations(
284 &self,
285 module_id: ModuleId,
286 ) -> Maybe<Arc<OrderedHashMap<MacroDeclarationId, ast::ItemMacroDeclaration>>>;
287 fn module_macro_declarations_ids(
289 &self,
290 module_id: ModuleId,
291 ) -> Maybe<Arc<[MacroDeclarationId]>>;
292 fn module_macro_declaration_by_id(
294 &self,
295 macro_declaration_id: MacroDeclarationId,
296 ) -> Maybe<Option<ast::ItemMacroDeclaration>>;
297 fn module_ancestors(&self, module_id: ModuleId) -> OrderedHashSet<ModuleId>;
298 fn module_generated_file_aux_data(
299 &self,
300 module_id: ModuleId,
301 ) -> Maybe<Arc<[Option<DynGeneratedFileAuxData>]>>;
302 fn module_plugin_diagnostics(
303 &self,
304 module_id: ModuleId,
305 ) -> Maybe<Arc<[(ModuleFileId, PluginDiagnostic)]>>;
306 fn module_plugin_diagnostics_notes(
309 &self,
310 module_id: ModuleId,
311 ) -> Maybe<Arc<PluginFileDiagnosticNotes>>;
312}
313
314pub fn init_defs_group(db: &mut dyn DefsGroup) {
316 db.set_macro_plugin_overrides(Arc::new(OrderedHashMap::default()));
317 db.set_inline_macro_plugin_overrides(Arc::new(OrderedHashMap::default()));
318}
319
320fn crate_macro_plugins(db: &dyn DefsGroup, crate_id: CrateId) -> Arc<[MacroPluginId]> {
321 db.macro_plugin_overrides()
322 .get(&crate_id)
323 .cloned()
324 .unwrap_or_else(|| db.default_macro_plugins())
325}
326
327fn crate_inline_macro_plugins(
328 db: &dyn DefsGroup,
329 crate_id: CrateId,
330) -> Arc<OrderedHashMap<String, InlineMacroExprPluginId>> {
331 db.inline_macro_plugin_overrides()
332 .get(&crate_id)
333 .cloned()
334 .unwrap_or_else(|| db.default_inline_macro_plugins())
335}
336
337fn allowed_attributes(db: &dyn DefsGroup, crate_id: CrateId) -> Arc<OrderedHashSet<String>> {
338 let base_attrs = [
339 INLINE_ATTR,
340 MUST_USE_ATTR,
341 UNSTABLE_ATTR,
342 DEPRECATED_ATTR,
343 INTERNAL_ATTR,
344 ALLOW_ATTR,
345 ALLOW_ATTR_ATTR,
346 FEATURE_ATTR,
347 PHANTOM_ATTR,
348 IMPLICIT_PRECEDENCE_ATTR,
349 FMT_SKIP_ATTR,
350 STARKNET_INTERFACE_ATTR,
352 ];
353
354 let crate_plugins = db.crate_macro_plugins(crate_id);
355
356 Arc::new(OrderedHashSet::from_iter(chain!(
357 base_attrs.map(|attr| attr.into()),
358 crate_plugins
359 .iter()
360 .flat_map(|plugin| db.lookup_intern_macro_plugin(*plugin).declared_attributes())
361 )))
362}
363
364fn allowed_statement_attributes(_db: &dyn DefsGroup) -> Arc<OrderedHashSet<String>> {
365 let all_attributes = [FMT_SKIP_ATTR, ALLOW_ATTR, FEATURE_ATTR];
366 Arc::new(OrderedHashSet::from_iter(all_attributes.map(|attr| attr.into())))
367}
368
369fn declared_derives(db: &dyn DefsGroup, crate_id: CrateId) -> Arc<OrderedHashSet<String>> {
370 Arc::new(OrderedHashSet::from_iter(
371 db.crate_macro_plugins(crate_id)
372 .iter()
373 .flat_map(|plugin| db.lookup_intern_macro_plugin(*plugin).declared_derives()),
374 ))
375}
376
377fn declared_phantom_type_attributes(
378 db: &dyn DefsGroup,
379 crate_id: CrateId,
380) -> Arc<OrderedHashSet<String>> {
381 let crate_plugins = db.crate_macro_plugins(crate_id);
382
383 Arc::new(OrderedHashSet::from_iter(chain!(
384 [PHANTOM_ATTR.into()],
385 crate_plugins
386 .iter()
387 .flat_map(|plugin| db.lookup_intern_macro_plugin(*plugin).phantom_type_attributes())
388 )))
389}
390
391fn is_submodule_inline(db: &dyn DefsGroup, submodule_id: SubmoduleId) -> bool {
392 match submodule_id.stable_ptr(db).lookup(db).body(db) {
393 MaybeModuleBody::Some(_) => true,
394 MaybeModuleBody::None(_) => false,
395 }
396}
397
398fn module_main_file(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<FileId> {
399 Ok(match module_id {
400 ModuleId::CrateRoot(crate_id) => {
401 db.crate_config(crate_id).to_maybe()?.root.file(db, "lib.cairo".into())
402 }
403 ModuleId::Submodule(submodule_id) => {
404 let parent = submodule_id.parent_module(db);
405 if db.is_submodule_inline(submodule_id) {
406 db.module_file(submodule_id.module_file_id(db))?
410 } else {
411 let name = submodule_id.name(db);
412 db.module_dir(parent)?.file(db, format!("{name}.cairo").into())
413 }
414 }
415 })
416}
417
418fn module_files(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[FileId]>> {
419 Ok(db.priv_module_data(module_id)?.files)
420}
421
422fn module_file(db: &dyn DefsGroup, module_file_id: ModuleFileId) -> Maybe<FileId> {
423 Ok(db.module_files(module_file_id.0)?[module_file_id.1.0])
424}
425
426fn module_dir(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Directory> {
427 match module_id {
428 ModuleId::CrateRoot(crate_id) => {
429 db.crate_config(crate_id).to_maybe().map(|config| config.root)
430 }
431 ModuleId::Submodule(submodule_id) => {
432 let parent = submodule_id.parent_module(db);
433 let name = submodule_id.name(db);
434 Ok(db.module_dir(parent)?.subdir(name))
435 }
436 }
437}
438
439fn collect_modules_under(db: &dyn DefsGroup, modules: &mut Vec<ModuleId>, module_id: ModuleId) {
441 modules.push(module_id);
442 if let Ok(submodule_ids) = db.module_submodules_ids(module_id) {
443 for submodule_module_id in submodule_ids.iter().copied() {
444 collect_modules_under(db, modules, ModuleId::Submodule(submodule_module_id));
445 }
446 }
447}
448
449fn crate_modules(db: &dyn DefsGroup, crate_id: CrateId) -> Arc<[ModuleId]> {
451 let mut modules = Vec::new();
452 collect_modules_under(db, &mut modules, ModuleId::CrateRoot(crate_id));
453 modules.into()
454}
455
456fn priv_file_to_module_mapping(db: &dyn DefsGroup) -> Arc<OrderedHashMap<FileId, Vec<ModuleId>>> {
457 let mut mapping = OrderedHashMap::<FileId, Vec<ModuleId>>::default();
458 for crate_id in db.crates() {
459 for module_id in db.crate_modules(crate_id).iter().copied() {
460 if let Ok(files) = db.module_files(module_id) {
461 for file_id in files.iter().copied() {
462 match mapping.get_mut(&file_id) {
463 Some(file_modules) => {
464 file_modules.push(module_id);
465 }
466 None => {
467 mapping.insert(file_id, vec![module_id]);
468 }
469 }
470 }
471 }
472 }
473 }
474 mapping.into()
475}
476fn file_modules(db: &dyn DefsGroup, file_id: FileId) -> Maybe<Arc<[ModuleId]>> {
477 Ok(db.priv_file_to_module_mapping().get(&file_id).to_maybe()?.clone().into())
478}
479
480#[derive(Clone, Debug, PartialEq, Eq)]
481pub struct ModuleData {
482 pub(crate) items: Arc<[ModuleItemId]>,
485
486 pub(crate) constants: Arc<OrderedHashMap<ConstantId, ast::ItemConstant>>,
488 pub(crate) submodules: Arc<OrderedHashMap<SubmoduleId, ast::ItemModule>>,
489 pub(crate) uses: Arc<OrderedHashMap<UseId, ast::UsePathLeaf>>,
490 pub(crate) free_functions: Arc<OrderedHashMap<FreeFunctionId, ast::FunctionWithBody>>,
491 pub(crate) structs: Arc<OrderedHashMap<StructId, ast::ItemStruct>>,
492 pub(crate) enums: Arc<OrderedHashMap<EnumId, ast::ItemEnum>>,
493 pub(crate) type_aliases: Arc<OrderedHashMap<ModuleTypeAliasId, ast::ItemTypeAlias>>,
494 pub(crate) impl_aliases: Arc<OrderedHashMap<ImplAliasId, ast::ItemImplAlias>>,
495 pub(crate) traits: Arc<OrderedHashMap<TraitId, ast::ItemTrait>>,
496 pub(crate) impls: Arc<OrderedHashMap<ImplDefId, ast::ItemImpl>>,
497 pub(crate) extern_types: Arc<OrderedHashMap<ExternTypeId, ast::ItemExternType>>,
498 pub(crate) extern_functions: Arc<OrderedHashMap<ExternFunctionId, ast::ItemExternFunction>>,
499 pub(crate) macro_declarations:
500 Arc<OrderedHashMap<MacroDeclarationId, ast::ItemMacroDeclaration>>,
501 pub(crate) global_uses: Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>,
502
503 pub(crate) files: Arc<[FileId]>,
504 pub(crate) generated_file_aux_data: Arc<[Option<DynGeneratedFileAuxData>]>,
506 pub(crate) plugin_diagnostics: Arc<[(ModuleFileId, PluginDiagnostic)]>,
507 pub(crate) diagnostics_notes: PluginFileDiagnosticNotes,
511}
512
513#[derive(Clone, Debug, Eq, PartialEq)]
515pub struct PrivModuleSubFiles {
516 files: OrderedHashMap<FileId, VirtualFile>,
518 aux_data: Vec<Option<DynGeneratedFileAuxData>>,
520 items: Vec<ast::ModuleItem>,
522 plugin_diagnostics: Vec<PluginDiagnostic>,
524 diagnostics_notes: PluginFileDiagnosticNotes,
528}
529
530fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData> {
531 let crate_id = module_id.owning_crate(db);
532
533 if let Some((map, _)) = db.cached_crate_modules(crate_id) {
534 if let Some(module_data) = map.get(&module_id) {
535 return Ok(module_data.clone());
536 } else {
537 panic!("module not found in cached modules_data {:?}", module_id.name(db));
538 }
539 };
540
541 let module_file = db.module_main_file(module_id)?;
542 let main_file_aux_data = if let ModuleId::Submodule(submodule_id) = module_id {
543 let parent_module_data = db.priv_module_data(submodule_id.parent_module(db))?;
544 let item_module_ast = &parent_module_data.submodules[&submodule_id];
545 if matches!(item_module_ast.body(db), MaybeModuleBody::Some(_)) {
546 parent_module_data.generated_file_aux_data[submodule_id.file_index(db).0].clone()
553 } else {
554 None
555 }
556 } else {
557 None
558 };
559 let mut file_queue = VecDeque::new();
560 file_queue.push_back(module_file);
561 let mut constants = OrderedHashMap::default();
562 let mut submodules = OrderedHashMap::default();
563 let mut uses = OrderedHashMap::default();
564 let mut free_functions = OrderedHashMap::default();
565 let mut structs = OrderedHashMap::default();
566 let mut enums = OrderedHashMap::default();
567 let mut type_aliases = OrderedHashMap::default();
568 let mut impl_aliases = OrderedHashMap::default();
569 let mut traits = OrderedHashMap::default();
570 let mut impls = OrderedHashMap::default();
571 let mut extern_types = OrderedHashMap::default();
572 let mut extern_functions = OrderedHashMap::default();
573 let mut macro_declarations = OrderedHashMap::default();
574 let mut global_uses = OrderedHashMap::default();
575 let mut aux_data = Vec::new();
576 let mut files = Vec::new();
577 let mut plugin_diagnostics = Vec::new();
578 let mut diagnostics_notes = OrderedHashMap::default();
579
580 let mut items = vec![];
581 aux_data.push(main_file_aux_data);
582 while let Some(file_id) = file_queue.pop_front() {
583 let file_index = FileIndex(files.len());
584 let module_file_id = ModuleFileId(module_id, file_index);
585 files.push(file_id);
586
587 let priv_module_data = db.priv_module_sub_files(module_id, file_id)?;
588 diagnostics_notes.extend(priv_module_data.diagnostics_notes.clone().into_iter());
589 file_queue.extend(priv_module_data.files.keys().copied());
590 for diag in &priv_module_data.plugin_diagnostics {
591 plugin_diagnostics.push((module_file_id, diag.clone()));
592 }
593 aux_data.extend(priv_module_data.aux_data.iter().cloned());
594 for item_ast in &priv_module_data.items {
595 match item_ast.clone() {
596 ast::ModuleItem::Constant(constant) => {
597 let item_id =
598 ConstantLongId(module_file_id, constant.stable_ptr(db)).intern(db);
599 constants.insert(item_id, constant);
600 items.push(ModuleItemId::Constant(item_id));
601 }
602 ast::ModuleItem::Module(module) => {
603 let item_id = SubmoduleLongId(module_file_id, module.stable_ptr(db)).intern(db);
604 submodules.insert(item_id, module);
605 items.push(ModuleItemId::Submodule(item_id));
606 }
607 ast::ModuleItem::Use(us) => {
608 for leaf in get_all_path_leaves(db, &us) {
609 let id = UseLongId(module_file_id, leaf.stable_ptr(db)).intern(db);
610 uses.insert(id, leaf);
611 items.push(ModuleItemId::Use(id));
612 }
613 for star in get_all_path_stars(db, &us) {
614 let id = GlobalUseLongId(module_file_id, star.stable_ptr(db)).intern(db);
615 global_uses.insert(id, star);
616 }
617 }
618 ast::ModuleItem::FreeFunction(function) => {
619 let item_id =
620 FreeFunctionLongId(module_file_id, function.stable_ptr(db)).intern(db);
621 free_functions.insert(item_id, function);
622 items.push(ModuleItemId::FreeFunction(item_id));
623 }
624 ast::ModuleItem::ExternFunction(extern_function) => {
625 let item_id =
626 ExternFunctionLongId(module_file_id, extern_function.stable_ptr(db))
627 .intern(db);
628 extern_functions.insert(item_id, extern_function);
629 items.push(ModuleItemId::ExternFunction(item_id));
630 }
631 ast::ModuleItem::ExternType(extern_type) => {
632 let item_id =
633 ExternTypeLongId(module_file_id, extern_type.stable_ptr(db)).intern(db);
634 extern_types.insert(item_id, extern_type);
635 items.push(ModuleItemId::ExternType(item_id));
636 }
637 ast::ModuleItem::Trait(trt) => {
638 let item_id = TraitLongId(module_file_id, trt.stable_ptr(db)).intern(db);
639 traits.insert(item_id, trt);
640 items.push(ModuleItemId::Trait(item_id));
641 }
642 ast::ModuleItem::Impl(imp) => {
643 let item_id = ImplDefLongId(module_file_id, imp.stable_ptr(db)).intern(db);
644 impls.insert(item_id, imp);
645 items.push(ModuleItemId::Impl(item_id));
646 }
647 ast::ModuleItem::Struct(structure) => {
648 let item_id = StructLongId(module_file_id, structure.stable_ptr(db)).intern(db);
649 structs.insert(item_id, structure);
650 items.push(ModuleItemId::Struct(item_id));
651 }
652 ast::ModuleItem::Enum(enm) => {
653 let item_id = EnumLongId(module_file_id, enm.stable_ptr(db)).intern(db);
654 enums.insert(item_id, enm);
655 items.push(ModuleItemId::Enum(item_id));
656 }
657 ast::ModuleItem::TypeAlias(type_alias) => {
658 let item_id =
659 ModuleTypeAliasLongId(module_file_id, type_alias.stable_ptr(db)).intern(db);
660 type_aliases.insert(item_id, type_alias);
661 items.push(ModuleItemId::TypeAlias(item_id));
662 }
663 ast::ModuleItem::ImplAlias(impl_alias) => {
664 let item_id =
665 ImplAliasLongId(module_file_id, impl_alias.stable_ptr(db)).intern(db);
666 impl_aliases.insert(item_id, impl_alias);
667 items.push(ModuleItemId::ImplAlias(item_id));
668 }
669 ast::ModuleItem::MacroDeclaration(macro_declaration) => {
670 let item_id =
671 MacroDeclarationLongId(module_file_id, macro_declaration.stable_ptr(db))
672 .intern(db);
673 macro_declarations.insert(item_id, macro_declaration);
674 items.push(ModuleItemId::MacroDeclaration(item_id));
675 }
676 ast::ModuleItem::InlineMacro(inline_macro_ast) => plugin_diagnostics.push((
677 module_file_id,
678 PluginDiagnostic::error(
679 inline_macro_ast.stable_ptr(db),
680 format!(
681 "Unknown inline item macro: '{}'.",
682 inline_macro_ast.path(db).as_syntax_node().get_text(db)
683 ),
684 ),
685 )),
686 ast::ModuleItem::HeaderDoc(_) => {}
687 ast::ModuleItem::Missing(_) => {}
688 }
689 }
690 }
691 let res = ModuleData {
692 items: items.into(),
693 constants: constants.into(),
694 submodules: submodules.into(),
695 uses: uses.into(),
696 free_functions: free_functions.into(),
697 structs: structs.into(),
698 enums: enums.into(),
699 type_aliases: type_aliases.into(),
700 impl_aliases: impl_aliases.into(),
701 traits: traits.into(),
702 impls: impls.into(),
703 extern_types: extern_types.into(),
704 extern_functions: extern_functions.into(),
705 macro_declarations: macro_declarations.into(),
706 global_uses: global_uses.into(),
707 files: files.into(),
708 generated_file_aux_data: aux_data.into(),
709 plugin_diagnostics: plugin_diagnostics.into(),
710 diagnostics_notes,
711 };
712 Ok(res)
713}
714
715pub type ModuleDataCacheAndLoadingData =
716 (Arc<OrderedHashMap<ModuleId, ModuleData>>, Arc<DefCacheLoadingData>);
717
718fn cached_crate_modules(
719 db: &dyn DefsGroup,
720 crate_id: CrateId,
721) -> Option<ModuleDataCacheAndLoadingData> {
722 load_cached_crate_modules(db, crate_id)
723}
724
725pub fn try_ext_as_virtual_impl(
727 db: &dyn DefsGroup,
728 external_id: salsa::InternId,
729) -> Option<VirtualFile> {
730 let long_id = PluginGeneratedFileId::from_intern_id(external_id).lookup_intern(db);
731 let file_id = FileLongId::External(external_id).intern(db);
732 let data = db.priv_module_sub_files(long_id.module_id, long_id.stable_ptr.file_id(db)).unwrap();
733 data.files.get(&file_id).cloned()
734}
735
736fn priv_module_sub_files(
737 db: &dyn DefsGroup,
738 module_id: ModuleId,
739 file_id: FileId,
740) -> Maybe<Arc<PrivModuleSubFiles>> {
741 let module_main_file = db.module_main_file(module_id)?;
742 let file_syntax = db.file_module_syntax(file_id)?;
743 let item_asts = if module_main_file == file_id {
744 if let ModuleId::Submodule(submodule_id) = module_id {
745 let data = db.priv_module_data(submodule_id.parent_module(db))?;
746 if let MaybeModuleBody::Some(body) = data.submodules[&submodule_id].body(db) {
747 Some(body.items(db))
748 } else {
749 None
750 }
751 } else {
752 None
753 }
754 } else {
755 None
756 }
757 .unwrap_or_else(|| file_syntax.items(db));
758
759 let crate_id = module_id.owning_crate(db);
760
761 let allowed_attributes = db.allowed_attributes(crate_id);
762 let allowed_features = Default::default();
764
765 let cfg_set = db
766 .crate_config(crate_id)
767 .and_then(|cfg| cfg.settings.cfg_set.map(Arc::new))
768 .unwrap_or(db.cfg_set());
769 let edition = db
770 .crate_config(module_id.owning_crate(db))
771 .map(|cfg| cfg.settings.edition)
772 .unwrap_or_default();
773 let metadata = MacroPluginMetadata {
774 cfg_set: &cfg_set,
775 declared_derives: &db.declared_derives(crate_id),
776 allowed_features: &allowed_features,
777 edition,
778 };
779
780 let mut files = OrderedHashMap::<_, _>::default();
781 let mut aux_data = Vec::new();
782 let mut items = Vec::new();
783 let mut plugin_diagnostics = Vec::new();
784 let mut diagnostics_notes = OrderedHashMap::default();
785 for item_ast in item_asts.elements(db) {
786 let mut remove_original_item = false;
787 for plugin_id in db.crate_macro_plugins(crate_id).iter() {
791 let plugin = db.lookup_intern_macro_plugin(*plugin_id);
792
793 let result = plugin.generate_code(db, item_ast.clone(), &metadata);
794 plugin_diagnostics.extend(result.diagnostics);
795 if result.remove_original_item {
796 remove_original_item = true;
797 }
798
799 if let Some(generated) = result.code {
800 let generated_file_id = FileLongId::External(
801 PluginGeneratedFileLongId {
802 module_id,
803 stable_ptr: item_ast.stable_ptr(db).untyped(),
804 name: generated.name.clone(),
805 }
806 .intern(db)
807 .as_intern_id(),
808 )
809 .intern(db);
810 if let Some(text) = generated.diagnostics_note {
811 diagnostics_notes
812 .insert(generated_file_id, DiagnosticNote { text, location: None });
813 }
814 files.insert(
815 generated_file_id,
816 VirtualFile {
817 parent: Some(file_id),
818 name: generated.name,
819 content: generated.content.into(),
820 code_mappings: generated.code_mappings.into(),
821 kind: FileKind::Module,
822 original_item_removed: remove_original_item,
823 },
824 );
825 aux_data.push(generated.aux_data);
826 }
827 if remove_original_item {
828 break;
829 }
830 }
831 if remove_original_item {
832 continue;
834 }
835 validate_attributes(db, &allowed_attributes, &item_ast, &mut plugin_diagnostics);
836 items.push(item_ast);
837 }
838 let res = PrivModuleSubFiles { files, aux_data, items, plugin_diagnostics, diagnostics_notes };
839 Ok(res.into())
840}
841
842fn collect_extra_allowed_attributes(
844 db: &dyn SyntaxGroup,
845 item: &impl QueryAttrs,
846 plugin_diagnostics: &mut Vec<PluginDiagnostic>,
847) -> OrderedHashSet<String> {
848 let mut extra_allowed_attributes = OrderedHashSet::default();
849 for attr in item.query_attr(db, ALLOW_ATTR_ATTR) {
850 let args = attr.clone().structurize(db).args;
851 if args.is_empty() {
852 plugin_diagnostics.push(PluginDiagnostic::error(
853 attr.stable_ptr(db),
854 "Expected arguments.".to_string(),
855 ));
856 continue;
857 }
858 for arg in args {
859 if let Some(ast::Expr::Path(path)) = try_extract_unnamed_arg(db, &arg.arg) {
860 if let Some([ast::PathSegment::Simple(segment)]) =
861 path.segments(db).elements(db).collect_array()
862 {
863 extra_allowed_attributes.insert(segment.ident(db).text(db).into());
864 continue;
865 }
866 }
867 plugin_diagnostics.push(PluginDiagnostic::error(
868 arg.arg.stable_ptr(db),
869 "Expected simple identifier.".to_string(),
870 ));
871 }
872 }
873 extra_allowed_attributes
874}
875
876pub fn validate_attributes_flat(
878 db: &dyn SyntaxGroup,
879 allowed_attributes: &OrderedHashSet<String>,
880 extra_allowed_attributes: &OrderedHashSet<String>,
881 item: &impl QueryAttrs,
882 plugin_diagnostics: &mut Vec<PluginDiagnostic>,
883) {
884 let local_extra_attributes = collect_extra_allowed_attributes(db, item, plugin_diagnostics);
885 for attr in item.attributes_elements(db) {
886 let attr_text = attr.attr(db).as_syntax_node().get_text_without_trivia(db);
887 if !(allowed_attributes.contains(&attr_text)
888 || extra_allowed_attributes.contains(&attr_text)
889 || local_extra_attributes.contains(&attr_text))
890 {
891 plugin_diagnostics.push(PluginDiagnostic::error(
892 attr.stable_ptr(db),
893 "Unsupported attribute.".to_string(),
894 ));
895 }
896 }
897}
898
899fn validate_attributes_element_list<Item: QueryAttrs + TypedSyntaxNode>(
902 db: &dyn SyntaxGroup,
903 allowed_attributes: &OrderedHashSet<String>,
904 extra_allowed_attributes: &OrderedHashSet<String>,
905 items: impl Iterator<Item = Item>,
906 plugin_diagnostics: &mut Vec<PluginDiagnostic>,
907) {
908 for item in items {
909 validate_attributes_flat(
910 db,
911 allowed_attributes,
912 extra_allowed_attributes,
913 &item,
914 plugin_diagnostics,
915 );
916 }
917}
918
919fn validate_attributes(
922 db: &dyn SyntaxGroup,
923 allowed_attributes: &OrderedHashSet<String>,
924 item_ast: &ast::ModuleItem,
925 plugin_diagnostics: &mut Vec<PluginDiagnostic>,
926) {
927 let extra_allowed_attributes =
928 collect_extra_allowed_attributes(db, item_ast, plugin_diagnostics);
929 validate_attributes_flat(
930 db,
931 allowed_attributes,
932 &extra_allowed_attributes,
933 item_ast,
934 plugin_diagnostics,
935 );
936
937 match item_ast {
938 ast::ModuleItem::Trait(item) => {
939 if let ast::MaybeTraitBody::Some(body) = item.body(db) {
940 validate_attributes_element_list(
941 db,
942 allowed_attributes,
943 &extra_allowed_attributes,
944 body.items(db).elements(db),
945 plugin_diagnostics,
946 );
947 }
948 }
949 ast::ModuleItem::Impl(item) => {
950 if let ast::MaybeImplBody::Some(body) = item.body(db) {
951 validate_attributes_element_list(
952 db,
953 allowed_attributes,
954 &extra_allowed_attributes,
955 body.items(db).elements(db),
956 plugin_diagnostics,
957 );
958 }
959 }
960 ast::ModuleItem::Struct(item) => {
961 validate_attributes_element_list(
962 db,
963 allowed_attributes,
964 &extra_allowed_attributes,
965 item.members(db).elements(db),
966 plugin_diagnostics,
967 );
968 }
969 ast::ModuleItem::Enum(item) => {
970 validate_attributes_element_list(
971 db,
972 allowed_attributes,
973 &extra_allowed_attributes,
974 item.variants(db).elements(db),
975 plugin_diagnostics,
976 );
977 }
978 _ => {}
979 }
980}
981
982pub fn get_all_path_leaves(db: &dyn SyntaxGroup, use_item: &ast::ItemUse) -> Vec<ast::UsePathLeaf> {
984 let mut res = vec![];
985 let mut stack = vec![use_item.use_path(db)];
986 while let Some(use_path) = stack.pop() {
987 match use_path {
988 ast::UsePath::Leaf(use_path) => res.push(use_path),
989 ast::UsePath::Single(use_path) => stack.push(use_path.use_path(db)),
990 ast::UsePath::Multi(use_path) => {
991 stack.extend(use_path.use_paths(db).elements(db).rev())
992 }
993 ast::UsePath::Star(_) => {}
994 }
995 }
996 res
997}
998
999pub fn get_all_path_stars(db: &dyn SyntaxGroup, use_item: &ast::ItemUse) -> Vec<ast::UsePathStar> {
1001 let mut res = vec![];
1002 let mut stack = vec![use_item.use_path(db)];
1003 while let Some(use_path) = stack.pop() {
1004 match use_path {
1005 ast::UsePath::Leaf(_) => {}
1006 ast::UsePath::Single(use_path) => stack.push(use_path.use_path(db)),
1007 ast::UsePath::Multi(use_path) => {
1008 stack.extend(use_path.use_paths(db).elements(db).rev())
1009 }
1010 ast::UsePath::Star(use_path) => res.push(use_path),
1011 }
1012 }
1013 res
1014}
1015
1016pub fn module_constants(
1018 db: &dyn DefsGroup,
1019 module_id: ModuleId,
1020) -> Maybe<Arc<OrderedHashMap<ConstantId, ast::ItemConstant>>> {
1021 Ok(db.priv_module_data(module_id)?.constants)
1022}
1023pub fn module_constants_ids(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[ConstantId]>> {
1024 Ok(db.module_constants(module_id)?.keys().copied().collect_vec().into())
1025}
1026pub fn module_constant_by_id(
1027 db: &dyn DefsGroup,
1028 constant_id: ConstantId,
1029) -> Maybe<Option<ast::ItemConstant>> {
1030 let module_constants = db.module_constants(constant_id.module_file_id(db).0)?;
1031 Ok(module_constants.get(&constant_id).cloned())
1032}
1033
1034fn module_submodules(
1037 db: &dyn DefsGroup,
1038 module_id: ModuleId,
1039) -> Maybe<Arc<OrderedHashMap<SubmoduleId, ast::ItemModule>>> {
1040 Ok(db.priv_module_data(module_id)?.submodules)
1041}
1042fn module_submodules_ids(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[SubmoduleId]>> {
1043 Ok(db.module_submodules(module_id)?.keys().copied().collect_vec().into())
1044}
1045pub fn module_submodule_by_id(
1046 db: &dyn DefsGroup,
1047 submodule_id: SubmoduleId,
1048) -> Maybe<Option<ast::ItemModule>> {
1049 let module_submodules = db.module_submodules(submodule_id.module_file_id(db).0)?;
1050 Ok(module_submodules.get(&submodule_id).cloned())
1051}
1052
1053pub fn module_free_functions(
1055 db: &dyn DefsGroup,
1056 module_id: ModuleId,
1057) -> Maybe<Arc<OrderedHashMap<FreeFunctionId, ast::FunctionWithBody>>> {
1058 Ok(db.priv_module_data(module_id)?.free_functions)
1059}
1060pub fn module_free_functions_ids(
1061 db: &dyn DefsGroup,
1062 module_id: ModuleId,
1063) -> Maybe<Arc<[FreeFunctionId]>> {
1064 Ok(db.module_free_functions(module_id)?.keys().copied().collect_vec().into())
1065}
1066pub fn module_free_function_by_id(
1067 db: &dyn DefsGroup,
1068 free_function_id: FreeFunctionId,
1069) -> Maybe<Option<ast::FunctionWithBody>> {
1070 let module_free_functions = db.module_free_functions(free_function_id.module_file_id(db).0)?;
1071 Ok(module_free_functions.get(&free_function_id).cloned())
1072}
1073
1074pub fn module_uses(
1076 db: &dyn DefsGroup,
1077 module_id: ModuleId,
1078) -> Maybe<Arc<OrderedHashMap<UseId, ast::UsePathLeaf>>> {
1079 Ok(db.priv_module_data(module_id)?.uses)
1080}
1081pub fn module_uses_ids(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[UseId]>> {
1082 Ok(db.module_uses(module_id)?.keys().copied().collect_vec().into())
1083}
1084pub fn module_use_by_id(db: &dyn DefsGroup, use_id: UseId) -> Maybe<Option<ast::UsePathLeaf>> {
1085 let module_uses = db.module_uses(use_id.module_file_id(db).0)?;
1086 Ok(module_uses.get(&use_id).cloned())
1087}
1088
1089pub fn module_global_use_by_id(
1091 db: &dyn DefsGroup,
1092 global_use_id: GlobalUseId,
1093) -> Maybe<Option<ast::UsePathStar>> {
1094 let module_global_uses = db.module_global_uses(global_use_id.module_file_id(db).0)?;
1095 Ok(module_global_uses.get(&global_use_id).cloned())
1096}
1097
1098pub fn module_structs(
1100 db: &dyn DefsGroup,
1101 module_id: ModuleId,
1102) -> Maybe<Arc<OrderedHashMap<StructId, ast::ItemStruct>>> {
1103 Ok(db.priv_module_data(module_id)?.structs)
1104}
1105pub fn module_structs_ids(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[StructId]>> {
1106 Ok(db.module_structs(module_id)?.keys().copied().collect_vec().into())
1107}
1108pub fn module_struct_by_id(
1109 db: &dyn DefsGroup,
1110 struct_id: StructId,
1111) -> Maybe<Option<ast::ItemStruct>> {
1112 let module_structs = db.module_structs(struct_id.module_file_id(db).0)?;
1113 Ok(module_structs.get(&struct_id).cloned())
1114}
1115
1116pub fn module_enums(
1118 db: &dyn DefsGroup,
1119 module_id: ModuleId,
1120) -> Maybe<Arc<OrderedHashMap<EnumId, ast::ItemEnum>>> {
1121 Ok(db.priv_module_data(module_id)?.enums)
1122}
1123pub fn module_enums_ids(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[EnumId]>> {
1124 Ok(db.module_enums(module_id)?.keys().copied().collect_vec().into())
1125}
1126pub fn module_enum_by_id(db: &dyn DefsGroup, enum_id: EnumId) -> Maybe<Option<ast::ItemEnum>> {
1127 let module_enums = db.module_enums(enum_id.module_file_id(db).0)?;
1128 Ok(module_enums.get(&enum_id).cloned())
1129}
1130
1131pub fn module_type_aliases(
1133 db: &dyn DefsGroup,
1134 module_id: ModuleId,
1135) -> Maybe<Arc<OrderedHashMap<ModuleTypeAliasId, ast::ItemTypeAlias>>> {
1136 Ok(db.priv_module_data(module_id)?.type_aliases)
1137}
1138pub fn module_type_aliases_ids(
1139 db: &dyn DefsGroup,
1140 module_id: ModuleId,
1141) -> Maybe<Arc<[ModuleTypeAliasId]>> {
1142 Ok(db.module_type_aliases(module_id)?.keys().copied().collect_vec().into())
1143}
1144pub fn module_type_alias_by_id(
1145 db: &dyn DefsGroup,
1146 module_type_alias_id: ModuleTypeAliasId,
1147) -> Maybe<Option<ast::ItemTypeAlias>> {
1148 let module_type_aliases = db.module_type_aliases(module_type_alias_id.module_file_id(db).0)?;
1149 Ok(module_type_aliases.get(&module_type_alias_id).cloned())
1150}
1151
1152pub fn module_impl_aliases(
1154 db: &dyn DefsGroup,
1155 module_id: ModuleId,
1156) -> Maybe<Arc<OrderedHashMap<ImplAliasId, ast::ItemImplAlias>>> {
1157 Ok(db.priv_module_data(module_id)?.impl_aliases)
1158}
1159pub fn module_impl_aliases_ids(
1160 db: &dyn DefsGroup,
1161 module_id: ModuleId,
1162) -> Maybe<Arc<[ImplAliasId]>> {
1163 Ok(db.module_impl_aliases(module_id)?.keys().copied().collect_vec().into())
1164}
1165pub fn module_impl_alias_by_id(
1166 db: &dyn DefsGroup,
1167 impl_alias_id: ImplAliasId,
1168) -> Maybe<Option<ast::ItemImplAlias>> {
1169 let module_impl_aliases = db.module_impl_aliases(impl_alias_id.module_file_id(db).0)?;
1170 Ok(module_impl_aliases.get(&impl_alias_id).cloned())
1171}
1172
1173pub fn module_traits(
1175 db: &dyn DefsGroup,
1176 module_id: ModuleId,
1177) -> Maybe<Arc<OrderedHashMap<TraitId, ast::ItemTrait>>> {
1178 Ok(db.priv_module_data(module_id)?.traits)
1179}
1180pub fn module_traits_ids(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[TraitId]>> {
1181 Ok(db.module_traits(module_id)?.keys().copied().collect_vec().into())
1182}
1183pub fn module_trait_by_id(db: &dyn DefsGroup, trait_id: TraitId) -> Maybe<Option<ast::ItemTrait>> {
1184 let module_traits = db.module_traits(trait_id.module_file_id(db).0)?;
1185 Ok(module_traits.get(&trait_id).cloned())
1186}
1187
1188pub fn module_impls(
1190 db: &dyn DefsGroup,
1191 module_id: ModuleId,
1192) -> Maybe<Arc<OrderedHashMap<ImplDefId, ast::ItemImpl>>> {
1193 Ok(db.priv_module_data(module_id)?.impls)
1194}
1195pub fn module_impls_ids(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[ImplDefId]>> {
1196 Ok(db.module_impls(module_id)?.keys().copied().collect_vec().into())
1197}
1198pub fn module_impl_by_id(
1199 db: &dyn DefsGroup,
1200 impl_def_id: ImplDefId,
1201) -> Maybe<Option<ast::ItemImpl>> {
1202 let module_impls = db.module_impls(impl_def_id.module_file_id(db).0)?;
1203 Ok(module_impls.get(&impl_def_id).cloned())
1204}
1205
1206pub fn module_extern_types(
1208 db: &dyn DefsGroup,
1209 module_id: ModuleId,
1210) -> Maybe<Arc<OrderedHashMap<ExternTypeId, ast::ItemExternType>>> {
1211 Ok(db.priv_module_data(module_id)?.extern_types)
1212}
1213pub fn module_extern_types_ids(
1214 db: &dyn DefsGroup,
1215 module_id: ModuleId,
1216) -> Maybe<Arc<[ExternTypeId]>> {
1217 Ok(db.module_extern_types(module_id)?.keys().copied().collect_vec().into())
1218}
1219pub fn module_extern_type_by_id(
1220 db: &dyn DefsGroup,
1221 extern_type_id: ExternTypeId,
1222) -> Maybe<Option<ast::ItemExternType>> {
1223 let module_extern_types = db.module_extern_types(extern_type_id.module_file_id(db).0)?;
1224 Ok(module_extern_types.get(&extern_type_id).cloned())
1225}
1226
1227pub fn module_macro_declarations(
1229 db: &dyn DefsGroup,
1230 module_id: ModuleId,
1231) -> Maybe<Arc<OrderedHashMap<MacroDeclarationId, ast::ItemMacroDeclaration>>> {
1232 Ok(db.priv_module_data(module_id)?.macro_declarations)
1233}
1234pub fn module_macro_declarations_ids(
1236 db: &dyn DefsGroup,
1237 module_id: ModuleId,
1238) -> Maybe<Arc<[MacroDeclarationId]>> {
1239 Ok(db.module_macro_declarations(module_id)?.keys().copied().collect_vec().into())
1240}
1241pub fn module_macro_declaration_by_id(
1243 db: &dyn DefsGroup,
1244 macro_declaration_id: MacroDeclarationId,
1245) -> Maybe<Option<ast::ItemMacroDeclaration>> {
1246 let module_macro_declarations =
1247 db.module_macro_declarations(macro_declaration_id.module_file_id(db).0)?;
1248 Ok(module_macro_declarations.get(¯o_declaration_id).cloned())
1249}
1250
1251pub fn module_extern_functions(
1253 db: &dyn DefsGroup,
1254 module_id: ModuleId,
1255) -> Maybe<Arc<OrderedHashMap<ExternFunctionId, ast::ItemExternFunction>>> {
1256 Ok(db.priv_module_data(module_id)?.extern_functions)
1257}
1258pub fn module_extern_functions_ids(
1259 db: &dyn DefsGroup,
1260 module_id: ModuleId,
1261) -> Maybe<Arc<[ExternFunctionId]>> {
1262 Ok(db.module_extern_functions(module_id)?.keys().copied().collect_vec().into())
1263}
1264pub fn module_extern_function_by_id(
1265 db: &dyn DefsGroup,
1266 extern_function_id: ExternFunctionId,
1267) -> Maybe<Option<ast::ItemExternFunction>> {
1268 let module_extern_functions =
1269 db.module_extern_functions(extern_function_id.module_file_id(db).0)?;
1270 Ok(module_extern_functions.get(&extern_function_id).cloned())
1271}
1272
1273pub fn module_ancestors(db: &dyn DefsGroup, module_id: ModuleId) -> OrderedHashSet<ModuleId> {
1274 let mut current = module_id;
1275 let mut ancestors = OrderedHashSet::default();
1276 while let ModuleId::Submodule(submodule_id) = current {
1277 let parent = submodule_id.parent_module(db);
1278 ancestors.insert(parent);
1279 current = parent
1280 }
1281 ancestors
1282}
1283
1284pub fn module_generated_file_aux_data(
1286 db: &dyn DefsGroup,
1287 module_id: ModuleId,
1288) -> Maybe<Arc<[Option<DynGeneratedFileAuxData>]>> {
1289 Ok(db.priv_module_data(module_id)?.generated_file_aux_data)
1290}
1291
1292pub fn module_plugin_diagnostics(
1294 db: &dyn DefsGroup,
1295 module_id: ModuleId,
1296) -> Maybe<Arc<[(ModuleFileId, PluginDiagnostic)]>> {
1297 Ok(db.priv_module_data(module_id)?.plugin_diagnostics)
1298}
1299
1300pub fn module_plugin_diagnostics_notes(
1303 db: &dyn DefsGroup,
1304 module_id: ModuleId,
1305) -> Maybe<Arc<PluginFileDiagnosticNotes>> {
1306 Ok(db.priv_module_data(module_id)?.diagnostics_notes.into())
1307}
1308
1309fn module_items(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<Arc<[ModuleItemId]>> {
1310 Ok(db.priv_module_data(module_id)?.items)
1311}
1312
1313fn module_global_uses(
1314 db: &dyn DefsGroup,
1315 module_id: ModuleId,
1316) -> Maybe<Arc<OrderedHashMap<GlobalUseId, ast::UsePathStar>>> {
1317 Ok(db.priv_module_data(module_id)?.global_uses)
1318}
1319
1320fn module_item_name_stable_ptr(
1321 db: &dyn DefsGroup,
1322 module_id: ModuleId,
1323 item_id: ModuleItemId,
1324) -> Maybe<SyntaxStablePtrId> {
1325 let data = db.priv_module_data(module_id)?;
1326 Ok(match &item_id {
1327 ModuleItemId::Constant(id) => data.constants[id].name(db).stable_ptr(db).untyped(),
1328 ModuleItemId::Submodule(id) => data.submodules[id].name(db).stable_ptr(db).untyped(),
1329 ModuleItemId::Use(id) => data.uses[id].name_stable_ptr(db),
1330 ModuleItemId::FreeFunction(id) => {
1331 data.free_functions[id].declaration(db).name(db).stable_ptr(db).untyped()
1332 }
1333 ModuleItemId::Struct(id) => data.structs[id].name(db).stable_ptr(db).untyped(),
1334 ModuleItemId::Enum(id) => data.enums[id].name(db).stable_ptr(db).untyped(),
1335 ModuleItemId::TypeAlias(id) => data.type_aliases[id].name(db).stable_ptr(db).untyped(),
1336 ModuleItemId::ImplAlias(id) => data.impl_aliases[id].name(db).stable_ptr(db).untyped(),
1337 ModuleItemId::Trait(id) => data.traits[id].name(db).stable_ptr(db).untyped(),
1338 ModuleItemId::Impl(id) => data.impls[id].name(db).stable_ptr(db).untyped(),
1339 ModuleItemId::ExternType(id) => data.extern_types[id].name(db).stable_ptr(db).untyped(),
1340 ModuleItemId::ExternFunction(id) => {
1341 data.extern_functions[id].declaration(db).name(db).stable_ptr(db).untyped()
1342 }
1343 ModuleItemId::MacroDeclaration(id) => {
1344 data.macro_declarations[id].name(db).stable_ptr(db).untyped()
1345 }
1346 })
1347}
1348
1349pub trait DefsGroupEx: DefsGroup {
1350 fn set_override_crate_macro_plugins(
1354 &mut self,
1355 crate_id: CrateId,
1356 plugins: Arc<[MacroPluginId]>,
1357 ) {
1358 let mut overrides = self.macro_plugin_overrides().as_ref().clone();
1359 overrides.insert(crate_id, plugins);
1360 self.set_macro_plugin_overrides(Arc::new(overrides));
1361 }
1362
1363 fn set_override_crate_inline_macro_plugins(
1367 &mut self,
1368 crate_id: CrateId,
1369 plugins: Arc<OrderedHashMap<String, InlineMacroExprPluginId>>,
1370 ) {
1371 let mut overrides = self.inline_macro_plugin_overrides().as_ref().clone();
1372 overrides.insert(crate_id, plugins);
1373 self.set_inline_macro_plugin_overrides(Arc::new(overrides));
1374 }
1375}
1376
1377impl<T: DefsGroup + ?Sized> DefsGroupEx for T {}