Skip to content

Commit d7fdc81

Browse files
committed
Cleanup
1 parent 180aec9 commit d7fdc81

37 files changed

+278
-269
lines changed

binding-generator/src/bin/binding-generator.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use std::env;
22
use std::fs::File;
33
use std::io::BufReader;
4+
use std::ops::ControlFlow;
45
use std::path::{Path, PathBuf};
56

67
use opencv_binding_generator::writer::RustNativeBindingWriter;
7-
use opencv_binding_generator::{line_reader, Generator, LineReaderAction};
8+
use opencv_binding_generator::{line_reader, Generator};
89

910
fn get_version_header(header_dir: &Path) -> Option<PathBuf> {
1011
let out = header_dir.join("opencv2/core/version.hpp");
@@ -44,10 +45,10 @@ fn get_version_from_headers(header_dir: &Path) -> Option<String> {
4445
}
4546
}
4647
if major.is_some() && minor.is_some() && revision.is_some() {
47-
return LineReaderAction::Break;
48+
return ControlFlow::Break(());
4849
}
4950
}
50-
LineReaderAction::Continue
51+
ControlFlow::Continue(())
5152
});
5253
if let (Some(major), Some(minor), Some(revision)) = (major, minor, revision) {
5354
Some(format!("{major}.{minor}.{revision}"))

binding-generator/src/bin/settings-cleanup.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::path::{Path, PathBuf};
55
use std::{env, fmt};
66

77
use clang::{Entity, EntityKind};
8-
98
use opencv_binding_generator::{
109
opencv_module_from_path, settings, Class, EntityExt, EntityWalkerExt, EntityWalkerVisitor, Func, FuncId, Generator,
1110
GeneratorEnv,

binding-generator/src/class.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use std::rc::Rc;
66
use std::{fmt, iter};
77

88
use clang::{Accessibility, Entity, EntityKind};
9-
109
pub use desc::ClassDesc;
1110

1211
use crate::comment::strip_doxygen_comment_markers;
@@ -448,7 +447,7 @@ impl<'tu, 'ge> Class<'tu, 'ge> {
448447
def_loc: fld.file_line_name().location,
449448
rust_generic_decls: Rc::new([]),
450449
arguments: Rc::new([]),
451-
return_type_ref: fld_type_ref.with_inherent_constness(Constness::Const),
450+
return_type_ref: fld_type_ref.as_ref().clone().with_inherent_constness(Constness::Const),
452451
cpp_body: FuncCppBody::ManualCall("{{name}}".into()),
453452
rust_body: FuncRustBody::Auto,
454453
rust_extern_definition: FuncRustExtern::Auto,
@@ -470,7 +469,7 @@ impl<'tu, 'ge> Class<'tu, 'ge> {
470469
def_loc: fld.file_line_name().location,
471470
rust_generic_decls: Rc::new([]),
472471
arguments: Rc::new([]),
473-
return_type_ref: fld_type_ref.with_inherent_constness(Constness::Mut),
472+
return_type_ref: fld_type_ref.as_ref().clone().with_inherent_constness(Constness::Mut),
474473
cpp_body: FuncCppBody::ManualCall("{{name}}".into()),
475474
rust_body: FuncRustBody::Auto,
476475
rust_extern_definition: FuncRustExtern::Auto,
@@ -521,7 +520,7 @@ impl<'tu, 'ge> Class<'tu, 'ge> {
521520
rust_generic_decls: Rc::new([]),
522521
arguments: Rc::new([Field::new_desc(FieldDesc {
523522
cpp_fullname: "val".into(),
524-
type_ref: fld_type_ref.with_inherent_constness(Constness::Const),
523+
type_ref: fld_type_ref.as_ref().clone().with_inherent_constness(Constness::Const),
525524
default_value: fld.default_value().map(|v| v.into()),
526525
})]),
527526
return_kind: ReturnKind::InfallibleNaked,

binding-generator/src/constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub fn render_constant_rust(tokens: &[Token]) -> Option<Value> {
4242
}
4343
TokenKind::Literal => {
4444
let spelling = t.get_spelling();
45-
if spelling.contains(|c| c == '"' || c == '\'') {
45+
if spelling.contains(['"', '\'']) {
4646
out.kind = ValueKind::String;
4747
} else if spelling.contains('.') {
4848
out.kind = ValueKind::Float;

binding-generator/src/enumeration.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl<'tu> Enum<'tu> {
3636
self.entity.is_anonymous() || /* clang-6 quirk */ self.cpp_name(CppNameStyle::Declaration).starts_with("(anonymous enum")
3737
}
3838

39-
pub fn as_typedefed(&self) -> Option<Entity> {
39+
pub fn as_typedefed(&self) -> Option<Entity<'tu>> {
4040
if matches!(self.entity.get_kind(), EntityKind::TypedefDecl | EntityKind::TypeAliasDecl) {
4141
let mut child = None;
4242
self.entity.walk_children_while(|c| {
@@ -49,7 +49,7 @@ impl<'tu> Enum<'tu> {
4949
}
5050
}
5151

52-
pub fn consts(&self) -> Vec<Const> {
52+
pub fn consts(&self) -> Vec<Const<'tu>> {
5353
let mut out = vec![];
5454
self.as_typedefed().unwrap_or(self.entity).visit_children(|const_decl, _| {
5555
if const_decl.get_kind() == EntityKind::EnumConstantDecl {

binding-generator/src/field.rs

+21-11
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,20 @@ impl<'tu, 'ge> Field<'tu, 'ge> {
4343
Self::Desc(Rc::new(desc))
4444
}
4545

46-
pub(crate) fn to_desc(&self) -> Rc<FieldDesc<'tu, 'ge>> {
46+
pub(crate) fn to_desc(&self, new_typeref: Option<TypeRef<'tu, 'ge>>) -> Rc<FieldDesc<'tu, 'ge>> {
4747
match self {
48-
Self::Clang { type_ref_type_hint, .. } => Rc::new(FieldDesc {
48+
Self::Clang { .. } => Rc::new(FieldDesc {
4949
cpp_fullname: self.cpp_name(CppNameStyle::Reference).into(),
50-
type_ref: self.type_ref().into_owned().with_type_hint(type_ref_type_hint.clone()), // todo: add an option to avoid inheriting type_ref
50+
type_ref: new_typeref.unwrap_or_else(|| self.type_ref().into_owned()),
5151
default_value: self.default_value().map(Rc::from),
5252
}),
53-
Self::Desc(desc) => Rc::clone(desc),
53+
Self::Desc(desc) => {
54+
let mut out = Rc::clone(desc);
55+
if let Some(new_typeref) = new_typeref {
56+
Rc::make_mut(&mut out).type_ref = new_typeref;
57+
}
58+
out
59+
}
5460
}
5561
}
5662

@@ -88,9 +94,7 @@ impl<'tu, 'ge> Field<'tu, 'ge> {
8894
..
8995
} => {
9096
let type_ref_type_hint = type_ref_type_hint.clone().something_or_else(|| {
91-
let default_value_string = self
92-
.default_value()
93-
.map_or(false, |def| def.contains(|c| c == '"' || c == '\''));
97+
let default_value_string = self.default_value().map_or(false, |def| def.contains(['"', '\'']));
9498
if default_value_string {
9599
TypeRefTypeHint::CharAsRustChar
96100
} else {
@@ -108,10 +112,16 @@ impl<'tu, 'ge> Field<'tu, 'ge> {
108112
}
109113
}
110114

111-
pub fn with_type_ref(&self, type_ref: TypeRef<'tu, 'ge>) -> Self {
112-
let mut desc = self.to_desc();
113-
Rc::make_mut(&mut desc).type_ref = type_ref;
114-
Self::Desc(desc)
115+
pub fn with_type_ref(mut self, type_ref: TypeRef<'tu, 'ge>) -> Self {
116+
self.set_type_ref(type_ref);
117+
self
118+
}
119+
120+
pub fn set_type_ref(&mut self, type_ref: TypeRef<'tu, 'ge>) {
121+
match self {
122+
Self::Clang { .. } => *self = Self::Desc(self.to_desc(Some(type_ref))),
123+
Self::Desc(desc) => Rc::make_mut(desc).type_ref = type_ref,
124+
}
115125
}
116126

117127
pub fn constness(&self) -> Constness {

binding-generator/src/generator.rs

+72-68
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::typedef::NewTypedefResult;
1515
use crate::writer::rust_native::element::RustElement;
1616
use crate::{
1717
get_definition_text, line_reader, settings, AbstractRefWrapper, Class, ClassKindOverride, Const, Element, EntityExt,
18-
EntityWalkerExt, EntityWalkerVisitor, Enum, Func, GeneratorEnv, LineReaderAction, SmartPtr, Tuple, Typedef, Vector,
18+
EntityWalkerExt, EntityWalkerVisitor, Enum, Func, GeneratorEnv, SmartPtr, Tuple, Typedef, Vector,
1919
};
2020

2121
#[derive(Debug)]
@@ -41,7 +41,7 @@ impl<'tu, 'ge> TryFrom<TypeRef<'tu, 'ge>> for GeneratedType<'tu, 'ge> {
4141

4242
/// Visitor of the different supported OpenCV entities, used in conjunction with [Generator]
4343
#[allow(unused)]
44-
pub trait GeneratorVisitor {
44+
pub trait GeneratorVisitor<'tu>: Sized {
4545
/// Check whether the visitor is interested in entities from the specified file
4646
fn wants_file(&mut self, path: &Path) -> bool {
4747
true
@@ -51,36 +51,39 @@ pub trait GeneratorVisitor {
5151
fn visit_module_comment(&mut self, comment: String) {}
5252

5353
/// Top-level constant
54-
fn visit_const(&mut self, cnst: Const) {}
54+
fn visit_const(&mut self, cnst: Const<'tu>) {}
5555

5656
/// Top-level enum
57-
fn visit_enum(&mut self, enm: Enum) {}
57+
fn visit_enum(&mut self, enm: Enum<'tu>) {}
5858

5959
/// Top-level function
60-
fn visit_func(&mut self, func: Func) {}
60+
fn visit_func(&mut self, func: Func<'tu, '_>) {}
6161

6262
/// Top-level type alias
63-
fn visit_typedef(&mut self, typedef: Typedef) {}
63+
fn visit_typedef(&mut self, typedef: Typedef<'tu, '_>) {}
6464

6565
/// Top-level class or an internal class of another class
66-
fn visit_class(&mut self, class: Class) {}
66+
fn visit_class(&mut self, class: Class<'tu, '_>) {}
6767

6868
/// Dependent generated type like `std::vector<Mat>` or `std::tuple<1, 2, 3>`
69-
fn visit_generated_type(&mut self, typ: GeneratedType) {}
69+
fn visit_generated_type(&mut self, typ: GeneratedType<'tu, '_>) {}
70+
71+
/// Called at the end of the visitation
72+
fn goodbye(self) {}
7073
}
7174

7275
/// Bridge between [EntityWalkerVisitor] and [GeneratorVisitor]
7376
///
7477
/// It takes [Entity]s supplied by the entity walker, extracts their export data (whether the entity should appear in bindings at
7578
/// all or is internal) and calls the corresponding method in [GeneratorVisitor] based on their type. This is the 2nd pass of the
7679
/// binding generation.
77-
struct OpenCvWalker<'tu, 'r, V: GeneratorVisitor> {
80+
struct OpenCvWalker<'tu, 'r, V> {
7881
opencv_module_header_dir: &'r Path,
7982
visitor: V,
8083
gen_env: GeneratorEnv<'tu>,
8184
}
8285

83-
impl<'tu, V: GeneratorVisitor> EntityWalkerVisitor<'tu> for OpenCvWalker<'tu, '_, V> {
86+
impl<'tu, V: GeneratorVisitor<'tu>> EntityWalkerVisitor<'tu> for OpenCvWalker<'tu, '_, V> {
8487
fn wants_file(&mut self, path: &Path) -> bool {
8588
self.visitor.wants_file(path) || path.ends_with("ocvrs_common.hpp")
8689
}
@@ -148,9 +151,61 @@ impl<'tu, V: GeneratorVisitor> EntityWalkerVisitor<'tu> for OpenCvWalker<'tu, '_
148151
}
149152
ControlFlow::Continue(())
150153
}
154+
155+
fn goodbye(mut self) {
156+
// Some module level comments like "bioinspired" are not attached to anything and libclang
157+
// doesn't seem to offer a way to extract them, do it the hard way then.
158+
// That's actually the case for all modules starting with OpenCV 4.8.0 so this is now a single
159+
// method of extracting comments
160+
let mut comment = String::with_capacity(2048);
161+
let mut found_module_comment = false;
162+
let module_path = self.opencv_module_header_dir.join(format!("{}.hpp", self.gen_env.module()));
163+
if let Ok(module_file) = File::open(module_path) {
164+
let f = BufReader::new(module_file);
165+
let mut defgroup_found = false;
166+
line_reader(f, |line| {
167+
if !found_module_comment && line.trim_start().starts_with("/**") {
168+
found_module_comment = true;
169+
defgroup_found = false;
170+
}
171+
if found_module_comment {
172+
if comment.contains("@defgroup") {
173+
defgroup_found = true;
174+
}
175+
comment.push_str(line);
176+
if line.trim_end().ends_with("*/") {
177+
if defgroup_found {
178+
return ControlFlow::Break(());
179+
} else {
180+
comment.clear();
181+
found_module_comment = false;
182+
}
183+
}
184+
}
185+
ControlFlow::Continue(())
186+
});
187+
}
188+
if found_module_comment {
189+
self.visitor.visit_module_comment(comment);
190+
}
191+
for inject_func_fact in settings::FUNC_INJECT.get(self.gen_env.module()).into_iter().flatten() {
192+
let inject_func: Func = inject_func_fact();
193+
if !inject_func.kind().as_class_method().is_some() {
194+
self.visitor.visit_func(inject_func);
195+
}
196+
}
197+
if let Some(tweaks) = settings::GENERATOR_MODULE_TWEAKS.get(self.gen_env.module()) {
198+
for generated in &tweaks.generate_types {
199+
if let Ok(generated) = GeneratedType::try_from(generated()) {
200+
self.visitor.visit_generated_type(generated);
201+
}
202+
}
203+
}
204+
self.visitor.goodbye();
205+
}
151206
}
152207

153-
impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
208+
impl<'tu, 'r, V: GeneratorVisitor<'tu>> OpenCvWalker<'tu, 'r, V> {
154209
pub fn new(opencv_module_header_dir: &'r Path, visitor: V, gen_env: GeneratorEnv<'tu>) -> Self {
155210
Self {
156211
opencv_module_header_dir,
@@ -159,7 +214,7 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
159214
}
160215
}
161216

162-
fn process_const(visitor: &mut V, const_decl: Entity) {
217+
fn process_const(visitor: &mut V, const_decl: Entity<'tu>) {
163218
let cnst = Const::new(const_decl);
164219
if cnst.exclude_kind().is_included() {
165220
visitor.visit_const(cnst);
@@ -202,7 +257,7 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
202257
}
203258
}
204259

205-
fn process_enum(visitor: &mut V, enum_decl: Entity) {
260+
fn process_enum(visitor: &mut V, enum_decl: Entity<'tu>) {
206261
let enm = Enum::new(enum_decl);
207262
if enm.exclude_kind().is_included() {
208263
for cnst in enm.consts() {
@@ -294,57 +349,6 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
294349
}
295350
}
296351

297-
impl<V: GeneratorVisitor> Drop for OpenCvWalker<'_, '_, V> {
298-
fn drop(&mut self) {
299-
// Some module level comments like "bioinspired" are not attached to anything and libclang
300-
// doesn't seem to offer a way to extract them, do it the hard way then.
301-
// That's actually the case for all modules starting with OpenCV 4.8.0 so this is now a single
302-
// method of extracting comments
303-
let mut comment = String::with_capacity(2048);
304-
let module_path = self.opencv_module_header_dir.join(format!("{}.hpp", self.gen_env.module()));
305-
let f = BufReader::new(File::open(module_path).expect("Can't open main module file"));
306-
let mut found_module_comment = false;
307-
let mut defgroup_found = false;
308-
line_reader(f, |line| {
309-
if !found_module_comment && line.trim_start().starts_with("/**") {
310-
found_module_comment = true;
311-
defgroup_found = false;
312-
}
313-
if found_module_comment {
314-
if comment.contains("@defgroup") {
315-
defgroup_found = true;
316-
}
317-
comment.push_str(line);
318-
if line.trim_end().ends_with("*/") {
319-
if defgroup_found {
320-
return LineReaderAction::Break;
321-
} else {
322-
comment.clear();
323-
found_module_comment = false;
324-
}
325-
}
326-
}
327-
LineReaderAction::Continue
328-
});
329-
if found_module_comment {
330-
self.visitor.visit_module_comment(comment);
331-
}
332-
for inject_func_fact in settings::FUNC_INJECT.get(self.gen_env.module()).into_iter().flatten() {
333-
let inject_func: Func = inject_func_fact();
334-
if !inject_func.kind().as_class_method().is_some() {
335-
self.visitor.visit_func(inject_func);
336-
}
337-
}
338-
if let Some(tweaks) = settings::GENERATOR_MODULE_TWEAKS.get(self.gen_env.module()) {
339-
for generated in &tweaks.generate_types {
340-
if let Ok(generated) = GeneratedType::try_from(generated()) {
341-
self.visitor.visit_generated_type(generated);
342-
}
343-
}
344-
}
345-
}
346-
}
347-
348352
/// Main workhorse for generating OpenCV bindings for a specific module
349353
///
350354
/// Full binding generation for a module is happening in the following major phases:
@@ -436,9 +440,9 @@ impl Generator {
436440
// need to have c++14 here because VS headers contain features that require it
437441
args.push("-std=c++14".into());
438442
// allow us to use some custom clang args
439-
if let Some(clang_arg_str) = env::var_os("OPENCV_CLANG_ARGS") {
440-
let clang_arg = clang_arg_str.to_str().expect("Try to get OPENCV_CLANG_ARGS failed.");
441-
Shlex::new(clang_arg).into_iter().for_each(|i| args.push(i.into()))
443+
let clang_arg = env::var_os("OPENCV_CLANG_ARGS");
444+
if let Some(clang_arg) = clang_arg.as_ref().and_then(|s| s.to_str()) {
445+
args.extend(Shlex::new(clang_arg).map(Cow::Owned));
442446
}
443447
args
444448
}
@@ -462,7 +466,7 @@ impl Generator {
462466
}
463467

464468
/// Runs the full binding generation process using the supplied `visitor`
465-
pub fn generate(&self, module: &str, visitor: impl GeneratorVisitor) {
469+
pub fn generate(&self, module: &str, visitor: impl for<'tu> GeneratorVisitor<'tu>) {
466470
self.pre_process(module, true, |root_entity| {
467471
let gen_env = GeneratorEnv::new(root_entity, module);
468472
let opencv_walker = OpenCvWalker::new(&self.opencv_module_header_dir, visitor, gen_env);

0 commit comments

Comments
 (0)