Recursively walk statements and extract class information. This handles classes at the top level as well as classes nested inside namespace declarations.
(
statements: impl Iterator<Item = &'a Statement<'a>>,
classes: &mut Vec<ClassInfo>,
doc_ctx: Option<&DocblockCtx<'a>>,
)
| 821 | /// This handles classes at the top level as well as classes nested |
| 822 | /// inside namespace declarations. |
| 823 | pub(crate) fn extract_classes_from_statements<'a>( |
| 824 | statements: impl Iterator<Item = &'a Statement<'a>>, |
| 825 | classes: &mut Vec<ClassInfo>, |
| 826 | doc_ctx: Option<&DocblockCtx<'a>>, |
| 827 | ) { |
| 828 | for statement in statements { |
| 829 | match statement { |
| 830 | Statement::Class(class) => { |
| 831 | // Skip classes whose docblock has `@removed X.Y` |
| 832 | // where X.Y <= the target PHP version. |
| 833 | if let Some(ctx) = doc_ctx |
| 834 | && let Some(ver) = ctx.php_version |
| 835 | && is_removed_for_version(class, ctx, ver) |
| 836 | { |
| 837 | continue; |
| 838 | } |
| 839 | |
| 840 | let class_name = atom(class.name.value); |
| 841 | |
| 842 | let parent_class = class |
| 843 | .extends |
| 844 | .as_ref() |
| 845 | .and_then(|ext| ext.types.first().map(|ident| atom(ident.value()))); |
| 846 | |
| 847 | let interfaces: Vec<Atom> = class |
| 848 | .implements |
| 849 | .as_ref() |
| 850 | .map(|imp| imp.types.iter().map(|ident| atom(ident.value())).collect()) |
| 851 | .unwrap_or_default(); |
| 852 | |
| 853 | let doc_info = extract_class_docblock(class, doc_ctx); |
| 854 | |
| 855 | let ExtractedMembers { |
| 856 | methods, |
| 857 | properties, |
| 858 | constants, |
| 859 | used_traits, |
| 860 | trait_precedences, |
| 861 | trait_aliases, |
| 862 | inline_use_generics, |
| 863 | } = Self::extract_class_like_members( |
| 864 | class.members.iter(), |
| 865 | doc_ctx, |
| 866 | &doc_info.template_params, |
| 867 | ); |
| 868 | |
| 869 | let mut use_generics: Vec<(Atom, Vec<PhpType>)> = doc_info.use_generics; |
| 870 | use_generics.extend(inline_use_generics); |
| 871 | |
| 872 | let keyword_offset = class.class.span.start.offset; |
| 873 | let start_offset = class.left_brace.start.offset; |
| 874 | let end_offset = class.right_brace.end.offset; |
| 875 | |
| 876 | let content = doc_ctx.map(|c| c.content).unwrap_or(""); |
| 877 | let custom_collection = extract_custom_collection( |
| 878 | &class.attribute_lists, |
| 879 | &use_generics, |
| 880 | &methods, |
nothing calls this directly
no test coverage detected