mago_codex/populator/
mod.rs1mod docblock;
2mod hierarchy;
3mod merge;
4mod methods;
5mod properties;
6mod signatures;
7mod sorter;
8mod templates;
9
10use ahash::HashSet;
11use mago_atom::AtomMap;
12use mago_atom::AtomSet;
13
14use crate::metadata::CodebaseMetadata;
15use crate::reference::ReferenceSource;
16use crate::reference::SymbolReferences;
17use crate::symbol::SymbolIdentifier;
18use crate::ttype::union::populate_union_type;
19
20pub fn populate_codebase(
31 codebase: &mut CodebaseMetadata,
32 symbol_references: &mut SymbolReferences,
33 safe_symbols: AtomSet,
34 safe_symbol_members: HashSet<SymbolIdentifier>,
35) {
36 let mut class_likes_to_repopulate = AtomSet::default();
37 for (name, metadata) in &codebase.class_likes {
38 if !metadata.flags.is_populated() || (metadata.flags.is_user_defined() && !safe_symbols.contains(name)) {
40 class_likes_to_repopulate.insert(*name);
41 }
42 }
43
44 for class_like_name in &class_likes_to_repopulate {
45 if let Some(classlike_info) = codebase.class_likes.get_mut(class_like_name) {
46 classlike_info.flags &= !crate::metadata::flags::MetadataFlags::POPULATED;
47 classlike_info.declaring_property_ids.clear();
48 classlike_info.appearing_property_ids.clear();
49 classlike_info.declaring_method_ids.clear();
50 classlike_info.appearing_method_ids.clear();
51 }
52 }
53
54 let sorted_classes = sorter::sort_class_likes(codebase, &class_likes_to_repopulate);
55 for class_name in sorted_classes {
56 hierarchy::populate_class_like_metadata_iterative(class_name, codebase, symbol_references);
57 }
58
59 for (name, function_like_metadata) in &mut codebase.function_likes {
60 let force_repopulation = function_like_metadata.flags.is_user_defined() && !safe_symbols.contains(&name.0);
61
62 let reference_source = if name.1.is_empty() || function_like_metadata.get_kind().is_closure() {
63 ReferenceSource::Symbol(true, name.0)
65 } else {
66 ReferenceSource::ClassLikeMember(true, name.0, name.1)
68 };
69
70 signatures::populate_function_like_metadata(
71 function_like_metadata,
72 &codebase.symbols,
73 &reference_source,
74 symbol_references,
75 force_repopulation,
76 );
77 }
78
79 for (name, metadata) in &mut codebase.class_likes {
80 let userland_force_repopulation = metadata.flags.is_user_defined() && !safe_symbols.contains(name);
81
82 hierarchy::populate_class_like_types(
83 *name,
84 metadata,
85 &codebase.symbols,
86 symbol_references,
87 userland_force_repopulation,
88 );
89 }
90
91 for (name, constant) in &mut codebase.constants {
92 for attribute_metadata in &constant.attributes {
93 symbol_references.add_symbol_reference_to_symbol(*name, attribute_metadata.name, true);
94 }
95
96 if let Some(type_metadata) = &mut constant.type_metadata {
97 populate_union_type(
98 &mut type_metadata.type_union,
99 &codebase.symbols,
100 Some(&ReferenceSource::Symbol(true, *name)),
101 symbol_references,
102 !safe_symbols.contains(name),
103 );
104 }
105
106 if let Some(inferred_type) = &mut constant.inferred_type {
107 populate_union_type(
108 inferred_type,
109 &codebase.symbols,
110 Some(&ReferenceSource::Symbol(true, *name)),
111 symbol_references,
112 !safe_symbols.contains(name),
113 );
114 }
115 }
116
117 let mut direct_classlike_descendants = AtomMap::default();
118 let mut all_classlike_descendants = AtomMap::default();
119
120 for (class_like_name, class_like_metadata) in &codebase.class_likes {
121 for parent_interface in &class_like_metadata.all_parent_interfaces {
122 all_classlike_descendants
123 .entry(*parent_interface)
124 .or_insert_with(AtomSet::default)
125 .insert(*class_like_name);
126 }
127
128 for parent_interface in &class_like_metadata.direct_parent_interfaces {
129 direct_classlike_descendants
130 .entry(*parent_interface)
131 .or_insert_with(AtomSet::default)
132 .insert(*class_like_name);
133 }
134
135 for parent_class in &class_like_metadata.all_parent_classes {
136 all_classlike_descendants.entry(*parent_class).or_insert_with(AtomSet::default).insert(*class_like_name);
137 }
138
139 for used_trait in &class_like_metadata.used_traits {
140 all_classlike_descendants.entry(*used_trait).or_default().insert(*class_like_name);
141 }
142
143 if let Some(parent_class) = &class_like_metadata.direct_parent_class {
144 direct_classlike_descendants.entry(*parent_class).or_insert_with(AtomSet::default).insert(*class_like_name);
145 }
146 }
147
148 docblock::inherit_method_docblocks(codebase);
150
151 codebase.all_class_like_descendants = all_classlike_descendants;
152 codebase.direct_classlike_descendants = direct_classlike_descendants;
153 codebase.safe_symbols = safe_symbols;
154 codebase.safe_symbol_members = safe_symbol_members;
155}