opencv_binding_generator/
entity.rs

1use 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_invalid_declaration", &self.0.is_invalid_declaration())
235				.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}