1#![deny(missing_docs)]
22#![doc(html_logo_url = "https://raw.githubusercontent.com/emit-rs/emit/main/asset/logo.svg")]
23
24extern crate proc_macro;
25
26#[macro_use]
27extern crate quote;
28
29#[macro_use]
30extern crate syn;
31
32use std::collections::HashMap;
33
34use proc_macro2::TokenStream;
35
36mod args;
37mod build;
38mod capture;
39mod dbg;
40mod emit;
41mod fmt;
42mod format;
43mod hook;
44mod key;
45mod optional;
46mod props;
47mod span;
48mod template;
49mod util;
50
51use util::ResultToTokens;
52
53fn hooks() -> HashMap<&'static str, fn(TokenStream, TokenStream) -> syn::Result<TokenStream>> {
59 let mut map = HashMap::new();
60
61 map.insert(
62 "fmt",
63 (|args: TokenStream, expr: TokenStream| {
64 fmt::rename_hook_tokens(fmt::RenameHookTokens { args, expr })
65 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
66 );
67
68 map.insert(
69 "key",
70 (|args: TokenStream, expr: TokenStream| {
71 key::rename_hook_tokens(key::RenameHookTokens { args, expr })
72 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
73 );
74
75 map.insert(
76 "optional",
77 (|args: TokenStream, expr: TokenStream| {
78 optional::rename_hook_tokens(optional::RenameHookTokens { args, expr })
79 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
80 );
81
82 map.insert(
83 "as_value",
84 (|args: TokenStream, expr: TokenStream| {
85 capture_as(
86 "as_value",
87 args,
88 expr,
89 quote!(__private_capture_as_value),
90 quote!(__private_capture_anon_as_value),
91 )
92 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
93 );
94
95 map.insert(
96 "as_debug",
97 (|args: TokenStream, expr: TokenStream| {
98 capture_as(
99 "as_debug",
100 args,
101 expr,
102 quote!(__private_capture_as_debug),
103 quote!(__private_capture_anon_as_debug),
104 )
105 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
106 );
107
108 map.insert(
109 "as_display",
110 (|args: TokenStream, expr: TokenStream| {
111 capture_as(
112 "as_display",
113 args,
114 expr,
115 quote!(__private_capture_as_display),
116 quote!(__private_capture_anon_as_display),
117 )
118 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
119 );
120
121 map.insert(
122 "as_sval",
123 (|args: TokenStream, expr: TokenStream| {
124 #[cfg(feature = "sval")]
125 {
126 capture_as(
127 "as_sval",
128 args,
129 expr,
130 quote!(__private_capture_as_sval),
131 quote!(__private_capture_anon_as_sval),
132 )
133 }
134 #[cfg(not(feature = "sval"))]
135 {
136 use syn::spanned::Spanned;
137
138 let _ = args;
139
140 Err(syn::Error::new(expr.span(), "capturing with `sval` is only possible when the `sval` Cargo feature is enabled"))
141 }
142 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>
143 );
144
145 map.insert(
146 "as_serde",
147 (|args: TokenStream, expr: TokenStream| {
148 #[cfg(feature = "serde")]
149 {
150 capture_as(
151 "as_serde",
152 args,
153 expr,
154 quote!(__private_capture_as_serde),
155 quote!(__private_capture_anon_as_serde),
156 )
157 }
158 #[cfg(not(feature = "serde"))]
159 {
160 use syn::spanned::Spanned;
161
162 let _ = args;
163
164 Err(syn::Error::new(expr.span(), "capturing with `serde` is only possible when the `serde` Cargo feature is enabled"))
165 }
166 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>
167 );
168
169 map.insert(
170 "as_error",
171 (|args: TokenStream, expr: TokenStream| {
172 #[cfg(feature = "std")]
173 {
174 capture_as(
175 "as_error",
176 args,
177 expr,
178 quote!(__private_capture_as_error),
179 quote!(__private_capture_as_error),
180 )
181 }
182 #[cfg(not(feature = "std"))]
183 {
184 use syn::spanned::Spanned;
185
186 let _ = args;
187
188 Err(syn::Error::new(
189 expr.span(),
190 "capturing errors is only possible when the `std` Cargo feature is enabled",
191 ))
192 }
193 }) as fn(TokenStream, TokenStream) -> syn::Result<TokenStream>,
194 );
195
196 map
197}
198
199#[doc = "Format a template."]
200#[doc = ""]
201#[doc = include_str!("./doc_fmt.md")]
202#[proc_macro]
203pub fn format(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
204 format::expand_tokens(format::ExpandTokens {
205 input: TokenStream::from(item),
206 })
207 .unwrap_or_compile_error()
208}
209
210#[doc = "Construct an event that can be emitted manually."]
211#[doc = ""]
212#[doc = include_str!("./doc_evt.md")]
213#[proc_macro]
214pub fn evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
215 build::expand_evt_tokens(build::ExpandEvtTokens {
216 level: None,
217 input: item.into(),
218 })
219 .unwrap_or_compile_error()
220}
221
222#[doc = "Construct an event at the debug level that can be emitted manually."]
223#[doc = ""]
224#[doc = include_str!("./doc_evt.md")]
225#[proc_macro]
226pub fn debug_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
227 build::expand_evt_tokens(build::ExpandEvtTokens {
228 level: Some(quote!(emit::Level::Debug)),
229 input: item.into(),
230 })
231 .unwrap_or_compile_error()
232}
233
234#[doc = "Construct an event at the info level that can be emitted manually."]
235#[doc = ""]
236#[doc = include_str!("./doc_evt.md")]
237#[proc_macro]
238pub fn info_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
239 build::expand_evt_tokens(build::ExpandEvtTokens {
240 level: Some(quote!(emit::Level::Info)),
241 input: item.into(),
242 })
243 .unwrap_or_compile_error()
244}
245
246#[doc = "Construct an event at the warn level that can be emitted manually."]
247#[doc = ""]
248#[doc = include_str!("./doc_evt.md")]
249#[proc_macro]
250pub fn warn_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
251 build::expand_evt_tokens(build::ExpandEvtTokens {
252 level: Some(quote!(emit::Level::Warn)),
253 input: item.into(),
254 })
255 .unwrap_or_compile_error()
256}
257
258#[doc = "Construct an event at the error level that can be emitted manually."]
259#[doc = ""]
260#[doc = include_str!("./doc_evt.md")]
261#[proc_macro]
262pub fn error_evt(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
263 build::expand_evt_tokens(build::ExpandEvtTokens {
264 level: Some(quote!(emit::Level::Error)),
265 input: item.into(),
266 })
267 .unwrap_or_compile_error()
268}
269
270#[doc = "Trace the execution of a function."]
271#[doc = ""]
272#[doc = include_str!("./doc_span.md")]
273#[proc_macro_attribute]
274pub fn span(
275 args: proc_macro::TokenStream,
276 item: proc_macro::TokenStream,
277) -> proc_macro::TokenStream {
278 span::expand_tokens(span::ExpandTokens {
279 level: None,
280 input: TokenStream::from(args),
281 item: TokenStream::from(item),
282 })
283 .unwrap_or_compile_error()
284}
285
286#[doc = "Trace the execution of a function at the debug level."]
287#[doc = ""]
288#[doc = include_str!("./doc_span.md")]
289#[proc_macro_attribute]
290pub fn debug_span(
291 args: proc_macro::TokenStream,
292 item: proc_macro::TokenStream,
293) -> proc_macro::TokenStream {
294 span::expand_tokens(span::ExpandTokens {
295 level: Some(quote!(emit::Level::Debug)),
296 input: TokenStream::from(args),
297 item: TokenStream::from(item),
298 })
299 .unwrap_or_compile_error()
300}
301
302#[doc = "Trace the execution of a function at the info level."]
303#[doc = ""]
304#[doc = include_str!("./doc_span.md")]
305#[proc_macro_attribute]
306pub fn info_span(
307 args: proc_macro::TokenStream,
308 item: proc_macro::TokenStream,
309) -> proc_macro::TokenStream {
310 span::expand_tokens(span::ExpandTokens {
311 level: Some(quote!(emit::Level::Info)),
312 input: TokenStream::from(args),
313 item: TokenStream::from(item),
314 })
315 .unwrap_or_compile_error()
316}
317
318#[doc = "Trace the execution of a function at the warn level."]
319#[doc = ""]
320#[doc = include_str!("./doc_span.md")]
321#[proc_macro_attribute]
322pub fn warn_span(
323 args: proc_macro::TokenStream,
324 item: proc_macro::TokenStream,
325) -> proc_macro::TokenStream {
326 span::expand_tokens(span::ExpandTokens {
327 level: Some(quote!(emit::Level::Warn)),
328 input: TokenStream::from(args),
329 item: TokenStream::from(item),
330 })
331 .unwrap_or_compile_error()
332}
333
334#[doc = "Trace the execution of a function at the error level."]
335#[doc = ""]
336#[doc = include_str!("./doc_span.md")]
337#[proc_macro_attribute]
338pub fn error_span(
339 args: proc_macro::TokenStream,
340 item: proc_macro::TokenStream,
341) -> proc_macro::TokenStream {
342 span::expand_tokens(span::ExpandTokens {
343 level: Some(quote!(emit::Level::Error)),
344 input: TokenStream::from(args),
345 item: TokenStream::from(item),
346 })
347 .unwrap_or_compile_error()
348}
349
350#[doc = "Create a span that can be started and completed manually."]
351#[doc = ""]
352#[doc = include_str!("./doc_new_span.md")]
353#[proc_macro]
354pub fn new_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
355 span::expand_new_tokens(span::ExpandNewTokens {
356 level: None,
357 input: TokenStream::from(item),
358 })
359 .unwrap_or_compile_error()
360}
361
362#[doc = "Create a span at the debug level that can be started and completed manually."]
363#[doc = ""]
364#[doc = include_str!("./doc_new_span.md")]
365#[proc_macro]
366pub fn new_debug_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
367 span::expand_new_tokens(span::ExpandNewTokens {
368 level: Some(quote!(emit::Level::Debug)),
369 input: TokenStream::from(item),
370 })
371 .unwrap_or_compile_error()
372}
373
374#[doc = "Create a span at the info level that can be started and completed manually."]
375#[doc = ""]
376#[doc = include_str!("./doc_new_span.md")]
377#[proc_macro]
378pub fn new_info_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
379 span::expand_new_tokens(span::ExpandNewTokens {
380 level: Some(quote!(emit::Level::Info)),
381 input: TokenStream::from(item),
382 })
383 .unwrap_or_compile_error()
384}
385
386#[doc = "Create a span at the warn level that can be started and completed manually."]
387#[doc = ""]
388#[doc = include_str!("./doc_new_span.md")]
389#[proc_macro]
390pub fn new_warn_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
391 span::expand_new_tokens(span::ExpandNewTokens {
392 level: Some(quote!(emit::Level::Warn)),
393 input: TokenStream::from(item),
394 })
395 .unwrap_or_compile_error()
396}
397
398#[doc = "Create a span at the error level that can be started and completed manually."]
399#[doc = ""]
400#[doc = include_str!("./doc_new_span.md")]
401#[proc_macro]
402pub fn new_error_span(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
403 span::expand_new_tokens(span::ExpandNewTokens {
404 level: Some(quote!(emit::Level::Error)),
405 input: TokenStream::from(item),
406 })
407 .unwrap_or_compile_error()
408}
409
410#[doc = "Construct a template."]
411#[doc = ""]
412#[doc = include_str!("./doc_tpl.md")]
413#[proc_macro]
414pub fn tpl(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
415 build::expand_tpl_tokens(build::ExpandTplTokens {
416 input: TokenStream::from(item),
417 })
418 .unwrap_or_compile_error()
419}
420
421#[doc = "Emit an event."]
422#[doc = ""]
423#[doc = include_str!("./doc_emit.md")]
424#[proc_macro]
425pub fn emit(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
426 emit::expand_tokens(emit::ExpandTokens {
427 level: None,
428 input: TokenStream::from(item),
429 })
430 .unwrap_or_compile_error()
431}
432
433#[doc = "Emit an event at the debug level."]
434#[doc = ""]
435#[doc = include_str!("./doc_emit.md")]
436#[proc_macro]
437pub fn debug(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
438 emit::expand_tokens(emit::ExpandTokens {
439 level: Some(quote!(emit::Level::Debug)),
440 input: TokenStream::from(item),
441 })
442 .unwrap_or_compile_error()
443}
444
445#[doc = "Emit an event at the info level."]
446#[doc = ""]
447#[doc = include_str!("./doc_emit.md")]
448#[proc_macro]
449pub fn info(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
450 emit::expand_tokens(emit::ExpandTokens {
451 level: Some(quote!(emit::Level::Info)),
452 input: TokenStream::from(item),
453 })
454 .unwrap_or_compile_error()
455}
456
457#[doc = "Emit an event at the warn level."]
458#[doc = ""]
459#[doc = include_str!("./doc_emit.md")]
460#[proc_macro]
461pub fn warn(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
462 emit::expand_tokens(emit::ExpandTokens {
463 level: Some(quote!(emit::Level::Warn)),
464 input: TokenStream::from(item),
465 })
466 .unwrap_or_compile_error()
467}
468
469#[doc = "Emit an event at the error level."]
470#[doc = ""]
471#[doc = include_str!("./doc_emit.md")]
472#[proc_macro]
473pub fn error(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
474 emit::expand_tokens(emit::ExpandTokens {
475 level: Some(quote!(emit::Level::Error)),
476 input: TokenStream::from(item),
477 })
478 .unwrap_or_compile_error()
479}
480
481#[doc = "Emit a temporary event as a quick-and-dirty debugging aid."]
482#[doc = ""]
483#[doc = include_str!("./doc_dbg.md")]
484#[proc_macro]
485pub fn dbg(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
486 dbg::expand_tokens(dbg::ExpandTokens {
487 input: TokenStream::from(item),
488 })
489 .unwrap_or_compile_error()
490}
491
492#[proc_macro]
506pub fn path(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
507 build::expand_path_tokens(build::ExpandPathTokens {
508 input: TokenStream::from(item),
509 })
510 .unwrap_or_compile_error()
511}
512
513#[proc_macro]
527pub fn props(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
528 build::expand_props_tokens(build::ExpandPropsTokens {
529 input: TokenStream::from(item),
530 })
531 .unwrap_or_compile_error()
532}
533
534#[proc_macro_attribute]
552pub fn fmt(
553 args: proc_macro::TokenStream,
554 item: proc_macro::TokenStream,
555) -> proc_macro::TokenStream {
556 (hook::get("fmt").unwrap())(TokenStream::from(args), TokenStream::from(item))
557 .unwrap_or_compile_error()
558}
559
560#[proc_macro_attribute]
578pub fn key(
579 args: proc_macro::TokenStream,
580 item: proc_macro::TokenStream,
581) -> proc_macro::TokenStream {
582 (hook::get("key").unwrap())(TokenStream::from(args), TokenStream::from(item))
583 .unwrap_or_compile_error()
584}
585
586#[proc_macro_attribute]
598pub fn optional(
599 args: proc_macro::TokenStream,
600 item: proc_macro::TokenStream,
601) -> proc_macro::TokenStream {
602 (hook::get("optional").unwrap())(TokenStream::from(args), TokenStream::from(item))
603 .unwrap_or_compile_error()
604}
605
606#[proc_macro_attribute]
618pub fn as_value(
619 args: proc_macro::TokenStream,
620 item: proc_macro::TokenStream,
621) -> proc_macro::TokenStream {
622 (hook::get("as_value").unwrap())(TokenStream::from(args), TokenStream::from(item))
623 .unwrap_or_compile_error()
624}
625
626#[proc_macro_attribute]
638pub fn as_debug(
639 args: proc_macro::TokenStream,
640 item: proc_macro::TokenStream,
641) -> proc_macro::TokenStream {
642 (hook::get("as_debug").unwrap())(TokenStream::from(args), TokenStream::from(item))
643 .unwrap_or_compile_error()
644}
645
646#[proc_macro_attribute]
658pub fn as_display(
659 args: proc_macro::TokenStream,
660 item: proc_macro::TokenStream,
661) -> proc_macro::TokenStream {
662 (hook::get("as_display").unwrap())(TokenStream::from(args), TokenStream::from(item))
663 .unwrap_or_compile_error()
664}
665
666#[proc_macro_attribute]
678pub fn as_sval(
679 args: proc_macro::TokenStream,
680 item: proc_macro::TokenStream,
681) -> proc_macro::TokenStream {
682 (hook::get("as_sval").unwrap())(TokenStream::from(args), TokenStream::from(item))
683 .unwrap_or_compile_error()
684}
685
686#[proc_macro_attribute]
698pub fn as_serde(
699 args: proc_macro::TokenStream,
700 item: proc_macro::TokenStream,
701) -> proc_macro::TokenStream {
702 (hook::get("as_serde").unwrap())(TokenStream::from(args), TokenStream::from(item))
703 .unwrap_or_compile_error()
704}
705
706#[proc_macro_attribute]
718pub fn as_error(
719 args: proc_macro::TokenStream,
720 item: proc_macro::TokenStream,
721) -> proc_macro::TokenStream {
722 (hook::get("as_error").unwrap())(TokenStream::from(args), TokenStream::from(item))
723 .unwrap_or_compile_error()
724}
725
726fn capture_as(
745 name: &'static str,
746 args: TokenStream,
747 expr: TokenStream,
748 as_fn: TokenStream,
749 as_anon_fn: TokenStream,
750) -> syn::Result<TokenStream> {
751 capture::rename_hook_tokens(capture::RenameHookTokens {
752 name,
753 args,
754 expr,
755 to: |args: &capture::Args| {
756 if args.inspect {
757 as_fn.clone()
758 } else {
759 as_anon_fn.clone()
760 }
761 },
762 })
763}