1use ahash::HashSet;
2use ahash::RandomState;
3use indexmap::IndexMap;
4
5use mago_atom::Atom;
6use mago_atom::AtomMap;
7use mago_atom::AtomSet;
8use mago_atom::atom;
9
10use crate::is_method_abstract;
11use crate::metadata::CodebaseMetadata;
12use crate::metadata::class_like::ClassLikeMetadata;
13use crate::metadata::flags::MetadataFlags;
14use crate::metadata::function_like::FunctionLikeMetadata;
15use crate::misc::GenericParent;
16use crate::reference::ReferenceSource;
17use crate::reference::SymbolReferences;
18use crate::symbol::SymbolIdentifier;
19use crate::symbol::Symbols;
20use crate::ttype::TType;
21use crate::ttype::atomic::TAtomic;
22use crate::ttype::atomic::generic::TGenericParameter;
23use crate::ttype::atomic::populate_atomic_type;
24use crate::ttype::union::TUnion;
25use crate::ttype::union::populate_union_type;
26
27pub fn populate_codebase(
38 codebase: &mut CodebaseMetadata,
39 symbol_references: &mut SymbolReferences,
40 safe_symbols: AtomSet,
41 safe_symbol_members: HashSet<SymbolIdentifier>,
42) {
43 let mut class_likes_to_repopulate = Vec::new();
44 for (name, metadata) in codebase.class_likes.iter() {
45 if !metadata.flags.is_populated() || (metadata.flags.is_user_defined() && !safe_symbols.contains(name)) {
47 class_likes_to_repopulate.push(*name);
48 }
49 }
50
51 for class_like_name in &class_likes_to_repopulate {
52 if let Some(classlike_info) = codebase.class_likes.get_mut(class_like_name) {
53 classlike_info.flags &= !MetadataFlags::POPULATED;
54 classlike_info.declaring_property_ids.clear();
55 classlike_info.appearing_property_ids.clear();
56 classlike_info.declaring_method_ids.clear();
57 classlike_info.appearing_method_ids.clear();
58 }
59 }
60
61 for class_name in &class_likes_to_repopulate {
62 populate_class_like_metadata(class_name, codebase, symbol_references, &safe_symbols);
63 }
64
65 for (name, function_like_metadata) in codebase.function_likes.iter_mut() {
66 let force_repopulation = function_like_metadata.flags.is_user_defined() && !safe_symbols.contains(&name.0);
67
68 let reference_source = if name.1.is_empty() || function_like_metadata.get_kind().is_closure() {
69 ReferenceSource::Symbol(true, name.0)
71 } else {
72 ReferenceSource::ClassLikeMember(true, name.0, name.1)
74 };
75
76 populate_function_like_metadata(
77 function_like_metadata,
78 &codebase.symbols,
79 &reference_source,
80 symbol_references,
81 force_repopulation,
82 );
83 }
84
85 for (name, metadata) in codebase.class_likes.iter_mut() {
86 let userland_force_repopulation = metadata.flags.is_user_defined() && !safe_symbols.contains(name);
87 let class_like_reference_source = ReferenceSource::Symbol(true, *name);
88
89 for (property_name, property_metadata) in &mut metadata.properties {
90 let property_reference_source = ReferenceSource::ClassLikeMember(true, *name, *property_name);
91
92 if let Some(signature) = property_metadata.type_declaration_metadata.as_mut() {
93 populate_union_type(
94 &mut signature.type_union,
95 &codebase.symbols,
96 Some(&property_reference_source),
97 symbol_references,
98 userland_force_repopulation,
99 );
100 }
101
102 if let Some(signature) = property_metadata.type_metadata.as_mut() {
103 populate_union_type(
104 &mut signature.type_union,
105 &codebase.symbols,
106 Some(&property_reference_source),
107 symbol_references,
108 userland_force_repopulation,
109 );
110 }
111
112 if let Some(default) = property_metadata.default_type_metadata.as_mut() {
113 populate_union_type(
114 &mut default.type_union,
115 &codebase.symbols,
116 Some(&property_reference_source),
117 symbol_references,
118 userland_force_repopulation,
119 );
120 }
121 }
122
123 for map in metadata.template_extended_parameters.values_mut() {
124 for (_, v) in map {
125 if v.needs_population() || userland_force_repopulation {
126 populate_union_type(
127 v,
128 &codebase.symbols,
129 Some(&class_like_reference_source),
130 symbol_references,
131 userland_force_repopulation,
132 );
133 }
134 }
135 }
136
137 for (_, map) in &mut metadata.template_types {
138 for (_, v) in map {
139 if v.needs_population() || userland_force_repopulation {
140 populate_union_type(
141 v,
142 &codebase.symbols,
143 Some(&class_like_reference_source),
144 symbol_references,
145 userland_force_repopulation,
146 );
147 }
148 }
149 }
150
151 for (constant_name, constant) in &mut metadata.constants {
152 let constant_reference_source = ReferenceSource::ClassLikeMember(true, *name, *constant_name);
153
154 for attribute_metadata in &constant.attributes {
155 symbol_references.add_class_member_reference_to_symbol(
156 (*name, *constant_name),
157 attribute_metadata.name,
158 true,
159 );
160 }
161
162 if let Some(signature) = &mut constant.type_metadata {
163 populate_union_type(
164 &mut signature.type_union,
165 &codebase.symbols,
166 Some(&constant_reference_source),
167 symbol_references,
168 userland_force_repopulation,
169 );
170 }
171
172 if let Some(inferred) = &mut constant.inferred_type {
173 populate_atomic_type(
174 inferred,
175 &codebase.symbols,
176 Some(&constant_reference_source),
177 symbol_references,
178 userland_force_repopulation,
179 );
180 }
181 }
182
183 for (enum_case_name, enum_case) in &mut metadata.enum_cases {
184 let enum_case_reference_source = ReferenceSource::ClassLikeMember(true, *name, *enum_case_name);
185
186 for attribute_metadata in &enum_case.attributes {
187 symbol_references.add_class_member_reference_to_symbol(
188 (*name, *enum_case_name),
189 attribute_metadata.name,
190 true,
191 );
192 }
193
194 if let Some(value_type) = &mut enum_case.value_type {
195 populate_atomic_type(
196 value_type,
197 &codebase.symbols,
198 Some(&enum_case_reference_source),
199 symbol_references,
200 userland_force_repopulation,
201 );
202 }
203 }
204
205 if let Some(enum_type) = &mut metadata.enum_type {
206 populate_atomic_type(
207 enum_type,
208 &codebase.symbols,
209 Some(&ReferenceSource::Symbol(true, *name)),
210 symbol_references,
211 userland_force_repopulation,
212 );
213 }
214 }
215
216 for (name, constant) in &mut codebase.constants {
217 for attribute_metadata in &constant.attributes {
218 symbol_references.add_symbol_reference_to_symbol(*name, attribute_metadata.name, true);
219 }
220
221 if let Some(type_metadata) = &mut constant.type_metadata {
222 populate_union_type(
223 &mut type_metadata.type_union,
224 &codebase.symbols,
225 Some(&ReferenceSource::Symbol(true, *name)),
226 symbol_references,
227 !safe_symbols.contains(name),
228 );
229 }
230
231 if let Some(inferred_type) = &mut constant.inferred_type {
232 populate_union_type(
233 inferred_type,
234 &codebase.symbols,
235 Some(&ReferenceSource::Symbol(true, *name)),
236 symbol_references,
237 !safe_symbols.contains(name),
238 );
239 }
240 }
241
242 let mut direct_classlike_descendants = AtomMap::default();
243 let mut all_classlike_descendants = AtomMap::default();
244
245 for (class_like_name, class_like_metadata) in &codebase.class_likes {
246 for parent_interface in &class_like_metadata.all_parent_interfaces {
247 all_classlike_descendants
248 .entry(*parent_interface)
249 .or_insert_with(AtomSet::default)
250 .insert(*class_like_name);
251 }
252
253 for parent_interface in &class_like_metadata.direct_parent_interfaces {
254 direct_classlike_descendants
255 .entry(*parent_interface)
256 .or_insert_with(AtomSet::default)
257 .insert(*class_like_name);
258 }
259
260 for parent_class in &class_like_metadata.all_parent_classes {
261 all_classlike_descendants.entry(*parent_class).or_insert_with(AtomSet::default).insert(*class_like_name);
262 }
263
264 for used_trait in &class_like_metadata.used_traits {
265 all_classlike_descendants.entry(*used_trait).or_default().insert(*class_like_name);
266 }
267
268 if let Some(parent_class) = &class_like_metadata.direct_parent_class {
269 direct_classlike_descendants.entry(*parent_class).or_insert_with(AtomSet::default).insert(*class_like_name);
270 }
271 }
272
273 codebase.all_class_like_descendants = all_classlike_descendants;
274 codebase.direct_classlike_descendants = direct_classlike_descendants;
275 codebase.safe_symbols = safe_symbols;
276 codebase.safe_symbol_members = safe_symbol_members;
277}
278
279fn populate_function_like_metadata(
284 metadata: &mut FunctionLikeMetadata,
285 codebase_symbols: &Symbols,
286 reference_source: &ReferenceSource,
287 symbol_references: &mut SymbolReferences,
288 force_type_population: bool,
289) {
290 if metadata.flags.is_populated() && !force_type_population {
292 return;
293 }
294
295 for attribute_metadata in metadata.get_attributes() {
296 match reference_source {
297 ReferenceSource::Symbol(_, a) => {
298 symbol_references.add_symbol_reference_to_symbol(*a, attribute_metadata.name, true)
299 }
300 ReferenceSource::ClassLikeMember(_, a, b) => {
301 symbol_references.add_class_member_reference_to_symbol((*a, *b), attribute_metadata.name, true)
302 }
303 }
304 }
305
306 if let Some(return_type) = metadata.return_type_declaration_metadata.as_mut() {
307 populate_union_type(
308 &mut return_type.type_union,
309 codebase_symbols,
310 Some(reference_source),
311 symbol_references,
312 force_type_population,
313 );
314 }
315
316 if let Some(return_type) = metadata.return_type_metadata.as_mut() {
317 populate_union_type(
318 &mut return_type.type_union,
319 codebase_symbols,
320 Some(reference_source),
321 symbol_references,
322 force_type_population,
323 );
324 }
325
326 for parameter_metadata in metadata.get_parameters_mut() {
327 if let Some(type_metadata) = parameter_metadata.type_metadata.as_mut() {
328 populate_union_type(
329 &mut type_metadata.type_union,
330 codebase_symbols,
331 Some(reference_source),
332 symbol_references,
333 force_type_population,
334 );
335 }
336
337 if let Some(type_metadata) = parameter_metadata.out_type.as_mut() {
338 populate_union_type(
339 &mut type_metadata.type_union,
340 codebase_symbols,
341 Some(reference_source),
342 symbol_references,
343 force_type_population,
344 );
345 }
346
347 if let Some(type_metadata) = parameter_metadata.default_type.as_mut() {
348 populate_union_type(
349 &mut type_metadata.type_union,
350 codebase_symbols,
351 Some(reference_source),
352 symbol_references,
353 force_type_population,
354 );
355 }
356
357 for attribute_metadata in ¶meter_metadata.attributes {
358 match reference_source {
359 ReferenceSource::Symbol(in_signature, a) => {
360 symbol_references.add_symbol_reference_to_symbol(*a, attribute_metadata.name, *in_signature)
361 }
362 ReferenceSource::ClassLikeMember(in_signature, a, b) => symbol_references
363 .add_class_member_reference_to_symbol((*a, *b), attribute_metadata.name, *in_signature),
364 }
365 }
366 }
367
368 for (_, type_parameter_map) in &mut metadata.template_types {
369 for (_, type_parameter) in type_parameter_map {
370 if force_type_population || type_parameter.needs_population() {
371 populate_union_type(
372 type_parameter,
373 codebase_symbols,
374 Some(reference_source),
375 symbol_references,
376 force_type_population,
377 );
378 }
379 }
380 }
381
382 if let Some(type_resolution_context) = metadata.type_resolution_context.as_mut() {
383 for (_, type_parameter_map) in type_resolution_context.get_template_definitions_mut() {
384 for (_, type_parameter) in type_parameter_map {
385 if force_type_population || type_parameter.needs_population() {
386 populate_union_type(
387 type_parameter,
388 codebase_symbols,
389 Some(reference_source),
390 symbol_references,
391 force_type_population,
392 );
393 }
394 }
395 }
396 }
397
398 if let Some(method_metadata) = metadata.method_metadata.as_mut() {
399 for where_constraint in method_metadata.where_constraints.values_mut() {
400 populate_union_type(
401 &mut where_constraint.type_union,
402 codebase_symbols,
403 Some(reference_source),
404 symbol_references,
405 force_type_population,
406 );
407 }
408 }
409
410 for thrown_type in &mut metadata.thrown_types {
411 populate_union_type(
412 &mut thrown_type.type_union,
413 codebase_symbols,
414 Some(reference_source),
415 symbol_references,
416 force_type_population,
417 );
418 }
419
420 for assertions in metadata.assertions.values_mut() {
421 for assertion in assertions {
422 if let Some(assertion_type) = assertion.get_type_mut() {
423 populate_atomic_type(
424 assertion_type,
425 codebase_symbols,
426 Some(reference_source),
427 symbol_references,
428 force_type_population,
429 );
430 }
431 }
432 }
433
434 for assertions in metadata.if_true_assertions.values_mut() {
435 for assertion in assertions {
436 if let Some(assertion_type) = assertion.get_type_mut() {
437 populate_atomic_type(
438 assertion_type,
439 codebase_symbols,
440 Some(reference_source),
441 symbol_references,
442 force_type_population,
443 );
444 }
445 }
446 }
447
448 for assertions in metadata.if_false_assertions.values_mut() {
449 for assertion in assertions {
450 if let Some(assertion_type) = assertion.get_type_mut() {
451 populate_atomic_type(
452 assertion_type,
453 codebase_symbols,
454 Some(reference_source),
455 symbol_references,
456 force_type_population,
457 );
458 }
459 }
460 }
461
462 metadata.flags |= MetadataFlags::POPULATED;
463}
464
465fn populate_class_like_metadata(
471 classlike_name: &Atom,
472 codebase: &mut CodebaseMetadata,
473 symbol_references: &mut SymbolReferences,
474 safe_symbols: &AtomSet,
475) {
476 if let Some(metadata) = codebase.class_likes.get(classlike_name)
477 && metadata.flags.is_populated()
478 {
479 return; }
481
482 let mut metadata = if let Some(metadata) = codebase.class_likes.remove(classlike_name) {
483 metadata
484 } else {
485 return;
486 };
487
488 for attribute_metadata in &metadata.attributes {
489 symbol_references.add_symbol_reference_to_symbol(metadata.name, attribute_metadata.name, true);
490 }
491
492 for property_name in metadata.get_property_names() {
493 metadata.add_declaring_property_id(property_name, *classlike_name);
494 }
495
496 for method_name in &metadata.methods {
497 metadata.appearing_method_ids.insert(*method_name, *classlike_name);
498 metadata.declaring_method_ids.insert(*method_name, *classlike_name);
499 }
500
501 let force_repopulation = !safe_symbols.contains(classlike_name);
502 for parameter_types in metadata.template_extended_offsets.values_mut() {
503 for parameter_type in parameter_types {
504 populate_union_type(
505 parameter_type,
506 &codebase.symbols,
507 Some(&ReferenceSource::Symbol(true, *classlike_name)),
508 symbol_references,
509 force_repopulation,
510 );
511 }
512 }
513
514 for trait_name in metadata.used_traits.iter().copied().collect::<Vec<_>>() {
515 populate_metadata_from_trait(&mut metadata, codebase, trait_name, symbol_references, safe_symbols);
516 }
517
518 if let Some(parent_classname) = metadata.direct_parent_class {
519 populate_metadata_from_parent_class_like(
520 &mut metadata,
521 codebase,
522 parent_classname,
523 symbol_references,
524 safe_symbols,
525 );
526 }
527
528 let direct_parent_interfaces = metadata.direct_parent_interfaces.clone();
529 for direct_parent_interface in direct_parent_interfaces {
530 populate_interface_metadata_from_parent_interface(
531 &mut metadata,
532 codebase,
533 direct_parent_interface,
534 symbol_references,
535 safe_symbols,
536 );
537 }
538
539 for required_class in metadata.require_extends.iter().copied().collect::<Vec<_>>() {
540 populate_metadata_from_required_class_like(
541 &mut metadata,
542 codebase,
543 required_class,
544 symbol_references,
545 safe_symbols,
546 );
547 }
548
549 for required_interface in metadata.require_implements.iter().copied().collect::<Vec<_>>() {
550 populate_interface_metadata_from_parent_interface(
551 &mut metadata,
552 codebase,
553 required_interface,
554 symbol_references,
555 safe_symbols,
556 );
557 }
558
559 if metadata.flags.is_readonly() {
561 for property_metadata in metadata.properties.values_mut() {
562 if !property_metadata.flags.is_static() {
563 property_metadata.flags |= MetadataFlags::READONLY;
564 }
565 }
566 }
567
568 metadata.mark_as_populated();
569 codebase.class_likes.insert(*classlike_name, metadata);
570}
571
572fn populate_interface_metadata_from_parent_interface(
574 metadata: &mut ClassLikeMetadata,
575 codebase: &mut CodebaseMetadata,
576 parent_interface: Atom,
577 symbol_references: &mut SymbolReferences,
578 safe_symbols: &AtomSet,
579) {
580 populate_class_like_metadata(&parent_interface, codebase, symbol_references, safe_symbols);
581
582 symbol_references.add_symbol_reference_to_symbol(metadata.name, parent_interface, true);
583
584 let parent_interface_metadata = if let Some(parent_meta) = codebase.class_likes.get(&parent_interface) {
585 parent_meta
586 } else {
587 metadata.invalid_dependencies.insert(parent_interface);
588 return;
589 };
590
591 for (interface_constant_name, interface_constant_metadata) in &parent_interface_metadata.constants {
592 if !metadata.constants.contains_key(interface_constant_name) {
593 metadata.constants.insert(*interface_constant_name, interface_constant_metadata.clone());
594 }
595 }
596
597 metadata.all_parent_interfaces.extend(parent_interface_metadata.all_parent_interfaces.iter().copied());
598 metadata.invalid_dependencies.extend(parent_interface_metadata.invalid_dependencies.iter().copied());
599
600 if let Some(inheritors) = &parent_interface_metadata.permitted_inheritors {
601 metadata.permitted_inheritors.get_or_insert_default().extend(inheritors.iter().copied());
602 }
603
604 extend_template_parameters(metadata, parent_interface_metadata);
606 inherit_methods_from_parent(metadata, parent_interface_metadata, codebase);
609 inherit_properties_from_parent(metadata, parent_interface_metadata);
610}
611
612fn populate_metadata_from_parent_class_like(
614 metadata: &mut ClassLikeMetadata,
615 codebase: &mut CodebaseMetadata,
616 parent_class: Atom,
617 symbol_references: &mut SymbolReferences,
618 safe_symbols: &AtomSet,
619) {
620 populate_class_like_metadata(&parent_class, codebase, symbol_references, safe_symbols);
621
622 symbol_references.add_symbol_reference_to_symbol(metadata.name, parent_class, true);
623
624 let parent_metadata = if let Some(parent_meta) = codebase.class_likes.get(&parent_class) {
625 parent_meta
626 } else {
627 metadata.invalid_dependencies.insert(parent_class);
628 return;
629 };
630
631 metadata.all_parent_classes.extend(parent_metadata.all_parent_classes.iter().copied());
632 metadata.all_parent_interfaces.extend(parent_metadata.all_parent_interfaces.iter().copied());
633 metadata.used_traits.extend(parent_metadata.used_traits.iter().copied());
634 metadata.invalid_dependencies.extend(parent_metadata.invalid_dependencies.iter().copied());
635
636 if let Some(inheritors) = &parent_metadata.permitted_inheritors {
637 metadata.permitted_inheritors.get_or_insert_default().extend(inheritors.iter().copied());
638 }
639
640 extend_template_parameters(metadata, parent_metadata);
641
642 inherit_methods_from_parent(metadata, parent_metadata, codebase);
643 inherit_properties_from_parent(metadata, parent_metadata);
644
645 for (parent_constant_name, parent_constant_metadata) in &parent_metadata.constants {
646 if !metadata.constants.contains_key(parent_constant_name) {
647 metadata.constants.insert(*parent_constant_name, parent_constant_metadata.clone());
648 }
649 }
650
651 if parent_metadata.flags.has_consistent_templates() {
652 metadata.flags |= MetadataFlags::CONSISTENT_TEMPLATES;
653 }
654}
655
656fn populate_metadata_from_required_class_like(
658 metadata: &mut ClassLikeMetadata,
659 codebase: &mut CodebaseMetadata,
660 parent_class: Atom,
661 symbol_references: &mut SymbolReferences,
662 safe_symbols: &AtomSet,
663) {
664 populate_class_like_metadata(&parent_class, codebase, symbol_references, safe_symbols);
665
666 symbol_references.add_symbol_reference_to_symbol(metadata.name, parent_class, true);
667
668 let parent_metadata = if let Some(parent_meta) = codebase.class_likes.get(&parent_class) {
669 parent_meta
670 } else {
671 metadata.invalid_dependencies.insert(parent_class);
672 return;
673 };
674
675 metadata.require_extends.extend(parent_metadata.all_parent_classes.iter().copied());
676 metadata.require_implements.extend(parent_metadata.all_parent_interfaces.iter().copied());
677}
678
679fn populate_metadata_from_trait(
681 metadata: &mut ClassLikeMetadata,
682 codebase: &mut CodebaseMetadata,
683 trait_name: Atom,
684 symbol_references: &mut SymbolReferences,
685 safe_symbols: &AtomSet,
686) {
687 populate_class_like_metadata(&trait_name, codebase, symbol_references, safe_symbols);
688
689 symbol_references.add_symbol_reference_to_symbol(metadata.name, trait_name, true);
690
691 let Some(trait_metadata) = codebase.class_likes.get(&trait_name) else {
692 metadata.invalid_dependencies.insert(trait_name);
693 return;
694 };
695
696 for (trait_constant_name, trait_constant_metadata) in &trait_metadata.constants {
698 if !metadata.constants.contains_key(trait_constant_name) {
699 metadata.constants.insert(*trait_constant_name, trait_constant_metadata.clone());
700 }
701 }
702
703 metadata.all_parent_interfaces.extend(trait_metadata.direct_parent_interfaces.iter().copied());
705
706 metadata.invalid_dependencies.extend(trait_metadata.invalid_dependencies.iter().copied());
708
709 extend_template_parameters(metadata, trait_metadata);
711
712 inherit_methods_from_parent(metadata, trait_metadata, codebase);
714 inherit_properties_from_parent(metadata, trait_metadata);
715}
716
717fn inherit_methods_from_parent(
720 metadata: &mut ClassLikeMetadata,
721 parent_metadata: &ClassLikeMetadata,
722 codebase: &CodebaseMetadata,
723) {
724 let class_like_name = metadata.name;
725 let is_trait = metadata.kind.is_trait();
726
727 for (method_name, appearing_class_like) in &parent_metadata.appearing_method_ids {
728 if metadata.has_appearing_method(method_name) {
729 continue;
730 }
731
732 metadata
733 .appearing_method_ids
734 .insert(*method_name, if is_trait { class_like_name } else { *appearing_class_like });
735
736 if codebase.function_likes.contains_key(&(class_like_name, *method_name)) {
737 metadata.potential_declaring_method_ids.insert(*method_name, AtomSet::from_iter([class_like_name]));
738 } else {
739 if let Some(parent_potential_method_ids) = parent_metadata.get_potential_declaring_method_id(method_name) {
740 metadata.potential_declaring_method_ids.insert(*method_name, parent_potential_method_ids.clone());
741 }
742
743 metadata.add_potential_declaring_method(*method_name, class_like_name);
744 metadata.add_potential_declaring_method(*method_name, parent_metadata.name);
745 }
746 }
747
748 for (method_name, declaring_class) in &parent_metadata.inheritable_method_ids {
749 if !method_name.eq(&atom("__construct")) || parent_metadata.flags.has_consistent_constructor() {
750 if !parent_metadata.kind.is_trait() || is_method_abstract(codebase, declaring_class, method_name) {
751 metadata.add_overridden_method_parent(*method_name, *declaring_class);
752 }
753
754 if let Some(map) = metadata.overridden_method_ids.get_mut(method_name)
755 && let Some(overridden_method_ids) = parent_metadata.overridden_method_ids.get(method_name)
756 {
757 map.extend(overridden_method_ids.iter().copied());
758 }
759 }
760
761 let mut aliased_method_names = vec![*method_name];
762 if parent_metadata.kind.is_trait() {
763 aliased_method_names
764 .extend(metadata.get_trait_alias_map().iter().filter(|(_, v)| *v == method_name).map(|(k, _)| *k));
765 }
766
767 for aliased_method_name in aliased_method_names {
768 let implementing_method_id = metadata.declaring_method_ids.get(&aliased_method_name);
769 if let Some(implementing_method_id) = implementing_method_id
770 && !is_method_abstract(codebase, implementing_method_id, &aliased_method_name)
771 {
772 continue;
773 }
774
775 metadata.declaring_method_ids.insert(aliased_method_name, *declaring_class);
776 metadata.inheritable_method_ids.insert(aliased_method_name, *declaring_class);
777 }
778 }
779}
780
781fn inherit_properties_from_parent(metadata: &mut ClassLikeMetadata, parent_metadata: &ClassLikeMetadata) {
784 let classlike_name = metadata.name;
785 let is_trait = metadata.kind.is_trait();
786 let parent_is_trait = parent_metadata.kind.is_trait();
787
788 for (property_name, appearing_classlike) in &parent_metadata.appearing_property_ids {
789 if metadata.has_appearing_property(property_name) {
790 continue;
791 }
792
793 if !parent_is_trait
794 && let Some(parent_property_metadata) = parent_metadata.properties.get(property_name)
795 && parent_property_metadata.is_final()
796 {
797 continue;
798 }
799
800 metadata
801 .appearing_property_ids
802 .insert(*property_name, if is_trait { classlike_name } else { *appearing_classlike });
803 }
804
805 for (property_name, declaring_classlike) in &parent_metadata.declaring_property_ids {
806 if metadata.declaring_property_ids.contains_key(property_name) {
807 continue;
808 }
809
810 if !parent_is_trait
811 && let Some(parent_property_metadata) = parent_metadata.properties.get(property_name)
812 && parent_property_metadata.is_final()
813 {
814 continue;
815 }
816
817 metadata.declaring_property_ids.insert(*property_name, *declaring_classlike);
818 }
819
820 for (property_name, inheritable_classlike) in &parent_metadata.inheritable_property_ids {
821 let mut is_overridable = true;
822 if !parent_is_trait {
823 if let Some(parent_property_metadata) = parent_metadata.properties.get(property_name)
824 && parent_property_metadata.is_final()
825 {
826 is_overridable = false;
827 }
828
829 if is_overridable {
830 metadata.overridden_property_ids.entry(*property_name).or_default().insert(*inheritable_classlike);
831 }
832 }
833
834 if is_overridable {
835 metadata.inheritable_property_ids.insert(*property_name, *inheritable_classlike);
836 }
837 }
838}
839
840fn extend_template_parameters(metadata: &mut ClassLikeMetadata, parent_metadata: &ClassLikeMetadata) {
843 let parent_name = parent_metadata.name;
844
845 if !parent_metadata.template_types.is_empty() {
846 metadata.template_extended_parameters.entry(parent_name).or_default();
847
848 if let Some(parent_offsets) = metadata.template_extended_offsets.get(&parent_name).cloned() {
849 let parent_template_type_names = parent_metadata.get_template_type_names();
850
851 for (i, extended_type_arc) in parent_offsets.into_iter().enumerate() {
852 if let Some(mapped_name) = parent_template_type_names.get(i).copied() {
853 metadata.add_template_extended_parameter(parent_name, mapped_name, extended_type_arc);
854 }
855 }
856
857 let current_child_extended_params = metadata.template_extended_parameters.clone();
858 for (grandparent_fqcn, type_map) in &parent_metadata.template_extended_parameters {
859 for (template_name, type_to_resolve_arc) in type_map {
860 let resolved_type = extend_type(type_to_resolve_arc, ¤t_child_extended_params);
861
862 metadata.add_template_extended_parameter(*grandparent_fqcn, *template_name, resolved_type);
863 }
864 }
865 } else {
866 for (parameter_name, parameter_type_map) in &parent_metadata.template_types {
867 for (_, parameter_type) in parameter_type_map {
868 metadata.add_template_extended_parameter(parent_name, *parameter_name, parameter_type.clone());
869 }
870 }
871
872 metadata.extend_template_extended_parameters(parent_metadata.template_extended_parameters.clone());
873 }
874 } else {
875 metadata.extend_template_extended_parameters(parent_metadata.template_extended_parameters.clone());
877 }
878}
879
880fn extend_type(
886 extended_type: &TUnion,
887 template_extended_parameters: &AtomMap<IndexMap<Atom, TUnion, RandomState>>,
888) -> TUnion {
889 if !extended_type.has_template() {
890 return extended_type.clone();
891 }
892
893 let mut extended_types = Vec::new();
894
895 let mut worklist = extended_type.types.clone().into_owned();
896 while let Some(atomic_type) = worklist.pop() {
897 if let TAtomic::GenericParameter(TGenericParameter {
898 parameter_name,
899 defining_entity: GenericParent::ClassLike(defining_entity),
900 ..
901 }) = &atomic_type
902 && let Some(extended_parameters) = template_extended_parameters.get(defining_entity)
903 && let Some(referenced_type) = extended_parameters.get(parameter_name)
904 {
905 extended_types.extend(referenced_type.types.clone().into_owned());
906 continue;
907 }
908
909 extended_types.push(atomic_type);
910 }
911
912 TUnion::from_vec(extended_types)
913}