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
7 use crate::clang;
8
9 /// What kind of accessor should we provide for a field?
10 #[derive(Copy, PartialEq, Clone, Debug)]
11 pub 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(Clone, PartialEq, Debug)]
29 pub 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 fields should be marked as private or not. You can set this on
46 /// structs (it will apply to all the fields), or individual fields.
47 private_fields: Option<bool>,
48 /// The kind of accessor this field will have. Also can be applied to
49 /// structs so all the fields inside share it by default.
50 accessor_kind: Option<FieldAccessorKind>,
51 /// Whether this enum variant should be constified.
52 ///
53 /// This is controlled by the `constant` attribute, this way:
54 ///
55 /// ```cpp
56 /// enum Foo {
57 /// Bar = 0, /**< <div rustbindgen constant></div> */
58 /// Baz = 0,
59 /// };
60 /// ```
61 ///
62 /// In that case, bindgen will generate a constant for `Bar` instead of
63 /// `Baz`.
64 constify_enum_variant: bool,
65 /// List of explicit derives for this type.
66 derives: Vec<String>,
67 }
68
parse_accessor(s: &str) -> FieldAccessorKind69 fn parse_accessor(s: &str) -> FieldAccessorKind {
70 match s {
71 "false" => FieldAccessorKind::None,
72 "unsafe" => FieldAccessorKind::Unsafe,
73 "immutable" => FieldAccessorKind::Immutable,
74 _ => FieldAccessorKind::Regular,
75 }
76 }
77
78 impl Default for Annotations {
default() -> Self79 fn default() -> Self {
80 Annotations {
81 opaque: false,
82 hide: false,
83 use_instead_of: None,
84 disallow_copy: false,
85 disallow_debug: false,
86 disallow_default: false,
87 private_fields: None,
88 accessor_kind: None,
89 constify_enum_variant: false,
90 derives: vec![],
91 }
92 }
93 }
94
95 impl Annotations {
96 /// Construct new annotations for the given cursor and its bindgen comments
97 /// (if any).
new(cursor: &clang::Cursor) -> Option<Annotations>98 pub fn new(cursor: &clang::Cursor) -> Option<Annotations> {
99 let mut anno = Annotations::default();
100 let mut matched_one = false;
101 anno.parse(&cursor.comment(), &mut matched_one);
102
103 if matched_one {
104 Some(anno)
105 } else {
106 None
107 }
108 }
109
110 /// Should this type be hidden?
hide(&self) -> bool111 pub fn hide(&self) -> bool {
112 self.hide
113 }
114
115 /// Should this type be opaque?
opaque(&self) -> bool116 pub fn opaque(&self) -> bool {
117 self.opaque
118 }
119
120 /// For a given type, indicates the type it should replace.
121 ///
122 /// For example, in the following code:
123 ///
124 /// ```cpp
125 ///
126 /// /** <div rustbindgen replaces="Bar"></div> */
127 /// struct Foo { int x; };
128 ///
129 /// struct Bar { char foo; };
130 /// ```
131 ///
132 /// the generated code would look something like:
133 ///
134 /// ```
135 /// /** <div rustbindgen replaces="Bar"></div> */
136 /// struct Bar {
137 /// x: ::std::os::raw::c_int,
138 /// };
139 /// ```
140 ///
141 /// That is, code for `Foo` is used to generate `Bar`.
use_instead_of(&self) -> Option<&[String]>142 pub fn use_instead_of(&self) -> Option<&[String]> {
143 self.use_instead_of.as_ref().map(|s| &**s)
144 }
145
146 /// The list of derives that have been specified in this annotation.
derives(&self) -> &[String]147 pub fn derives(&self) -> &[String] {
148 &self.derives
149 }
150
151 /// Should we avoid implementing the `Copy` trait?
disallow_copy(&self) -> bool152 pub fn disallow_copy(&self) -> bool {
153 self.disallow_copy
154 }
155
156 /// Should we avoid implementing the `Debug` trait?
disallow_debug(&self) -> bool157 pub fn disallow_debug(&self) -> bool {
158 self.disallow_debug
159 }
160
161 /// Should we avoid implementing the `Default` trait?
disallow_default(&self) -> bool162 pub fn disallow_default(&self) -> bool {
163 self.disallow_default
164 }
165
166 /// Should the fields be private?
private_fields(&self) -> Option<bool>167 pub fn private_fields(&self) -> Option<bool> {
168 self.private_fields
169 }
170
171 /// What kind of accessors should we provide for this type's fields?
accessor_kind(&self) -> Option<FieldAccessorKind>172 pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
173 self.accessor_kind
174 }
175
parse(&mut self, comment: &clang::Comment, matched: &mut bool)176 fn parse(&mut self, comment: &clang::Comment, matched: &mut bool) {
177 use clang_sys::CXComment_HTMLStartTag;
178 if comment.kind() == CXComment_HTMLStartTag &&
179 comment.get_tag_name() == "div" &&
180 comment
181 .get_tag_attrs()
182 .next()
183 .map_or(false, |attr| attr.name == "rustbindgen")
184 {
185 *matched = true;
186 for attr in comment.get_tag_attrs() {
187 match attr.name.as_str() {
188 "opaque" => self.opaque = true,
189 "hide" => self.hide = true,
190 "nocopy" => self.disallow_copy = true,
191 "nodebug" => self.disallow_debug = true,
192 "nodefault" => self.disallow_default = true,
193 "replaces" => {
194 self.use_instead_of = Some(
195 attr.value.split("::").map(Into::into).collect(),
196 )
197 }
198 "derive" => self.derives.push(attr.value),
199 "private" => {
200 self.private_fields = Some(attr.value != "false")
201 }
202 "accessor" => {
203 self.accessor_kind = Some(parse_accessor(&attr.value))
204 }
205 "constant" => self.constify_enum_variant = true,
206 _ => {}
207 }
208 }
209 }
210
211 for child in comment.get_children() {
212 self.parse(&child, matched);
213 }
214 }
215
216 /// Returns whether we've parsed a "constant" attribute.
constify_enum_variant(&self) -> bool217 pub fn constify_enum_variant(&self) -> bool {
218 self.constify_enum_variant
219 }
220 }
221