1 use crate::base
::{self, *}
;
2 use crate::proc_macro_server
;
7 use rustc_ast
::tokenstream
::{CanSynthesizeMissingTokens, TokenStream, TokenTree}
;
8 use rustc_data_structures
::sync
::Lrc
;
9 use rustc_errors
::ErrorReported
;
10 use rustc_parse
::nt_to_tokenstream
;
11 use rustc_parse
::parser
::ForceCollect
;
12 use rustc_span
::{Span, DUMMY_SP}
;
14 const EXEC_STRATEGY
: pm
::bridge
::server
::SameThread
= pm
::bridge
::server
::SameThread
;
16 pub struct BangProcMacro
{
17 pub client
: pm
::bridge
::client
::Client
<fn(pm
::TokenStream
) -> pm
::TokenStream
>,
20 impl base
::ProcMacro
for BangProcMacro
{
23 ecx
: &'cx
mut ExtCtxt
<'_
>,
26 ) -> Result
<TokenStream
, ErrorReported
> {
27 let server
= proc_macro_server
::Rustc
::new(ecx
);
28 self.client
.run(&EXEC_STRATEGY
, server
, input
, ecx
.ecfg
.proc_macro_backtrace
).map_err(|e
| {
29 let mut err
= ecx
.struct_span_err(span
, "proc macro panicked");
30 if let Some(s
) = e
.as_str() {
31 err
.help(&format
!("message: {}", s
));
39 pub struct AttrProcMacro
{
40 pub client
: pm
::bridge
::client
::Client
<fn(pm
::TokenStream
, pm
::TokenStream
) -> pm
::TokenStream
>,
43 impl base
::AttrProcMacro
for AttrProcMacro
{
46 ecx
: &'cx
mut ExtCtxt
<'_
>,
48 annotation
: TokenStream
,
49 annotated
: TokenStream
,
50 ) -> Result
<TokenStream
, ErrorReported
> {
51 let server
= proc_macro_server
::Rustc
::new(ecx
);
53 .run(&EXEC_STRATEGY
, server
, annotation
, annotated
, ecx
.ecfg
.proc_macro_backtrace
)
55 let mut err
= ecx
.struct_span_err(span
, "custom attribute panicked");
56 if let Some(s
) = e
.as_str() {
57 err
.help(&format
!("message: {}", s
));
65 pub struct ProcMacroDerive
{
66 pub client
: pm
::bridge
::client
::Client
<fn(pm
::TokenStream
) -> pm
::TokenStream
>,
69 impl MultiItemModifier
for ProcMacroDerive
{
72 ecx
: &mut ExtCtxt
<'_
>,
74 _meta_item
: &ast
::MetaItem
,
76 ) -> ExpandResult
<Vec
<Annotatable
>, Annotatable
> {
77 // We need special handling for statement items
78 // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
79 let mut is_stmt
= false;
80 let item
= match item
{
81 Annotatable
::Item(item
) => token
::NtItem(item
),
82 Annotatable
::Stmt(stmt
) => {
84 assert
!(stmt
.is_item());
86 // A proc macro can't observe the fact that we're passing
87 // them an `NtStmt` - it can only see the underlying tokens
88 // of the wrapped item
89 token
::NtStmt(stmt
.into_inner())
93 let input
= if crate::base
::pretty_printing_compatibility_hack(&item
, &ecx
.sess
.parse_sess
)
95 TokenTree
::token(token
::Interpolated(Lrc
::new(item
)), DUMMY_SP
).into()
97 nt_to_tokenstream(&item
, &ecx
.sess
.parse_sess
, CanSynthesizeMissingTokens
::Yes
)
100 let server
= proc_macro_server
::Rustc
::new(ecx
);
102 match self.client
.run(&EXEC_STRATEGY
, server
, input
, ecx
.ecfg
.proc_macro_backtrace
) {
103 Ok(stream
) => stream
,
105 let mut err
= ecx
.struct_span_err(span
, "proc-macro derive panicked");
106 if let Some(s
) = e
.as_str() {
107 err
.help(&format
!("message: {}", s
));
110 return ExpandResult
::Ready(vec
![]);
114 let error_count_before
= ecx
.sess
.parse_sess
.span_diagnostic
.err_count();
116 rustc_parse
::stream_to_parser(&ecx
.sess
.parse_sess
, stream
, Some("proc-macro derive"));
117 let mut items
= vec
![];
120 match parser
.parse_item(ForceCollect
::No
) {
124 items
.push(Annotatable
::Stmt(P(ecx
.stmt_item(span
, item
))));
126 items
.push(Annotatable
::Item(item
));
136 // fail if there have been errors emitted
137 if ecx
.sess
.parse_sess
.span_diagnostic
.err_count() > error_count_before
{
138 ecx
.struct_span_err(span
, "proc-macro derive produced unparseable tokens").emit();
141 ExpandResult
::Ready(items
)