parser: Unify a bit the attribute code.
This commit is contained in:
parent
8cb6e03cea
commit
6323a5d981
@ -18,7 +18,7 @@ use crate::bindgen::ir::{
|
||||
AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParams, ItemMap,
|
||||
OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
|
||||
};
|
||||
use crate::bindgen::utilities::{SynAbiHelpers, SynItemFnHelpers, SynItemHelpers};
|
||||
use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemFnHelpers};
|
||||
|
||||
const STD_CRATES: &[&str] = &[
|
||||
"std",
|
||||
|
@ -39,7 +39,7 @@ pub fn find_first_some<T>(slice: &[Option<T>]) -> Option<&T> {
|
||||
None
|
||||
}
|
||||
|
||||
pub trait SynItemFnHelpers: SynItemHelpers {
|
||||
pub trait SynItemFnHelpers: SynAttributeHelpers {
|
||||
fn exported_name(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
@ -71,16 +71,52 @@ impl SynItemFnHelpers for syn::ImplItemMethod {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SynItemHelpers {
|
||||
pub trait SynAttributeHelpers {
|
||||
/// Returns the list of attributes for an item.
|
||||
fn attrs(&self) -> &[syn::Attribute];
|
||||
|
||||
/// Searches for attributes like `#[test]`.
|
||||
/// Example:
|
||||
/// - `item.has_attr_word("test")` => `#[test]`
|
||||
fn has_attr_word(&self, name: &str) -> bool;
|
||||
fn has_attr_word(&self, name: &str) -> bool {
|
||||
self.attrs()
|
||||
.iter()
|
||||
.filter_map(|x| x.parse_meta().ok())
|
||||
.any(|attr| {
|
||||
if let syn::Meta::Path(ref path) = attr {
|
||||
path.is_ident(name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Searches for attributes like `#[cfg(test)]`.
|
||||
/// Example:
|
||||
/// - `item.has_attr_list("cfg", &["test"])` => `#[cfg(test)]`
|
||||
fn has_attr_list(&self, name: &str, args: &[&str]) -> bool;
|
||||
fn has_attr_list(&self, name: &str, args: &[&str]) -> bool {
|
||||
self.attrs()
|
||||
.iter()
|
||||
.filter_map(|x| x.parse_meta().ok())
|
||||
.any(|attr| {
|
||||
if let syn::Meta::List(syn::MetaList { path, nested, .. }) = attr {
|
||||
if !path.is_ident(name) {
|
||||
return false;
|
||||
}
|
||||
args.iter().all(|arg| {
|
||||
nested.iter().any(|nested_meta| {
|
||||
if let syn::NestedMeta::Meta(syn::Meta::Path(path)) = nested_meta {
|
||||
path.is_ident(arg)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn is_no_mangle(&self) -> bool {
|
||||
self.has_attr_word("no_mangle")
|
||||
@ -90,58 +126,88 @@ pub trait SynItemHelpers {
|
||||
fn has_test_attr(&self) -> bool {
|
||||
self.has_attr_list("cfg", &["test"]) || self.has_attr_word("test")
|
||||
}
|
||||
|
||||
fn attr_name_value_lookup(&self, name: &str) -> Option<String> {
|
||||
self.attrs()
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
let attr = attr.parse_meta().ok()?;
|
||||
if let syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) = attr
|
||||
{
|
||||
if path.is_ident(name) {
|
||||
return Some(lit.value());
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.next()
|
||||
}
|
||||
|
||||
fn get_comment_lines(&self) -> Vec<String> {
|
||||
let mut comment = Vec::new();
|
||||
|
||||
for attr in self.attrs() {
|
||||
if attr.style == syn::AttrStyle::Outer {
|
||||
if let Ok(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
lit: syn::Lit::Str(content),
|
||||
..
|
||||
})) = attr.parse_meta()
|
||||
{
|
||||
if path.is_ident("doc") {
|
||||
comment.extend(split_doc_attr(&content.value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
comment
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! syn_item_match_helper {
|
||||
($s:ident => has_attrs: |$i:ident| $a:block, otherwise: || $b:block) => {
|
||||
match *$s {
|
||||
syn::Item::Const(ref item) => (|$i: &syn::ItemConst| $a)(item),
|
||||
syn::Item::Enum(ref item) => (|$i: &syn::ItemEnum| $a)(item),
|
||||
syn::Item::ExternCrate(ref item) => (|$i: &syn::ItemExternCrate| $a)(item),
|
||||
syn::Item::Fn(ref item) => (|$i: &syn::ItemFn| $a)(item),
|
||||
syn::Item::ForeignMod(ref item) => (|$i: &syn::ItemForeignMod| $a)(item),
|
||||
syn::Item::Impl(ref item) => (|$i: &syn::ItemImpl| $a)(item),
|
||||
syn::Item::Macro(ref item) => (|$i: &syn::ItemMacro| $a)(item),
|
||||
syn::Item::Macro2(ref item) => (|$i: &syn::ItemMacro2| $a)(item),
|
||||
syn::Item::Mod(ref item) => (|$i: &syn::ItemMod| $a)(item),
|
||||
syn::Item::Static(ref item) => (|$i: &syn::ItemStatic| $a)(item),
|
||||
syn::Item::Struct(ref item) => (|$i: &syn::ItemStruct| $a)(item),
|
||||
syn::Item::Trait(ref item) => (|$i: &syn::ItemTrait| $a)(item),
|
||||
syn::Item::Type(ref item) => (|$i: &syn::ItemType| $a)(item),
|
||||
syn::Item::Union(ref item) => (|$i: &syn::ItemUnion| $a)(item),
|
||||
syn::Item::Use(ref item) => (|$i: &syn::ItemUse| $a)(item),
|
||||
syn::Item::TraitAlias(ref item) => (|$i: &syn::ItemTraitAlias| $a)(item),
|
||||
syn::Item::Verbatim(_) => (|| $b)(),
|
||||
syn::Item::Const(ref $i) => $a,
|
||||
syn::Item::Enum(ref $i) => $a,
|
||||
syn::Item::ExternCrate(ref $i) => $a,
|
||||
syn::Item::Fn(ref $i) => $a,
|
||||
syn::Item::ForeignMod(ref $i) => $a,
|
||||
syn::Item::Impl(ref $i) => $a,
|
||||
syn::Item::Macro(ref $i) => $a,
|
||||
syn::Item::Macro2(ref $i) => $a,
|
||||
syn::Item::Mod(ref $i) => $a,
|
||||
syn::Item::Static(ref $i) => $a,
|
||||
syn::Item::Struct(ref $i) => $a,
|
||||
syn::Item::Trait(ref $i) => $a,
|
||||
syn::Item::Type(ref $i) => $a,
|
||||
syn::Item::Union(ref $i) => $a,
|
||||
syn::Item::Use(ref $i) => $a,
|
||||
syn::Item::TraitAlias(ref $i) => $a,
|
||||
syn::Item::Verbatim(_) => $b,
|
||||
_ => panic!("Unhandled syn::Item: {:?}", $s),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl SynItemHelpers for syn::Item {
|
||||
fn has_attr_word(&self, name: &str) -> bool {
|
||||
impl SynAttributeHelpers for syn::Item {
|
||||
fn attrs(&self) -> &[syn::Attribute] {
|
||||
syn_item_match_helper!(self =>
|
||||
has_attrs: |item| { item.has_attr_word(name) },
|
||||
otherwise: || { false }
|
||||
)
|
||||
}
|
||||
|
||||
fn has_attr_list(&self, name: &str, args: &[&str]) -> bool {
|
||||
syn_item_match_helper!(self =>
|
||||
has_attrs: |item| { item.has_attr_list(name, args) },
|
||||
otherwise: || { false }
|
||||
has_attrs: |item| { &item.attrs },
|
||||
otherwise: || { &[] }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_syn_item_helper {
|
||||
($t:ty) => {
|
||||
impl SynItemHelpers for $t {
|
||||
fn has_attr_word(&self, name: &str) -> bool {
|
||||
self.attrs.has_attr_word(name)
|
||||
}
|
||||
|
||||
fn has_attr_list(&self, name: &str, args: &[&str]) -> bool {
|
||||
self.attrs.has_attr_list(name, args)
|
||||
impl SynAttributeHelpers for $t {
|
||||
fn attrs(&self) -> &[syn::Attribute] {
|
||||
&self.attrs
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -202,83 +268,9 @@ impl SynAbiHelpers for syn::Abi {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SynAttributeHelpers {
|
||||
fn get_comment_lines(&self) -> Vec<String>;
|
||||
fn has_attr_word(&self, name: &str) -> bool;
|
||||
fn has_attr_list(&self, name: &str, args: &[&str]) -> bool;
|
||||
fn attr_name_value_lookup(&self, name: &str) -> Option<String>;
|
||||
}
|
||||
|
||||
impl SynAttributeHelpers for [syn::Attribute] {
|
||||
fn has_attr_word(&self, name: &str) -> bool {
|
||||
self.iter().filter_map(|x| x.parse_meta().ok()).any(|attr| {
|
||||
if let syn::Meta::Path(ref path) = attr {
|
||||
path.is_ident(name)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn has_attr_list(&self, name: &str, args: &[&str]) -> bool {
|
||||
self.iter().filter_map(|x| x.parse_meta().ok()).any(|attr| {
|
||||
if let syn::Meta::List(syn::MetaList { path, nested, .. }) = attr {
|
||||
if !path.is_ident(name) {
|
||||
return false;
|
||||
}
|
||||
args.iter().all(|arg| {
|
||||
nested.iter().any(|nested_meta| {
|
||||
if let syn::NestedMeta::Meta(syn::Meta::Path(path)) = nested_meta {
|
||||
path.is_ident(arg)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn attr_name_value_lookup(&self, name: &str) -> Option<String> {
|
||||
self.iter()
|
||||
.filter_map(|attr| {
|
||||
let attr = attr.parse_meta().ok()?;
|
||||
if let syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) = attr
|
||||
{
|
||||
if path.is_ident(name) {
|
||||
return Some(lit.value());
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.next()
|
||||
}
|
||||
|
||||
fn get_comment_lines(&self) -> Vec<String> {
|
||||
let mut comment = Vec::new();
|
||||
|
||||
for attr in self {
|
||||
if attr.style == syn::AttrStyle::Outer {
|
||||
if let Ok(syn::Meta::NameValue(syn::MetaNameValue {
|
||||
path,
|
||||
lit: syn::Lit::Str(content),
|
||||
..
|
||||
})) = attr.parse_meta()
|
||||
{
|
||||
if path.is_ident("doc") {
|
||||
comment.extend(split_doc_attr(&content.value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
comment
|
||||
fn attrs(&self) -> &[syn::Attribute] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user