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