Parsers for the attributes
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
This commit is contained in:
parent
c4e7cb806c
commit
2f50c7807c
3 changed files with 147 additions and 0 deletions
|
|
@ -41,6 +41,7 @@ pub(crate) mod must_use;
|
|||
pub(crate) mod no_implicit_prelude;
|
||||
pub(crate) mod non_exhaustive;
|
||||
pub(crate) mod path;
|
||||
pub(crate) mod proc_macro_attrs;
|
||||
pub(crate) mod repr;
|
||||
pub(crate) mod rustc_internal;
|
||||
pub(crate) mod semantics;
|
||||
|
|
|
|||
139
compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
Normal file
139
compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
use rustc_attr_data_structures::AttributeKind;
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::attributes::{
|
||||
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
|
||||
};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
|
||||
pub(crate) struct ProcMacroParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
|
||||
const PATH: &[Symbol] = &[sym::proc_macro];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro;
|
||||
}
|
||||
|
||||
pub(crate) struct ProcMacroAttributeParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
|
||||
const PATH: &[Symbol] = &[sym::proc_macro_attribute];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute;
|
||||
}
|
||||
|
||||
pub(crate) struct ProcMacroDeriveParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
|
||||
const PATH: &[Symbol] = &[sym::proc_macro_derive];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let (trait_name, helper_attrs) = parse_derive_like(cx, args, true)?;
|
||||
Some(AttributeKind::ProcMacroDerive {
|
||||
trait_name: trait_name.expect("Trait name is mandatory, so it is present"),
|
||||
helper_attrs,
|
||||
span: cx.attr_span,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcBuiltinMacroParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_builtin_macro];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const TEMPLATE: AttributeTemplate =
|
||||
template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let (builtin_name, helper_attrs) = parse_derive_like(cx, args, false)?;
|
||||
Some(AttributeKind::RustcBuiltinMacro { builtin_name, helper_attrs, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_derive_like<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser<'_>,
|
||||
trait_name_mandatory: bool,
|
||||
) -> Option<(Option<Symbol>, ThinVec<Symbol>)> {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return None;
|
||||
};
|
||||
let mut items = list.mixed();
|
||||
|
||||
// Parse the name of the trait that is derived.
|
||||
let Some(trait_attr) = items.next() else {
|
||||
// For #[rustc_builtin_macro], it is permitted to leave out the trait name
|
||||
if !trait_name_mandatory {
|
||||
return None;
|
||||
}
|
||||
cx.expected_at_least_one_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
let Some(trait_attr) = trait_attr.meta_item() else {
|
||||
cx.unexpected_literal(trait_attr.span());
|
||||
return None;
|
||||
};
|
||||
let Some(trait_ident) = trait_attr.path().word() else {
|
||||
cx.expected_identifier(trait_attr.path().span());
|
||||
return None;
|
||||
};
|
||||
if !trait_ident.name.can_be_raw() {
|
||||
cx.expected_identifier(trait_ident.span);
|
||||
return None;
|
||||
}
|
||||
if let Err(e) = trait_attr.args().no_args() {
|
||||
cx.expected_no_args(e);
|
||||
return None;
|
||||
};
|
||||
|
||||
// Parse optional attributes
|
||||
let mut attributes = ThinVec::new();
|
||||
if let Some(attrs) = items.next() {
|
||||
let Some(attr_list) = attrs.meta_item() else {
|
||||
cx.expected_list(attrs.span());
|
||||
return None;
|
||||
};
|
||||
if !attr_list.path().word_is(sym::attributes) {
|
||||
cx.expected_specific_argument(attrs.span(), vec!["attributes"]);
|
||||
return None;
|
||||
}
|
||||
let Some(attr_list) = attr_list.args().list() else {
|
||||
cx.expected_list(attrs.span());
|
||||
return None;
|
||||
};
|
||||
|
||||
// Parse item in `attributes(...)` argument
|
||||
for attr in attr_list.mixed() {
|
||||
let Some(attr) = attr.meta_item() else {
|
||||
cx.expected_identifier(attr.span());
|
||||
return None;
|
||||
};
|
||||
if let Err(e) = attr.args().no_args() {
|
||||
cx.expected_no_args(e);
|
||||
return None;
|
||||
};
|
||||
let Some(ident) = attr.path().word() else {
|
||||
cx.expected_identifier(attr.path().span());
|
||||
return None;
|
||||
};
|
||||
if !ident.name.can_be_raw() {
|
||||
cx.expected_identifier(ident.span);
|
||||
return None;
|
||||
}
|
||||
attributes.push(ident.name);
|
||||
}
|
||||
}
|
||||
|
||||
// If anything else is specified, we should reject it
|
||||
if let Some(next) = items.next() {
|
||||
cx.expected_no_args(next.span());
|
||||
}
|
||||
|
||||
Some((Some(trait_ident.name), attributes))
|
||||
}
|
||||
|
|
@ -38,6 +38,9 @@ use crate::attributes::must_use::MustUseParser;
|
|||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
use crate::attributes::non_exhaustive::NonExhaustiveParser;
|
||||
use crate::attributes::path::PathParser as PathAttributeParser;
|
||||
use crate::attributes::proc_macro_attrs::{
|
||||
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
|
||||
};
|
||||
use crate::attributes::repr::{AlignParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
|
||||
|
|
@ -154,6 +157,8 @@ attribute_parsers!(
|
|||
Single<MustUseParser>,
|
||||
Single<OptimizeParser>,
|
||||
Single<PathAttributeParser>,
|
||||
Single<ProcMacroDeriveParser>,
|
||||
Single<RustcBuiltinMacroParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<RustcLayoutScalarValidRangeEnd>,
|
||||
Single<RustcLayoutScalarValidRangeStart>,
|
||||
|
|
@ -186,6 +191,8 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<ParenSugarParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PointeeParser>>,
|
||||
Single<WithoutArgs<ProcMacroAttributeParser>>,
|
||||
Single<WithoutArgs<ProcMacroParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue