Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/cfg_attr #189

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/bindgen/ir/repr.rs
Expand Up @@ -58,6 +58,28 @@ impl Repr {
{
if ident == "repr" {
return Some(nested.into_iter().collect::<Vec<_>>());
} else if ident == "cfg_attr" {
// e.g.: #[cfg_attr(feature = "cffi", repr(C))]
// TODO: interpret firts part like `feature = "cffi"` and check out cfg
let v = nested
.into_iter()
.filter_map(|attr| {
if let syn::NestedMeta::Meta(syn::Meta::List(syn::MetaList {
ident,
nested,
..
})) = attr
{
if ident == "repr" {
return Some(nested.into_iter().collect::<Vec<_>>());
}
}
None
}).flat_map(|i| i)
.collect::<Vec<_>>();
if !v.is_empty() {
return Some(v);
}
}
}
None
Expand Down
77 changes: 37 additions & 40 deletions src/bindgen/utilities.rs
Expand Up @@ -45,68 +45,65 @@ pub trait SynItemHelpers {
}
}

fn has_attr_word(attrs: &Vec<syn::Attribute>, word: &str) -> bool {
return attrs
.iter()
.filter_map(|x| x.interpret_meta())
.any(|attr| match attr {
syn::Meta::Word(ref ident) if ident == word => true,
// e.g.: #[cfg_attr(feature = "cffi", no_mangle)]
// TODO: interpret firts part like `feature = "cffi"` and check out cfg
syn::Meta::List(syn::MetaList {
ref ident,
ref nested,
..
})
if ident == "cfg_attr" =>
{
if nested.into_iter().any(|attr| match attr {
syn::NestedMeta::Meta(syn::Meta::Word(ref ident)) if ident == word => true,
syn::NestedMeta::Meta(syn::Meta::List(syn::MetaList { ident, .. }))
if ident == word =>
{
true
}
_ => false,
}) {
return true;
}
false
}
_ => false,
});
}

impl SynItemHelpers for syn::ItemStruct {
fn has_attr_word(&self, word: &str) -> bool {
return self
.attrs
.iter()
.filter_map(|x| x.interpret_meta())
.any(|attr| match attr {
syn::Meta::Word(ref ident) if ident == word => true,
_ => false,
});
return has_attr_word(&self.attrs, word);
}
}

impl SynItemHelpers for syn::ItemFn {
fn has_attr_word(&self, word: &str) -> bool {
return self
.attrs
.iter()
.filter_map(|x| x.interpret_meta())
.any(|attr| match attr {
syn::Meta::Word(ref ident) if ident == word => true,
_ => false,
});
return has_attr_word(&self.attrs, word);
}
}

impl SynItemHelpers for syn::ItemStatic {
fn has_attr_word(&self, word: &str) -> bool {
return self
.attrs
.iter()
.filter_map(|x| x.interpret_meta())
.any(|attr| match attr {
syn::Meta::Word(ref ident) if ident == word => true,
_ => false,
});
return has_attr_word(&self.attrs, word);
}
}

impl SynItemHelpers for syn::Variant {
fn has_attr_word(&self, word: &str) -> bool {
return self
.attrs
.iter()
.filter_map(|x| x.interpret_meta())
.any(|attr| match attr {
syn::Meta::Word(ref ident) if ident == word => true,
_ => false,
});
return has_attr_word(&self.attrs, word);
}
}

impl SynItemHelpers for syn::Field {
fn has_attr_word(&self, word: &str) -> bool {
return self
.attrs
.iter()
.filter_map(|x| x.interpret_meta())
.any(|attr| match attr {
syn::Meta::Word(ref ident) if ident == word => true,
_ => false,
});
return has_attr_word(&self.attrs, word);
}
}

Expand Down
20 changes: 20 additions & 0 deletions tests/expectations/both/cfg_attr.c
@@ -0,0 +1,20 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct Normal {
int32_t x;
float y;
} Normal;

typedef struct TupleRenamed {
int32_t m0;
float m1;
} TupleRenamed;

typedef struct TupleNamed {
int32_t x;
float y;
} TupleNamed;

void root(Normal b, TupleRenamed d, TupleNamed e);
20 changes: 20 additions & 0 deletions tests/expectations/cfg_attr.c
@@ -0,0 +1,20 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct {
int32_t x;
float y;
} Normal;

typedef struct {
int32_t m0;
float m1;
} TupleRenamed;

typedef struct {
int32_t x;
float y;
} TupleNamed;

void root(Normal b, TupleRenamed d, TupleNamed e);
23 changes: 23 additions & 0 deletions tests/expectations/cfg_attr.cpp
@@ -0,0 +1,23 @@
#include <cstdint>
#include <cstdlib>

struct Normal {
int32_t x;
float y;
};

struct TupleRenamed {
int32_t m0;
float m1;
};

struct TupleNamed {
int32_t x;
float y;
};

extern "C" {

void root(Normal b, TupleRenamed d, TupleNamed e);

} // extern "C"
20 changes: 20 additions & 0 deletions tests/expectations/tag/cfg_attr.c
@@ -0,0 +1,20 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>

struct Normal {
int32_t x;
float y;
};

struct TupleRenamed {
int32_t m0;
float m1;
};

struct TupleNamed {
int32_t x;
float y;
};

void root(struct Normal b, struct TupleRenamed d, struct TupleNamed e);
20 changes: 20 additions & 0 deletions tests/rust/cfg_attr.rs
@@ -0,0 +1,20 @@
#[cfg_attr(feature = "cffi", repr(C))]
struct Normal {
x: i32,
y: f32,
}

/// cbindgen:rename-all=GeckoCase
#[cfg_attr(feature = "cffi", repr(C))]
struct TupleRenamed(i32, f32);

/// cbindgen:field-names=[x, y]
#[cfg_attr(feature = "cffi", repr(C))]
struct TupleNamed(i32, f32);

#[cfg_attr(feature = "cffi", no_mangle)]
pub extern "C" fn root(
b: Normal,
d: TupleRenamed,
e: TupleNamed
) { }