summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--book/src/objc.md2
-rw-r--r--src/codegen/mod.rs32
-rw-r--r--tests/expectations/tests/objc_blocklist.rs42
-rw-r--r--tests/headers/objc_blocklist.h9
4 files changed, 78 insertions, 7 deletions
diff --git a/book/src/objc.md b/book/src/objc.md
index 60e5638d..ce6d7567 100644
--- a/book/src/objc.md
+++ b/book/src/objc.md
@@ -32,6 +32,8 @@ methods found in `NSObject`.
In order to initialize a class `Foo`, you will have to do something like `let
foo = Foo(Foo::alloc().initWithStuff())`.
+To blocklist an Objective-C method, you should add the bindgen generated method
+path (e.g. `IFoo::method` or `IFoo::class_method`) as a blocklist item.
## Supported Features
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 5660b126..a8a7b076 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -4191,9 +4191,19 @@ impl CodeGenerator for Function {
fn objc_method_codegen(
ctx: &BindgenContext,
method: &ObjCMethod,
+ methods: &mut Vec<proc_macro2::TokenStream>,
class_name: Option<&str>,
+ rust_class_name: &str,
prefix: &str,
-) -> proc_macro2::TokenStream {
+) {
+ // This would ideally resolve the method into an Item, and use
+ // Item::process_before_codegen; however, ObjC methods are not currently
+ // made into function items.
+ let name = format!("{}::{}{}", rust_class_name, prefix, method.rust_name());
+ if ctx.options().blocklisted_items.matches(name) {
+ return;
+ }
+
let signature = method.signature();
let fn_args = utils::fnsig_arguments(ctx, signature);
let fn_ret = utils::fnsig_return_ty(ctx, signature);
@@ -4229,11 +4239,11 @@ fn objc_method_codegen(
let method_name =
ctx.rust_ident(format!("{}{}", prefix, method.rust_name()));
- quote! {
+ methods.push(quote! {
unsafe fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized {
#body
}
- }
+ });
}
impl CodeGenerator for ObjCInterface {
@@ -4249,10 +4259,17 @@ impl CodeGenerator for ObjCInterface {
debug_assert!(item.is_enabled_for_codegen(ctx));
let mut impl_items = vec![];
+ let rust_class_name = item.path_for_allowlisting(ctx)[1..].join("::");
for method in self.methods() {
- let impl_item = objc_method_codegen(ctx, method, None, "");
- impl_items.push(impl_item);
+ objc_method_codegen(
+ ctx,
+ method,
+ &mut impl_items,
+ None,
+ &rust_class_name,
+ "",
+ );
}
for class_method in self.class_methods() {
@@ -4262,13 +4279,14 @@ impl CodeGenerator for ObjCInterface {
.map(|m| m.rust_name())
.any(|x| x == class_method.rust_name());
let prefix = if ambiquity { "class_" } else { "" };
- let impl_item = objc_method_codegen(
+ objc_method_codegen(
ctx,
class_method,
+ &mut impl_items,
Some(self.name()),
+ &rust_class_name,
prefix,
);
- impl_items.push(impl_item);
}
let trait_name = ctx.rust_ident(self.rust_name());
diff --git a/tests/expectations/tests/objc_blocklist.rs b/tests/expectations/tests/objc_blocklist.rs
new file mode 100644
index 00000000..7d5d19b0
--- /dev/null
+++ b/tests/expectations/tests/objc_blocklist.rs
@@ -0,0 +1,42 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+#![cfg(target_os = "macos")]
+
+#[macro_use]
+extern crate objc;
+#[allow(non_camel_case_types)]
+pub type id = *mut objc::runtime::Object;
+#[repr(transparent)]
+#[derive(Debug, Copy, Clone)]
+pub struct SomeClass(pub id);
+impl std::ops::Deref for SomeClass {
+ type Target = objc::runtime::Object;
+ fn deref(&self) -> &Self::Target {
+ unsafe { &*self.0 }
+ }
+}
+unsafe impl objc::Message for SomeClass {}
+impl SomeClass {
+ pub fn alloc() -> Self {
+ Self(unsafe { msg_send!(class!(SomeClass), alloc) })
+ }
+}
+impl ISomeClass for SomeClass {}
+pub trait ISomeClass: Sized + std::ops::Deref {
+ unsafe fn ambiguouslyBlockedMethod(&self)
+ where
+ <Self as std::ops::Deref>::Target: objc::Message + Sized,
+ {
+ msg_send!(*self, ambiguouslyBlockedMethod)
+ }
+ unsafe fn instanceMethod(&self)
+ where
+ <Self as std::ops::Deref>::Target: objc::Message + Sized,
+ {
+ msg_send!(*self, instanceMethod)
+ }
+}
diff --git a/tests/headers/objc_blocklist.h b/tests/headers/objc_blocklist.h
new file mode 100644
index 00000000..605f2993
--- /dev/null
+++ b/tests/headers/objc_blocklist.h
@@ -0,0 +1,9 @@
+// bindgen-flags: --objc-extern-crate --blocklist-item ISomeClass::class_ambiguouslyBlockedMethod --blocklist-item ISomeClass::blockedInstanceMethod -- -x objective-c
+// bindgen-osx-only
+
+@interface SomeClass
++ (void)ambiguouslyBlockedMethod;
+- (void)ambiguouslyBlockedMethod;
+- (void)instanceMethod;
+- (void)blockedInstanceMethod;
+@end