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 fn walk_parents<T>(&self, predicate: impl FnMut(Entity<'tu>) -> ControlFlow<T>) -> ControlFlow<T>;
81}
82
83impl<'tu> EntityExt<'tu> for Entity<'tu> {
84 fn walk_children_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
85 let res = self.visit_children(|child, _| predicate(child).into_entity_visit_result());
86 if res {
87 ControlFlow::Break(())
88 } else {
89 ControlFlow::Continue(())
90 }
91 }
92
93 fn walk_bases_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
94 self.walk_children_while(|child| match child.get_kind() {
95 EntityKind::BaseSpecifier => predicate(child),
96 _ => ControlFlow::Continue(()),
97 })
98 }
99
100 fn walk_enums_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
101 self.walk_children_while(|child| match child.get_kind() {
102 EntityKind::EnumDecl => predicate(child),
103 _ => ControlFlow::Continue(()),
104 })
105 }
106
107 fn walk_classes_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
108 self.walk_children_while(|child| match child.get_kind() {
109 EntityKind::ClassDecl | EntityKind::StructDecl => predicate(child),
110 _ => ControlFlow::Continue(()),
111 })
112 }
113
114 fn walk_typedefs_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
115 self.walk_children_while(|child| match child.get_kind() {
116 EntityKind::TypedefDecl | EntityKind::TypeAliasDecl => predicate(child),
117 _ => ControlFlow::Continue(()),
118 })
119 }
120
121 fn walk_fields_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
122 self.walk_children_while(|child| match child.get_kind() {
123 EntityKind::FieldDecl => predicate(child),
124 _ => ControlFlow::Continue(()),
125 })
126 }
127
128 fn walk_consts_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
129 self.walk_children_while(|child| match child.get_kind() {
130 EntityKind::VarDecl => {
131 if let Some(StorageClass::Static) = child.get_storage_class() {
132 if child.evaluate().is_some() {
133 predicate(child)
134 } else {
135 ControlFlow::Continue(())
136 }
137 } else {
138 panic!("Non-static constant: {child:#?}")
139 }
140 }
141 _ => ControlFlow::Continue(()),
142 })
143 }
144
145 fn walk_methods_while(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<()>) -> ControlFlow<()> {
146 self.walk_children_while(|child| match child.get_kind() {
147 EntityKind::Constructor | EntityKind::Method | EntityKind::FunctionTemplate | EntityKind::ConversionFunction => {
148 predicate(child)
149 }
150 _ => ControlFlow::Continue(()),
151 })
152 }
153
154 fn walk_parents<T>(&self, mut predicate: impl FnMut(Entity<'tu>) -> ControlFlow<T>) -> ControlFlow<T> {
155 let mut current = *self;
156 while let Some(parent) = current.get_semantic_parent() {
157 match predicate(parent) {
158 ControlFlow::Continue(()) => current = parent,
159 ControlFlow::Break(out) => return ControlFlow::Break(out),
160 }
161 }
162 ControlFlow::Continue(())
163 }
164}
165
166#[allow(unused)]
167pub fn dbg_clang_entity<'tu>(entity: impl ToEntity<'tu>) {
168 struct EntityWrapper<'tu>(Entity<'tu>);
169
170 impl fmt::Debug for EntityWrapper<'_> {
171 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172 f.debug_struct("Entity")
173 .field("evaluate", &self.0.evaluate())
174 .field("kind", &self.0.get_kind())
175 .field("display_name", &self.0.get_display_name())
176 .field("location", &self.0.get_location())
177 .field("range", &self.0.get_range())
178 .field("accessibility", &self.0.get_accessibility())
179 .field("arguments", &self.0.get_arguments())
180 .field("availability", &self.0.get_availability())
181 .field("bit_field_width", &self.0.get_bit_field_width())
182 .field("canonical_entity", &self.0.get_canonical_entity())
183 .field("comment", &self.0.get_comment())
184 .field("parsed_comment", &self.0.get_parsed_comment())
185 .field("comment_brief", &self.0.get_comment_brief())
186 .field("comment_range", &self.0.get_comment_range())
187 .field("completion_string", &self.0.get_completion_string())
188 .field("children", &self.0.get_children())
189 .field("definition", &self.0.get_definition())
190 .field("enum_constant_value", &self.0.get_enum_constant_value())
191 .field("enum_underlying_type", &self.0.get_enum_underlying_type())
192 .field("exception_specification", &self.0.get_exception_specification())
193 .field("external_symbol", &self.0.get_external_symbol())
194 .field("file", &self.0.get_file())
195 .field("language", &self.0.get_language())
196 .field("lexical_parent", &self.0.get_lexical_parent())
197 .field("linkage", &self.0.get_linkage())
198 .field("mangled_name", &self.0.get_mangled_name())
199 .field("mangled_names", &self.0.get_mangled_names())
200 .field("module", &self.0.get_module())
201 .field("name", &self.0.get_name())
202 .field("name_ranges", &self.0.get_name_ranges())
203 .field("offset_of_field", &self.0.get_offset_of_field())
204 .field("overloaded_declarations", &self.0.get_overloaded_declarations())
205 .field("overridden_methods", &self.0.get_overridden_methods())
206 .field("platform_availability", &self.0.get_platform_availability())
207 .field("reference", &self.0.get_reference())
208 .field("semantic_parent", &self.0.get_semantic_parent())
209 .field("storage_class", &self.0.get_storage_class())
210 .field("template", &self.0.get_template())
211 .field("template_arguments", &self.0.get_template_arguments())
212 .field("template_kind", &self.0.get_template_kind())
213 .field("tls_kind", &self.0.get_tls_kind())
214 .field("translation_unit", &self.0.get_translation_unit())
215 .field("type", &self.0.get_type())
216 .field("typedef_underlying_type", &self.0.get_typedef_underlying_type())
217 .field("usr", &self.0.get_usr())
218 .field("visibility", &self.0.get_visibility())
219 .field("result_type", &self.0.get_result_type())
220 .field("has_attributes", &self.0.has_attributes())
221 .field("is_abstract_record", &self.0.is_abstract_record())
222 .field("is_anonymous", &self.0.is_anonymous())
223 .field("is_bit_field", &self.0.is_bit_field())
224 .field("is_builtin_macro", &self.0.is_builtin_macro())
225 .field("is_const_method", &self.0.is_const_method())
226 .field("is_converting_constructor", &self.0.is_converting_constructor())
227 .field("is_copy_constructor", &self.0.is_copy_constructor())
228 .field("is_default_constructor", &self.0.is_default_constructor())
229 .field("is_defaulted", &self.0.is_defaulted())
230 .field("is_definition", &self.0.is_definition())
231 .field("is_dynamic_call", &self.0.is_dynamic_call())
232 .field("is_function_like_macro", &self.0.is_function_like_macro())
233 .field("is_inline_function", &self.0.is_inline_function())
234.field("is_move_constructor", &self.0.is_move_constructor())
236 .field("is_mutable", &self.0.is_mutable())
237 .field("is_pure_virtual_method", &self.0.is_pure_virtual_method())
238 .field("is_scoped", &self.0.is_scoped())
239 .field("is_static_method", &self.0.is_static_method())
240 .field("is_variadic", &self.0.is_variadic())
241 .field("is_virtual_base", &self.0.is_virtual_base())
242 .field("is_virtual_method", &self.0.is_virtual_method())
243 .field("is_attribute", &self.0.is_attribute())
244 .field("is_declaration", &self.0.is_declaration())
245 .field("is_expression", &self.0.is_expression())
246 .field("is_preprocessing", &self.0.is_preprocessing())
247 .field("is_reference", &self.0.is_reference())
248 .field("is_statement", &self.0.is_statement())
249 .field("is_unexposed", &self.0.is_unexposed())
250 .field("is_in_main_file", &self.0.is_in_main_file())
251 .field("is_in_system_header", &self.0.is_in_system_header())
252 .finish()
253 }
254 }
255 if let Some(entity) = entity.to_entity() {
256 eprintln!("{:#?}", EntityWrapper(entity));
257 }
258}