proc_macro_api/
lib.rs

1#![doc = include_str!("../doc.md")]
2
3/*
4checklist:
5 tt, ident, expr ;
6 doc_hidden macro_export `pma` ;
7 path $crate::`pma`! ;
8 path $crate::__private ;
9*/
10
11extern crate proc_macro;
12
13#[doc(hidden)]
14pub mod __private;
15
16mod err_syn;
17mod fmt;
18
19/// See the [crate documentation][self].
20#[macro_export]
21macro_rules! proc_macro_api {
22    ($($tt:tt)+) => {
23        $crate::proc_macro_api_parse_seg! {
24            [/*rest*/] [ { $($tt)+ } ] [/*prv*/]
25            [
26                [/*[proc]*/] [/*[doc]*/] [/*[[other]+[proc]]*/]
27                [ [/*cc*/] [/*al*/] ]
28            ]
29        }
30    };
31    () => {};
32}
33
34#[doc(hidden)]
35#[macro_export]
36macro_rules! proc_macro_api_err_attr_mul {
37    // [first] [second]
38    ($msg:expr , [ $($note:expr),* $(,)? ] , $plural_s:expr =>
39        [ $first_0:tt $($first:tt)* ] [ $second_0:tt $($second:tt)* ]
40        $path:tt
41    ) => {
42        $crate::__private::compile_error!($crate::__private::concat!(
43            $msg,
44            "\n/ #", $crate::__private::stringify!($first_0),
45            $("\n| #", $crate::__private::stringify!($first),)*
46            "\n|_^ the first attribute", $plural_s,
47            "\n...",
48            "\n/ #", $crate::__private::stringify!($second_0),
49            $("\n| #", $crate::__private::stringify!($second),)*
50            "\n|_^ the second attribute", $plural_s,
51            "\n\n  ", $crate::proc_macro_api_fmt_path!($path),
52            "\n  ^\n",
53            $("\n= note: ", $note,)*
54        ));
55    };
56}
57
58#[cfg(not(feature = "deny_shadow"))]
59#[doc(hidden)]
60#[macro_export]
61macro_rules! proc_macro_api_err_attr_shadow {
62    ($($tt:tt)*) => {};
63}
64
65#[cfg(feature = "deny_shadow")]
66#[doc(hidden)]
67#[macro_export]
68macro_rules! proc_macro_api_err_attr_shadow {
69    ([] $_0:tt $_1:tt) => {};
70
71    // [[proc]] [cover] [path]
72    ($proc:tt $cover:tt $path:tt) => {
73        $crate::proc_macro_api_err_attr_mul! {
74            "multiple proc-macro attributes are applied together",
75            [
76                "feature `deny_shadow` is enabled",
77                "disabling the feature to \
78leave the possible error to the compiler",
79            ],
80            "" =>
81            $proc [ $cover ] $path
82        }
83    };
84}
85
86#[cfg(not(feature = "deny_override"))]
87#[doc(hidden)]
88#[macro_export]
89macro_rules! proc_macro_api_err_attr_override {
90    ($($tt:tt)*) => {};
91}
92
93#[cfg(feature = "deny_override")]
94#[doc(hidden)]
95#[macro_export]
96macro_rules! proc_macro_api_err_attr_override {
97    ($_0:tt $($_1:tt)?) => {};
98
99    // [[old]] [[new]] [path]
100    ($old:tt $new:tt $path:tt) => {
101        $crate::proc_macro_api_err_attr_mul! {
102            "attributes are overridden inside one path",
103            [ "feature `deny_override` is enabled" ],
104            "(s)" =>
105            $old $new $path
106        }
107    };
108}
109
110#[doc(hidden)]
111#[macro_export]
112macro_rules! proc_macro_api_parse_attr {
113    // [doc]
114    (
115    [ [ doc $($arg_doc:tt)* ] $(, $at:tt)* ]
116    [ $($doc:tt)* ] $other:tt $proc:tt
117    [ $($seg:tt $($rest:tt)*)? ]
118    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
119    $bag:tt
120    ) => {
121        $crate::proc_macro_api_parse_attr! {
122            [ $($at),* ] [ $($doc)* [ doc $($arg_doc)* ] ] $other $proc
123            [ $($($rest)*)? ] [ $($prv)* $($to_prv)? ] [ $($seg)? $last ]
124            $bag
125        }
126    };
127
128    // -> out
129    (
130    [] [ $($doc:tt)* ] [ $($($other:tt)+)? ] [
131        $([ proc_macro $($arg_fn_0:tt)* ])?
132        $([ fn $($arg_fn:tt)* ])?
133        $([ proc_macro_attribute $($arg_at_0:tt)* ])?
134        $([ at $($arg_at:tt)* ])?
135        $([ proc_macro_derive $($arg_dr_0:tt)* ])?
136        $([ dr $($arg_dr:tt)* ])?
137    ]
138    [ $($seg:tt)* ]
139    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
140    [
141        [ $($bg_proc:tt)? ] [ $($bg_doc:tt)* ] [ $($bg_oth:tt)? ]
142        [ $($bg_prv:tt)* ] $path:tt
143    ]
144    ) => {
145        $crate::proc_macro_api_err_attr_override! {
146            $($bg_oth)? $([ $($other)+ ])?
147            [ $($prv)* $($to_prv)? $last $($seg)* ]
148        }
149        $crate::proc_macro_api_parse_seg! {
150            [ $($seg)* ] [ $last ] [ $($bg_prv)* $($prv)* $($to_prv)? ]
151            [
152                [
153                    $([ proc_macro $($arg_fn_0)* ] ;)?
154                    $([ proc_macro $($arg_fn)* ] ;)?
155                    $([ proc_macro_attribute $($arg_at_0)* ] ;)?
156                    $([ proc_macro_attribute $($arg_at)* ] ;)?
157                    $([ proc_macro_derive $($arg_dr_0)* ] ;)?
158                    $([ proc_macro_derive $($arg_dr)* ] ;)?
159                    $($bg_proc)?
160                ] [
161                    $($bg_doc)*
162                    $($doc)*
163                ] [
164                    $([ $($other)+ ] ;)?
165                    $($bg_oth)?
166                ] $path
167            ]
168        }
169    };
170
171    // [proc_macro]
172    // [proc_macro_attribute]
173    // [proc_macro_derive]
174    (
175    [
176        $([ proc_macro $($arg_fn_0:tt)* ])?
177        $([ fn $($arg_fn:tt)* ])?
178        $([ proc_macro_attribute $($arg_at_0:tt)* ])?
179        $([ at $($arg_at:tt)* ])?
180        $([ proc_macro_derive $($arg_dr_0:tt)* ])?
181        $([ dr $($arg_dr:tt)* ])?
182        $(, $at:tt)*
183    ]
184    $doc:tt [ $($other:tt)* ] [ $($proc:tt)? ]
185    [ $($seg:tt $($rest:tt)*)? ]
186    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
187    $bag:tt
188    ) => {
189        $crate::proc_macro_api_err_attr_shadow! {
190            [ $($proc)? ]
191            $([proc_macro$($arg_fn_0)*])?
192            $([fn$($arg_fn)*])?
193            $([proc_macro_attribute$($arg_at_0)*])?
194            $([at$($arg_at)*])?
195            $([proc_macro_derive$($arg_dr_0)*])?
196            $([dr$($arg_dr)*])?
197            [ $($prv)* $($to_prv)? $last $($seg $($rest)*)? ]
198        }
199        $crate::proc_macro_api_parse_attr! {
200            [ $($at),* ] $doc
201            [ $($other)*
202                $([ proc_macro $($arg_fn_0)* ])?
203                $([ proc_macro $($arg_fn)* ])?
204                $([ proc_macro_attribute $($arg_at_0)* ])?
205                $([ proc_macro_attribute $($arg_at)* ])?
206                $([ proc_macro_derive $($arg_dr_0)* ])?
207                $([ proc_macro_derive $($arg_dr)* ])?
208            ] [
209                $([proc_macro$($arg_fn_0)*])?
210                $([fn$($arg_fn)*])?
211                $([proc_macro_attribute$($arg_at_0)*])?
212                $([at$($arg_at)*])?
213                $([proc_macro_derive$($arg_dr_0)*])?
214                $([dr$($arg_dr)*])?
215            ]
216            [ $($($rest)*)? ] [ $($prv)* $($to_prv)? ] [ $($seg)? $last ]
217            $bag
218        }
219    };
220
221    // [`any`]
222    (
223    [ $any:tt $(, $at:tt)* ]
224    [ $($doc:tt)* ] $other:tt $proc:tt
225    [ $($seg:tt $($rest:tt)*)? ]
226    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
227    $bag:tt
228    ) => {
229        $crate::proc_macro_api_parse_attr! {
230            [ $($at),* ] [ $($doc)* $any ] $other $proc
231            [ $($($rest)*)? ] [ $($prv)* $($to_prv)? ] [ $($seg)? $last ]
232            $bag
233        }
234    };
235}
236
237#[doc(hidden)]
238#[macro_export]
239macro_rules! proc_macro_api_parse_seg {
240    (
241    [ $seg:tt $($rest:tt)* ] [ $last:tt ] [ $($prv:tt)* ] $bag:tt
242    ) => {
243        $crate::proc_macro_api_parse_seg! {
244            [ $($rest)* ] [ $seg ] [ $($prv)* $last ] $bag
245        }
246    };
247
248    (
249    [] [
250        $($api:ident)?
251        $({
252            $(# $at_0:tt)*
253            $($seg_0:ident)?
254            $(:: $seg_cc_0:ident $(:: $rest_0:ident)*)?
255            $(:: { $($seg_blk_cc_0:tt)* })?
256            $({ $($seg_blk_0:tt)* })?
257            $(as $al_0:tt)?
258            $(,
259                $(# $at:tt)*
260                $($seg:ident)?
261                $(:: $seg_cc:ident $(:: $rest:ident)*)?
262                $(:: { $($seg_blk_cc:tt)* })?
263                $({ $($seg_blk:tt)* })?
264                $(as $al:tt)?
265            )*
266        })?
267    ] $prv:tt
268    [ $bg_proc:tt $bg_doc:tt $bg_oth:tt [ $bg_cc:tt $bg_al:tt ] ]
269    ) => {
270        $(
271        $crate::proc_macro_api_parse_fn! {
272            $bg_al $bg_proc [ $bg_doc $bg_oth $bg_cc $prv ] $api
273        }
274        )?
275        $(
276        $crate::proc_macro_api_err_seg_blk_al! {
277            $bg_al
278        }
279        $crate::proc_macro_api_parse_seg_call_attr! {
280            [
281                $(0 $bg_cc [] $seg_0)?
282                $(1 [ :: ] [ :: ] $seg_cc_0 2 [ $($rest_0)* ])?
283                $(3 [ :: ] [ :: ] { $($seg_blk_cc_0)* })?
284                $(4 $bg_cc [] { $($seg_blk_0)* })?
285            ]
286            [ $($at_0),* ] [ $($al_0)? ]
287            [ $prv $bg_cc $bg_proc $bg_doc $bg_oth ]
288        }
289        $(
290        $crate::proc_macro_api_parse_seg_call_attr! {
291            [
292                $(0 $bg_cc [] $seg)?
293                $(1 [ :: ] [ :: ] $seg_cc 2 [ $($rest)* ])?
294                $(3 [ :: ] [ :: ] { $($seg_blk_cc)* })?
295                $(4 $bg_cc [] { $($seg_blk)* })?
296            ]
297            [ $($at),* ] [ $($al)? ]
298            [ $prv $bg_cc $bg_proc $bg_doc $bg_oth ]
299        }
300        )*
301        )?
302    };
303}
304
305#[doc(hidden)]
306#[macro_export]
307macro_rules! proc_macro_api_err_seg_blk_al {
308    ([]) => {};
309
310    ([ $al:tt ]) => {
311        $crate::__private::compile_error!($crate::__private::concat!(
312            "no rules expected `as`",
313            "\n  {...} as ",
314            $crate::__private::stringify!($al),
315            "\n        ^^",
316        ));
317    };
318}
319
320#[doc(hidden)]
321#[macro_export]
322macro_rules! proc_macro_api_parse_seg_call_attr {
323    (
324    [
325        $_i:tt $cc:tt $cc_tag:tt $seg:tt
326        $(1 [ :: ] [ :: ] $seg_cc:tt)?
327        $(2 [ $($rest:tt)* ])?
328        $(3 [ :: ] [ :: ] $seg_blk_cc:tt)?
329    ]
330    $at:tt $al:tt
331    [
332        $prv:tt $bg_cc:tt
333        [ $($bg_proc:tt)? $(; $_0:tt)? $(;)? ] $bg_doc:tt
334        [ $($bg_oth:tt)? $(; $_1:tt)? $(;)? ]
335    ]
336    ) => {
337        $crate::proc_macro_api_err_seg_inner_cc! {
338            $cc_tag $bg_cc $prv [ $seg ]
339        }
340        $crate::proc_macro_api_err_seg_gp_attr! {
341            $at [ $_i $($seg_blk_cc)? ] [
342                $cc_tag $_i $seg $(1 $seg_cc)? $(2 [ $($rest)* ])?
343            ]
344        }
345        $crate::proc_macro_api_parse_attr! {
346            $at [/*[doc]*/] [/*[other]+[proc]*/] [/*[proc]*/]
347            [ $($seg_cc)? $($($rest)*)? $($seg_blk_cc)? ] [/*prv*/] [ $seg ]
348            [
349                [ $($bg_proc)? ] $bg_doc [ $($bg_oth)? ]
350                $prv [ $cc $al ]
351            ]
352        }
353    };
354
355    ([] [] [] $_:tt) => { /* empty comma (`,,`) and trailing comma (`... ,`) */ };
356
357    // err: no seg
358    ([] $at:tt $al:tt $_:tt) => {
359        $crate::proc_macro_api_err_seg_no_seg! {
360            $at $al
361        }
362    };
363
364    // err: multiple seg
365    (
366    [
367        $(0 $cc_0:tt [] $seg:tt)?
368        $(1 [ :: ] [ :: ] $seg_cc:tt)?
369        $(2 [ $($rest:tt)* ])?
370        $(3 [ :: ] [ :: ] $seg_blk_cc:tt)?
371        4 $cc_1:tt [] $seg_blk:tt
372    ]
373    $at:tt $al:tt $_:tt
374    ) => {
375        $crate::proc_macro_api_err_syn_gt_one! {
376            "" =>
377            [
378                $($seg)? $(:: $seg_cc)? $($(:: $rest)*)?
379                $(:: $seg_blk_cc)?
380            ]
381            [ $seg_blk ]
382        }
383    };
384}
385
386#[doc(hidden)]
387#[macro_export]
388macro_rules! proc_macro_api_err_seg_inner_cc {
389    ([] $_0:tt $_1:tt $_:tt) => {};
390    ([ :: ] [] [] $_:tt) => {};
391
392    // [path]
393    ([ :: ] $_0:tt $_1:tt $path:tt) => {
394        $crate::__private::compile_error!($crate::__private::concat!(
395            "leading `::` is in the middle of a path",
396            "\n  :: ",
397            $crate::proc_macro_api_fmt_path!($path),
398            "\n  ^^",
399        ));
400    };
401}
402
403#[doc(hidden)]
404#[macro_export]
405macro_rules! proc_macro_api_err_seg_no_seg {
406    // [at] al
407    ([ $($at:tt)* ] [ $($al:tt)? ]) => {
408        $crate::__private::compile_error!($crate::__private::concat!(
409            "expected path segments",
410            "\n/",
411            $("\n| #", $crate::__private::stringify!($at),)*
412            $("\n| as ", $crate::__private::stringify!($al),)?
413            "\n|\n|_^ expected path segments",
414        ));
415    };
416}
417
418#[cfg(not(feature = "deny_group_attr"))]
419#[doc(hidden)]
420#[macro_export]
421macro_rules! proc_macro_api_err_seg_gp_attr {
422    ($($tt:tt)*) => {};
423}
424
425#[cfg(feature = "deny_group_attr")]
426#[doc(hidden)]
427#[macro_export]
428macro_rules! proc_macro_api_err_seg_gp_attr {
429    ([] $_:tt $path:tt) => {};
430    ($at:tt [ $(0)? $(1)? ] $path:tt) => {};
431
432    (
433        [ $at_0:tt $(, $at:tt)* ] $_:tt
434        [
435            [ $($cc:tt)? ]
436            $(0 $seg:tt)?
437            $(1 $seg_cc:tt)?
438            $(2 [ $($rest:tt)* ])?
439            $(3 $seg_blk_cc:tt)?
440            $(4 $seg_blk:tt)?
441        ]
442    ) => {
443        $crate::__private::compile_error!($crate::__private::concat!(
444            "attributes are applied to a path group",
445            "\n/ #", $crate::__private::stringify!($at_0),
446            $("\n| #", $crate::__private::stringify!($at),)*
447            "\n| ",
448            $crate::proc_macro_api_fmt_str_tt! {
449                $($cc)? $($seg ::)? $($seg_cc ::)? $($($rest ::)*)? { ... }
450            },
451            "\n|_^",
452            "\n= note: feature `deny_group_attr` is enabled",
453        ));
454    };
455}
456
457#[doc(hidden)]
458#[macro_export]
459macro_rules! proc_macro_api_err_fn_no_proc {
460    ([ $($cc:tt)? ] [ $($prv:tt)* ] [ $($al:tt)? ] $api:tt) => {
461        $crate::__private::compile_error!($crate::__private::concat!(
462            "expected a proc-macro attribute",
463            "\n/ ", $($crate::__private::stringify!($cc),)?
464            $($crate::__private::stringify!($prv), "::",)*
465            $crate::__private::stringify!($api),
466            $("\n| as ", $crate::__private::stringify!($al),)?
467            "\n|_^",
468        ));
469    };
470}
471
472#[doc(hidden)]
473#[macro_export]
474macro_rules! proc_macro_api_parse_fn {
475    ([ _ ] $proc:tt $bag:tt $api:tt) => { /* underscore alias */ };
476
477    ($al:tt [] [ $_0:tt $_1:tt $cc:tt $prv:tt ] $api:tt) => {
478        $crate::proc_macro_api_err_fn_no_proc!($cc $prv $al $api);
479    };
480
481    // $bg_al $bg_proc [ $bg_doc $bg_oth $bg_cc $prv ] $api
482    (
483    [ $($al:tt)? ]
484    [
485        $([ proc_macro $($arg_fn:tt)* ])?
486        $([ proc_macro_attribute $($arg_at:tt)* ])?
487        $([ proc_macro_derive $($arg_dr:tt)* ])?
488        $(; $_0:tt)? $(;)?
489    ]
490    [ $doc:tt [ $other:tt $(; $_1:tt)? $(;)? ] $cc:tt $prv:tt ]
491    $api:tt
492    ) => {
493        $crate::proc_macro_api_fn! {
494            $doc $other $cc $prv $api [ $($al)? $api ]
495            $((input) [ $($arg_fn)* ])?
496            $((args, item) [ $($arg_at)* ])?
497            $((item) [ $($arg_dr)* ])?
498        }
499    };
500}
501
502#[doc(hidden)]
503#[macro_export]
504macro_rules! proc_macro_api_fn {
505    (
506    [ $($doc:tt)* ] [ $($other:tt)* ]
507    [ $($cc:tt)? ] [ $($prv:tt)* ] $api:tt [ $name:tt $($_0:tt)? ]
508    ( $($args:tt),* $(,)? ) $_1:tt
509    ) => {
510        $(# $doc)*
511        $(# $other)*
512        pub fn $name (
513            $($args : $crate::__private::TokenStream),*
514        ) -> $crate::__private::TokenStream {
515            $crate::proc_macro_api_call! {
516                ( $($args),* ) $($cc)? $($prv ::)* $api
517            }
518        }
519    };
520}
521
522#[cfg(not(feature = "auto_transform"))]
523#[doc(hidden)]
524#[macro_export]
525macro_rules! proc_macro_api_call {
526    ($args:tt $($path:tt)*) => {
527        $($path)* $args
528    };
529}
530
531#[cfg(feature = "auto_transform")]
532#[doc(hidden)]
533#[macro_export]
534macro_rules! proc_macro_api_call {
535    (( $($args:tt),* ) $($path:tt)*) => {
536        $crate::__private::From::from(
537            $($path)* (
538                $($crate::__private::From::from($args),)*
539            ),
540        )
541    };
542}