diff options
-rw-r--r-- | src/ir/objc.rs | 52 | ||||
-rw-r--r-- | src/ir/ty.rs | 5 | ||||
-rw-r--r-- | tests/expectations/tests/objc_whitelist.rs | 25 | ||||
-rw-r--r-- | tests/headers/objc_whitelist.h | 22 |
4 files changed, 101 insertions, 3 deletions
diff --git a/src/ir/objc.rs b/src/ir/objc.rs index 963c8e20..485bda8a 100644 --- a/src/ir/objc.rs +++ b/src/ir/objc.rs @@ -1,13 +1,16 @@ //! Objective C types -use super::context::BindgenContext; +use super::context::{BindgenContext, ItemId}; use super::function::FunctionSig; +use super::traversal::{Trace, Tracer}; +use super::ty::TypeKind; use clang; use clang_sys::CXChildVisit_Continue; use clang_sys::CXCursor_ObjCCategoryDecl; use clang_sys::CXCursor_ObjCClassRef; use clang_sys::CXCursor_ObjCInstanceMethodDecl; use clang_sys::CXCursor_ObjCProtocolDecl; +use clang_sys::CXCursor_ObjCProtocolRef; /// Objective C interface as used in TypeKind /// @@ -22,6 +25,8 @@ pub struct ObjCInterface { is_protocol: bool, + conforms_to: Vec<ItemId>, + /// List of the methods defined in this interfae methods: Vec<ObjCInstanceMethod>, } @@ -46,6 +51,7 @@ impl ObjCInterface { name: name.to_owned(), category: None, is_protocol: false, + conforms_to: Vec::new(), methods: Vec::new(), } } @@ -97,6 +103,34 @@ impl ObjCInterface { interface.category = Some(cursor.spelling()); } } + CXCursor_ObjCProtocolRef => { + // Gather protocols this interface conforms to + let needle = format!("protocol_{}", c.spelling()); + let items_map = ctx.items(); + debug!("Interface {} conforms to {}, find the item", interface.name, needle); + + for (id, item) in items_map + { + if let Some(ty) = item.as_type() { + match *ty.kind() { + TypeKind::ObjCInterface(ref protocol) => { + if protocol.is_protocol + { + debug!("Checking protocol {}, ty.name {:?}", protocol.name, ty.name()); + if Some(needle.as_ref()) == ty.name() + { + debug!("Found conforming protocol {:?}", item); + interface.conforms_to.push(*id); + break; + } + } + } + _ => {} + } + } + } + + } CXCursor_ObjCInstanceMethodDecl => { let name = c.spelling(); let signature = @@ -168,3 +202,19 @@ impl ObjCInstanceMethod { .join("") } } + +impl Trace for ObjCInterface { + type Extra = (); + + fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, _: &()) + where T: Tracer, + { + for method in &self.methods { + method.signature.trace(context, tracer, &()); + } + + for protocol in &self.conforms_to { + tracer.visit(*protocol); + } + } +} diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 329f4f54..51652000 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -1268,6 +1268,7 @@ impl Type { CXType_ObjCInterface => { let interface = ObjCInterface::from_ty(&location.unwrap(), ctx) .expect("Not a valid objc interface?"); + name = interface.rust_name(); TypeKind::ObjCInterface(interface) } _ => { @@ -1325,8 +1326,8 @@ impl Trace for Type { tracer.visit(id); } - TypeKind::ObjCInterface(_) => { - // TODO: + TypeKind::ObjCInterface(ref interface) => { + interface.trace(context, tracer, &()); } // None of these variants have edges to other items and types. diff --git a/tests/expectations/tests/objc_whitelist.rs b/tests/expectations/tests/objc_whitelist.rs new file mode 100644 index 00000000..332453f1 --- /dev/null +++ b/tests/expectations/tests/objc_whitelist.rs @@ -0,0 +1,25 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + +#![cfg(target_os="macos")] + +#[macro_use] +extern crate objc; +#[allow(non_camel_case_types)] +pub type id = *mut objc::runtime::Object; +pub trait protocol_SomeProtocol { + unsafe fn protocolMethod(self); +} +impl protocol_SomeProtocol for id { + unsafe fn protocolMethod(self) { msg_send!(self , protocolMethod) } +} +pub trait WhitelistMe { + unsafe fn method(self); +} +impl WhitelistMe for id { + unsafe fn method(self) { msg_send!(self , method) } +} +pub trait WhitelistMe_InterestingCategory { } +impl WhitelistMe_InterestingCategory for id { } diff --git a/tests/headers/objc_whitelist.h b/tests/headers/objc_whitelist.h new file mode 100644 index 00000000..7cbe43d6 --- /dev/null +++ b/tests/headers/objc_whitelist.h @@ -0,0 +1,22 @@ +// bindgen-flags: --objc-extern-crate --whitelist-type WhitelistMe --whitelist-type WhitelistMe_InterestingCategory -- -x objective-c +// bindgen-osx-only + + +// Protocol should be included, since it is used by the WhitelistMe +@protocol SomeProtocol +-(void)protocolMethod; +@end + +// The whitelisted item +@interface WhitelistMe <SomeProtocol> +-(void)method; +@end + +// This was also explicitly whitelisted +@interface WhitelistMe (InterestingCategory) +@end + +// This was not automatically whitelisted +@interface WhitelistMe (IgnoredCategory) +@end + |