1 use crate::ast
::{self, ItemKind, Attribute, Mac}
;
2 use crate::attr
::{mark_used, mark_known}
;
3 use crate::errors
::{Applicability, FatalError}
;
4 use crate::ext
::base
::{self, *}
;
5 use crate::ext
::proc_macro_server
;
6 use crate::parse
::{self, token}
;
7 use crate::parse
::parser
::PathStyle
;
8 use crate::symbol
::sym
;
9 use crate::tokenstream
::{self, TokenStream}
;
10 use crate::visit
::Visitor
;
12 use rustc_data_structures
::sync
::Lrc
;
13 use syntax_pos
::{Span, DUMMY_SP}
;
15 const EXEC_STRATEGY
: proc_macro
::bridge
::server
::SameThread
=
16 proc_macro
::bridge
::server
::SameThread
;
18 pub struct BangProcMacro
{
19 pub client
: proc_macro
::bridge
::client
::Client
<
20 fn(proc_macro
::TokenStream
) -> proc_macro
::TokenStream
,
24 impl base
::ProcMacro
for BangProcMacro
{
26 ecx
: &'cx
mut ExtCtxt
<'_
>,
30 let server
= proc_macro_server
::Rustc
::new(ecx
);
31 match self.client
.run(&EXEC_STRATEGY
, server
, input
) {
34 let msg
= "proc macro panicked";
35 let mut err
= ecx
.struct_span_fatal(span
, msg
);
36 if let Some(s
) = e
.as_str() {
37 err
.help(&format
!("message: {}", s
));
47 pub struct AttrProcMacro
{
48 pub client
: proc_macro
::bridge
::client
::Client
<
49 fn(proc_macro
::TokenStream
, proc_macro
::TokenStream
) -> proc_macro
::TokenStream
,
53 impl base
::AttrProcMacro
for AttrProcMacro
{
55 ecx
: &'cx
mut ExtCtxt
<'_
>,
57 annotation
: TokenStream
,
58 annotated
: TokenStream
)
60 let server
= proc_macro_server
::Rustc
::new(ecx
);
61 match self.client
.run(&EXEC_STRATEGY
, server
, annotation
, annotated
) {
64 let msg
= "custom attribute panicked";
65 let mut err
= ecx
.struct_span_fatal(span
, msg
);
66 if let Some(s
) = e
.as_str() {
67 err
.help(&format
!("message: {}", s
));
77 pub struct ProcMacroDerive
{
78 pub client
: proc_macro
::bridge
::client
::Client
<
79 fn(proc_macro
::TokenStream
) -> proc_macro
::TokenStream
,
81 pub attrs
: Vec
<ast
::Name
>,
84 impl MultiItemModifier
for ProcMacroDerive
{
86 ecx
: &mut ExtCtxt
<'_
>,
88 _meta_item
: &ast
::MetaItem
,
91 let item
= match item
{
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 // Mark attributes as known, and used.
115 MarkAttrs(&self.attrs
).visit_item(&item
);
117 let token
= token
::Interpolated(Lrc
::new(token
::NtItem(item
)));
118 let input
= tokenstream
::TokenTree
::token(token
, DUMMY_SP
).into();
120 let server
= proc_macro_server
::Rustc
::new(ecx
);
121 let stream
= match self.client
.run(&EXEC_STRATEGY
, server
, input
) {
122 Ok(stream
) => stream
,
124 let msg
= "proc-macro derive panicked";
125 let mut err
= ecx
.struct_span_fatal(span
, msg
);
126 if let Some(s
) = e
.as_str() {
127 err
.help(&format
!("message: {}", s
));
135 let error_count_before
= ecx
.parse_sess
.span_diagnostic
.err_count();
136 let msg
= "proc-macro derive produced unparseable tokens";
138 let mut parser
= parse
::stream_to_parser(ecx
.parse_sess
, stream
, Some("proc-macro derive"));
139 let mut items
= vec
![];
142 match parser
.parse_item() {
145 items
.push(Annotatable
::Item(item
))
148 // FIXME: handle this better
150 ecx
.struct_span_fatal(span
, msg
).emit();
157 // fail if there have been errors emitted
158 if ecx
.parse_sess
.span_diagnostic
.err_count() > error_count_before
{
159 ecx
.struct_span_fatal(span
, msg
).emit();
167 struct MarkAttrs
<'a
>(&'a
[ast
::Name
]);
169 impl<'a
> Visitor
<'a
> for MarkAttrs
<'a
> {
170 fn visit_attribute(&mut self, attr
: &Attribute
) {
171 if let Some(ident
) = attr
.ident() {
172 if self.0.contains(&ident
.name
) {
179 fn visit_mac(&mut self, _mac
: &Mac
) {}
182 pub fn is_proc_macro_attr(attr
: &Attribute
) -> bool
{
183 [sym
::proc_macro
, sym
::proc_macro_attribute
, sym
::proc_macro_derive
]
184 .iter().any(|kind
| attr
.check_name(*kind
))
187 crate fn collect_derives(cx
: &mut ExtCtxt
<'_
>, attrs
: &mut Vec
<ast
::Attribute
>) -> Vec
<ast
::Path
> {
188 let mut result
= Vec
::new();
189 attrs
.retain(|attr
| {
190 if attr
.path
!= sym
::derive
{
193 if !attr
.is_meta_item_list() {
194 cx
.struct_span_err(attr
.span
, "malformed `derive` attribute input")
197 "missing traits to be derived",
198 "#[derive(Trait1, Trait2, ...)]".to_owned(),
199 Applicability
::HasPlaceholders
,
204 match attr
.parse_list(cx
.parse_sess
,
205 |parser
| parser
.parse_path_allowing_meta(PathStyle
::Mod
)) {
207 result
.extend(traits
);