diff --git a/Cargo.lock b/Cargo.lock index 12e62f8..4311aa4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,9 +24,9 @@ version = "0.4.3" dependencies = [ "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.10 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -80,11 +80,27 @@ name = "num-traits" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "proc-macro2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "quote" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.3.15" @@ -95,7 +111,7 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.21" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -128,7 +144,7 @@ dependencies = [ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -146,6 +162,16 @@ dependencies = [ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.12.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synom" version = "0.11.3" @@ -177,7 +203,7 @@ name = "toml" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -195,6 +221,11 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" version = "0.8.0" @@ -221,14 +252,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e" "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" +"checksum proc-macro2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9786e83afb5654ab1b336584548011f252db3c320c0ddba5dc21a1a76f83ca" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" -"checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" "checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788" "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" "checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum syn 0.12.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7d12ebcea3f1027a817b98e91cfe30805634ea1f63e36015f765960a7782494d" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" @@ -236,6 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index 985c815..4c18b75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,9 +23,8 @@ tempdir = "0.3" toml = "0.4" [dependencies.syn] -version = "0.11" -default-features = false -features = ["full"] +version = "0.12.6" +features = ["extra-traits", "full"] [[bin]] name = "cbindgen" diff --git a/src/bindgen/error.rs b/src/bindgen/error.rs index d4fb717..04670fd 100644 --- a/src/bindgen/error.rs +++ b/src/bindgen/error.rs @@ -4,6 +4,7 @@ use std::fmt; +pub use syn::synom::ParseError; pub use bindgen::cargo::cargo_metadata::Error as CargoMetadataError; pub use bindgen::cargo::cargo_toml::Error as CargoTomlError; pub use bindgen::cargo::cargo_expand::Error as CargoExpandError; @@ -13,7 +14,7 @@ pub enum Error { CargoMetadata(String, CargoMetadataError), CargoToml(String, CargoTomlError), CargoExpand(String, CargoExpandError), - ParseSyntaxError{crate_name: String, src_path: String, message: String}, + ParseSyntaxError{crate_name: String, src_path: String, error: ParseError}, ParseCannotOpenFile{crate_name: String, src_path: String}, } @@ -29,8 +30,8 @@ impl fmt::Display for Error { &Error::CargoExpand(ref crate_name, ref error) => { write!(f, "Parsing crate `{}`: couldn't run `cargo rustc --pretty=expanded`: {:?}", crate_name, error) } - &Error::ParseSyntaxError{ref crate_name, ref src_path, ref message} => { - write!(f, "Parsing crate `{}`:`{}`:\n{}", crate_name, src_path, message) + &Error::ParseSyntaxError{ref crate_name, ref src_path, ref error} => { + write!(f, "Parsing crate `{}`:`{}`:\n{:?}", crate_name, src_path, error) } &Error::ParseCannotOpenFile{ref crate_name, ref src_path} => { write!(f, "Parsing crate `{}`: cannot open file `{}`.", crate_name, src_path) diff --git a/src/bindgen/ir/annotation.rs b/src/bindgen/ir/annotation.rs index 31e1222..54bdc41 100644 --- a/src/bindgen/ir/annotation.rs +++ b/src/bindgen/ir/annotation.rs @@ -45,15 +45,16 @@ impl AnnotationSet { self.annotations.is_empty() } - pub fn load(attrs: &Vec) -> Result { + pub fn load(attrs: &[syn::Attribute]) -> Result { let mut lines = Vec::new(); for attr in attrs { if attr.style == syn::AttrStyle::Outer { - if let syn::MetaItem::NameValue(ref name, syn::Lit::Str(ref comment, _)) = - attr.value + if let Some(syn::Meta::NameValue(syn::MetaNameValue { ident, lit: syn::Lit::Str(comment), .. })) = + attr.interpret_meta() { - if &*name == "doc" { + let comment = comment.value(); + if &*ident.to_string() == "doc" { let line = comment.trim_left_matches("///").trim(); if line.starts_with("cbindgen:") { lines.push(line.to_owned()); diff --git a/src/bindgen/ir/cfg.rs b/src/bindgen/ir/cfg.rs index 1c84528..db9080a 100644 --- a/src/bindgen/ir/cfg.rs +++ b/src/bindgen/ir/cfg.rs @@ -16,7 +16,7 @@ enum DefineKey<'a> { impl<'a> DefineKey<'a> { fn load(key: &str) -> DefineKey { - // TODO - dirty parser + // TODO: dirty parser if key.contains("=") { let mut splits = key.trim().split("="); @@ -72,7 +72,7 @@ impl Cfg { } } - pub fn load(attrs: &Vec) -> Option { + pub fn load(attrs: &[syn::Attribute]) -> Option { let mut configs = Vec::new(); for attr in attrs { @@ -80,18 +80,17 @@ impl Cfg { continue; } - match &attr.value { - &syn::MetaItem::Word(..) => {} - &syn::MetaItem::NameValue(..) => {} - &syn::MetaItem::List(ref ident, ref nested) => { + match attr.interpret_meta() { + Some(syn::Meta::List(syn::MetaList { ident, nested, .. })) => { if ident.as_ref() != "cfg" || nested.len() != 1 { continue; } - if let Some(config) = Cfg::load_single(&nested[0]) { + if let Some(config) = Cfg::load_single(nested.first().unwrap().value()) { configs.push(config); } } + _ => {} } } @@ -102,27 +101,27 @@ impl Cfg { } } - fn load_single(item: &syn::NestedMetaItem) -> Option { + fn load_single(item: &syn::NestedMeta) -> Option { match item { - &syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref ident)) => { + &syn::NestedMeta::Meta(syn::Meta::Word(ref ident)) => { Some(Cfg::Boolean(ident.as_ref().to_owned())) } - &syn::NestedMetaItem::MetaItem(syn::MetaItem::NameValue(ref ident, ref value)) => { - match value { - &syn::Lit::Str(ref value, _) => { - Some(Cfg::Named(ident.as_ref().to_owned(), value.clone())) + &syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue { ref ident, ref lit, .. })) => { + match lit { + &syn::Lit::Str(ref value) => { + Some(Cfg::Named(ident.as_ref().to_owned(), value.value())) } _ => None, } } - &syn::NestedMetaItem::MetaItem(syn::MetaItem::List(ref ident, ref nested)) => { + &syn::NestedMeta::Meta(syn::Meta::List(syn::MetaList { ref ident, ref nested, .. })) => { match ident.as_ref() { - "any" => if let Some(configs) = Cfg::load_list(nested) { + "any" => if let Some(configs) = Cfg::load_list(nested.iter()) { Some(Cfg::Any(configs)) } else { None }, - "all" => if let Some(configs) = Cfg::load_list(nested) { + "all" => if let Some(configs) = Cfg::load_list(nested.iter()) { Some(Cfg::All(configs)) } else { None @@ -145,11 +144,7 @@ impl Cfg { } } - fn load_list(attrs: &Vec) -> Option> { - if attrs.len() == 0 { - return None; - } - + fn load_list<'a, I: Iterator>(attrs: I) -> Option> { let mut configs = Vec::new(); for attr in attrs { @@ -160,7 +155,11 @@ impl Cfg { } } - Some(configs) + if configs.is_empty() { + None + } else { + Some(configs) + } } fn has_defines(&self, config: &Config) -> bool { diff --git a/src/bindgen/ir/constant.rs b/src/bindgen/ir/constant.rs index c54ec9d..2d7fbc2 100644 --- a/src/bindgen/ir/constant.rs +++ b/src/bindgen/ir/constant.rs @@ -16,34 +16,36 @@ pub struct LiteralExpr(String); impl LiteralExpr { pub fn load(expr: &syn::Expr) -> Result { - match &expr.node { - &syn::ExprKind::Lit(syn::Lit::Str(ref text, ..)) => { - Ok(LiteralExpr(format!("u8\"{}\"", text))) + match expr { + &syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(ref value), .. }) => { + Ok(LiteralExpr(format!("u8\"{}\"", value.value()))) } - &syn::ExprKind::Lit(syn::Lit::Byte(value)) => Ok(LiteralExpr(format!("{}", value))), - &syn::ExprKind::Lit(syn::Lit::Char(value)) => Ok(LiteralExpr(format!("{}", value))), - &syn::ExprKind::Lit(syn::Lit::Int(value, ref ty)) => match ty { - &syn::IntTy::Usize - | &syn::IntTy::U8 - | &syn::IntTy::U16 - | &syn::IntTy::U32 - | &syn::IntTy::U64 - | &syn::IntTy::Unsuffixed => Ok(LiteralExpr(format!("{}", value))), - &syn::IntTy::Isize - | &syn::IntTy::I8 - | &syn::IntTy::I16 - | &syn::IntTy::I32 - | &syn::IntTy::I64 => unsafe { + &syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Byte(ref value), .. }) => Ok(LiteralExpr(format!("{}", value.value()))), + &syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Char(ref value), .. }) => Ok(LiteralExpr(format!("{}", value.value()))), + &syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(ref value), .. }) => match value.suffix() { + syn::IntSuffix::Usize + | syn::IntSuffix::U8 + | syn::IntSuffix::U16 + | syn::IntSuffix::U32 + | syn::IntSuffix::U64 + | syn::IntSuffix::U128 + | syn::IntSuffix::None => Ok(LiteralExpr(format!("{}", value.value()))), + syn::IntSuffix::Isize + | syn::IntSuffix::I8 + | syn::IntSuffix::I16 + | syn::IntSuffix::I32 + | syn::IntSuffix::I64 + | syn::IntSuffix::I128 => unsafe { Ok(LiteralExpr(format!( "{}", - mem::transmute::(value) + mem::transmute::(value.value()) ))) }, }, - &syn::ExprKind::Lit(syn::Lit::Float(ref value, ref _ty)) => { - Ok(LiteralExpr(format!("{}", value))) + &syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Float(ref value), .. }) => { + Ok(LiteralExpr(format!("{}", value.value()))) } - &syn::ExprKind::Lit(syn::Lit::Bool(value)) => Ok(LiteralExpr(format!("{}", value))), + &syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Bool(ref value), .. }) => Ok(LiteralExpr(format!("{}", value.value))), _ => Err("Unsupported literal expression.".to_owned()), } } @@ -62,12 +64,10 @@ pub struct Constant { impl Constant { pub fn load( name: String, - ty: &syn::Ty, - expr: &syn::Expr, - attrs: &Vec, + item: &syn::ItemConst, mod_cfg: &Option, ) -> Result { - let ty = Type::load(ty)?; + let ty = Type::load(&item.ty)?; if ty.is_none() { return Err("Cannot have a zero sized const definition.".to_owned()); @@ -82,10 +82,10 @@ impl Constant { Ok(Constant { name: name, ty: ty, - value: LiteralExpr::load(expr)?, - cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), - annotations: AnnotationSet::load(attrs)?, - documentation: Documentation::load(attrs), + value: LiteralExpr::load(&item.expr)?, + cfg: Cfg::append(mod_cfg, Cfg::load(&item.attrs)), + annotations: AnnotationSet::load(&item.attrs)?, + documentation: Documentation::load(&item.attrs), }) } } diff --git a/src/bindgen/ir/documentation.rs b/src/bindgen/ir/documentation.rs index e4f36ff..fbac223 100644 --- a/src/bindgen/ir/documentation.rs +++ b/src/bindgen/ir/documentation.rs @@ -15,7 +15,7 @@ pub struct Documentation { } impl Documentation { - pub fn load(attrs: &Vec) -> Self { + pub fn load(attrs: &[syn::Attribute]) -> Self { let mut doc = Vec::new(); for attr in attrs { @@ -26,9 +26,12 @@ impl Documentation { // step through rust. In that case they are stored as doc // attributes and the leading three slashes (and optional space) // are not included. - if let syn::MetaItem::NameValue(ref name, syn::Lit::Str(ref comment, _)) = - attr.value + if let Some(syn::Meta::NameValue(syn::MetaNameValue{ident, lit: syn::Lit::Str(comment), ..})) = + attr.interpret_meta() { + let name = ident.to_string(); + let comment = comment.value(); + if &*name == "doc" { let line = if attr.is_sugared_doc { comment diff --git a/src/bindgen/ir/enumeration.rs b/src/bindgen/ir/enumeration.rs index a05339c..db65397 100644 --- a/src/bindgen/ir/enumeration.rs +++ b/src/bindgen/ir/enumeration.rs @@ -29,59 +29,75 @@ impl EnumVariant { variant: &syn::Variant, mod_cfg: &Option, ) -> Result { - let discriminant = match variant.discriminant { - Some(syn::ConstExpr::Lit(syn::Lit::Int(i, _))) => Some(i), - Some(_) => { + let discriminant = match &variant.discriminant { + &Some((_, syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(ref lit), .. }))) => Some(lit.value()), + &Some(_) => { return Err("Unsupported discriminant.".to_owned()); } - None => None, + &None => None, }; - let body = match variant.data { - syn::VariantData::Unit => None, - syn::VariantData::Struct(ref fields) | syn::VariantData::Tuple(ref fields) => { + + fn parse_fields( + is_tagged: bool, + fields: &syn::punctuated::Punctuated + ) -> Result, String> { + let mut res = Vec::new(); + + if is_tagged { + res.push(( + "tag".to_string(), + Type::Path(GenericPath { + name: "Tag".to_string(), + generics: vec![], + }), + Documentation::none(), + )); + } + + for (i, field) in fields.iter().enumerate() { + if let Some(ty) = Type::load(&field.ty)? { + res.push(( + match field.ident { + Some(ref ident) => ident.to_string(), + None => i.to_string(), + }, + ty, + Documentation::load(&field.attrs), + )); + } + } + + Ok(res) + } + + let body = match variant.fields { + syn::Fields::Unit => None, + syn::Fields::Named(ref fields) => { Some(Struct { name: format!("{}_Body", variant.ident), generic_params: GenericParams::default(), - fields: { - let mut res = Vec::new(); - - if is_tagged { - res.push(( - "tag".to_string(), - Type::Path(GenericPath { - name: "Tag".to_string(), - generics: vec![], - }), - Documentation::none(), - )); - } - - for (i, field) in fields.iter().enumerate() { - if let Some(ty) = Type::load(&field.ty)? { - res.push(( - match field.ident { - Some(ref ident) => ident.to_string(), - None => i.to_string(), - }, - ty, - Documentation::load(&field.attrs), - )); - } - } - - res - }, + fields: parse_fields(is_tagged, &fields.named)?, is_tagged, - tuple_struct: match variant.data { - syn::VariantData::Tuple(_) => true, - _ => false, - }, + tuple_struct: false, + cfg: Cfg::append(mod_cfg, Cfg::load(&variant.attrs)), + annotations: AnnotationSet::load(&variant.attrs)?, + documentation: Documentation::none(), + }) + } + syn::Fields::Unnamed(ref fields) => { + Some(Struct { + name: format!("{}_Body", variant.ident), + generic_params: GenericParams::default(), + fields: parse_fields(is_tagged, &fields.unnamed)?, + is_tagged, + tuple_struct: true, cfg: Cfg::append(mod_cfg, Cfg::load(&variant.attrs)), annotations: AnnotationSet::load(&variant.attrs)?, documentation: Documentation::none(), }) } }; + Ok(EnumVariant { name: variant.ident.to_string(), discriminant, @@ -127,12 +143,10 @@ pub struct Enum { impl Enum { pub fn load( - name: String, - values: &Vec, - attrs: &Vec, + item: &syn::ItemEnum, mod_cfg: &Option, ) -> Result { - let repr = Repr::load(attrs)?; + let repr = Repr::load(&item.attrs)?; if repr == Repr::RUST { return Err("Enum not marked with a valid repr(prim) or repr(C).".to_owned()); } @@ -140,13 +154,13 @@ impl Enum { let mut variants = Vec::new(); let mut is_tagged = false; - for variant in values { + for variant in item.variants.iter() { let variant = EnumVariant::load(repr.style == ReprStyle::Rust, variant, mod_cfg)?; is_tagged = is_tagged || variant.body.is_some(); variants.push(variant); } - let annotations = AnnotationSet::load(attrs)?; + let annotations = AnnotationSet::load(&item.attrs)?; if let Some(names) = annotations.list("enum-trailing-values") { for name in names { @@ -160,7 +174,7 @@ impl Enum { } Ok(Enum { - name, + name: item.ident.to_string(), repr, variants, tag: if is_tagged { @@ -168,9 +182,9 @@ impl Enum { } else { None }, - cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), + cfg: Cfg::append(mod_cfg, Cfg::load(&item.attrs)), annotations, - documentation: Documentation::load(attrs), + documentation: Documentation::load(&item.attrs), }) } } diff --git a/src/bindgen/ir/function.rs b/src/bindgen/ir/function.rs index 4abb401..e40bed0 100644 --- a/src/bindgen/ir/function.rs +++ b/src/bindgen/ir/function.rs @@ -9,7 +9,7 @@ use syn; use bindgen::cdecl; use bindgen::config::{Config, Layout, Language}; use bindgen::dependencies::Dependencies; -use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, SynFnRetTyHelpers, Type}; +use bindgen::ir::{AnnotationSet, Cfg, CfgWrite, Documentation, Type, PrimitiveType}; use bindgen::library::Library; use bindgen::monomorph::Monomorphs; use bindgen::rename::{IdentifierType, RenameRule}; @@ -32,11 +32,22 @@ impl Function { name: String, decl: &syn::FnDecl, extern_decl: bool, - attrs: &Vec, + attrs: &[syn::Attribute], mod_cfg: &Option, ) -> Result { let args = decl.inputs.iter().try_skip_map(|x| x.as_ident_and_type())?; - let ret = decl.output.as_type()?; + let ret = match decl.output { + syn::ReturnType::Default => { + Type::Primitive(PrimitiveType::Void) + } + syn::ReturnType::Type(_, ref ty) => { + if let Some(x) = Type::load(ty)? { + x + } else { + Type::Primitive(PrimitiveType::Void) + } + } + }; Ok(Function { name: name, @@ -181,7 +192,7 @@ pub trait SynFnArgHelpers { impl SynFnArgHelpers for syn::FnArg { fn as_ident_and_type(&self) -> Result, String> { match self { - &syn::FnArg::Captured(syn::Pat::Ident(_, ref ident, _), ref ty) => { + &syn::FnArg::Captured(syn::ArgCaptured { pat: syn::Pat::Ident(syn::PatIdent { ref ident, .. }), ref ty, .. }) => { if let Some(x) = Type::load(ty)? { Ok(Some((ident.to_string(), x))) } else { diff --git a/src/bindgen/ir/generics.rs b/src/bindgen/ir/generics.rs index 2e3ff92..d1c68a5 100644 --- a/src/bindgen/ir/generics.rs +++ b/src/bindgen/ir/generics.rs @@ -13,9 +13,12 @@ impl GenericParams { pub fn new(generics: &syn::Generics) -> Self { GenericParams( generics - .ty_params + .params .iter() - .map(|x| x.ident.to_string()) + .filter_map(|x| match x { + &syn::GenericParam::Type(syn::TypeParam { ref ident, .. }) => Some(ident.to_string()), + _ => None, + }) .collect::>(), ) } diff --git a/src/bindgen/ir/global.rs b/src/bindgen/ir/global.rs index 8fa56f0..0d43502 100644 --- a/src/bindgen/ir/global.rs +++ b/src/bindgen/ir/global.rs @@ -24,28 +24,22 @@ pub struct Static { impl Static { pub fn load( - name: String, - ty: &syn::Ty, - mutable: &syn::Mutability, - attrs: &Vec, + item: &syn::ItemStatic, mod_cfg: &Option, ) -> Result { - let ty = Type::load(ty)?; + let ty = Type::load(&item.ty)?; if ty.is_none() { return Err("Cannot have a zero sized static definition.".to_owned()); } - let ty = ty.unwrap(); - let mutable = mutable == &syn::Mutability::Mutable; - Ok(Static { - name: name, - ty: ty, - mutable: mutable, - cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), - annotations: AnnotationSet::load(attrs)?, - documentation: Documentation::load(attrs), + name: item.ident.to_string(), + ty: ty.unwrap(), + mutable: item.mutability.is_some(), + cfg: Cfg::append(mod_cfg, Cfg::load(&item.attrs)), + annotations: AnnotationSet::load(&item.attrs)?, + documentation: Documentation::load(&item.attrs), }) } diff --git a/src/bindgen/ir/path.rs b/src/bindgen/ir/path.rs index 9bd44cd..cd61c4d 100644 --- a/src/bindgen/ir/path.rs +++ b/src/bindgen/ir/path.rs @@ -25,21 +25,27 @@ impl GenericPath { pub fn load(path: &syn::Path) -> Result { assert!(path.segments.len() > 0); - let last_segment = path.segments.last().unwrap(); - + let last_segment_token = path.segments.last().unwrap(); + let last_segment = last_segment_token.value(); let name = last_segment.ident.to_string(); if name == "PhantomData" { return Ok(GenericPath::new(name, Vec::new())); } - let generics = match &last_segment.parameters { - &syn::PathParameters::AngleBracketed(ref d) => { - d.types.iter().try_skip_map(|x| Type::load(x))? + let generics = match &last_segment.arguments { + &syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments { ref args, .. }) => { + args.iter().try_skip_map(|x| { + match *x { + &syn::GenericArgument::Type(ref x) => Type::load(x), + _ => { Err(String::new()) } + } + })? } - &syn::PathParameters::Parenthesized(_) => { + &syn::PathArguments::Parenthesized(_) => { return Err("Path contains parentheses.".to_owned()); } + _ => Vec::new() }; Ok(GenericPath::new(name, generics)) diff --git a/src/bindgen/ir/repr.rs b/src/bindgen/ir/repr.rs index b512e94..2c541b0 100644 --- a/src/bindgen/ir/repr.rs +++ b/src/bindgen/ir/repr.rs @@ -48,26 +48,27 @@ impl Repr { pub fn load(attrs: &[syn::Attribute]) -> Result { let ids = attrs .iter() - .filter_map(|attr| match *attr { - syn::Attribute { - style: syn::AttrStyle::Outer, - is_sugared_doc: false, - value: syn::MetaItem::List(ref id, ref nested), - } if id == "repr" => - { - Some(nested) + .filter_map(|attr| { + if attr.is_sugared_doc || attr.style != syn::AttrStyle::Outer { + return None; } - _ => None, + + if let Some(syn::Meta::List(syn::MetaList { ident, nested, .. })) = attr.interpret_meta() { + if ident.as_ref() == "repr" { + return Some(nested.into_iter().collect::>()); + } + } + None }) .flat_map(|nested| nested) - .filter_map(|meta| match *meta { - syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref id)) => Some(id.as_ref()), + .filter_map(|meta| match meta { + syn::NestedMeta::Meta(syn::Meta::Word(ident)) => Some(ident.to_string()), _ => None, }); let mut repr = Repr::default(); for id in ids { - let new_ty = match id { + let new_ty = match id.as_ref() { "u8" => ReprType::U8, "u16" => ReprType::U16, "u32" => ReprType::U32, diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 866d3fc..ee0b445 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -31,25 +31,23 @@ pub struct Struct { impl Struct { pub fn load( - name: String, - decl: &syn::VariantData, - generics: &syn::Generics, - attrs: &Vec, + item: &syn::ItemStruct, mod_cfg: &Option, ) -> Result { - if Repr::load(attrs)? != Repr::C { + if Repr::load(&item.attrs)? != Repr::C { return Err("Struct is not marked #[repr(C)].".to_owned()); } - let (fields, tuple_struct) = match decl { - &syn::VariantData::Struct(ref fields) => { - let out = fields.iter().try_skip_map(|x| x.as_ident_and_type())?; + let (fields, tuple_struct) = match &item.fields { + &syn::Fields::Unit => (Vec::new(), false), + &syn::Fields::Named(ref fields) => { + let out = fields.named.iter().try_skip_map(|x| x.as_ident_and_type())?; (out, false) } - &syn::VariantData::Tuple(ref fields) => { + &syn::Fields::Unnamed(ref fields) => { let mut out = Vec::new(); let mut current = 0; - for field in fields { + for field in fields.unnamed.iter() { if let Some(x) = Type::load(&field.ty)? { out.push((format!("{}", current), x, Documentation::load(&field.attrs))); current += 1; @@ -57,18 +55,17 @@ impl Struct { } (out, true) } - &syn::VariantData::Unit => (vec![], false), }; Ok(Struct { - name: name, - generic_params: GenericParams::new(generics), + name: item.ident.to_string(), + generic_params: GenericParams::new(&item.generics), fields: fields, is_tagged: false, tuple_struct: tuple_struct, - cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), - annotations: AnnotationSet::load(attrs)?, - documentation: Documentation::load(attrs), + cfg: Cfg::append(mod_cfg, Cfg::load(&item.attrs)), + annotations: AnnotationSet::load(&item.attrs)?, + documentation: Documentation::load(&item.attrs), }) } diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index 0ff9115..3017cdd 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -176,10 +176,10 @@ pub enum Type { } impl Type { - pub fn load(ty: &syn::Ty) -> Result, String> { + pub fn load(ty: &syn::Type) -> Result, String> { let converted = match ty { - &syn::Ty::Rptr(_, ref mut_ty) => { - let converted = Type::load(&mut_ty.ty)?; + &syn::Type::Reference(ref reference) => { + let converted = Type::load(&reference.elem)?; let converted = match converted { Some(converted) => converted, @@ -190,13 +190,13 @@ impl Type { } }; - match mut_ty.mutability { - syn::Mutability::Mutable => Type::Ptr(Box::new(converted)), - syn::Mutability::Immutable => Type::ConstPtr(Box::new(converted)), + match reference.mutability { + Some(_) => Type::Ptr(Box::new(converted)), + None => Type::ConstPtr(Box::new(converted)), } } - &syn::Ty::Ptr(ref mut_ty) => { - let converted = Type::load(&mut_ty.ty)?; + &syn::Type::Ptr(ref pointer) => { + let converted = Type::load(&pointer.elem)?; let converted = match converted { Some(converted) => converted, @@ -207,13 +207,13 @@ impl Type { } }; - match mut_ty.mutability { - syn::Mutability::Mutable => Type::Ptr(Box::new(converted)), - syn::Mutability::Immutable => Type::ConstPtr(Box::new(converted)), + match pointer.mutability { + Some(_) => Type::Ptr(Box::new(converted)), + None => Type::ConstPtr(Box::new(converted)), } } - &syn::Ty::Path(_, ref path) => { - let path = GenericPath::load(path)?; + &syn::Type::Path(ref path) => { + let path = GenericPath::load(&path.path)?; if path.name == "PhantomData" { return Ok(None); @@ -228,36 +228,47 @@ impl Type { Type::Path(path) } } - &syn::Ty::Array(ref ty, syn::ConstExpr::Lit(syn::Lit::Int(size, _))) => { - let converted = Type::load(ty)?; + &syn::Type::Array(syn::TypeArray { ref elem, len: syn::Expr::Path(ref path), .. }) => { + let converted = Type::load(elem)?; let converted = match converted { Some(converted) => converted, None => return Err("Cannot have an array of zero sized types.".to_owned()), }; - Type::Array(Box::new(converted), format!("{}", size)) - } - &syn::Ty::Array(ref ty, syn::ConstExpr::Path(ref path)) => { - let converted = Type::load(ty)?; - - let converted = match converted { - Some(converted) => converted, - None => return Err("Cannot have an array of zero sized types.".to_owned()), - }; - - let path = GenericPath::load(path)?; + let path = GenericPath::load(&path.path)?; Type::Array(Box::new(converted), path.name) } - &syn::Ty::BareFn(ref function) => { + &syn::Type::Array(syn::TypeArray { ref elem, len: syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Int(ref len), .. }), .. }) => { + let converted = Type::load(elem)?; + + let converted = match converted { + Some(converted) => converted, + None => return Err("Cannot have an array of zero sized types.".to_owned()), + }; + + Type::Array(Box::new(converted), format!("{}", len.value())) + } + &syn::Type::BareFn(ref function) => { let args = function.inputs.iter().try_skip_map(|x| Type::load(&x.ty))?; - let ret = function.output.as_type()?; + let ret = match function.output { + syn::ReturnType::Default => { + Type::Primitive(PrimitiveType::Void) + } + syn::ReturnType::Type(_, ref ty) => { + if let Some(x) = Type::load(ty)? { + x + } else { + Type::Primitive(PrimitiveType::Void) + } + } + }; Type::FuncPtr(Box::new(ret), args) } - &syn::Ty::Tup(ref fields) => { - if fields.len() == 0 { + &syn::Type::Tuple(ref tuple) => { + if tuple.elems.len() == 0 { return Ok(None); } return Err("Tuples are not supported types.".to_owned()); @@ -554,20 +565,3 @@ impl Source for (String, Type, Documentation) { cdecl::write_field(out, &self.1, &self.0); } } - -pub trait SynFnRetTyHelpers { - fn as_type(&self) -> Result; -} - -impl SynFnRetTyHelpers for syn::FunctionRetTy { - fn as_type(&self) -> Result { - match self { - &syn::FunctionRetTy::Default => Ok(Type::Primitive(PrimitiveType::Void)), - &syn::FunctionRetTy::Ty(ref t) => if let Some(x) = Type::load(t)? { - Ok(x) - } else { - Ok(Type::Primitive(PrimitiveType::Void)) - }, - } - } -} diff --git a/src/bindgen/ir/typedef.rs b/src/bindgen/ir/typedef.rs index 61d2b47..d03483b 100644 --- a/src/bindgen/ir/typedef.rs +++ b/src/bindgen/ir/typedef.rs @@ -29,20 +29,17 @@ pub struct Typedef { impl Typedef { pub fn load( - name: String, - ty: &syn::Ty, - generics: &syn::Generics, - attrs: &Vec, + item: &syn::ItemType, mod_cfg: &Option, ) -> Result { - if let Some(x) = Type::load(ty)? { + if let Some(x) = Type::load(&item.ty)? { Ok(Typedef { - name: name, - generic_params: GenericParams::new(generics), + name: item.ident.to_string(), + generic_params: GenericParams::new(&item.generics), aliased: x, - cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), - annotations: AnnotationSet::load(attrs)?, - documentation: Documentation::load(attrs), + cfg: Cfg::append(mod_cfg, Cfg::load(&item.attrs)), + annotations: AnnotationSet::load(&item.attrs)?, + documentation: Documentation::load(&item.attrs), }) } else { Err("Cannot have a typedef of a zero sized type.".to_owned()) diff --git a/src/bindgen/ir/union.rs b/src/bindgen/ir/union.rs index d6353ee..22a720c 100644 --- a/src/bindgen/ir/union.rs +++ b/src/bindgen/ir/union.rs @@ -31,43 +31,26 @@ pub struct Union { impl Union { pub fn load( - name: String, - decl: &syn::VariantData, - generics: &syn::Generics, - attrs: &Vec, + item: &syn::ItemUnion, mod_cfg: &Option, ) -> Result { - if Repr::load(attrs)? != Repr::C { + if Repr::load(&item.attrs)? != Repr::C { return Err("Union is not marked #[repr(C)].".to_owned()); } - let (fields, tuple_union) = match decl { - &syn::VariantData::Struct(ref fields) => { - let out = fields.iter().try_skip_map(|x| x.as_ident_and_type())?; - (out, false) - } - &syn::VariantData::Tuple(ref fields) => { - let mut out = Vec::new(); - let mut current = 0; - for field in fields { - if let Some(x) = Type::load(&field.ty)? { - out.push((format!("{}", current), x, Documentation::load(&field.attrs))); - current += 1; - } - } - (out, true) - } - &syn::VariantData::Unit => (vec![], false), + let (fields, tuple_union) = { + let out = item.fields.named.iter().try_skip_map(|x| x.as_ident_and_type())?; + (out, false) }; Ok(Union { - name: name, - generic_params: GenericParams::new(generics), + name: item.ident.to_string(), + generic_params: GenericParams::new(&item.generics), fields: fields, tuple_union: tuple_union, - cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), - annotations: AnnotationSet::load(attrs)?, - documentation: Documentation::load(attrs), + cfg: Cfg::append(mod_cfg, Cfg::load(&item.attrs)), + annotations: AnnotationSet::load(&item.attrs)?, + documentation: Documentation::load(&item.attrs), }) } diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs index 592802f..d03a914 100644 --- a/src/bindgen/parser.rs +++ b/src/bindgen/parser.rs @@ -164,11 +164,11 @@ impl Parser { pkg.name.clone(), x ))?; - let i = syn::parse_crate(&s) - .map_err(|msg| Error::ParseSyntaxError{ + let i = syn::parse_file(&s) + .map_err(|x| Error::ParseSyntaxError{ crate_name: pkg.name.clone(), src_path: "".to_owned(), - message: msg, + error: x, })?; self.cache_expanded_crate.insert(pkg.name.clone(), i.items); } @@ -182,7 +182,7 @@ impl Parser { fn process_expanded_mod( &mut self, pkg: &PackageRef, - items: &Vec, + items: &[syn::Item], ) -> Result<(), Error> { self.out.load_syn_crate_mod( &self.binding_crate_name, @@ -192,14 +192,14 @@ impl Parser { ); for item in items { - match item.node { - syn::ItemKind::Mod(ref inline_items) => { + match item { + &syn::Item::Mod(ref item) => { let cfg = Cfg::load(&item.attrs); if let &Some(ref cfg) = &cfg { self.cfg_stack.push(cfg.clone()); } - if let &Some(ref inline_items) = inline_items { + if let Some((_, ref inline_items)) = item.content { self.process_expanded_mod(pkg, inline_items)?; } else { unreachable!(); @@ -209,7 +209,7 @@ impl Parser { self.cfg_stack.pop(); } } - syn::ItemKind::ExternCrate(_) => { + &syn::Item::ExternCrate(ref item) => { let dep_pkg_name = item.ident.to_string(); let cfg = Cfg::load(&item.attrs); @@ -256,14 +256,6 @@ impl Parser { let owned_mod_path = mod_path.to_path_buf(); if !self.cache_src.contains_key(&owned_mod_path) { - fn limit_string(text: &str) -> &str { - if text.len() <= 100 { - text - } else { - &text[..100] - } - } - let mut s = String::new(); let mut f = File::open(mod_path).map_err(|_| { Error::ParseCannotOpenFile{ @@ -278,11 +270,11 @@ impl Parser { } })?; - let i = syn::parse_crate(&s).map_err(|msg| { + let i = syn::parse_file(&s).map_err(|x| { Error::ParseSyntaxError{ crate_name: pkg.name.clone(), src_path: "".to_owned(), - message: limit_string(&msg).to_owned(), + error: x, } })?; @@ -301,7 +293,7 @@ impl Parser { &mut self, pkg: &PackageRef, mod_dir: &Path, - items: &Vec, + items: &[syn::Item], ) -> Result<(), Error> { self.out.load_syn_crate_mod( &self.binding_crate_name, @@ -311,8 +303,8 @@ impl Parser { ); for item in items { - match item.node { - syn::ItemKind::Mod(ref inline_items) => { + match item { + &syn::Item::Mod(ref item) => { let next_mod_name = item.ident.to_string(); let cfg = Cfg::load(&item.attrs); @@ -320,7 +312,7 @@ impl Parser { self.cfg_stack.push(cfg.clone()); } - if let &Some(ref inline_items) = inline_items { + if let Some((_, ref inline_items)) = item.content { self.process_mod(pkg, &mod_dir.join(&next_mod_name), inline_items)?; } else { let next_mod_path1 = mod_dir.join(next_mod_name.clone() + ".rs"); @@ -344,8 +336,8 @@ impl Parser { self.cfg_stack.pop(); } } - syn::ItemKind::ExternCrate(ref cr) => { - let dep_pkg_name = if let Some(ref name) = *cr { + &syn::Item::ExternCrate(ref item) => { + let dep_pkg_name = if let Some((_, ref name)) = item.rename { name.to_string() } else { item.ident.to_string() @@ -461,47 +453,33 @@ impl Parse { binding_crate_name: &str, crate_name: &str, mod_cfg: &Option, - items: &Vec, + items: &[syn::Item], ) { for item in items { - match item.node { - syn::ItemKind::ForeignMod(ref block) => { - self.load_syn_foreign_mod(binding_crate_name, crate_name, mod_cfg, item, block); + match item { + &syn::Item::ForeignMod(ref item) => { + self.load_syn_foreign_mod(binding_crate_name, crate_name, mod_cfg, item); } - syn::ItemKind::Fn( - ref decl, - ref _unsafe, - ref _const, - ref abi, - ref _generic, - ref _block, - ) => { - self.load_syn_fn(binding_crate_name, crate_name, mod_cfg, item, decl, abi); + &syn::Item::Fn(ref item) => { + self.load_syn_fn(binding_crate_name, crate_name, mod_cfg, item); } - syn::ItemKind::Const(ref ty, ref expr) => { - self.load_syn_const(binding_crate_name, crate_name, mod_cfg, item, ty, expr); + &syn::Item::Const(ref item) => { + self.load_syn_const(binding_crate_name, crate_name, mod_cfg, item); } - syn::ItemKind::Static(ref ty, ref mutability, ref _expr) => { - self.load_syn_static( - binding_crate_name, - crate_name, - mod_cfg, - item, - ty, - mutability, - ); + &syn::Item::Static(ref item) => { + self.load_syn_static(binding_crate_name, crate_name, mod_cfg, item); } - syn::ItemKind::Struct(ref variant, ref generics) => { - self.load_syn_struct(crate_name, mod_cfg, item, variant, generics); + &syn::Item::Struct(ref item) => { + self.load_syn_struct(crate_name, mod_cfg, item); } - syn::ItemKind::Union(ref variant, ref generics) => { - self.load_syn_union(crate_name, mod_cfg, item, variant, generics); + &syn::Item::Union(ref item) => { + self.load_syn_union(crate_name, mod_cfg, item); } - syn::ItemKind::Enum(ref variants, ref generics) => { - self.load_syn_enum(crate_name, mod_cfg, item, variants, generics); + &syn::Item::Enum(ref item) => { + self.load_syn_enum(crate_name, mod_cfg, item); } - syn::ItemKind::Ty(ref ty, ref generics) => { - self.load_syn_ty(crate_name, mod_cfg, item, ty, generics); + &syn::Item::Type(ref item) => { + self.load_syn_ty(crate_name, mod_cfg, item); } _ => {} } @@ -514,44 +492,43 @@ impl Parse { binding_crate_name: &str, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - block: &syn::ForeignMod, + item: &syn::ItemForeignMod, ) { - if !block.abi.is_c() { + if !item.abi.is_c() { info!( - "Skip {}::{} - (extern block must be extern C).", - crate_name, &item.ident + "Skip {} - (extern block must be extern C).", + crate_name ); return; } - for foreign_item in &block.items { - match foreign_item.node { - syn::ForeignItemKind::Fn(ref decl, ref _generic) => { + for foreign_item in &item.items { + match foreign_item { + &syn::ForeignItem::Fn(ref function) => { if crate_name != binding_crate_name { info!( "Skip {}::{} - (fn's outside of the binding crate are not used).", - crate_name, &foreign_item.ident + crate_name, &function.ident ); return; } match Function::load( - foreign_item.ident.to_string(), - decl, + function.ident.to_string(), + &function.decl, true, - &foreign_item.attrs, + &function.attrs, mod_cfg, ) { Ok(func) => { - info!("Take {}::{}.", crate_name, &foreign_item.ident); + info!("Take {}::{}.", crate_name, &function.ident); self.functions.push(func); } Err(msg) => { error!( "Cannot use fn {}::{} ({}).", - crate_name, &foreign_item.ident, msg + crate_name, &function.ident, msg ); } } @@ -567,9 +544,7 @@ impl Parse { binding_crate_name: &str, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - decl: &syn::FnDecl, - abi: &Option, + item: &syn::ItemFn ) { if crate_name != binding_crate_name { info!( @@ -579,36 +554,40 @@ impl Parse { return; } - if item.vis == syn::Visibility::Public && item.is_no_mangle() && (abi.is_omitted() || abi.is_c()) { - match Function::load(item.ident.to_string(), decl, false, &item.attrs, mod_cfg) { - Ok(func) => { - info!("Take {}::{}.", crate_name, &item.ident); + if let syn::Visibility::Public(_) = item.vis { + if item.is_no_mangle() && (item.abi.is_omitted() || item.abi.is_c()) { + match Function::load(item.ident.to_string(), &item.decl, false, &item.attrs, mod_cfg) { + Ok(func) => { + info!("Take {}::{}.", crate_name, &item.ident); - self.functions.push(func); - } - Err(msg) => { - error!("Cannot use fn {}::{} ({}).", crate_name, &item.ident, msg); + self.functions.push(func); + } + Err(msg) => { + error!("Cannot use fn {}::{} ({}).", crate_name, &item.ident, msg); + } } + return; } - } else { - if item.vis != syn::Visibility::Public { - warn!( - "Skip {}::{} - (not `pub`).", - crate_name, &item.ident - ); - } - if (abi.is_omitted() || abi.is_c()) && !item.is_no_mangle() { - warn!( - "Skip {}::{} - (`extern` but not `no_mangle`).", - crate_name, &item.ident - ); - } - if abi.is_some() && !(abi.is_omitted() || abi.is_c()) { - warn!( - "Skip {}::{} - (non `extern \"C\"`).", - crate_name, &item.ident - ); - } + } + + // TODO + if let syn::Visibility::Public(_) = item.vis { } else { + warn!( + "Skip {}::{} - (not `pub`).", + crate_name, &item.ident + ); + } + if (item.abi.is_omitted() || item.abi.is_c()) && !item.is_no_mangle() { + warn!( + "Skip {}::{} - (`extern` but not `no_mangle`).", + crate_name, &item.ident + ); + } + if item.abi.is_some() && !(item.abi.is_omitted() || item.abi.is_c()) { + warn!( + "Skip {}::{} - (non `extern \"C\"`).", + crate_name, &item.ident + ); } } @@ -618,9 +597,7 @@ impl Parse { binding_crate_name: &str, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - ty: &syn::Ty, - expr: &syn::Expr, + item: &syn::ItemConst, ) { if crate_name != binding_crate_name { info!( @@ -632,7 +609,7 @@ impl Parse { let const_name = item.ident.to_string(); - match Constant::load(const_name.clone(), ty, expr, &item.attrs, mod_cfg) { + match Constant::load(const_name.clone(), item, mod_cfg) { Ok(constant) => { info!("Take {}::{}.", crate_name, &item.ident); @@ -650,9 +627,7 @@ impl Parse { binding_crate_name: &str, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - ty: &syn::Ty, - mutability: &syn::Mutability, + item: &syn::ItemStatic ) { if crate_name != binding_crate_name { info!( @@ -662,32 +637,33 @@ impl Parse { return; } - let static_name = item.ident.to_string(); + if let syn::Visibility::Public(_) = item.vis { + if item.is_no_mangle() { + match Static::load(item, mod_cfg) { + Ok(constant) => { + info!("Take {}::{}.", crate_name, &item.ident); - if item.vis == syn::Visibility::Public && item.is_no_mangle() { - match Static::load(static_name.clone(), ty, mutability, &item.attrs, mod_cfg) { - Ok(constant) => { - info!("Take {}::{}.", crate_name, &item.ident); - - self.globals.try_insert(constant); - } - Err(msg) => { - warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg); + self.globals.try_insert(constant); + } + Err(msg) => { + warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg); + } } } - } else { - if item.vis != syn::Visibility::Public { - warn!( - "Skip {}::{} - (not `pub`).", - crate_name, &item.ident - ); - } - if !item.is_no_mangle() { - warn!( - "Skip {}::{} - (not `no_mangle`).", - crate_name, &item.ident - ); - } + } + + // TODO + if let syn::Visibility::Public(_) = item.vis { } else { + warn!( + "Skip {}::{} - (not `pub`).", + crate_name, &item.ident + ); + } + if !item.is_no_mangle() { + warn!( + "Skip {}::{} - (not `no_mangle`).", + crate_name, &item.ident + ); } } @@ -696,13 +672,9 @@ impl Parse { &mut self, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - variant: &syn::VariantData, - generics: &syn::Generics, + item: &syn::ItemStruct, ) { - let struct_name = item.ident.to_string(); - - match Struct::load(struct_name.clone(), variant, generics, &item.attrs, mod_cfg) { + match Struct::load(item, mod_cfg) { Ok(st) => { info!("Take {}::{}.", crate_name, &item.ident); @@ -711,8 +683,8 @@ impl Parse { Err(msg) => { info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg); self.opaque_items.try_insert(OpaqueItem::new( - struct_name, - generics, + item.ident.to_string(), + &item.generics, &item.attrs, mod_cfg, )); @@ -725,13 +697,9 @@ impl Parse { &mut self, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - variant: &syn::VariantData, - generics: &syn::Generics, + item: &syn::ItemUnion, ) { - let union_name = item.ident.to_string(); - - match Union::load(union_name.clone(), variant, generics, &item.attrs, mod_cfg) { + match Union::load(item, mod_cfg) { Ok(st) => { info!("Take {}::{}.", crate_name, &item.ident); @@ -740,8 +708,8 @@ impl Parse { Err(msg) => { info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg); self.opaque_items.try_insert(OpaqueItem::new( - union_name, - generics, + item.ident.to_string(), + &item.generics, &item.attrs, mod_cfg, )); @@ -754,22 +722,18 @@ impl Parse { &mut self, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - variants: &Vec, - generics: &syn::Generics, + item: &syn::ItemEnum, ) { - if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() - || !generics.where_clause.predicates.is_empty() - { + if item.generics.lifetimes().count() > 0 || + item.generics.type_params().count() > 0 { info!( "Skip {}::{} - (has generics or lifetimes or where bounds).", crate_name, &item.ident ); return; } - let enum_name = item.ident.to_string(); - match Enum::load(enum_name.clone(), variants, &item.attrs, mod_cfg) { + match Enum::load(item, mod_cfg) { Ok(en) => { info!("Take {}::{}.", crate_name, &item.ident); self.enums.try_insert(en); @@ -777,8 +741,8 @@ impl Parse { Err(msg) => { info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg); self.opaque_items.try_insert(OpaqueItem::new( - enum_name, - generics, + item.ident.to_string(), + &item.generics, &item.attrs, mod_cfg, )); @@ -791,13 +755,9 @@ impl Parse { &mut self, crate_name: &str, mod_cfg: &Option, - item: &syn::Item, - ty: &syn::Ty, - generics: &syn::Generics, + item: &syn::ItemType, ) { - let alias_name = item.ident.to_string(); - - match Typedef::load(alias_name.clone(), ty, generics, &item.attrs, mod_cfg) { + match Typedef::load(item, mod_cfg) { Ok(st) => { info!("Take {}::{}.", crate_name, &item.ident); @@ -806,8 +766,8 @@ impl Parse { Err(msg) => { info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg); self.opaque_items.try_insert(OpaqueItem::new( - alias_name, - generics, + item.ident.to_string(), + &item.generics, &item.attrs, mod_cfg, )); diff --git a/src/bindgen/utilities.rs b/src/bindgen/utilities.rs index c206a22..e1e82e7 100644 --- a/src/bindgen/utilities.rs +++ b/src/bindgen/utilities.rs @@ -38,42 +38,55 @@ pub fn find_first_some(slice: &[Option]) -> Option<&T> { } pub trait SynItemHelpers { - fn has_attr(&self, target: syn::MetaItem) -> bool; + fn has_attr(&self, target: syn::Meta) -> bool; fn is_no_mangle(&self) -> bool { - self.has_attr(syn::MetaItem::Word(syn::Ident::new("no_mangle"))) + self.has_attr(syn::Meta::Word("no_mangle".into())) } } -impl SynItemHelpers for syn::Item { - fn has_attr(&self, target: syn::MetaItem) -> bool { +impl SynItemHelpers for syn::ItemStruct { + fn has_attr(&self, target: syn::Meta) -> bool { return self.attrs .iter() - .any(|ref attr| attr.style == syn::AttrStyle::Outer && attr.value == target); + .filter_map(|x| x.interpret_meta()) + .any(|attr| attr == target); } } -impl SynItemHelpers for syn::ForeignItem { - fn has_attr(&self, target: syn::MetaItem) -> bool { +impl SynItemHelpers for syn::ItemFn { + fn has_attr(&self, target: syn::Meta) -> bool { return self.attrs .iter() - .any(|ref attr| attr.style == syn::AttrStyle::Outer && attr.value == target); + .filter_map(|x| x.interpret_meta()) + .any(|attr| attr == target); + } +} + +impl SynItemHelpers for syn::ItemStatic { + fn has_attr(&self, target: syn::Meta) -> bool { + return self.attrs + .iter() + .filter_map(|x| x.interpret_meta()) + .any(|attr| attr == target); } } impl SynItemHelpers for syn::Variant { - fn has_attr(&self, target: syn::MetaItem) -> bool { + fn has_attr(&self, target: syn::Meta) -> bool { return self.attrs .iter() - .any(|ref attr| attr.style == syn::AttrStyle::Outer && attr.value == target); + .filter_map(|x| x.interpret_meta()) + .any(|attr| attr == target); } } impl SynItemHelpers for syn::Field { - fn has_attr(&self, target: syn::MetaItem) -> bool { + fn has_attr(&self, target: syn::Meta) -> bool { return self.attrs .iter() - .any(|ref attr| attr.style == syn::AttrStyle::Outer && attr.value == target); + .filter_map(|x| x.interpret_meta()) + .any(|attr| attr == target); } } @@ -85,18 +98,31 @@ pub trait SynAbiHelpers { impl SynAbiHelpers for Option { fn is_c(&self) -> bool { - self == &Some(syn::Abi::Named(String::from("C"))) + if let &Some(ref abi) = self { + if let Some(ref lit_string) = abi.name { + return lit_string.value() == String::from("C") + } + } + false } fn is_omitted(&self) -> bool { - self == &Some(syn::Abi::Rust) + if let &Some(ref abi) = self { + abi.name.is_none() + } else { + false + } } } impl SynAbiHelpers for syn::Abi { fn is_c(&self) -> bool { - self == &syn::Abi::Named(String::from("C")) + if let Some(ref lit_string) = self.name { + lit_string.value() == String::from("C") + } else { + false + } } fn is_omitted(&self) -> bool { - self == &syn::Abi::Rust + self.name.is_none() } } diff --git a/test.py b/test.py index 174011b..f5020ba 100755 --- a/test.py +++ b/test.py @@ -14,7 +14,7 @@ def build_cbindgen(): return False def cbindgen(path, out, c): - bin = ["target/debug/cbindgen"] + bin = ["cargo", "run", "--"] compile = [path, "-o", out] flags = [] diff --git a/tests/expectations/cfg-field.c b/tests/expectations/cfg-field.c new file mode 100644 index 0000000..e26b4c5 --- /dev/null +++ b/tests/expectations/cfg-field.c @@ -0,0 +1,3 @@ +#include +#include +#include diff --git a/tests/expectations/fail-str.cpp b/tests/expectations/cfg-field.cpp similarity index 51% rename from tests/expectations/fail-str.cpp rename to tests/expectations/cfg-field.cpp index df605c8..6c1e42e 100644 --- a/tests/expectations/fail-str.cpp +++ b/tests/expectations/cfg-field.cpp @@ -1,12 +1,6 @@ #include #include -struct Foo { - const str *x; -}; - extern "C" { -void root(Foo a, const str *b); - } // extern "C" diff --git a/tests/expectations/fail-str.c b/tests/expectations/fail-str.c deleted file mode 100644 index a60843e..0000000 --- a/tests/expectations/fail-str.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include - -typedef struct { - const str *x; -} Foo; - -void root(Foo a, const str *b); diff --git a/tests/rust/cfg-field.rs b/tests/rust/cfg-field.rs new file mode 100644 index 0000000..aed5165 --- /dev/null +++ b/tests/rust/cfg-field.rs @@ -0,0 +1,11 @@ +struct Foo { + #[cfg(windows)] + x: i32, +} + +pub fn foo() { + Foo { + #[cfg(windows)] + x: 0, + }; +} diff --git a/tests/rust/fail-str.rs b/tests/rust/fail-str.rs deleted file mode 100644 index 1306859..0000000 --- a/tests/rust/fail-str.rs +++ /dev/null @@ -1,12 +0,0 @@ -#[repr(C)] -struct Foo<'a> { - x: &'a str, -} - -const BAR: &'static str = ""; - -#[no_mangle] -pub extern "C" fn root( - a: Foo<'static>, - b: &'static str -) { }