opencv_binding_generator/
entity.rs1use std::borrow::Cow;
2use std::fmt;
3use std::ops::ControlFlow;
4
5use clang::{Entity, EntityKind, EntityVisitResult, StorageClass};
6
7use crate::comment::strip_doxygen_comment_markers;
8use crate::type_ref::CppNameStyle;
9use crate::{DefaultElement, Element, EntityElement};
10
11impl<'tu> EntityElement<'tu> for Entity<'tu> {
12 fn entity(&self) -> Entity<'tu> {
13 *self
14 }
15}
16
17impl Element for Entity<'_> {
18 fn is_system(&self) -> bool {
19 DefaultElement::is_system(self.entity())
20 }
21
22 fn is_public(&self) -> bool {
23 DefaultElement::is_public(self.entity())
24 }
25
26 fn doc_comment(&self) -> Cow<str> {
27 strip_doxygen_comment_markers(&self.get_comment().unwrap_or_default()).into()
28 }
29
30 fn cpp_namespace(&self) -> Cow<str> {
31 DefaultElement::cpp_namespace(self.entity()).into()
32 }
33
34 fn cpp_name(&self, style: CppNameStyle) -> Cow<str> {
35 DefaultElement::cpp_name(self, self.entity(), style)
36 }
37}
38
39pub trait ToEntity<'tu> {
40 fn to_entity(self) -> Option<Entity<'tu>>;
41}
42
43impl<'tu> ToEntity<'tu> for &Entity<'tu> {
44 fn to_entity(self) -> Option<Entity<'tu>> {
45 Some(*self)
46 }
47}
48
49pub trait ControlFlowExt {
50 fn continue_until(condition: bool) -> Self;
51 fn into_entity_visit_result(self) -> EntityVisitResult;
52}
53
54impl ControlFlowExt for ControlFlow<()> {
55 fn continue_until(condition: bool) -> Self {
56 if condition {
57 ControlFlow::Break(())
58 } else {
59 ControlFlow::Continue(())
60 }
61 }
62
63 fn into_entity_visit_result(self) -> EntityVisitResult {
64 match self {
65 ControlFlow::Continue(_) => EntityVisitResult::Continue,
66 ControlFlow::Break(_) => EntityVisitResult::Break,
67 }
68 }
69}
70
71pub trait EntityExt<'tu> {
72 fn walk_children_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
73 fn walk_bases_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
74 fn walk_enums_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
75 fn walk_classes_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
76 fn walk_typedefs_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
77 fn walk_fields_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
78 fn walk_consts_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
79 fn walk_methods_while(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()>;
80}
81
82impl<'tu> EntityExt<'tu> for Entity<'tu> {
83 fn walk_children_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
84 let res = self.visit_children(|child, _| predicate(child).into_entity_visit_result());
85 if res {
86 ControlFlow::Break(())
87 } else {
88 ControlFlow::Continue(())
89 }
90 }
91
92 fn walk_bases_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
93 self.walk_children_while(|child| match child.get_kind() {
94 EntityKind::BaseSpecifier => predicate(child),
95 _ => ControlFlow::Continue(()),
96 })
97 }
98
99 fn walk_enums_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
100 self.walk_children_while(|child| match child.get_kind() {
101 EntityKind::EnumDecl => predicate(child),
102 _ => ControlFlow::Continue(()),
103 })
104 }
105
106 fn walk_classes_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
107 self.walk_children_while(|child| match child.get_kind() {
108 EntityKind::ClassDecl | EntityKind::StructDecl => predicate(child),
109 _ => ControlFlow::Continue(()),
110 })
111 }
112
113 fn walk_typedefs_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
114 self.walk_children_while(|child| match child.get_kind() {
115 EntityKind::TypedefDecl | EntityKind::TypeAliasDecl => predicate(child),
116 _ => ControlFlow::Continue(()),
117 })
118 }
119
120 fn walk_fields_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
121 self.walk_children_while(|child| match child.get_kind() {
122 EntityKind::FieldDecl => predicate(child),
123 _ => ControlFlow::Continue(()),
124 })
125 }
126
127 fn walk_consts_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
128 self.walk_children_while(|child| match child.get_kind() {
129 EntityKind::VarDecl => {
130 if let Some(StorageClass::Static) = child.get_storage_class() {
131 if child.evaluate().is_some() {
132 predicate(child)
133 } else {
134 ControlFlow::Continue(())
135 }
136 } else {
137 panic!("Non-static constant: {child:#?}")
138 }
139 }
140 _ => ControlFlow::Continue(()),
141 })
142 }
143
144 fn walk_methods_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
145 self.walk_children_while(|child| match child.get_kind() {
146 EntityKind::Constructor | EntityKind::Method | EntityKind::FunctionTemplate | EntityKind::ConversionFunction => {
147 predicate(child)
148 }
149 _ => ControlFlow::Continue(()),
150 })
151 }
152}
153
154#[allow(unused)]
155pub fn dbg_clang_entity<'tu>(entity: impl ToEntity<'tu>) {
156 struct EntityWrapper<'tu>(Entity<'tu>);
157
158 impl fmt::Debug for EntityWrapper<'_> {
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 f.debug_struct("Entity")
161 .field("evaluate", &self.0.evaluate())
162 .field("kind", &self.0.get_kind())
163 .field("display_name", &self.0.get_display_name())
164 .field("location", &self.0.get_location())
165 .field("range", &self.0.get_range())
166 .field("accessibility", &self.0.get_accessibility())
167 .field("arguments", &self.0.get_arguments())
168 .field("availability", &self.0.get_availability())
169 .field("bit_field_width", &self.0.get_bit_field_width())
170 .field("canonical_entity", &self.0.get_canonical_entity())
171 .field("comment", &self.0.get_comment())
172 .field("parsed_comment", &self.0.get_parsed_comment())
173 .field("comment_brief", &self.0.get_comment_brief())
174 .field("comment_range", &self.0.get_comment_range())
175 .field("completion_string", &self.0.get_completion_string())
176 .field("children", &self.0.get_children())
177 .field("definition", &self.0.get_definition())
178 .field("enum_constant_value", &self.0.get_enum_constant_value())
179 .field("enum_underlying_type", &self.0.get_enum_underlying_type())
180 .field("exception_specification", &self.0.get_exception_specification())
181 .field("external_symbol", &self.0.get_external_symbol())
182 .field("file", &self.0.get_file())
183 .field("language", &self.0.get_language())
184 .field("lexical_parent", &self.0.get_lexical_parent())
185 .field("linkage", &self.0.get_linkage())
186 .field("mangled_name", &self.0.get_mangled_name())
187 .field("mangled_names", &self.0.get_mangled_names())
188 .field("module", &self.0.get_module())
189 .field("name", &self.0.get_name())
190 .field("name_ranges", &self.0.get_name_ranges())
191 .field("offset_of_field", &self.0.get_offset_of_field())
192 .field("overloaded_declarations", &self.0.get_overloaded_declarations())
193 .field("overridden_methods", &self.0.get_overridden_methods())
194 .field("platform_availability", &self.0.get_platform_availability())
195 .field("reference", &self.0.get_reference())
196 .field("semantic_parent", &self.0.get_semantic_parent())
197 .field("storage_class", &self.0.get_storage_class())
198 .field("template", &self.0.get_template())
199 .field("template_arguments", &self.0.get_template_arguments())
200 .field("template_kind", &self.0.get_template_kind())
201 .field("tls_kind", &self.0.get_tls_kind())
202 .field("translation_unit", &self.0.get_translation_unit())
203 .field("type", &self.0.get_type())
204 .field("typedef_underlying_type", &self.0.get_typedef_underlying_type())
205 .field("usr", &self.0.get_usr())
206 .field("visibility", &self.0.get_visibility())
207 .field("result_type", &self.0.get_result_type())
208 .field("has_attributes", &self.0.has_attributes())
209 .field("is_abstract_record", &self.0.is_abstract_record())
210 .field("is_anonymous", &self.0.is_anonymous())
211 .field("is_bit_field", &self.0.is_bit_field())
212 .field("is_builtin_macro", &self.0.is_builtin_macro())
213 .field("is_const_method", &self.0.is_const_method())
214 .field("is_converting_constructor", &self.0.is_converting_constructor())
215 .field("is_copy_constructor", &self.0.is_copy_constructor())
216 .field("is_default_constructor", &self.0.is_default_constructor())
217 .field("is_defaulted", &self.0.is_defaulted())
218 .field("is_definition", &self.0.is_definition())
219 .field("is_dynamic_call", &self.0.is_dynamic_call())
220 .field("is_function_like_macro", &self.0.is_function_like_macro())
221 .field("is_inline_function", &self.0.is_inline_function())
222.field("is_move_constructor", &self.0.is_move_constructor())
224 .field("is_mutable", &self.0.is_mutable())
225 .field("is_pure_virtual_method", &self.0.is_pure_virtual_method())
226 .field("is_scoped", &self.0.is_scoped())
227 .field("is_static_method", &self.0.is_static_method())
228 .field("is_variadic", &self.0.is_variadic())
229 .field("is_virtual_base", &self.0.is_virtual_base())
230 .field("is_virtual_method", &self.0.is_virtual_method())
231 .field("is_attribute", &self.0.is_attribute())
232 .field("is_declaration", &self.0.is_declaration())
233 .field("is_expression", &self.0.is_expression())
234 .field("is_preprocessing", &self.0.is_preprocessing())
235 .field("is_reference", &self.0.is_reference())
236 .field("is_statement", &self.0.is_statement())
237 .field("is_unexposed", &self.0.is_unexposed())
238 .field("is_in_main_file", &self.0.is_in_main_file())
239 .field("is_in_system_header", &self.0.is_in_system_header())
240 .finish()
241 }
242 }
243 if let Some(entity) = entity.to_entity() {
244 eprintln!("{:#?}", EntityWrapper(entity));
245 }
246}