1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::path::Path;
use clang::{Entity, EntityKind, EntityVisitResult, Type};
use crate::main_opencv_module_from_path;
#[allow(unused)]
pub trait EntityWalkerVisitor<'tu> {
fn wants_file(&mut self, path: &Path) -> bool { true }
fn visit_resolve_type(&mut self, typ: Type<'tu>) -> bool { true }
fn visit_entity(&mut self, entity: Entity<'tu>) -> bool;
}
pub struct EntityWalker<'tu> {
root_entity: Entity<'tu>,
}
impl<'tu> EntityWalker<'tu> {
pub fn new(root_entity: Entity<'tu>) -> Self {
Self { root_entity }
}
fn visit_resolve_types_namespace(ns: Entity<'tu>, visitor: &mut impl EntityWalkerVisitor<'tu>) -> bool {
!ns.visit_children(|decl, _| {
let res = match decl.get_kind() {
EntityKind::TypedefDecl => {
if let Some(typ) = decl.get_typedef_underlying_type() {
visitor.visit_resolve_type(typ)
} else {
true
}
},
_ => {
true
}
};
if res {
EntityVisitResult::Continue
} else {
EntityVisitResult::Break
}
})
}
fn visit_cv_namespace(ns: Entity<'tu>, visitor: &mut impl EntityWalkerVisitor<'tu>) -> bool {
!ns.visit_children(|decl, _| {
let res = match decl.get_kind() {
EntityKind::Namespace => {
Self::visit_cv_namespace(decl, visitor)
}
EntityKind::ClassDecl | EntityKind::ClassTemplate | EntityKind::ClassTemplatePartialSpecialization
| EntityKind::StructDecl | EntityKind::EnumDecl | EntityKind::FunctionDecl
| EntityKind::TypedefDecl | EntityKind::VarDecl => {
visitor.visit_entity(decl)
}
EntityKind::Constructor | EntityKind::ConversionFunction | EntityKind::Destructor
| EntityKind::Method | EntityKind::UnexposedDecl | EntityKind::FunctionTemplate
| EntityKind::UsingDeclaration | EntityKind::UsingDirective => {
true
}
_ => {
unreachable!("Unsupported decl for OpenCV namespace: {:#?}", decl)
}
};
if res {
EntityVisitResult::Continue
} else {
EntityVisitResult::Break
}
})
}
pub fn walk_opencv_entities(&self, mut visitor: impl EntityWalkerVisitor<'tu>) {
self.root_entity.visit_children(|root_decl, _| {
let res = if let Some(loc) = root_decl.get_location() {
if let Some(file) = loc.get_file_location().file.map(|f| f.get_path()) {
if visitor.wants_file(&file) {
match root_decl.get_kind() {
EntityKind::Namespace => {
if let Some(name) = root_decl.get_name() {
if name == "ocvrs_resolve_types" {
Self::visit_resolve_types_namespace(root_decl, &mut visitor)
}
else if name.starts_with("cv") {
if main_opencv_module_from_path(&file).is_some() {
visitor.visit_entity(root_decl);
}
Self::visit_cv_namespace(root_decl, &mut visitor)
} else {
true
}
} else {
true
}
}
EntityKind::MacroDefinition | EntityKind::MacroExpansion | EntityKind::EnumDecl
| EntityKind::TypedefDecl => {
visitor.visit_entity(root_decl)
}
EntityKind::FunctionDecl | EntityKind::InclusionDirective
| EntityKind::UnionDecl | EntityKind::UnexposedDecl | EntityKind::StructDecl
| EntityKind::Constructor | EntityKind::Method | EntityKind::FunctionTemplate
| EntityKind::ConversionFunction | EntityKind::ClassTemplate | EntityKind::ClassDecl
| EntityKind::Destructor => {
true
}
_ => {
unreachable!("Unsupported decl for file: {:#?}", root_decl)
}
}
} else {
true
}
} else {
true
}
} else {
true
};
if res {
EntityVisitResult::Continue
} else {
EntityVisitResult::Break
}
});
}
}