Respect attributes on proc macro definitions

This commit is contained in:
Vadim Petrochenkov
2019-08-20 21:22:32 +03:00
parent 32e5acb3eb
commit 52c62eaae4
6 changed files with 131 additions and 67 deletions

View File

@@ -1,11 +1,11 @@
use crate::ast::{self, NodeId, Attribute, Name, PatKind};
use crate::attr::{HasAttrs, Stability, Deprecation};
use crate::attr::{self, HasAttrs, Stability, Deprecation};
use crate::source_map::SourceMap;
use crate::edition::Edition;
use crate::ext::expand::{self, AstFragment, Invocation};
use crate::ext::hygiene::{ExpnId, Transparency};
use crate::mut_visit::{self, MutVisitor};
use crate::parse::{self, parser, DirectoryOwnership};
use crate::parse::{self, parser, ParseSess, DirectoryOwnership};
use crate::parse::token;
use crate::ptr::P;
use crate::symbol::{kw, sym, Ident, Symbol};
@@ -601,6 +601,69 @@ impl SyntaxExtension {
}
}
/// Constructs a syntax extension with the given properties
/// and other properties converted from attributes.
pub fn new(
sess: &ParseSess,
kind: SyntaxExtensionKind,
span: Span,
helper_attrs: Vec<Symbol>,
edition: Edition,
name: Name,
attrs: &[ast::Attribute],
) -> SyntaxExtension {
let allow_internal_unstable =
attr::find_by_name(attrs, sym::allow_internal_unstable).map(|attr| {
attr.meta_item_list()
.map(|list| {
list.iter()
.filter_map(|it| {
let name = it.ident().map(|ident| ident.name);
if name.is_none() {
sess.span_diagnostic.span_err(
it.span(), "allow internal unstable expects feature names"
)
}
name
})
.collect::<Vec<Symbol>>()
.into()
})
.unwrap_or_else(|| {
sess.span_diagnostic.span_warn(
attr.span,
"allow_internal_unstable expects list of feature names. In the future \
this will become a hard error. Please use `allow_internal_unstable(\
foo, bar)` to only allow the `foo` and `bar` features",
);
vec![sym::allow_internal_unstable_backcompat_hack].into()
})
});
let mut local_inner_macros = false;
if let Some(macro_export) = attr::find_by_name(attrs, sym::macro_export) {
if let Some(l) = macro_export.meta_item_list() {
local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
}
}
let is_builtin = attr::contains_name(attrs, sym::rustc_builtin_macro);
SyntaxExtension {
kind,
span,
allow_internal_unstable,
allow_internal_unsafe: attr::contains_name(attrs, sym::allow_internal_unsafe),
local_inner_macros,
stability: attr::find_stability(&sess, attrs, span),
deprecation: attr::find_deprecation(&sess, attrs, span),
helper_attrs,
edition,
is_builtin,
is_derive_copy: is_builtin && name == sym::Copy,
}
}
pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree])
-> Box<dyn MacResult + 'cx> {

View File

@@ -1,3 +1,5 @@
use crate::ast;
use crate::attr::{self, TransparencyError};
use crate::edition::Edition;
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
@@ -15,7 +17,6 @@ use crate::parse::token::{self, NtTT, Token};
use crate::parse::{Directory, ParseSess};
use crate::symbol::{kw, sym, Symbol};
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
use crate::{ast, attr, attr::TransparencyError};
use errors::{DiagnosticBuilder, FatalError};
use log::debug;
@@ -290,6 +291,7 @@ pub fn compile(
def: &ast::Item,
edition: Edition,
) -> SyntaxExtension {
let diag = &sess.span_diagnostic;
let lhs_nm = ast::Ident::new(sym::lhs, def.span);
let rhs_nm = ast::Ident::new(sym::rhs, def.span);
let tt_spec = ast::Ident::new(sym::tt, def.span);
@@ -423,13 +425,9 @@ pub fn compile(
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy);
match transparency_error {
Some(TransparencyError::UnknownTransparency(value, span)) =>
sess.span_diagnostic.span_err(
span, &format!("unknown macro transparency: `{}`", value)
),
diag.span_err(span, &format!("unknown macro transparency: `{}`", value)),
Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) =>
sess.span_diagnostic.span_err(
vec![old_span, new_span], "multiple macro transparency attributes"
),
diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"),
None => {}
}
@@ -437,57 +435,15 @@ pub fn compile(
name: def.ident, span: def.span, transparency, lhses, rhses, valid
});
let allow_internal_unstable =
attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| {
attr.meta_item_list()
.map(|list| {
list.iter()
.filter_map(|it| {
let name = it.ident().map(|ident| ident.name);
if name.is_none() {
sess.span_diagnostic.span_err(
it.span(),
"allow internal unstable expects feature names",
)
}
name
})
.collect::<Vec<Symbol>>()
.into()
})
.unwrap_or_else(|| {
sess.span_diagnostic.span_warn(
attr.span,
"allow_internal_unstable expects list of feature names. In the \
future this will become a hard error. Please use `allow_internal_unstable(\
foo, bar)` to only allow the `foo` and `bar` features",
);
vec![sym::allow_internal_unstable_backcompat_hack].into()
})
});
let mut local_inner_macros = false;
if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) {
if let Some(l) = macro_export.meta_item_list() {
local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
}
}
let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro);
SyntaxExtension {
kind: SyntaxExtensionKind::LegacyBang(expander),
span: def.span,
allow_internal_unstable,
allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe),
local_inner_macros,
stability: attr::find_stability(&sess, &def.attrs, def.span),
deprecation: attr::find_deprecation(&sess, &def.attrs, def.span),
helper_attrs: Vec::new(),
SyntaxExtension::new(
sess,
SyntaxExtensionKind::LegacyBang(expander),
def.span,
Vec::new(),
edition,
is_builtin,
is_derive_copy: is_builtin && def.ident.name == sym::Copy,
}
def.ident.name,
&def.attrs,
)
}
fn check_lhs_nt_follows(