]>
Commit | Line | Data |
---|---|---|
e74abb32 XL |
1 | use crate::base::{self, *}; |
2 | use crate::proc_macro_server; | |
3 | ||
6a06907d | 4 | use rustc_ast as ast; |
fc512014 | 5 | use rustc_ast::ptr::P; |
74b04a01 | 6 | use rustc_ast::token; |
04454e1e | 7 | use rustc_ast::tokenstream::{TokenStream, TokenTree}; |
dfeec247 | 8 | use rustc_data_structures::sync::Lrc; |
5e7ed085 | 9 | use rustc_errors::ErrorGuaranteed; |
5869c6ff | 10 | use rustc_parse::parser::ForceCollect; |
04454e1e | 11 | use rustc_span::profiling::SpannedEventArgRecorder; |
dfeec247 | 12 | use rustc_span::{Span, DUMMY_SP}; |
416331ca | 13 | |
e74abb32 | 14 | const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread; |
416331ca XL |
15 | |
16 | pub struct BangProcMacro { | |
923072b8 | 17 | pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>, |
416331ca XL |
18 | } |
19 | ||
923072b8 | 20 | impl base::BangProcMacro for BangProcMacro { |
dfeec247 XL |
21 | fn expand<'cx>( |
22 | &self, | |
23 | ecx: &'cx mut ExtCtxt<'_>, | |
24 | span: Span, | |
25 | input: TokenStream, | |
5e7ed085 | 26 | ) -> Result<TokenStream, ErrorGuaranteed> { |
04454e1e FG |
27 | let _timer = |
28 | ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| { | |
29 | recorder.record_arg_with_span(ecx.expansion_descr(), span); | |
30 | }); | |
31 | ||
3c0e092e | 32 | let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; |
136023e0 | 33 | let server = proc_macro_server::Rustc::new(ecx); |
3c0e092e | 34 | self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace).map_err(|e| { |
ba9703b0 XL |
35 | let mut err = ecx.struct_span_err(span, "proc macro panicked"); |
36 | if let Some(s) = e.as_str() { | |
37 | err.help(&format!("message: {}", s)); | |
416331ca | 38 | } |
5e7ed085 | 39 | err.emit() |
ba9703b0 | 40 | }) |
416331ca XL |
41 | } |
42 | } | |
43 | ||
44 | pub struct AttrProcMacro { | |
923072b8 | 45 | pub client: pm::bridge::client::Client<(pm::TokenStream, pm::TokenStream), pm::TokenStream>, |
416331ca XL |
46 | } |
47 | ||
48 | impl base::AttrProcMacro for AttrProcMacro { | |
dfeec247 XL |
49 | fn expand<'cx>( |
50 | &self, | |
51 | ecx: &'cx mut ExtCtxt<'_>, | |
52 | span: Span, | |
53 | annotation: TokenStream, | |
54 | annotated: TokenStream, | |
5e7ed085 | 55 | ) -> Result<TokenStream, ErrorGuaranteed> { |
04454e1e FG |
56 | let _timer = |
57 | ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| { | |
58 | recorder.record_arg_with_span(ecx.expansion_descr(), span); | |
59 | }); | |
60 | ||
3c0e092e | 61 | let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; |
136023e0 | 62 | let server = proc_macro_server::Rustc::new(ecx); |
1b1a35ee | 63 | self.client |
3c0e092e | 64 | .run(&EXEC_STRATEGY, server, annotation, annotated, proc_macro_backtrace) |
1b1a35ee XL |
65 | .map_err(|e| { |
66 | let mut err = ecx.struct_span_err(span, "custom attribute panicked"); | |
67 | if let Some(s) = e.as_str() { | |
68 | err.help(&format!("message: {}", s)); | |
69 | } | |
5e7ed085 | 70 | err.emit() |
1b1a35ee | 71 | }) |
416331ca XL |
72 | } |
73 | } | |
74 | ||
923072b8 FG |
75 | pub struct DeriveProcMacro { |
76 | pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>, | |
416331ca XL |
77 | } |
78 | ||
923072b8 | 79 | impl MultiItemModifier for DeriveProcMacro { |
dfeec247 XL |
80 | fn expand( |
81 | &self, | |
82 | ecx: &mut ExtCtxt<'_>, | |
83 | span: Span, | |
84 | _meta_item: &ast::MetaItem, | |
85 | item: Annotatable, | |
ba9703b0 | 86 | ) -> ExpandResult<Vec<Annotatable>, Annotatable> { |
fc512014 XL |
87 | // We need special handling for statement items |
88 | // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`) | |
04454e1e FG |
89 | let is_stmt = matches!(item, Annotatable::Stmt(..)); |
90 | let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.parse_sess); | |
91 | let input = if hack { | |
92 | let nt = match item { | |
93 | Annotatable::Item(item) => token::NtItem(item), | |
94 | Annotatable::Stmt(stmt) => token::NtStmt(stmt), | |
95 | _ => unreachable!(), | |
96 | }; | |
97 | TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into() | |
f035d41b | 98 | } else { |
923072b8 | 99 | item.to_tokens() |
f035d41b | 100 | }; |
416331ca | 101 | |
04454e1e FG |
102 | let stream = { |
103 | let _timer = | |
104 | ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| { | |
105 | recorder.record_arg_with_span(ecx.expansion_descr(), span); | |
106 | }); | |
107 | let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace; | |
108 | let server = proc_macro_server::Rustc::new(ecx); | |
109 | match self.client.run(&EXEC_STRATEGY, server, input, proc_macro_backtrace) { | |
110 | Ok(stream) => stream, | |
111 | Err(e) => { | |
112 | let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); | |
113 | if let Some(s) = e.as_str() { | |
114 | err.help(&format!("message: {}", s)); | |
115 | } | |
116 | err.emit(); | |
117 | return ExpandResult::Ready(vec![]); | |
416331ca | 118 | } |
3c0e092e XL |
119 | } |
120 | }; | |
416331ca | 121 | |
3dfed10e | 122 | let error_count_before = ecx.sess.parse_sess.span_diagnostic.err_count(); |
dfeec247 | 123 | let mut parser = |
3dfed10e | 124 | rustc_parse::stream_to_parser(&ecx.sess.parse_sess, stream, Some("proc-macro derive")); |
416331ca XL |
125 | let mut items = vec![]; |
126 | ||
127 | loop { | |
5869c6ff | 128 | match parser.parse_item(ForceCollect::No) { |
416331ca | 129 | Ok(None) => break, |
fc512014 XL |
130 | Ok(Some(item)) => { |
131 | if is_stmt { | |
132 | items.push(Annotatable::Stmt(P(ecx.stmt_item(span, item)))); | |
133 | } else { | |
134 | items.push(Annotatable::Item(item)); | |
135 | } | |
136 | } | |
416331ca | 137 | Err(mut err) => { |
ba9703b0 XL |
138 | err.emit(); |
139 | break; | |
416331ca XL |
140 | } |
141 | } | |
142 | } | |
143 | ||
416331ca | 144 | // fail if there have been errors emitted |
3dfed10e | 145 | if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before { |
ba9703b0 | 146 | ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit(); |
416331ca XL |
147 | } |
148 | ||
ba9703b0 | 149 | ExpandResult::Ready(items) |
416331ca XL |
150 | } |
151 | } |