webidl_utils/symbol/with_docstring.rs
1use weedle::dictionary::DictionaryMember;
2use weedle::interface::*;
3use weedle::namespace::{AttributeNamespaceMember, OperationNamespaceMember};
4use weedle::*;
5
6/// A WebIDL symbol that may have a documentation string
7pub trait SymbolWithDocstring {
8 /// Returns a string literal with the starting whitespace removed.
9 /// If the symbol has no docstring, it will return an empty string literal.
10 ///
11 /// ## Examples
12 /// The following examples compare the behavior and APIs of `weedle2` and `webidl-utils`.
13 /// To summarize:
14 /// - weedle2:
15 /// - Symbols that can contain a docstring will have type `Option<Docstring>`.
16 /// - If there is no docstring, it will be `None`.
17 /// - A parsed `Docstring` will have a non-normalized string. For example, if
18 /// a docstring is written as `/// This is an enum`, the resulting string will be
19 /// `" This is an enum"`.
20 /// - webidl-utils:
21 /// - `SymbolWithDocString` will return a `&str`.
22 /// - If there is no docstring, it will be `""` (empty string literal).
23 /// - It will normalize strings by removing the beginning whitespace.
24 ///
25 /// ```
26 /// use webidl_utils::symbol::SymbolWithDocstring;
27 /// use weedle::{EnumDefinition, Parse};
28 ///
29 /// let (_, enum_def) = EnumDefinition::parse(
30 /// r#"
31 /// /// This is an enum
32 /// enum Color { "red", "green", "blue" };
33 /// "#)
34 /// .expect("EnumDefinition parsed with an error");
35 ///
36 /// // weedle2 behavior
37 /// assert_eq!(enum_def.docstring.clone().unwrap().0.as_str(), " This is an enum");
38 ///
39 /// // webidl-utils behavior
40 /// assert_eq!(enum_def.docstring(), "This is an enum");
41 /// ```
42 fn docstring(&self) -> &str;
43 fn has_docstring(&self) -> bool;
44}
45
46macro_rules! impl_symbol_with_docstring {
47 ($($sym:ident),+ $(,)?) => {
48 $(
49 impl<'a> SymbolWithDocstring for $sym<'a> {
50 fn docstring(&self) -> &str {
51 self.docstring.as_ref()
52 .map(|docstring| &docstring.0[..])
53 .unwrap_or("")
54 .trim_start()
55 }
56
57 fn has_docstring(&self) -> bool {
58 self.docstring.is_some()
59 }
60 }
61 )+
62 };
63}
64
65impl_symbol_with_docstring!(
66 CallbackInterfaceDefinition,
67 InterfaceDefinition,
68 NamespaceDefinition,
69 DictionaryDefinition,
70 EnumDefinition,
71 EnumVariant,
72 DictionaryMember,
73 ConstructorInterfaceMember,
74 OperationInterfaceMember,
75 OperationNamespaceMember,
76 AttributeNamespaceMember,
77);
78
79#[cfg(test)]
80mod tests {
81 use crate::symbol::SymbolWithDocstring;
82 use weedle::{EnumDefinition, Parse};
83
84 #[test]
85 fn test() {
86 let (_, enum_def) = EnumDefinition::parse(
87 r#"
88 /// This is an enum
89 enum Color { "red", "green", "blue" };
90 "#,
91 )
92 .expect("EnumDefinition parsed with an error");
93
94 assert_eq!(enum_def.docstring(), "This is an enum");
95 assert_eq!(enum_def.has_docstring(), true);
96 }
97}