1 | // |
2 | // Doc comment |
3 | // |
4 | // Copyright (c) 2018 Guillaume Gomez |
5 | // |
6 | |
7 | #![cfg_attr (feature = "no_core" , feature(no_core))] |
8 | #![cfg_attr (feature = "no_core" , no_core)] |
9 | #![cfg_attr (not(feature = "no_core" ), no_std)] |
10 | |
11 | //! The point of this (small) crate is to allow you to add doc comments from macros or |
12 | //! to test external markdown files' code blocks through `rustdoc`. |
13 | //! |
14 | //! ## Including file(s) for testing |
15 | //! |
16 | //! Let's assume you want to test code examples in your `README.md` file which |
17 | //! looks like this: |
18 | //! |
19 | //! ````text |
20 | //! # A crate |
21 | //! |
22 | //! Here is a code example: |
23 | //! |
24 | //! ```rust |
25 | //! let x = 2; |
26 | //! assert!(x != 0); |
27 | //! ``` |
28 | //! ```` |
29 | //! |
30 | //! You can use the `doc_comment!` macro to test it like this: |
31 | //! |
32 | //! ``` |
33 | //! #[macro_use] |
34 | //! extern crate doc_comment; |
35 | //! |
36 | //! // When running `cargo test`, rustdoc will check this file as well. |
37 | //! doc_comment!(include_str!("../README.md" )); |
38 | //! # fn main() {} |
39 | //! ``` |
40 | //! |
41 | //! Please note that can also use the `doctest!` macro to have a shorter way to test an outer |
42 | //! file: |
43 | //! |
44 | //! ```no_run |
45 | //! #[macro_use] |
46 | //! extern crate doc_comment; |
47 | //! |
48 | //! doctest!("../README.md" ); |
49 | //! # fn main() {} |
50 | //! ``` |
51 | //! |
52 | //! Please also note that you can use `#[cfg(doctest)]`: |
53 | //! |
54 | //! ```no_run |
55 | //! # #[macro_use ] |
56 | //! # extern crate doc_comment; |
57 | //! #[cfg(doctest)] |
58 | //! doctest!("../README.md" ); |
59 | //! # fn main() {} |
60 | //! ``` |
61 | //! |
62 | //! In this case, the examples in the `README.md` file will only be run on `cargo test`. You |
63 | //! can find more information about `#[cfg(doctest)]` in [this blogpost](https://blog.guillaume-gomez.fr/articles/2020-03-07+cfg%28doctest%29+is+stable+and+you+should+use+it). |
64 | //! |
65 | //! ## Generic documentation |
66 | //! |
67 | //! Now let's imagine you want to write documentation once for multiple types but |
68 | //! still having examples specific to each type: |
69 | //! |
70 | //! ``` |
71 | //! // The macro which generates types |
72 | //! macro_rules! gen_types { |
73 | //! ($tyname:ident) => { |
74 | //! /// This is a wonderful generated struct! |
75 | //! /// |
76 | //! /// You can use it as follow: |
77 | //! /// |
78 | //! /// ``` |
79 | //! /// let x = FirstOne { |
80 | //! /// field1: 0, |
81 | //! /// field2: 0, |
82 | //! /// field3: 0, |
83 | //! /// field4: 0, |
84 | //! /// }; |
85 | //! /// |
86 | //! /// println!("Created a new instance of FirstOne: {:?}", x); |
87 | //! /// ``` |
88 | //! #[derive(Debug)] |
89 | //! pub struct $tyname { |
90 | //! pub field1: u8, |
91 | //! pub field2: u16, |
92 | //! pub field3: u32, |
93 | //! pub field4: u64, |
94 | //! } |
95 | //! } |
96 | //! } |
97 | //! |
98 | //! // Now let's actually generate types: |
99 | //! gen_types!(FirstOne); |
100 | //! gen_types!(SecondOne); |
101 | //! gen_types!(Another); |
102 | //! ``` |
103 | //! |
104 | //! So now we have created three structs with different names, but they all have the exact same |
105 | //! documentation, which is an issue for any structs not called `FirstOne`. That's where |
106 | //! [`doc_comment!`] macro comes in handy! |
107 | //! |
108 | //! Let's rewrite the `gen_types!` macro: |
109 | //! |
110 | //! // Of course, we need to import the `doc_comment` macro: |
111 | //! #[macro_use] |
112 | //! extern crate doc_comment; |
113 | //! |
114 | //! macro_rules! gen_types { |
115 | //! ($tyname:ident) => { |
116 | //! doc_comment! { |
117 | //! concat!("This is a wonderful generated struct! |
118 | //! |
119 | //! You can use it as follow: |
120 | //! |
121 | //! ``` |
122 | //! let x = ", stringify!($tyname), " { |
123 | //! field1: 0, |
124 | //! field2: 0, |
125 | //! field3: 0, |
126 | //! field4: 0, |
127 | //! }; |
128 | //! |
129 | //! println!(\"Created a new instance of " , stringify!($tyname), ": {:?} \", x); |
130 | //! ```"), |
131 | //! #[derive(Debug)] |
132 | //! pub struct $tyname { |
133 | //! pub field1: u8, |
134 | //! pub field2: u16, |
135 | //! pub field3: u32, |
136 | //! pub field4: u64, |
137 | //! } |
138 | //! } |
139 | //! } |
140 | //! } |
141 | //! |
142 | //! gen_types!(FirstOne); |
143 | //! gen_types!(SecondOne); |
144 | //! gen_types!(Another); |
145 | //! # fn main() {} |
146 | //! |
147 | //! Now each struct has doc which match itself! |
148 | |
149 | /// This macro can be used to generate documentation upon a type/item (or just to test outer |
150 | /// markdown file code examples). |
151 | /// |
152 | /// # Example |
153 | /// |
154 | /// ``` |
155 | /// #[macro_use] |
156 | /// extern crate doc_comment; |
157 | /// |
158 | /// // If you just want to test an outer markdown file: |
159 | /// doc_comment!(include_str!("../README.md" )); |
160 | /// |
161 | /// // If you want to document an item: |
162 | /// doc_comment!("fooo" , pub struct Foo {}); |
163 | /// # fn main() {} |
164 | /// ``` |
165 | #[macro_export ] |
166 | macro_rules! doc_comment { |
167 | ($x:expr) => { |
168 | #[doc = $x] |
169 | extern {} |
170 | }; |
171 | ($x:expr, $($tt:tt)*) => { |
172 | #[doc = $x] |
173 | $($tt)* |
174 | }; |
175 | } |
176 | |
177 | /// This macro provides a simpler way to test an outer markdown file. |
178 | /// |
179 | /// # Example |
180 | /// |
181 | /// ``` |
182 | /// extern crate doc_comment; |
183 | /// |
184 | /// // The two next lines are doing exactly the same thing: |
185 | /// doc_comment::doc_comment!(include_str!("../README.md" )); |
186 | /// doc_comment::doctest!("../README.md" ); |
187 | /// |
188 | /// // If you want to have a name for your tests: |
189 | /// doc_comment::doctest!("../README.md" , another); |
190 | /// # fn main() {} |
191 | /// ``` |
192 | #[cfg (not(feature = "old_macros" ))] |
193 | #[macro_export ] |
194 | macro_rules! doctest { |
195 | ($x:expr) => { |
196 | doc_comment::doc_comment!(include_str!($x)); |
197 | }; |
198 | ($x:expr, $y:ident) => { |
199 | doc_comment::doc_comment!(include_str!($x), mod $y {}); |
200 | }; |
201 | } |
202 | |
203 | /// This macro provides a simpler way to test an outer markdown file. |
204 | /// |
205 | /// # Example |
206 | /// |
207 | /// ``` |
208 | /// #[macro_use] |
209 | /// extern crate doc_comment; |
210 | /// |
211 | /// // The two next lines are doing exactly the same thing: |
212 | /// doc_comment!(include_str!("../README.md")); |
213 | /// doctest!("../README.md"); |
214 | /// |
215 | /// // If you want to have a name for your tests: |
216 | /// doctest!("../README.md", another); |
217 | /// # fn main() {} |
218 | /// ``` |
219 | #[cfg (feature = "old_macros" )] |
220 | #[macro_export ] |
221 | macro_rules! doctest { |
222 | ($x:expr) => { |
223 | doc_comment!(include_str!($x)); |
224 | }; |
225 | ($x:expr, $y:ident) => { |
226 | doc_comment!(include_str!($x), mod $y {}); |
227 | }; |
228 | } |
229 | |