Skip to content

Commit 4c1fb08

Browse files
committed
Added inheritance to objective-c support and changed unsafe logic.
1 parent 63ae30b commit 4c1fb08

11 files changed

+191
-47
lines changed

src/codegen/mod.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3674,19 +3674,19 @@ fn objc_method_codegen(
36743674
.to_owned(),
36753675
);
36763676
quote! {
3677-
msg_send!(class!(#class_name), #methods_and_args)
3677+
unsafe { msg_send!(class!(#class_name), #methods_and_args) }
36783678
}
36793679
} else {
36803680
quote! {
3681-
msg_send!(self, #methods_and_args)
3681+
unsafe { msg_send!(self, #methods_and_args) }
36823682
}
36833683
};
36843684

36853685
let method_name =
36863686
ctx.rust_ident(format!("{}{}", prefix, method.rust_name()));
36873687

36883688
quote! {
3689-
unsafe fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized {
3689+
fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized {
36903690
#body
36913691
}
36923692
}
@@ -3785,6 +3785,31 @@ impl CodeGenerator for ObjCInterface {
37853785
};
37863786
result.push(impl_trait);
37873787
}
3788+
for parent_id in self.parent_classes.iter() {
3789+
match ctx.resolve_type(parent_id.expect_type_id(ctx)).kind() {
3790+
TypeKind::ObjCInterface(ref parent) => {
3791+
let parent_name = ctx.rust_ident(parent.rust_name());
3792+
let impl_trait = if parent.is_template() {
3793+
let template_names: Vec<Ident> = parent
3794+
.template_names
3795+
.iter()
3796+
.map(|g| ctx.rust_ident(g))
3797+
.collect();
3798+
quote! {
3799+
impl <#(#template_names :'static),*> #parent_name <#(#template_names),*> for #class_name {
3800+
}
3801+
}
3802+
} else {
3803+
quote! {
3804+
impl #parent_name for #class_name { }
3805+
}
3806+
};
3807+
result.push(impl_trait);
3808+
}
3809+
_ => {}
3810+
}
3811+
3812+
}
37883813
}
37893814

37903815
if !self.is_protocol() {

src/ir/objc.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::ty::TypeKind;
77
use clang;
88
use clang_sys::CXChildVisit_Continue;
99
use clang_sys::CXCursor_ObjCCategoryDecl;
10+
use clang_sys::CXCursor_ObjCSuperClassRef;
1011
use clang_sys::CXCursor_ObjCClassMethodDecl;
1112
use clang_sys::CXCursor_ObjCClassRef;
1213
use clang_sys::CXCursor_ObjCInstanceMethodDecl;
@@ -34,6 +35,8 @@ pub struct ObjCInterface {
3435
/// The list of protocols that this interface conforms to.
3536
pub conforms_to: Vec<ItemId>,
3637

38+
pub parent_classes: Vec<ItemId>,
39+
3740
/// List of the methods defined in this interfae
3841
methods: Vec<ObjCMethod>,
3942

@@ -64,6 +67,7 @@ impl ObjCInterface {
6467
category: None,
6568
is_protocol: false,
6669
template_names: Vec::new(),
70+
parent_classes: Vec::new(),
6771
conforms_to: Vec::new(),
6872
methods: Vec::new(),
6973
class_methods: Vec::new(),
@@ -179,6 +183,35 @@ impl ObjCInterface {
179183
let name = c.spelling();
180184
interface.template_names.push(name);
181185
}
186+
CXCursor_ObjCSuperClassRef => {
187+
let items_map = ctx.items();
188+
189+
let needle = format!("I{}", c.spelling());
190+
debug!("Interface {} has a parent class {}, find the item", interface.name, needle);
191+
192+
for (id, item) in items_map
193+
{
194+
if let Some(ty) = item.as_type() {
195+
match *ty.kind() {
196+
TypeKind::ObjCInterface(ref class) => {
197+
if !class.is_protocol
198+
{
199+
debug!("Checking class {}, ty.name {:?}", class.name, ty.name());
200+
if Some(needle.as_ref()) == ty.name() {
201+
debug!("Found parent class {:?}", item);
202+
interface.parent_classes.push(id);
203+
for i in class.parent_classes.clone() {
204+
interface.parent_classes.push(i);
205+
}
206+
break;
207+
}
208+
}
209+
}
210+
_=> {}
211+
}
212+
}
213+
}
214+
},
182215
_ => {}
183216
}
184217
CXChildVisit_Continue
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(
4+
dead_code,
5+
non_snake_case,
6+
non_camel_case_types,
7+
non_upper_case_globals
8+
)]
9+
#![cfg(target_os = "macos")]
10+
11+
#[macro_use]
12+
extern crate objc;
13+
#[allow(non_camel_case_types)]
14+
pub type id = *mut objc::runtime::Object;
15+
#[repr(transparent)]
16+
#[derive(Clone, Copy)]
17+
pub struct Baz(pub id);
18+
impl std::ops::Deref for Baz {
19+
type Target = objc::runtime::Object;
20+
fn deref(&self) -> &Self::Target {
21+
unsafe { &*self.0 }
22+
}
23+
}
24+
unsafe impl objc::Message for Baz {}
25+
impl Baz {
26+
pub fn alloc() -> Self {
27+
Self(unsafe { msg_send!(objc::class!(Baz), alloc) })
28+
}
29+
}
30+
impl IBaz for Baz {}
31+
pub trait IBaz: Sized + std::ops::Deref {
32+
fn initWithFirstNumber_(
33+
self,
34+
firstNumber: ::std::os::raw::c_int,
35+
) -> instancetype
36+
where
37+
<Self as std::ops::Deref>::Target: objc::Message + Sized,
38+
{
39+
unsafe { msg_send!(self, initWithFirstNumber: firstNumber) }
40+
}
41+
}
42+
#[repr(transparent)]
43+
#[derive(Clone, Copy)]
44+
pub struct Foo(pub id);
45+
impl std::ops::Deref for Foo {
46+
type Target = objc::runtime::Object;
47+
fn deref(&self) -> &Self::Target {
48+
unsafe { &*self.0 }
49+
}
50+
}
51+
unsafe impl objc::Message for Foo {}
52+
impl Foo {
53+
pub fn alloc() -> Self {
54+
Self(unsafe { msg_send!(objc::class!(Foo), alloc) })
55+
}
56+
}
57+
impl IBaz for Foo {}
58+
impl IFoo for Foo {}
59+
pub trait IFoo: Sized + std::ops::Deref {
60+
fn initWithFirstNumber_(
61+
self,
62+
firstNumber: ::std::os::raw::c_int,
63+
) -> instancetype
64+
where
65+
<Self as std::ops::Deref>::Target: objc::Message + Sized,
66+
{
67+
unsafe { msg_send!(self, initWithFirstNumber: firstNumber) }
68+
}
69+
}
70+
pub type instancetype = id;

tests/expectations/tests/libclang-9/objc_template.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ impl Foo {
2929
}
3030
impl<ObjectType: 'static> IFoo<ObjectType> for Foo {}
3131
pub trait IFoo<ObjectType>: Sized + std::ops::Deref {
32-
unsafe fn get(self) -> u64
32+
fn get(self) -> u64
3333
where
3434
<Self as std::ops::Deref>::Target: objc::Message + Sized,
3535
{
36-
msg_send!(self, get)
36+
unsafe { msg_send!(self, get) }
3737
}
3838
}
3939
#[repr(transparent)]
@@ -58,10 +58,10 @@ impl<KeyType: 'static, ObjectType: 'static>
5858
pub trait IFooMultiGeneric<KeyType, ObjectType>:
5959
Sized + std::ops::Deref
6060
{
61-
unsafe fn objectForKey_(self, key: u64) -> u64
61+
fn objectForKey_(self, key: u64) -> u64
6262
where
6363
<Self as std::ops::Deref>::Target: objc::Message + Sized,
6464
{
65-
msg_send!(self, objectForKey: key)
65+
unsafe { msg_send!(self, objectForKey: key) }
6666
}
6767
}

tests/expectations/tests/objc_category.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,19 @@ impl Foo {
2929
}
3030
impl IFoo for Foo {}
3131
pub trait IFoo: Sized + std::ops::Deref {
32-
unsafe fn method(self)
32+
fn method(self)
3333
where
3434
<Self as std::ops::Deref>::Target: objc::Message + Sized,
3535
{
36-
msg_send!(self, method)
36+
unsafe { msg_send!(self, method) }
3737
}
3838
}
3939
impl Foo_BarCategory for Foo {}
4040
pub trait Foo_BarCategory: Sized + std::ops::Deref {
41-
unsafe fn categoryMethod(self)
41+
fn categoryMethod(self)
4242
where
4343
<Self as std::ops::Deref>::Target: objc::Message + Sized,
4444
{
45-
msg_send!(self, categoryMethod)
45+
unsafe { msg_send!(self, categoryMethod) }
4646
}
4747
}

tests/expectations/tests/objc_class.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ impl Foo {
3232
}
3333
impl IFoo for Foo {}
3434
pub trait IFoo: Sized + std::ops::Deref {
35-
unsafe fn method(self)
35+
fn method(self)
3636
where
3737
<Self as std::ops::Deref>::Target: objc::Message + Sized,
3838
{
39-
msg_send!(self, method)
39+
unsafe { msg_send!(self, method) }
4040
}
4141
}

tests/expectations/tests/objc_class_method.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,43 +29,45 @@ impl Foo {
2929
}
3030
impl IFoo for Foo {}
3131
pub trait IFoo: Sized + std::ops::Deref {
32-
unsafe fn method()
32+
fn method()
3333
where
3434
<Self as std::ops::Deref>::Target: objc::Message + Sized,
3535
{
36-
msg_send!(class!(Foo), method)
36+
unsafe { msg_send!(class!(Foo), method) }
3737
}
38-
unsafe fn methodWithInt_(foo: ::std::os::raw::c_int)
38+
fn methodWithInt_(foo: ::std::os::raw::c_int)
3939
where
4040
<Self as std::ops::Deref>::Target: objc::Message + Sized,
4141
{
42-
msg_send!(class!(Foo), methodWithInt: foo)
42+
unsafe { msg_send!(class!(Foo), methodWithInt: foo) }
4343
}
44-
unsafe fn methodWithFoo_(foo: id)
44+
fn methodWithFoo_(foo: id)
4545
where
4646
<Self as std::ops::Deref>::Target: objc::Message + Sized,
4747
{
48-
msg_send!(class!(Foo), methodWithFoo: foo)
48+
unsafe { msg_send!(class!(Foo), methodWithFoo: foo) }
4949
}
50-
unsafe fn methodReturningInt() -> ::std::os::raw::c_int
50+
fn methodReturningInt() -> ::std::os::raw::c_int
5151
where
5252
<Self as std::ops::Deref>::Target: objc::Message + Sized,
5353
{
54-
msg_send!(class!(Foo), methodReturningInt)
54+
unsafe { msg_send!(class!(Foo), methodReturningInt) }
5555
}
56-
unsafe fn methodReturningFoo() -> *mut objc::runtime::Object
56+
fn methodReturningFoo() -> *mut objc::runtime::Object
5757
where
5858
<Self as std::ops::Deref>::Target: objc::Message + Sized,
5959
{
60-
msg_send!(class!(Foo), methodReturningFoo)
60+
unsafe { msg_send!(class!(Foo), methodReturningFoo) }
6161
}
62-
unsafe fn methodWithArg1_andArg2_andArg3_(
62+
fn methodWithArg1_andArg2_andArg3_(
6363
intvalue: ::std::os::raw::c_int,
6464
ptr: *mut ::std::os::raw::c_char,
6565
floatvalue: f32,
6666
) where
6767
<Self as std::ops::Deref>::Target: objc::Message + Sized,
6868
{
69-
msg_send ! ( class ! ( Foo ) , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue )
69+
unsafe {
70+
msg_send ! ( class ! ( Foo ) , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue )
71+
}
7072
}
7173
}

tests/expectations/tests/objc_method.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,47 +29,49 @@ impl Foo {
2929
}
3030
impl IFoo for Foo {}
3131
pub trait IFoo: Sized + std::ops::Deref {
32-
unsafe fn method(self)
32+
fn method(self)
3333
where
3434
<Self as std::ops::Deref>::Target: objc::Message + Sized,
3535
{
36-
msg_send!(self, method)
36+
unsafe { msg_send!(self, method) }
3737
}
38-
unsafe fn methodWithInt_(self, foo: ::std::os::raw::c_int)
38+
fn methodWithInt_(self, foo: ::std::os::raw::c_int)
3939
where
4040
<Self as std::ops::Deref>::Target: objc::Message + Sized,
4141
{
42-
msg_send!(self, methodWithInt: foo)
42+
unsafe { msg_send!(self, methodWithInt: foo) }
4343
}
44-
unsafe fn methodWithFoo_(self, foo: id)
44+
fn methodWithFoo_(self, foo: id)
4545
where
4646
<Self as std::ops::Deref>::Target: objc::Message + Sized,
4747
{
48-
msg_send!(self, methodWithFoo: foo)
48+
unsafe { msg_send!(self, methodWithFoo: foo) }
4949
}
50-
unsafe fn methodReturningInt(self) -> ::std::os::raw::c_int
50+
fn methodReturningInt(self) -> ::std::os::raw::c_int
5151
where
5252
<Self as std::ops::Deref>::Target: objc::Message + Sized,
5353
{
54-
msg_send!(self, methodReturningInt)
54+
unsafe { msg_send!(self, methodReturningInt) }
5555
}
56-
unsafe fn methodReturningFoo(self) -> *mut objc::runtime::Object
56+
fn methodReturningFoo(self) -> *mut objc::runtime::Object
5757
where
5858
<Self as std::ops::Deref>::Target: objc::Message + Sized,
5959
{
60-
msg_send!(self, methodReturningFoo)
60+
unsafe { msg_send!(self, methodReturningFoo) }
6161
}
62-
unsafe fn methodWithArg1_andArg2_andArg3_(
62+
fn methodWithArg1_andArg2_andArg3_(
6363
self,
6464
intvalue: ::std::os::raw::c_int,
6565
ptr: *mut ::std::os::raw::c_char,
6666
floatvalue: f32,
6767
) where
6868
<Self as std::ops::Deref>::Target: objc::Message + Sized,
6969
{
70-
msg_send ! ( self , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue )
70+
unsafe {
71+
msg_send ! ( self , methodWithArg1 : intvalue andArg2 : ptr andArg3 : floatvalue )
72+
}
7173
}
72-
unsafe fn methodWithAndWithoutKeywords_arg2Name__arg4Name_(
74+
fn methodWithAndWithoutKeywords_arg2Name__arg4Name_(
7375
self,
7476
arg1: ::std::os::raw::c_int,
7577
arg2: f32,
@@ -79,7 +81,9 @@ pub trait IFoo: Sized + std::ops::Deref {
7981
where
8082
<Self as std::ops::Deref>::Target: objc::Message + Sized,
8183
{
82-
msg_send ! ( self , methodWithAndWithoutKeywords : arg1 arg2Name : arg2 arg3 : arg3 arg4Name : arg4 )
84+
unsafe {
85+
msg_send ! ( self , methodWithAndWithoutKeywords : arg1 arg2Name : arg2 arg3 : arg3 arg4Name : arg4 )
86+
}
8387
}
8488
}
8589
pub type instancetype = id;

0 commit comments

Comments
 (0)