1//! Types and functions related to bindgen annotation comments.
2//!
3//! Users can add annotations in doc comments to types that they would like to
4//! replace other types with, mark as opaque, etc. This module deals with all of
5//! that stuff.
6
7use crate::clang;
8
9/// What kind of accessor should we provide for a field?
10#[derive(Copy, PartialEq, Eq, Clone, Debug)]
11pub enum FieldAccessorKind {
12 /// No accessor.
13 None,
14 /// Plain accessor.
15 Regular,
16 /// Unsafe accessor.
17 Unsafe,
18 /// Immutable accessor.
19 Immutable,
20}
21
22/// Annotations for a given item, or a field.
23///
24/// You can see the kind of comments that are accepted in the Doxygen
25/// documentation:
26///
27/// http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
28#[derive(Default, Clone, PartialEq, Eq, Debug)]
29pub struct Annotations {
30 /// Whether this item is marked as opaque. Only applies to types.
31 opaque: bool,
32 /// Whether this item should be hidden from the output. Only applies to
33 /// types, or enum variants.
34 hide: bool,
35 /// Whether this type should be replaced by another. The name is a
36 /// namespace-aware path.
37 use_instead_of: Option<Vec<String>>,
38 /// Manually disable deriving copy/clone on this type. Only applies to
39 /// struct or union types.
40 disallow_copy: bool,
41 /// Manually disable deriving debug on this type.
42 disallow_debug: bool,
43 /// Manually disable deriving/implement default on this type.
44 disallow_default: bool,
45 /// Whether to add a #[must_use] annotation to this type.
46 must_use_type: bool,
47 /// Whether fields should be marked as private or not. You can set this on
48 /// structs (it will apply to all the fields), or individual fields.
49 private_fields: Option<bool>,
50 /// The kind of accessor this field will have. Also can be applied to
51 /// structs so all the fields inside share it by default.
52 accessor_kind: Option<FieldAccessorKind>,
53 /// Whether this enum variant should be constified.
54 ///
55 /// This is controlled by the `constant` attribute, this way:
56 ///
57 /// ```cpp
58 /// enum Foo {
59 /// Bar = 0, /**< <div rustbindgen constant></div> */
60 /// Baz = 0,
61 /// };
62 /// ```
63 ///
64 /// In that case, bindgen will generate a constant for `Bar` instead of
65 /// `Baz`.
66 constify_enum_variant: bool,
67 /// List of explicit derives for this type.
68 derives: Vec<String>,
69}
70
71fn parse_accessor(s: &str) -> FieldAccessorKind {
72 match s {
73 "false" => FieldAccessorKind::None,
74 "unsafe" => FieldAccessorKind::Unsafe,
75 "immutable" => FieldAccessorKind::Immutable,
76 _ => FieldAccessorKind::Regular,
77 }
78}
79
80impl Annotations {
81 /// Construct new annotations for the given cursor and its bindgen comments
82 /// (if any).
83 pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
84 let mut anno = Annotations::default();
85 let mut matched_one = false;
86 anno.parse(&cursor.comment(), &mut matched_one);
87
88 if matched_one {
89 Some(anno)
90 } else {
91 None
92 }
93 }
94
95 /// Should this type be hidden?
96 pub fn hide(&self) -> bool {
97 self.hide
98 }
99
100 /// Should this type be opaque?
101 pub fn opaque(&self) -> bool {
102 self.opaque
103 }
104
105 /// For a given type, indicates the type it should replace.
106 ///
107 /// For example, in the following code:
108 ///
109 /// ```cpp
110 ///
111 /// /** <div rustbindgen replaces="Bar"></div> */
112 /// struct Foo { int x; };
113 ///
114 /// struct Bar { char foo; };
115 /// ```
116 ///
117 /// the generated code would look something like:
118 ///
119 /// ```
120 /// /** <div rustbindgen replaces="Bar"></div> */
121 /// struct Bar {
122 /// x: ::std::os::raw::c_int,
123 /// };
124 /// ```
125 ///
126 /// That is, code for `Foo` is used to generate `Bar`.
127 pub fn use_instead_of(&self) -> Option<&[String]> {
128 self.use_instead_of.as_deref()
129 }
130
131 /// The list of derives that have been specified in this annotation.
132 pub fn derives(&self) -> &[String] {
133 &self.derives
134 }
135
136 /// Should we avoid implementing the `Copy` trait?
137 pub fn disallow_copy(&self) -> bool {
138 self.disallow_copy
139 }
140
141 /// Should we avoid implementing the `Debug` trait?
142 pub fn disallow_debug(&self) -> bool {
143 self.disallow_debug
144 }
145
146 /// Should we avoid implementing the `Default` trait?
147 pub fn disallow_default(&self) -> bool {
148 self.disallow_default
149 }
150
151 /// Should this type get a `#[must_use]` annotation?
152 pub fn must_use_type(&self) -> bool {
153 self.must_use_type
154 }
155
156 /// Should the fields be private?
157 pub fn private_fields(&self) -> Option<bool> {
158 self.private_fields
159 }
160
161 /// What kind of accessors should we provide for this type's fields?
162 pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
163 self.accessor_kind
164 }
165
166 fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
167 use clang_sys::CXComment_HTMLStartTag;
168 if comment.kind() == CXComment_HTMLStartTag &&
169 comment.get_tag_name() == "div" &&
170 comment
171 .get_tag_attrs()
172 .next()
173 .map_or(false, |attr| attr.name == "rustbindgen")
174 {
175 *matched = true;
176 for attr in comment.get_tag_attrs() {
177 match attr.name.as_str() {
178 "opaque" => self.opaque = true,
179 "hide" => self.hide = true,
180 "nocopy" => self.disallow_copy = true,
181 "nodebug" => self.disallow_debug = true,
182 "nodefault" => self.disallow_default = true,
183 "mustusetype" => self.must_use_type = true,
184 "replaces" => {
185 self.use_instead_of = Some(
186 attr.value.split("::").map(Into::into).collect(),
187 )
188 }
189 "derive" => self.derives.push(attr.value),
190 "private" => {
191 self.private_fields = Some(attr.value != "false")
192 }
193 "accessor" => {
194 self.accessor_kind = Some(parse_accessor(&attr.value))
195 }
196 "constant" => self.constify_enum_variant = true,
197 _ => {}
198 }
199 }
200 }
201
202 for child in comment.get_children() {
203 self.parse(&child, matched);
204 }
205 }
206
207 /// Returns whether we've parsed a "constant" attribute.
208 pub fn constify_enum_variant(&self) -> bool {
209 self.constify_enum_variant
210 }
211}
212