1 use crate::base::{self, *};
2 use crate::proc_macro_server;
4 use syntax::ast::{self, ItemKind};
5 use syntax::errors::{Applicability, FatalError};
6 use syntax::symbol::sym;
8 use syntax::tokenstream::{self, TokenStream};
10 use rustc_data_structures::sync::Lrc;
11 use syntax_pos::{Span, DUMMY_SP};
13 const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread;
15 pub struct BangProcMacro {
16 pub client: pm::bridge::client::Client<
17 fn(pm::TokenStream) -> pm::TokenStream,
21 impl base::ProcMacro for BangProcMacro {
23 ecx: &'cx mut ExtCtxt<'_>,
27 let server = proc_macro_server::Rustc::new(ecx);
28 match self.client.run(&EXEC_STRATEGY, server, input) {
31 let msg = "proc macro panicked";
32 let mut err = ecx.struct_span_fatal(span, msg);
33 if let Some(s) = e.as_str() {
34 err.help(&format!("message: {}", s));
44 pub struct AttrProcMacro {
45 pub client: pm::bridge::client::Client<fn(pm::TokenStream, pm::TokenStream) -> pm::TokenStream>,
48 impl base::AttrProcMacro for AttrProcMacro {
50 ecx: &'cx mut ExtCtxt<'_>,
52 annotation: TokenStream,
53 annotated: TokenStream)
55 let server = proc_macro_server::Rustc::new(ecx);
56 match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
59 let msg = "custom attribute panicked";
60 let mut err = ecx.struct_span_fatal(span, msg);
61 if let Some(s) = e.as_str() {
62 err.help(&format!("message: {}", s));
72 pub struct ProcMacroDerive {
73 pub client: pm::bridge::client::Client<fn(pm::TokenStream) -> pm::TokenStream>,
76 impl MultiItemModifier for ProcMacroDerive {
78 ecx: &mut ExtCtxt<'_>,
80 _meta_item: &ast::MetaItem,
83 let item = match item {
84 Annotatable::Arm(..) |
85 Annotatable::Field(..) |
86 Annotatable::FieldPat(..) |
87 Annotatable::GenericParam(..) |
88 Annotatable::Param(..) |
89 Annotatable::StructField(..) |
90 Annotatable::Variant(..)
91 => panic!("unexpected annotatable"),
92 Annotatable::Item(item) => item,
93 Annotatable::ImplItem(_) |
94 Annotatable::TraitItem(_) |
95 Annotatable::ForeignItem(_) |
96 Annotatable::Stmt(_) |
97 Annotatable::Expr(_) => {
98 ecx.span_err(span, "proc-macro derives may only be \
99 applied to a struct, enum, or union");
104 ItemKind::Struct(..) |
106 ItemKind::Union(..) => {},
108 ecx.span_err(span, "proc-macro derives may only be \
109 applied to a struct, enum, or union");
114 let token = token::Interpolated(Lrc::new(token::NtItem(item)));
115 let input = tokenstream::TokenTree::token(token, DUMMY_SP).into();
117 let server = proc_macro_server::Rustc::new(ecx);
118 let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
119 Ok(stream) => stream,
121 let msg = "proc-macro derive panicked";
122 let mut err = ecx.struct_span_fatal(span, msg);
123 if let Some(s) = e.as_str() {
124 err.help(&format!("message: {}", s));
132 let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
133 let msg = "proc-macro derive produced unparseable tokens";
135 let mut parser = rustc_parse::stream_to_parser(
138 Some("proc-macro derive"),
140 let mut items = vec![];
143 match parser.parse_item() {
146 items.push(Annotatable::Item(item))
149 // FIXME: handle this better
151 ecx.struct_span_fatal(span, msg).emit();
158 // fail if there have been errors emitted
159 if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
160 ecx.struct_span_fatal(span, msg).emit();
168 crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
169 let mut result = Vec::new();
170 attrs.retain(|attr| {
171 if !attr.has_name(sym::derive) {
174 if !attr.is_meta_item_list() {
175 cx.struct_span_err(attr.span, "malformed `derive` attribute input")
178 "missing traits to be derived",
179 "#[derive(Trait1, Trait2, ...)]".to_owned(),
180 Applicability::HasPlaceholders,
185 let parse_derive_paths = |attr: &ast::Attribute| {
186 if attr.get_normal_item().tokens.is_empty() {
187 return Ok(Vec::new());
189 rustc_parse::parse_in_attr(cx.parse_sess, attr, |p| p.parse_derive_paths())
192 match parse_derive_paths(attr) {
194 result.extend(traits);