summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/objc.rs52
-rw-r--r--src/ir/ty.rs5
-rw-r--r--tests/expectations/tests/objc_whitelist.rs25
-rw-r--r--tests/headers/objc_whitelist.h22
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
+