extract attribute filtering

This commit is contained in:
Aleksey Kladov 2019-05-21 18:30:19 +03:00
parent 940eed92a6
commit c816df7208

View file

@ -1,3 +1,5 @@
use std::convert::TryFrom;
use crate::parenthesized::Parenthesized;
use heck::CamelCase;
use proc_macro::TokenStream;
@ -6,8 +8,8 @@ use quote::ToTokens;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{
parse_macro_input, parse_quote, FnArg, Ident, ItemTrait, Lit, MetaNameValue, Path, TypeParamBound,
ReturnType, Token, TraitItem, Type, TraitBound, TraitBoundModifier
parse_macro_input, parse_quote, Attribute, FnArg, Ident, ItemTrait, Lit, MetaNameValue, Path,
ReturnType, Token, TraitBound, TraitBoundModifier, TraitItem, Type, TypeParamBound,
};
/// Implementation for `[salsa::query_group]` decorator.
@ -38,19 +40,8 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
let mut num_storages = 0;
// Extract attributes.
let mut attrs = vec![];
for attr in method.attrs {
// Leave non-salsa attributes untouched. These are
// attributes that don't start with `salsa::` or don't have
// exactly two segments in their path.
if is_not_salsa_attr_path(&attr.path) {
attrs.push(attr);
continue;
}
// Keep the salsa attributes around.
let name = attr.path.segments[1].ident.to_string();
let tts = attr.tts.into();
let (attrs, salsa_attrs) = filter_attrs(method.attrs);
for SalsaAttr { name, tts } in salsa_attrs {
match name.as_str() {
"memoized" => {
storage = QueryStorage::Memoized;
@ -517,6 +508,24 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
output.into()
}
struct SalsaAttr {
name: String,
tts: TokenStream,
}
impl TryFrom<syn::Attribute> for SalsaAttr {
type Error = syn::Attribute;
fn try_from(attr: syn::Attribute) -> Result<SalsaAttr, syn::Attribute> {
if is_not_salsa_attr_path(&attr.path) {
return Err(attr);
}
let name = attr.path.segments[1].ident.to_string();
let tts = attr.tts.into();
Ok(SalsaAttr { name, tts })
}
}
fn is_not_salsa_attr_path(path: &syn::Path) -> bool {
path.segments
.first()
@ -525,6 +534,22 @@ fn is_not_salsa_attr_path(path: &syn::Path) -> bool {
|| path.segments.len() != 2
}
fn filter_attrs(attrs: Vec<Attribute>) -> (Vec<Attribute>, Vec<SalsaAttr>) {
let mut other = vec![];
let mut salsa = vec![];
// Leave non-salsa attributes untouched. These are
// attributes that don't start with `salsa::` or don't have
// exactly two segments in their path.
// Keep the salsa attributes around.
for attr in attrs {
match SalsaAttr::try_from(attr) {
Ok(it) => salsa.push(it),
Err(it) => other.push(it),
}
}
(other, salsa)
}
#[derive(Debug)]
struct GroupDef {
group_struct: Ident,