2528 lines
46 KiB
Rust
2528 lines
46 KiB
Rust
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
// See Notices.txt for copyright information
|
|
|
|
use crate::{Cfg, CfgAttr, Cfgs, Errors};
|
|
use proc_macro2::Ident;
|
|
use std::{collections::VecDeque, marker::PhantomData};
|
|
use syn::{
|
|
punctuated::{Pair, Punctuated},
|
|
Token,
|
|
};
|
|
|
|
struct State<P: Phase> {
|
|
cfgs: Cfgs<P::CfgsValue>,
|
|
errors: Errors,
|
|
_phantom: PhantomData<P>,
|
|
}
|
|
|
|
impl<P: Phase> State<P> {
|
|
#[must_use]
|
|
fn eval_cfg(&mut self, cfg: Cfg) -> bool {
|
|
struct MyDispatch<'a> {
|
|
cfg: Cfg,
|
|
_phantom: PhantomData<&'a ()>,
|
|
}
|
|
impl<'a> PhaseDispatch for MyDispatch<'a> {
|
|
type Args<P: Phase> = &'a mut State<P>;
|
|
type Output<P: Phase> = bool;
|
|
|
|
fn dispatch_collect(
|
|
self,
|
|
args: Self::Args<CollectCfgsPhase>,
|
|
) -> Self::Output<CollectCfgsPhase> {
|
|
args.cfgs.insert_cfg(self.cfg, ());
|
|
true
|
|
}
|
|
|
|
fn dispatch_process(
|
|
self,
|
|
args: Self::Args<ProcessCfgsPhase>,
|
|
) -> Self::Output<ProcessCfgsPhase> {
|
|
if let Some(&retval) = args.cfgs.cfgs_map.get(&self.cfg) {
|
|
retval
|
|
} else {
|
|
args.errors.error(self.cfg, "unrecognized cfg -- cfg wasn't evaluated when running `__cfg_expansion_helper!`");
|
|
true
|
|
}
|
|
}
|
|
}
|
|
P::dispatch(
|
|
MyDispatch {
|
|
cfg,
|
|
_phantom: PhantomData,
|
|
},
|
|
self,
|
|
)
|
|
}
|
|
#[must_use]
|
|
fn eval_cfgs(
|
|
&mut self,
|
|
mut attrs: Vec<syn::Attribute>,
|
|
) -> Option<Output<Vec<syn::Attribute>, P>> {
|
|
let mut queue = VecDeque::from(attrs);
|
|
attrs = Vec::with_capacity(queue.len()); // cfg_attr is rare, and cfg can't increase length
|
|
while let Some(attr) = queue.pop_front() {
|
|
if attr.path().is_ident("cfg") {
|
|
if let Some(cfg) = self.errors.ok(Cfg::parse_meta(&attr.meta)) {
|
|
if !self.eval_cfg(cfg) {
|
|
return None;
|
|
}
|
|
continue;
|
|
}
|
|
} else if attr.path().is_ident("cfg_attr") {
|
|
if let Some(cfg_attr) = self.errors.ok(CfgAttr::parse_meta(&attr.meta)) {
|
|
if self.eval_cfg(cfg_attr.to_cfg()) {
|
|
// push onto queue since cfg_attr(<cond1>, cfg_attr(<cond2>, <attr>)) is valid
|
|
for meta in cfg_attr.attrs {
|
|
queue.push_front(syn::Attribute {
|
|
pound_token: attr.pound_token,
|
|
style: attr.style,
|
|
bracket_token: attr.bracket_token,
|
|
meta,
|
|
});
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
attrs.push(attr);
|
|
}
|
|
Some(Output::new(attrs))
|
|
}
|
|
fn process_qself_and_path(
|
|
&mut self,
|
|
qself: Option<syn::QSelf>,
|
|
path: syn::Path,
|
|
) -> Option<(Output<Option<syn::QSelf>, P>, Output<syn::Path, P>)> {
|
|
let qself = if let Some(syn::QSelf {
|
|
lt_token,
|
|
ty,
|
|
position,
|
|
as_token,
|
|
gt_token,
|
|
}) = qself
|
|
{
|
|
ty.process(self)?.map(|ty| {
|
|
Some(syn::QSelf {
|
|
lt_token,
|
|
ty,
|
|
position,
|
|
as_token,
|
|
gt_token,
|
|
})
|
|
})
|
|
} else {
|
|
Output::new(None)
|
|
};
|
|
let syn::Path {
|
|
leading_colon,
|
|
segments,
|
|
} = path;
|
|
// path segments don't get removed
|
|
let path = segments.process(self)?.map(|segments| syn::Path {
|
|
leading_colon,
|
|
segments,
|
|
});
|
|
Some((qself, path))
|
|
}
|
|
}
|
|
|
|
trait PhaseDispatch {
|
|
type Args<P: Phase>;
|
|
type Output<P: Phase>;
|
|
fn dispatch_collect(self, args: Self::Args<CollectCfgsPhase>)
|
|
-> Self::Output<CollectCfgsPhase>;
|
|
fn dispatch_process(self, args: Self::Args<ProcessCfgsPhase>)
|
|
-> Self::Output<ProcessCfgsPhase>;
|
|
}
|
|
|
|
trait Phase: Sized + 'static {
|
|
type Output<T>;
|
|
type CfgsValue;
|
|
fn output_new<T>(v: T) -> Output<T, Self>;
|
|
fn output_map<T, U, F: FnOnce(T) -> U>(v: Output<T, Self>, f: F) -> Output<U, Self>;
|
|
fn output_zip<T, U>(t: Output<T, Self>, u: Output<U, Self>) -> Output<(T, U), Self>;
|
|
fn dispatch<D: PhaseDispatch>(d: D, args: D::Args<Self>) -> D::Output<Self>;
|
|
}
|
|
|
|
struct CollectCfgsPhase;
|
|
|
|
impl Phase for CollectCfgsPhase {
|
|
type Output<T> = ();
|
|
type CfgsValue = ();
|
|
|
|
fn output_new<T>(_v: T) -> Output<T, Self> {
|
|
Output(())
|
|
}
|
|
|
|
fn output_map<T, U, F: FnOnce(T) -> U>(_v: Output<T, Self>, _f: F) -> Output<U, Self> {
|
|
Output(())
|
|
}
|
|
|
|
fn output_zip<T, U>(_t: Output<T, Self>, _u: Output<U, Self>) -> Output<(T, U), Self> {
|
|
Output(())
|
|
}
|
|
|
|
fn dispatch<D: PhaseDispatch>(d: D, args: D::Args<Self>) -> D::Output<Self> {
|
|
d.dispatch_collect(args)
|
|
}
|
|
}
|
|
|
|
struct ProcessCfgsPhase;
|
|
|
|
impl Phase for ProcessCfgsPhase {
|
|
type Output<T> = T;
|
|
type CfgsValue = bool;
|
|
|
|
fn output_new<T>(v: T) -> Output<T, Self> {
|
|
Output(v)
|
|
}
|
|
|
|
fn output_map<T, U, F: FnOnce(T) -> U>(v: Output<T, Self>, f: F) -> Output<U, Self> {
|
|
Output(f(v.0))
|
|
}
|
|
|
|
fn output_zip<T, U>(t: Output<T, Self>, u: Output<U, Self>) -> Output<(T, U), Self> {
|
|
Output((t.0, u.0))
|
|
}
|
|
|
|
fn dispatch<D: PhaseDispatch>(d: D, args: D::Args<Self>) -> D::Output<Self> {
|
|
d.dispatch_process(args)
|
|
}
|
|
}
|
|
|
|
struct Output<T, P: Phase>(P::Output<T>);
|
|
|
|
trait OutputZip<P: Phase>: Sized {
|
|
type Output;
|
|
fn zip(self) -> Output<Self::Output, P>;
|
|
fn call<R, F: FnOnce(Self::Output) -> R>(self, f: F) -> Output<R, P> {
|
|
self.zip().map(f)
|
|
}
|
|
}
|
|
|
|
impl<P: Phase> OutputZip<P> for () {
|
|
type Output = ();
|
|
|
|
fn zip(self) -> Output<Self::Output, P> {
|
|
Output::new(())
|
|
}
|
|
}
|
|
|
|
impl<P: Phase, T> OutputZip<P> for (Output<T, P>,) {
|
|
type Output = (T,);
|
|
|
|
fn zip(self) -> Output<Self::Output, P> {
|
|
self.0.map(|v| (v,))
|
|
}
|
|
}
|
|
|
|
macro_rules! impl_zip {
|
|
($first_arg:ident: $first_T:ident, $($arg:ident: $T:ident),* $(,)?) => {
|
|
impl_zip!(@step [], [($first_arg: $first_T) $(($arg: $T))*], (),);
|
|
};
|
|
(
|
|
@impl($first_arg:tt,),
|
|
$tuple_pat:tt,
|
|
) => {};
|
|
(
|
|
@impl(($first_arg:ident: $first_T:ident),
|
|
$(($arg:ident: $T:ident),)*),
|
|
$tuple_pat:tt,
|
|
) => {
|
|
impl<$first_T, $($T,)* P: Phase> OutputZip<P> for (Output<$first_T, P>, $(Output<$T, P>),*) {
|
|
type Output = ($first_T, $($T),*);
|
|
fn zip(self) -> Output<($first_T, $($T),*), P> {
|
|
let (tuples, $($arg),*) = self;
|
|
$(let tuples = P::output_zip(tuples, $arg);)*
|
|
tuples.map(|$tuple_pat| ($first_arg, $($arg),*))
|
|
}
|
|
}
|
|
};
|
|
(
|
|
@step [$($cur:tt)*],
|
|
[],
|
|
$tuple_pat:tt,
|
|
) => {};
|
|
(
|
|
@step [$($cur:tt)*],
|
|
[($next_arg:ident: $next_T:ident) $($rest:tt)*],
|
|
(),
|
|
) => {
|
|
impl_zip!(@impl($($cur,)* ($next_arg: $next_T),), $next_arg,);
|
|
impl_zip!(@step [$($cur)* ($next_arg: $next_T)], [$($rest)*], $next_arg,);
|
|
};
|
|
(
|
|
@step [$($cur:tt)*],
|
|
[($next_arg:ident: $next_T:ident) $($rest:tt)*],
|
|
$tuple_pat:tt,
|
|
) => {
|
|
impl_zip!(@impl($($cur,)* ($next_arg: $next_T),), ($tuple_pat, $next_arg),);
|
|
impl_zip!(@step [$($cur)* ($next_arg: $next_T)], [$($rest)*], ($tuple_pat, $next_arg),);
|
|
};
|
|
}
|
|
|
|
impl_zip!(t0: T0, t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8, t9: T9, t10: T10, t11: T11);
|
|
|
|
impl<T, P: Phase> Copy for Output<T, P> where P::Output<T>: Copy {}
|
|
|
|
impl<T, P: Phase> Clone for Output<T, P>
|
|
where
|
|
P::Output<T>: Clone,
|
|
{
|
|
fn clone(&self) -> Self {
|
|
Self(self.0.clone())
|
|
}
|
|
}
|
|
|
|
impl<T, P: Phase> Output<T, P> {
|
|
fn new(v: T) -> Self {
|
|
P::output_new(v)
|
|
}
|
|
fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Output<U, P> {
|
|
P::output_map(self, f)
|
|
}
|
|
}
|
|
|
|
trait Process<P: Phase>: Sized {
|
|
#[must_use]
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>>;
|
|
}
|
|
|
|
impl<P: Phase> Process<P> for syn::Item {
|
|
fn process(self, _state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
// don't recurse into items
|
|
Some(Output::new(self))
|
|
}
|
|
}
|
|
|
|
impl<P: Phase> Process<P> for Vec<syn::Attribute> {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
state.eval_cfgs(self)
|
|
}
|
|
}
|
|
|
|
impl<T: Process<P>, P: Phase> Process<P> for Box<T> {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
Some(T::process(*self, state)?.map(Box::new))
|
|
}
|
|
}
|
|
|
|
trait ProcessVecElement {
|
|
const REMOVE_ELEMENTS: bool;
|
|
}
|
|
|
|
impl ProcessVecElement for syn::Arm {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessVecElement for syn::Stmt {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessVecElement for syn::ForeignItem {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessVecElement for syn::ImplItem {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessVecElement for syn::Item {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessVecElement for syn::TraitItem {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl<T: Process<P> + ProcessVecElement, P: Phase> Process<P> for Vec<T> {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
let mut output = Output::new(Vec::new());
|
|
for value in self {
|
|
if let Some(value) = value.process(state) {
|
|
output = (output, value).call(|(mut output, value)| {
|
|
output.push(value);
|
|
output
|
|
});
|
|
} else if !T::REMOVE_ELEMENTS {
|
|
return None;
|
|
}
|
|
}
|
|
Some(output)
|
|
}
|
|
}
|
|
|
|
trait ProcessOption {
|
|
/// if a configured-off value causes this value to be `None` instead of propagating the configuring-off
|
|
const REMOVE_VALUE: bool;
|
|
}
|
|
|
|
impl ProcessOption for syn::Abi {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::Block {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::WhereClause {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::Expr {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::Type {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for Box<syn::Expr> {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::AngleBracketedGenericArguments {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::ImplRestriction {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
|
|
impl ProcessOption for syn::BoundLifetimes {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
|
|
impl ProcessOption for (Token![=], syn::Expr) {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Token![=], syn::Type) {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Token![if], Box<syn::Expr>) {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Token![else], Box<syn::Expr>) {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Token![&], Option<syn::Lifetime>) {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Token![as], Ident) {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Ident, Token![:]) {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Option<Token![!]>, syn::Path, Token![for]) {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
|
|
impl ProcessOption for syn::BareVariadic {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::Variadic {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::LocalInit {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
|
|
impl ProcessOption for syn::Label {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for syn::PatRest {
|
|
const REMOVE_VALUE: bool = true;
|
|
}
|
|
|
|
impl ProcessOption for (Box<syn::Pat>, Token![:]) {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
|
|
impl ProcessOption for (Token![@], Box<syn::Pat>) {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
|
|
impl ProcessOption for (syn::token::Brace, Vec<syn::Item>) {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
|
|
impl<T: Process<P> + ProcessOption, P: Phase> Process<P> for Option<T> {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
if let Some(this) = self {
|
|
match this.process(state) {
|
|
Some(v) => Some(v.map(Some)),
|
|
None => {
|
|
if T::REMOVE_VALUE {
|
|
Some(Output::new(None))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
Some(Output::new(None))
|
|
}
|
|
}
|
|
}
|
|
|
|
trait ProcessPunctuatedElement {
|
|
const REMOVE_ELEMENTS: bool;
|
|
}
|
|
|
|
impl<T: Process<P> + ProcessPunctuatedElement, P: Phase, Punct: Default> Process<P>
|
|
for Punctuated<T, Punct>
|
|
{
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
let mut output = Output::new(Punctuated::<T, Punct>::new());
|
|
for pair in self.into_pairs() {
|
|
let (value, punct) = pair.into_tuple();
|
|
if let Some(value) = value.process(state) {
|
|
output = (output, value).call(|(mut output, value)| {
|
|
output.extend([Pair::new(value, punct)]);
|
|
output
|
|
});
|
|
} else if !T::REMOVE_ELEMENTS {
|
|
return None;
|
|
}
|
|
}
|
|
Some(output)
|
|
}
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::PathSegment {
|
|
const REMOVE_ELEMENTS: bool = false;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::Type {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::Expr {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::Pat {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::CapturedParam {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::GenericArgument {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::GenericParam {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::Lifetime {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::WherePredicate {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::Variant {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::FnArg {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::BareFnArg {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::TypeParamBound {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::FieldValue {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::Field {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::FieldPat {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl ProcessPunctuatedElement for syn::UseTree {
|
|
const REMOVE_ELEMENTS: bool = true;
|
|
}
|
|
|
|
impl<T: Process<P>, U: Process<P>, P: Phase> Process<P> for (T, U) {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
let (t, u) = self;
|
|
let t = t.process(state)?;
|
|
let u = u.process(state)?;
|
|
Some((t, u).zip())
|
|
}
|
|
}
|
|
|
|
impl<T: Process<P>, U: Process<P>, V: Process<P>, P: Phase> Process<P> for (T, U, V) {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
let (t, u, v) = self;
|
|
let t = t.process(state)?;
|
|
let u = u.process(state)?;
|
|
let v = v.process(state)?;
|
|
Some((t, u, v).zip())
|
|
}
|
|
}
|
|
|
|
macro_rules! process_no_op {
|
|
($ty:ty) => {
|
|
impl<P: Phase> Process<P> for $ty {
|
|
fn process(self, _state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
Some(Output::new(self))
|
|
}
|
|
}
|
|
|
|
impl ProcessOption for $ty {
|
|
const REMOVE_VALUE: bool = false;
|
|
}
|
|
};
|
|
}
|
|
|
|
process_no_op!(Token![Self]);
|
|
process_no_op!(Token![abstract]);
|
|
process_no_op!(Token![as]);
|
|
process_no_op!(Token![async]);
|
|
process_no_op!(Token![auto]);
|
|
process_no_op!(Token![await]);
|
|
process_no_op!(Token![become]);
|
|
process_no_op!(Token![box]);
|
|
process_no_op!(Token![break]);
|
|
process_no_op!(Token![const]);
|
|
process_no_op!(Token![continue]);
|
|
process_no_op!(Token![crate]);
|
|
process_no_op!(Token![default]);
|
|
process_no_op!(Token![do]);
|
|
process_no_op!(Token![dyn]);
|
|
process_no_op!(Token![else]);
|
|
process_no_op!(Token![enum]);
|
|
process_no_op!(Token![extern]);
|
|
process_no_op!(Token![final]);
|
|
process_no_op!(Token![fn]);
|
|
process_no_op!(Token![for]);
|
|
process_no_op!(Token![if]);
|
|
process_no_op!(Token![impl]);
|
|
process_no_op!(Token![in]);
|
|
process_no_op!(Token![let]);
|
|
process_no_op!(Token![loop]);
|
|
process_no_op!(Token![macro]);
|
|
process_no_op!(Token![match]);
|
|
process_no_op!(Token![mod]);
|
|
process_no_op!(Token![move]);
|
|
process_no_op!(Token![mut]);
|
|
process_no_op!(Token![override]);
|
|
process_no_op!(Token![priv]);
|
|
process_no_op!(Token![pub]);
|
|
process_no_op!(Token![raw]);
|
|
process_no_op!(Token![ref]);
|
|
process_no_op!(Token![return]);
|
|
process_no_op!(Token![self]);
|
|
process_no_op!(Token![static]);
|
|
process_no_op!(Token![struct]);
|
|
process_no_op!(Token![super]);
|
|
process_no_op!(Token![trait]);
|
|
process_no_op!(Token![try]);
|
|
process_no_op!(Token![type]);
|
|
process_no_op!(Token![typeof]);
|
|
process_no_op!(Token![union]);
|
|
process_no_op!(Token![unsafe]);
|
|
process_no_op!(Token![unsized]);
|
|
process_no_op!(Token![use]);
|
|
process_no_op!(Token![virtual]);
|
|
process_no_op!(Token![where]);
|
|
process_no_op!(Token![while]);
|
|
process_no_op!(Token![yield]);
|
|
|
|
process_no_op!(Token![!]);
|
|
process_no_op!(Token![!=]);
|
|
process_no_op!(Token![#]);
|
|
process_no_op!(Token![$]);
|
|
process_no_op!(Token![%]);
|
|
process_no_op!(Token![%=]);
|
|
process_no_op!(Token![&]);
|
|
process_no_op!(Token![&&]);
|
|
process_no_op!(Token![&=]);
|
|
process_no_op!(Token![*]);
|
|
process_no_op!(Token![*=]);
|
|
process_no_op!(Token![+]);
|
|
process_no_op!(Token![+=]);
|
|
process_no_op!(Token![,]);
|
|
process_no_op!(Token![-]);
|
|
process_no_op!(Token![-=]);
|
|
process_no_op!(Token![->]);
|
|
process_no_op!(Token![.]);
|
|
process_no_op!(Token![..]);
|
|
process_no_op!(Token![...]);
|
|
process_no_op!(Token![..=]);
|
|
process_no_op!(Token![/]);
|
|
process_no_op!(Token![/=]);
|
|
process_no_op!(Token![:]);
|
|
process_no_op!(Token![::]);
|
|
process_no_op!(Token![;]);
|
|
process_no_op!(Token![<]);
|
|
process_no_op!(Token![<-]);
|
|
process_no_op!(Token![<<]);
|
|
process_no_op!(Token![<<=]);
|
|
process_no_op!(Token![<=]);
|
|
process_no_op!(Token![=]);
|
|
process_no_op!(Token![==]);
|
|
process_no_op!(Token![=>]);
|
|
process_no_op!(Token![>]);
|
|
process_no_op!(Token![>=]);
|
|
process_no_op!(Token![>>]);
|
|
process_no_op!(Token![>>=]);
|
|
process_no_op!(Token![?]);
|
|
process_no_op!(Token![@]);
|
|
process_no_op!(Token![^]);
|
|
process_no_op!(Token![^=]);
|
|
process_no_op!(Token![_]);
|
|
process_no_op!(Token![|]);
|
|
process_no_op!(Token![|=]);
|
|
process_no_op!(Token![||]);
|
|
process_no_op!(Token![~]);
|
|
|
|
process_no_op!(syn::token::Brace);
|
|
process_no_op!(syn::token::Bracket);
|
|
process_no_op!(syn::token::Paren);
|
|
process_no_op!(syn::token::Group);
|
|
|
|
process_no_op!(Ident);
|
|
process_no_op!(syn::Index);
|
|
process_no_op!(syn::Lifetime);
|
|
process_no_op!(syn::LitBool);
|
|
process_no_op!(syn::LitByte);
|
|
process_no_op!(syn::LitByteStr);
|
|
process_no_op!(syn::LitChar);
|
|
process_no_op!(syn::LitCStr);
|
|
process_no_op!(syn::LitFloat);
|
|
process_no_op!(syn::LitInt);
|
|
process_no_op!(syn::LitStr);
|
|
process_no_op!(proc_macro2::TokenStream);
|
|
process_no_op!(proc_macro2::Literal);
|
|
|
|
macro_rules! process_struct {
|
|
($ty:path {
|
|
$($field:ident,)*
|
|
}) => {
|
|
impl<P: Phase> Process<P> for $ty {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
let Self {
|
|
$($field,)*
|
|
} = self;
|
|
$(let $field = $field.process(state)?;)*
|
|
Some(($($field,)*).call(|($($field,)*)| Self {
|
|
$($field,)*
|
|
}))
|
|
}
|
|
}
|
|
};
|
|
($ty:path {
|
|
$($fields_before:ident,)*
|
|
#[qself]
|
|
$qself:ident,
|
|
$path:ident,
|
|
$($fields_after:ident,)*
|
|
}) => {
|
|
impl<P: Phase> Process<P> for $ty {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
let Self {
|
|
$($fields_before,)*
|
|
$qself,
|
|
$path,
|
|
$($fields_after,)*
|
|
} = self;
|
|
$(let $fields_before = $fields_before.process(state)?;)*
|
|
let ($qself, $path) = state.process_qself_and_path($qself, $path)?;
|
|
$(let $fields_after = $fields_after.process(state)?;)*
|
|
Some((
|
|
$($fields_before,)*
|
|
$qself,
|
|
$path,
|
|
$($fields_after,)*
|
|
).call(|(
|
|
$($fields_before,)*
|
|
$qself,
|
|
$path,
|
|
$($fields_after,)*
|
|
)| Self {
|
|
$($fields_before,)*
|
|
$qself,
|
|
$path,
|
|
$($fields_after,)*
|
|
}))
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Abi {
|
|
extern_token,
|
|
name,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::AngleBracketedGenericArguments {
|
|
colon2_token,
|
|
lt_token,
|
|
args,
|
|
gt_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Arm {
|
|
attrs,
|
|
pat,
|
|
guard,
|
|
fat_arrow_token,
|
|
body,
|
|
comma,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::AssocConst {
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
value,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::AssocType {
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
ty,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::BareFnArg {
|
|
attrs,
|
|
name,
|
|
ty,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::BareVariadic {
|
|
attrs,
|
|
name,
|
|
dots,
|
|
comma,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Block {
|
|
brace_token,
|
|
stmts,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::BoundLifetimes {
|
|
for_token,
|
|
lt_token,
|
|
lifetimes,
|
|
gt_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ConstParam {
|
|
attrs,
|
|
const_token,
|
|
ident,
|
|
colon_token,
|
|
ty,
|
|
eq_token,
|
|
default,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Constraint {
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::DataEnum {
|
|
enum_token,
|
|
brace_token,
|
|
variants,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::DataStruct {
|
|
struct_token,
|
|
fields,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::DataUnion {
|
|
union_token,
|
|
fields,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::DeriveInput {
|
|
attrs,
|
|
vis,
|
|
ident,
|
|
generics,
|
|
data,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprArray {
|
|
attrs,
|
|
bracket_token,
|
|
elems,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprAssign {
|
|
attrs,
|
|
left,
|
|
eq_token,
|
|
right,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprAsync {
|
|
attrs,
|
|
async_token,
|
|
capture,
|
|
block,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprAwait {
|
|
attrs,
|
|
base,
|
|
dot_token,
|
|
await_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprBinary {
|
|
attrs,
|
|
left,
|
|
op,
|
|
right,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprBlock {
|
|
attrs,
|
|
label,
|
|
block,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprBreak {
|
|
attrs,
|
|
break_token,
|
|
label,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprCall {
|
|
attrs,
|
|
func,
|
|
paren_token,
|
|
args,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprCast {
|
|
attrs,
|
|
expr,
|
|
as_token,
|
|
ty,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprClosure {
|
|
attrs,
|
|
lifetimes,
|
|
constness,
|
|
movability,
|
|
asyncness,
|
|
capture,
|
|
or1_token,
|
|
inputs,
|
|
or2_token,
|
|
output,
|
|
body,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprConst {
|
|
attrs,
|
|
const_token,
|
|
block,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprContinue {
|
|
attrs,
|
|
continue_token,
|
|
label,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprField {
|
|
attrs,
|
|
base,
|
|
dot_token,
|
|
member,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprForLoop {
|
|
attrs,
|
|
label,
|
|
for_token,
|
|
pat,
|
|
in_token,
|
|
expr,
|
|
body,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprGroup {
|
|
attrs,
|
|
group_token,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprIf {
|
|
attrs,
|
|
if_token,
|
|
cond,
|
|
then_branch,
|
|
else_branch,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprIndex {
|
|
attrs,
|
|
expr,
|
|
bracket_token,
|
|
index,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprInfer {
|
|
attrs,
|
|
underscore_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprLet {
|
|
attrs,
|
|
let_token,
|
|
pat,
|
|
eq_token,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprLit {
|
|
attrs,
|
|
lit,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprLoop {
|
|
attrs,
|
|
label,
|
|
loop_token,
|
|
body,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprMacro {
|
|
attrs,
|
|
mac,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprMatch {
|
|
attrs,
|
|
match_token,
|
|
expr,
|
|
brace_token,
|
|
arms,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprMethodCall {
|
|
attrs,
|
|
receiver,
|
|
dot_token,
|
|
method,
|
|
turbofish,
|
|
paren_token,
|
|
args,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprParen {
|
|
attrs,
|
|
paren_token,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprPath {
|
|
attrs,
|
|
#[qself]
|
|
qself,
|
|
path,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprRange {
|
|
attrs,
|
|
start,
|
|
limits,
|
|
end,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprRawAddr {
|
|
attrs,
|
|
and_token,
|
|
raw,
|
|
mutability,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprReference {
|
|
attrs,
|
|
and_token,
|
|
mutability,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprRepeat {
|
|
attrs,
|
|
bracket_token,
|
|
expr,
|
|
semi_token,
|
|
len,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprReturn {
|
|
attrs,
|
|
return_token,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprStruct {
|
|
attrs,
|
|
#[qself]
|
|
qself,
|
|
path,
|
|
brace_token,
|
|
fields,
|
|
dot2_token,
|
|
rest,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprTry {
|
|
attrs,
|
|
expr,
|
|
question_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprTryBlock {
|
|
attrs,
|
|
try_token,
|
|
block,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprTuple {
|
|
attrs,
|
|
paren_token,
|
|
elems,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprUnary {
|
|
attrs,
|
|
op,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprUnsafe {
|
|
attrs,
|
|
unsafe_token,
|
|
block,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprWhile {
|
|
attrs,
|
|
label,
|
|
while_token,
|
|
cond,
|
|
body,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ExprYield {
|
|
attrs,
|
|
yield_token,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Field {
|
|
attrs,
|
|
vis,
|
|
mutability,
|
|
ident,
|
|
colon_token,
|
|
ty,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::FieldPat {
|
|
attrs,
|
|
member,
|
|
colon_token,
|
|
pat,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::FieldValue {
|
|
attrs,
|
|
member,
|
|
colon_token,
|
|
expr,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::FieldsNamed {
|
|
brace_token,
|
|
named,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::FieldsUnnamed {
|
|
paren_token,
|
|
unnamed,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ForeignItemFn {
|
|
attrs,
|
|
vis,
|
|
sig,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ForeignItemMacro {
|
|
attrs,
|
|
mac,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ForeignItemStatic {
|
|
attrs,
|
|
vis,
|
|
static_token,
|
|
mutability,
|
|
ident,
|
|
colon_token,
|
|
ty,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ForeignItemType {
|
|
attrs,
|
|
vis,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Generics {
|
|
lt_token,
|
|
params,
|
|
gt_token,
|
|
where_clause,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ImplItemConst {
|
|
attrs,
|
|
vis,
|
|
defaultness,
|
|
const_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
ty,
|
|
eq_token,
|
|
expr,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ImplItemFn {
|
|
attrs,
|
|
vis,
|
|
defaultness,
|
|
sig,
|
|
block,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ImplItemMacro {
|
|
attrs,
|
|
mac,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ImplItemType {
|
|
attrs,
|
|
vis,
|
|
defaultness,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
ty,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemConst {
|
|
attrs,
|
|
vis,
|
|
const_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
ty,
|
|
eq_token,
|
|
expr,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemEnum {
|
|
attrs,
|
|
vis,
|
|
enum_token,
|
|
ident,
|
|
generics,
|
|
brace_token,
|
|
variants,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemExternCrate {
|
|
attrs,
|
|
vis,
|
|
extern_token,
|
|
crate_token,
|
|
ident,
|
|
rename,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemFn {
|
|
attrs,
|
|
vis,
|
|
sig,
|
|
block,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemForeignMod {
|
|
attrs,
|
|
unsafety,
|
|
abi,
|
|
brace_token,
|
|
items,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemImpl {
|
|
attrs,
|
|
defaultness,
|
|
unsafety,
|
|
impl_token,
|
|
generics,
|
|
trait_,
|
|
self_ty,
|
|
brace_token,
|
|
items,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemMacro {
|
|
attrs,
|
|
ident,
|
|
mac,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemMod {
|
|
attrs,
|
|
vis,
|
|
unsafety,
|
|
mod_token,
|
|
ident,
|
|
content,
|
|
semi,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemStatic {
|
|
attrs,
|
|
vis,
|
|
static_token,
|
|
mutability,
|
|
ident,
|
|
colon_token,
|
|
ty,
|
|
eq_token,
|
|
expr,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemStruct {
|
|
attrs,
|
|
vis,
|
|
struct_token,
|
|
ident,
|
|
generics,
|
|
fields,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemTrait {
|
|
attrs,
|
|
vis,
|
|
unsafety,
|
|
auto_token,
|
|
restriction,
|
|
trait_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
supertraits,
|
|
brace_token,
|
|
items,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemTraitAlias {
|
|
attrs,
|
|
vis,
|
|
trait_token,
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
bounds,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemType {
|
|
attrs,
|
|
vis,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
eq_token,
|
|
ty,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemUnion {
|
|
attrs,
|
|
vis,
|
|
union_token,
|
|
ident,
|
|
generics,
|
|
fields,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ItemUse {
|
|
attrs,
|
|
vis,
|
|
use_token,
|
|
leading_colon,
|
|
tree,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Label {
|
|
name,
|
|
colon_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::LifetimeParam {
|
|
attrs,
|
|
lifetime,
|
|
colon_token,
|
|
bounds,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Local {
|
|
attrs,
|
|
let_token,
|
|
pat,
|
|
init,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::LocalInit {
|
|
eq_token,
|
|
expr,
|
|
diverge,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Macro {
|
|
path,
|
|
bang_token,
|
|
delimiter,
|
|
tokens,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::MetaList {
|
|
path,
|
|
delimiter,
|
|
tokens,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::MetaNameValue {
|
|
path,
|
|
eq_token,
|
|
value,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::ParenthesizedGenericArguments {
|
|
paren_token,
|
|
inputs,
|
|
output,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatIdent {
|
|
attrs,
|
|
by_ref,
|
|
mutability,
|
|
ident,
|
|
subpat,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatOr {
|
|
attrs,
|
|
leading_vert,
|
|
cases,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatParen {
|
|
attrs,
|
|
paren_token,
|
|
pat,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatReference {
|
|
attrs,
|
|
and_token,
|
|
mutability,
|
|
pat,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatRest {
|
|
attrs,
|
|
dot2_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatSlice {
|
|
attrs,
|
|
bracket_token,
|
|
elems,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatStruct {
|
|
attrs,
|
|
#[qself]
|
|
qself,
|
|
path,
|
|
brace_token,
|
|
fields,
|
|
rest,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatTuple {
|
|
attrs,
|
|
paren_token,
|
|
elems,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatTupleStruct {
|
|
attrs,
|
|
#[qself]
|
|
qself,
|
|
path,
|
|
paren_token,
|
|
elems,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatType {
|
|
attrs,
|
|
pat,
|
|
colon_token,
|
|
ty,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PatWild {
|
|
attrs,
|
|
underscore_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Path {
|
|
leading_colon,
|
|
segments,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PathSegment {
|
|
ident,
|
|
arguments,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PreciseCapture {
|
|
use_token,
|
|
lt_token,
|
|
params,
|
|
gt_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PredicateLifetime {
|
|
lifetime,
|
|
colon_token,
|
|
bounds,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::PredicateType {
|
|
lifetimes,
|
|
bounded_ty,
|
|
colon_token,
|
|
bounds,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Receiver {
|
|
attrs,
|
|
reference,
|
|
mutability,
|
|
self_token,
|
|
colon_token,
|
|
ty,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Signature {
|
|
constness,
|
|
asyncness,
|
|
unsafety,
|
|
abi,
|
|
fn_token,
|
|
ident,
|
|
generics,
|
|
paren_token,
|
|
inputs,
|
|
variadic,
|
|
output,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::StmtMacro {
|
|
attrs,
|
|
mac,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TraitBound {
|
|
paren_token,
|
|
modifier,
|
|
lifetimes,
|
|
path,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TraitItemConst {
|
|
attrs,
|
|
const_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
ty,
|
|
default,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TraitItemFn {
|
|
attrs,
|
|
sig,
|
|
default,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TraitItemMacro {
|
|
attrs,
|
|
mac,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TraitItemType {
|
|
attrs,
|
|
type_token,
|
|
ident,
|
|
generics,
|
|
colon_token,
|
|
bounds,
|
|
default,
|
|
semi_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeArray {
|
|
bracket_token,
|
|
elem,
|
|
semi_token,
|
|
len,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeBareFn {
|
|
lifetimes,
|
|
unsafety,
|
|
abi,
|
|
fn_token,
|
|
paren_token,
|
|
inputs,
|
|
variadic,
|
|
output,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeGroup {
|
|
group_token,
|
|
elem,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeImplTrait {
|
|
impl_token,
|
|
bounds,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeInfer {
|
|
underscore_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeMacro {
|
|
mac,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeNever {
|
|
bang_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeParam {
|
|
attrs,
|
|
ident,
|
|
colon_token,
|
|
bounds,
|
|
eq_token,
|
|
default,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeParen {
|
|
paren_token,
|
|
elem,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypePath {
|
|
#[qself]
|
|
qself,
|
|
path,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypePtr {
|
|
star_token,
|
|
const_token,
|
|
mutability,
|
|
elem,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeReference {
|
|
and_token,
|
|
lifetime,
|
|
mutability,
|
|
elem,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeSlice {
|
|
bracket_token,
|
|
elem,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeTraitObject {
|
|
dyn_token,
|
|
bounds,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::TypeTuple {
|
|
paren_token,
|
|
elems,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::UseGlob {
|
|
star_token,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::UseGroup {
|
|
brace_token,
|
|
items,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::UseName {
|
|
ident,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::UsePath {
|
|
ident,
|
|
colon2_token,
|
|
tree,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::UseRename {
|
|
ident,
|
|
as_token,
|
|
rename,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Variadic {
|
|
attrs,
|
|
pat,
|
|
dots,
|
|
comma,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::Variant {
|
|
attrs,
|
|
ident,
|
|
fields,
|
|
discriminant,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::VisRestricted {
|
|
pub_token,
|
|
paren_token,
|
|
in_token,
|
|
path,
|
|
}
|
|
}
|
|
|
|
process_struct! {
|
|
syn::WhereClause {
|
|
where_token,
|
|
predicates,
|
|
}
|
|
}
|
|
|
|
macro_rules! process_enum {
|
|
($path:path {
|
|
$($variant:ident$(($($field:ident),* $(,)?))?,)*
|
|
}) => {
|
|
impl<P: Phase> Process<P> for $path {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
match self {
|
|
$(Self::$variant$(($($field),*))? => Some(($($($field.process(state)?,)*)?).call(|($($($field,)*)?)| Self::$variant$(($($field),*))?)),)*
|
|
}
|
|
}
|
|
}
|
|
};
|
|
($path:path {
|
|
$($variant:ident$(($($field:ident),* $(,)?))?,)*
|
|
#[no_op]
|
|
_,
|
|
}) => {
|
|
impl<P: Phase> Process<P> for $path {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
#![allow(unused_variables)]
|
|
match self {
|
|
$(Self::$variant$(($($field),*))? => Some(($($($field.process(state)?,)*)?).call(|($($($field,)*)?)| Self::$variant$(($($field),*))?)),)*
|
|
_ => Some(Output::new(self)),
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
process_enum! {
|
|
syn::AttrStyle {
|
|
Outer,
|
|
Inner(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::BinOp {
|
|
Add(f0),
|
|
Sub(f0),
|
|
Mul(f0),
|
|
Div(f0),
|
|
Rem(f0),
|
|
And(f0),
|
|
Or(f0),
|
|
BitXor(f0),
|
|
BitAnd(f0),
|
|
BitOr(f0),
|
|
Shl(f0),
|
|
Shr(f0),
|
|
Eq(f0),
|
|
Lt(f0),
|
|
Le(f0),
|
|
Ne(f0),
|
|
Ge(f0),
|
|
Gt(f0),
|
|
AddAssign(f0),
|
|
SubAssign(f0),
|
|
MulAssign(f0),
|
|
DivAssign(f0),
|
|
RemAssign(f0),
|
|
BitXorAssign(f0),
|
|
BitAndAssign(f0),
|
|
BitOrAssign(f0),
|
|
ShlAssign(f0),
|
|
ShrAssign(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::CapturedParam {
|
|
Lifetime(f0),
|
|
Ident(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Data {
|
|
Struct(f0),
|
|
Enum(f0),
|
|
Union(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Expr {
|
|
Array(f0),
|
|
Assign(f0),
|
|
Async(f0),
|
|
Await(f0),
|
|
Binary(f0),
|
|
Block(f0),
|
|
Break(f0),
|
|
Call(f0),
|
|
Cast(f0),
|
|
Closure(f0),
|
|
Const(f0),
|
|
Continue(f0),
|
|
Field(f0),
|
|
ForLoop(f0),
|
|
Group(f0),
|
|
If(f0),
|
|
Index(f0),
|
|
Infer(f0),
|
|
Let(f0),
|
|
Lit(f0),
|
|
Loop(f0),
|
|
Macro(f0),
|
|
Match(f0),
|
|
MethodCall(f0),
|
|
Paren(f0),
|
|
Path(f0),
|
|
Range(f0),
|
|
RawAddr(f0),
|
|
Reference(f0),
|
|
Repeat(f0),
|
|
Return(f0),
|
|
Struct(f0),
|
|
Try(f0),
|
|
TryBlock(f0),
|
|
Tuple(f0),
|
|
Unary(f0),
|
|
Unsafe(f0),
|
|
Verbatim(f0),
|
|
While(f0),
|
|
Yield(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::FieldMutability {
|
|
None,
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Fields {
|
|
Named(f0),
|
|
Unnamed(f0),
|
|
Unit,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::FnArg {
|
|
Receiver(f0),
|
|
Typed(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::ForeignItem {
|
|
Fn(f0),
|
|
Static(f0),
|
|
Type(f0),
|
|
Macro(f0),
|
|
Verbatim(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::GenericArgument {
|
|
Lifetime(f0),
|
|
Type(f0),
|
|
Const(f0),
|
|
AssocType(f0),
|
|
AssocConst(f0),
|
|
Constraint(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::GenericParam {
|
|
Lifetime(f0),
|
|
Type(f0),
|
|
Const(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::ImplItem {
|
|
Const(f0),
|
|
Fn(f0),
|
|
Type(f0),
|
|
Macro(f0),
|
|
Verbatim(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::ImplRestriction {
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Lit {
|
|
Str(f0),
|
|
ByteStr(f0),
|
|
CStr(f0),
|
|
Byte(f0),
|
|
Char(f0),
|
|
Int(f0),
|
|
Float(f0),
|
|
Bool(f0),
|
|
Verbatim(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::MacroDelimiter {
|
|
Paren(f0),
|
|
Brace(f0),
|
|
Bracket(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Member {
|
|
Named(f0),
|
|
Unnamed(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Meta {
|
|
Path(f0),
|
|
List(f0),
|
|
NameValue(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Pat {
|
|
Const(f0),
|
|
Ident(f0),
|
|
Lit(f0),
|
|
Macro(f0),
|
|
Or(f0),
|
|
Paren(f0),
|
|
Path(f0),
|
|
Range(f0),
|
|
Reference(f0),
|
|
Rest(f0),
|
|
Slice(f0),
|
|
Struct(f0),
|
|
Tuple(f0),
|
|
TupleStruct(f0),
|
|
Type(f0),
|
|
Verbatim(f0),
|
|
Wild(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::PathArguments {
|
|
None,
|
|
AngleBracketed(f0),
|
|
Parenthesized(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::PointerMutability {
|
|
Const(f0),
|
|
Mut(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::RangeLimits {
|
|
HalfOpen(f0),
|
|
Closed(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::ReturnType {
|
|
Default,
|
|
Type(f0, f1),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::StaticMutability {
|
|
Mut(f0),
|
|
None,
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Stmt {
|
|
Local(f0),
|
|
Item(f0),
|
|
Expr(f0, f1),
|
|
Macro(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::TraitBoundModifier {
|
|
None,
|
|
Maybe(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::TraitItem {
|
|
Const(f0),
|
|
Fn(f0),
|
|
Type(f0),
|
|
Macro(f0),
|
|
Verbatim(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Type {
|
|
Array(f0),
|
|
BareFn(f0),
|
|
Group(f0),
|
|
ImplTrait(f0),
|
|
Infer(f0),
|
|
Macro(f0),
|
|
Never(f0),
|
|
Paren(f0),
|
|
Path(f0),
|
|
Ptr(f0),
|
|
Reference(f0),
|
|
Slice(f0),
|
|
TraitObject(f0),
|
|
Tuple(f0),
|
|
Verbatim(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::TypeParamBound {
|
|
Trait(f0),
|
|
Lifetime(f0),
|
|
PreciseCapture(f0),
|
|
Verbatim(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::UnOp {
|
|
Deref(f0),
|
|
Not(f0),
|
|
Neg(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::UseTree {
|
|
Path(f0),
|
|
Name(f0),
|
|
Rename(f0),
|
|
Glob(f0),
|
|
Group(f0),
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::Visibility {
|
|
Public(f0),
|
|
Restricted(f0),
|
|
Inherited,
|
|
}
|
|
}
|
|
|
|
process_enum! {
|
|
syn::WherePredicate {
|
|
Lifetime(f0),
|
|
Type(f0),
|
|
#[no_op]
|
|
_,
|
|
}
|
|
}
|
|
|
|
struct TopItem(syn::Item);
|
|
|
|
impl<P: Phase> Process<P> for TopItem {
|
|
fn process(self, state: &mut State<P>) -> Option<Output<Self, P>> {
|
|
match self.0 {
|
|
syn::Item::Const(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Enum(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::ExternCrate(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Fn(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::ForeignMod(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Impl(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Macro(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Mod(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Static(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Struct(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Trait(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::TraitAlias(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Type(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Union(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
syn::Item::Use(item) => Some(item.process(state)?.map(Into::into).map(TopItem)),
|
|
_ => Some(Output::new(self)),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn process_cfgs(item: syn::Item, cfgs: Cfgs<bool>) -> syn::Result<Option<syn::Item>> {
|
|
let mut state = State::<ProcessCfgsPhase> {
|
|
cfgs,
|
|
errors: Errors::new(),
|
|
_phantom: PhantomData,
|
|
};
|
|
let retval = TopItem(item).process(&mut state).map(|v| v.0 .0);
|
|
state.errors.finish()?;
|
|
Ok(retval)
|
|
}
|
|
|
|
pub(crate) fn collect_cfgs(item: syn::Item) -> syn::Result<Cfgs<()>> {
|
|
let mut state = State::<CollectCfgsPhase> {
|
|
cfgs: Cfgs::default(),
|
|
errors: Errors::new(),
|
|
_phantom: PhantomData,
|
|
};
|
|
let (None | Some(Output(()))) = TopItem(item).process(&mut state);
|
|
state.errors.finish()?;
|
|
Ok(state.cfgs)
|
|
}
|