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