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(Default, 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 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 
parse_accessor(s: &str) -> FieldAccessorKind71 fn 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 
80 impl Annotations {
81     /// Construct new annotations for the given cursor and its bindgen comments
82     /// (if any).
new(cursor: &clang::Cursor) -> Option<Annotations>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?
hide(&self) -> bool96     pub fn hide(&self) -> bool {
97         self.hide
98     }
99 
100     /// Should this type be opaque?
opaque(&self) -> bool101     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`.
use_instead_of(&self) -> Option<&[String]>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.
derives(&self) -> &[String]132     pub fn derives(&self) -> &[String] {
133         &self.derives
134     }
135 
136     /// Should we avoid implementing the `Copy` trait?
disallow_copy(&self) -> bool137     pub fn disallow_copy(&self) -> bool {
138         self.disallow_copy
139     }
140 
141     /// Should we avoid implementing the `Debug` trait?
disallow_debug(&self) -> bool142     pub fn disallow_debug(&self) -> bool {
143         self.disallow_debug
144     }
145 
146     /// Should we avoid implementing the `Default` trait?
disallow_default(&self) -> bool147     pub fn disallow_default(&self) -> bool {
148         self.disallow_default
149     }
150 
151     /// Should this type get a `#[must_use]` annotation?
must_use_type(&self) -> bool152     pub fn must_use_type(&self) -> bool {
153         self.must_use_type
154     }
155 
156     /// Should the fields be private?
private_fields(&self) -> Option<bool>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?
accessor_kind(&self) -> Option<FieldAccessorKind>162     pub fn accessor_kind(&self) -> Option<FieldAccessorKind> {
163         self.accessor_kind
164     }
165 
parse(&mut self, comment: &clang::Comment, matched: &mut bool)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.
constify_enum_variant(&self) -> bool208     pub fn constify_enum_variant(&self) -> bool {
209         self.constify_enum_variant
210     }
211 }
212