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
128
use indexmap::set::IndexSet as HashSet;
use autocxx_parser::IncludeCppConfig;
use syn::ItemType;
use crate::{
conversion::{
analysis::type_converter::{add_analysis, Annotated, TypeConversionContext, TypeConverter},
api::{AnalysisPhase, Api, ApiName, NullPhase, TypedefKind},
apivec::ApiVec,
convert_error::{ConvertErrorWithContext, ErrorContext},
error_reporter::convert_apis,
parse::BindgenSemanticAttributes,
ConvertError,
},
types::QualifiedName,
};
pub(crate) struct TypedefAnalysis {
pub(crate) kind: TypedefKind,
pub(crate) deps: HashSet<QualifiedName>,
}
pub(crate) struct TypedefPhase;
impl AnalysisPhase for TypedefPhase {
type TypedefAnalysis = TypedefAnalysis;
type StructAnalysis = ();
type FunAnalysis = ();
}
#[allow(clippy::needless_collect)]
pub(crate) fn convert_typedef_targets(
config: &IncludeCppConfig,
apis: ApiVec<NullPhase>,
) -> ApiVec<TypedefPhase> {
let mut type_converter = TypeConverter::new(config, &apis);
let mut extra_apis = ApiVec::new();
let mut results = ApiVec::new();
convert_apis(
apis,
&mut results,
Api::fun_unchanged,
Api::struct_unchanged,
Api::enum_unchanged,
|name, item, old_tyname, _| {
Ok(Box::new(std::iter::once(match item {
TypedefKind::Type(ity) => get_replacement_typedef(
name,
ity,
old_tyname,
&mut type_converter,
&mut extra_apis,
)?,
TypedefKind::Use { .. } => Api::Typedef {
name,
item: item.clone(),
old_tyname,
analysis: TypedefAnalysis {
kind: item,
deps: HashSet::new(),
},
},
})))
},
);
results.extend(extra_apis.into_iter().map(add_analysis));
results
}
fn get_replacement_typedef(
name: ApiName,
ity: ItemType,
old_tyname: Option<QualifiedName>,
type_converter: &mut TypeConverter,
extra_apis: &mut ApiVec<NullPhase>,
) -> Result<Api<TypedefPhase>, ConvertErrorWithContext> {
if !ity.generics.params.is_empty() {
return Err(ConvertErrorWithContext(
ConvertError::TypedefTakesGenericParameters,
Some(ErrorContext::new_for_item(name.name.get_final_ident())),
));
}
let mut converted_type = ity.clone();
let metadata = BindgenSemanticAttributes::new_retaining_others(&mut converted_type.attrs);
metadata.check_for_fatal_attrs(&ity.ident)?;
let type_conversion_results = type_converter.convert_type(
(*ity.ty).clone(),
name.name.get_namespace(),
&TypeConversionContext::WithinReference,
);
match type_conversion_results {
Err(err) => Err(ConvertErrorWithContext(
err,
Some(ErrorContext::new_for_item(name.name.get_final_ident())),
)),
Ok(Annotated {
ty: syn::Type::Path(ref typ),
..
}) if QualifiedName::from_type_path(typ) == name.name => Err(ConvertErrorWithContext(
ConvertError::InfinitelyRecursiveTypedef(name.name.clone()),
Some(ErrorContext::new_for_item(name.name.get_final_ident())),
)),
Ok(mut final_type) => {
converted_type.ty = Box::new(final_type.ty.clone());
extra_apis.append(&mut final_type.extra_apis);
Ok(Api::Typedef {
name,
item: TypedefKind::Type(ity),
old_tyname,
analysis: TypedefAnalysis {
kind: TypedefKind::Type(converted_type),
deps: final_type.types_encountered,
},
})
}
}
}