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}