11use std:: borrow:: Cow ;
22use std:: fmt:: Debug ;
3+ use std:: ops:: ControlFlow ;
34
45use clang:: { Entity , EntityKind } ;
56
67use super :: comment:: RenderComment ;
78use crate :: type_ref:: FishStyle ;
89use crate :: {
9- opencv_module_from_path, reserved_rename, settings, CppNameStyle , Element , GeneratedType , IteratorExt , NameStyle , StringExt ,
10- SupportedModule ,
10+ opencv_module_from_path, reserved_rename, settings, CppNameStyle , Element , EntityExt , GeneratedType , IteratorExt , NameStyle ,
11+ StringExt , SupportedModule ,
1112} ;
1213
1314pub struct DefaultRustNativeElement ;
@@ -20,7 +21,7 @@ impl DefaultRustNativeElement {
2021 . get_spelling_location ( )
2122 . file
2223 . and_then ( |file| opencv_module_from_path ( & file. get_path ( ) ) )
23- . unwrap_or ( SupportedModule :: Core )
24+ . map_or ( SupportedModule :: Core , |m| rust_module_hack ( entity , m ) )
2425 }
2526
2627 pub fn rust_module_reference ( this : & ( impl RustElement + ?Sized ) ) -> Cow < ' _ , str > {
@@ -148,3 +149,28 @@ impl<'ne, 'tu: 'ne, 'ge: 'ne> AsRef<dyn RustNativeGeneratedElement + 'ne> for Ge
148149 }
149150 }
150151}
152+
153+ /// Adjusts the module for certain entities that are technically in one module but actually implemented in another.
154+ ///
155+ /// One (and for now the only) example is that some class declarations are technically in `hpp` files in the `video` module, but
156+ /// their code is actually in the `tracking` module of `opencv_contrib`. This mismatch leads to linking errors if only the
157+ /// `opencv_video` module is linked.
158+ fn rust_module_hack ( entity : Entity , module_from_path : SupportedModule ) -> SupportedModule {
159+ match module_from_path {
160+ SupportedModule :: Video => {
161+ let break_res = entity. walk_parents ( |parent| match parent. get_kind ( ) {
162+ EntityKind :: Namespace if parent. is_inline_namespace ( ) && parent. get_name ( ) . is_some_and ( |n| n == "tracking" ) => {
163+ ControlFlow :: Break ( SupportedModule :: Tracking )
164+ }
165+ _ => ControlFlow :: Continue ( ( ) ) ,
166+ } ) ;
167+ // todo: MSRV 1.83 use `break_value()`
168+ match break_res {
169+ ControlFlow :: Break ( m) => Some ( m) ,
170+ ControlFlow :: Continue ( _) => None ,
171+ }
172+ . unwrap_or ( module_from_path)
173+ }
174+ _ => module_from_path,
175+ }
176+ }
0 commit comments