Skip to content

Commit fcc1096

Browse files
authored
Merge pull request #1750 from simlay/objc-inheritance
Objective-c inheritance support
2 parents ee2f289 + 1f324ca commit fcc1096

File tree

8 files changed

+398
-1
lines changed

8 files changed

+398
-1
lines changed

src/codegen/mod.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3791,6 +3791,41 @@ impl CodeGenerator for ObjCInterface {
37913791
};
37923792
result.push(impl_trait);
37933793
}
3794+
let mut parent_class = self.parent_class;
3795+
while let Some(parent_id) = parent_class {
3796+
let parent = parent_id
3797+
.expect_type_id(ctx)
3798+
.into_resolver()
3799+
.through_type_refs()
3800+
.resolve(ctx)
3801+
.expect_type()
3802+
.kind();
3803+
3804+
parent_class = if let TypeKind::ObjCInterface(ref parent) =
3805+
parent
3806+
{
3807+
let parent_name = ctx.rust_ident(parent.rust_name());
3808+
let impl_trait = if parent.is_template() {
3809+
let template_names: Vec<Ident> = parent
3810+
.template_names
3811+
.iter()
3812+
.map(|g| ctx.rust_ident(g))
3813+
.collect();
3814+
quote! {
3815+
impl <#(#template_names :'static),*> #parent_name <#(#template_names),*> for #class_name {
3816+
}
3817+
}
3818+
} else {
3819+
quote! {
3820+
impl #parent_name for #class_name { }
3821+
}
3822+
};
3823+
result.push(impl_trait);
3824+
parent.parent_class
3825+
} else {
3826+
None
3827+
};
3828+
}
37943829
}
37953830

37963831
if !self.is_protocol() {

src/ir/objc.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@
22
33
use super::context::{BindgenContext, ItemId};
44
use super::function::FunctionSig;
5+
use super::item::Item;
56
use super::traversal::{Trace, Tracer};
67
use super::ty::TypeKind;
78
use crate::clang;
9+
use crate::parse::ClangItemParser;
810
use clang_sys::CXChildVisit_Continue;
911
use clang_sys::CXCursor_ObjCCategoryDecl;
1012
use clang_sys::CXCursor_ObjCClassMethodDecl;
1113
use clang_sys::CXCursor_ObjCClassRef;
1214
use clang_sys::CXCursor_ObjCInstanceMethodDecl;
1315
use clang_sys::CXCursor_ObjCProtocolDecl;
1416
use clang_sys::CXCursor_ObjCProtocolRef;
17+
use clang_sys::CXCursor_ObjCSuperClassRef;
1518
use clang_sys::CXCursor_TemplateTypeParameter;
1619
use proc_macro2::{Ident, Span, TokenStream};
1720

@@ -34,6 +37,9 @@ pub struct ObjCInterface {
3437
/// The list of protocols that this interface conforms to.
3538
pub conforms_to: Vec<ItemId>,
3639

40+
/// The direct parent for this interface.
41+
pub parent_class: Option<ItemId>,
42+
3743
/// List of the methods defined in this interfae
3844
methods: Vec<ObjCMethod>,
3945

@@ -64,6 +70,7 @@ impl ObjCInterface {
6470
category: None,
6571
is_protocol: false,
6672
template_names: Vec::new(),
73+
parent_class: None,
6774
conforms_to: Vec::new(),
6875
methods: Vec::new(),
6976
class_methods: Vec::new(),
@@ -146,7 +153,7 @@ impl ObjCInterface {
146153

147154
for (id, item) in items_map
148155
{
149-
if let Some(ty) = item.as_type() {
156+
if let Some(ty) = item.as_type() {
150157
match *ty.kind() {
151158
TypeKind::ObjCInterface(ref protocol) => {
152159
if protocol.is_protocol
@@ -179,6 +186,10 @@ impl ObjCInterface {
179186
let name = c.spelling();
180187
interface.template_names.push(name);
181188
}
189+
CXCursor_ObjCSuperClassRef => {
190+
let item = Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
191+
interface.parent_class = Some(item.into());
192+
},
182193
_ => {}
183194
}
184195
CXChildVisit_Continue
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 Foo(pub id);
18+
impl std::ops::Deref for Foo {
19+
type Target = objc::runtime::Object;
20+
fn deref(&self) -> &Self::Target {
21+
unsafe { &*self.0 }
22+
}
23+
}
24+
unsafe impl objc::Message for Foo {}
25+
impl Foo {
26+
pub fn alloc() -> Self {
27+
Self(unsafe { msg_send!(objc::class!(Foo), alloc) })
28+
}
29+
}
30+
impl IFoo for Foo {}
31+
pub trait IFoo: Sized + std::ops::Deref {}
32+
#[repr(transparent)]
33+
#[derive(Clone, Copy)]
34+
pub struct Bar(pub id);
35+
impl std::ops::Deref for Bar {
36+
type Target = objc::runtime::Object;
37+
fn deref(&self) -> &Self::Target {
38+
unsafe { &*self.0 }
39+
}
40+
}
41+
unsafe impl objc::Message for Bar {}
42+
impl Bar {
43+
pub fn alloc() -> Self {
44+
Self(unsafe { msg_send!(objc::class!(Bar), alloc) })
45+
}
46+
}
47+
impl IFoo for Bar {}
48+
impl IBar for Bar {}
49+
pub trait IBar: Sized + std::ops::Deref {}
50+
#[repr(transparent)]
51+
#[derive(Clone, Copy)]
52+
pub struct Baz(pub id);
53+
impl std::ops::Deref for Baz {
54+
type Target = objc::runtime::Object;
55+
fn deref(&self) -> &Self::Target {
56+
unsafe { &*self.0 }
57+
}
58+
}
59+
unsafe impl objc::Message for Baz {}
60+
impl Baz {
61+
pub fn alloc() -> Self {
62+
Self(unsafe { msg_send!(objc::class!(Baz), alloc) })
63+
}
64+
}
65+
impl IBar for Baz {}
66+
impl IFoo for Baz {}
67+
impl IBaz for Baz {}
68+
pub trait IBaz: Sized + std::ops::Deref {}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 Foo(pub id);
18+
impl std::ops::Deref for Foo {
19+
type Target = objc::runtime::Object;
20+
fn deref(&self) -> &Self::Target {
21+
unsafe { &*self.0 }
22+
}
23+
}
24+
unsafe impl objc::Message for Foo {}
25+
impl Foo {
26+
pub fn alloc() -> Self {
27+
Self(unsafe { msg_send!(objc::class!(Foo), alloc) })
28+
}
29+
}
30+
impl IFoo for Foo {}
31+
pub trait IFoo: Sized + std::ops::Deref {}
32+
#[repr(transparent)]
33+
#[derive(Clone, Copy)]
34+
pub struct Bar(pub id);
35+
impl std::ops::Deref for Bar {
36+
type Target = objc::runtime::Object;
37+
fn deref(&self) -> &Self::Target {
38+
unsafe { &*self.0 }
39+
}
40+
}
41+
unsafe impl objc::Message for Bar {}
42+
impl Bar {
43+
pub fn alloc() -> Self {
44+
Self(unsafe { msg_send!(objc::class!(Bar), alloc) })
45+
}
46+
}
47+
impl IFoo for Bar {}
48+
impl IBar for Bar {}
49+
pub trait IBar: Sized + std::ops::Deref {}
50+
#[repr(transparent)]
51+
#[derive(Clone, Copy)]
52+
pub struct Baz(pub id);
53+
impl std::ops::Deref for Baz {
54+
type Target = objc::runtime::Object;
55+
fn deref(&self) -> &Self::Target {
56+
unsafe { &*self.0 }
57+
}
58+
}
59+
unsafe impl objc::Message for Baz {}
60+
impl Baz {
61+
pub fn alloc() -> Self {
62+
Self(unsafe { msg_send!(objc::class!(Baz), alloc) })
63+
}
64+
}
65+
impl IBar for Baz {}
66+
impl IFoo for Baz {}
67+
impl IBaz for Baz {}
68+
pub trait IBaz: Sized + std::ops::Deref {}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 Foo(pub id);
18+
impl std::ops::Deref for Foo {
19+
type Target = objc::runtime::Object;
20+
fn deref(&self) -> &Self::Target {
21+
unsafe { &*self.0 }
22+
}
23+
}
24+
unsafe impl objc::Message for Foo {}
25+
impl Foo {
26+
pub fn alloc() -> Self {
27+
Self(unsafe { msg_send!(objc::class!(Foo), alloc) })
28+
}
29+
}
30+
impl IFoo for Foo {}
31+
pub trait IFoo: Sized + std::ops::Deref {}
32+
#[repr(transparent)]
33+
#[derive(Clone, Copy)]
34+
pub struct Bar(pub id);
35+
impl std::ops::Deref for Bar {
36+
type Target = objc::runtime::Object;
37+
fn deref(&self) -> &Self::Target {
38+
unsafe { &*self.0 }
39+
}
40+
}
41+
unsafe impl objc::Message for Bar {}
42+
impl Bar {
43+
pub fn alloc() -> Self {
44+
Self(unsafe { msg_send!(objc::class!(Bar), alloc) })
45+
}
46+
}
47+
impl IFoo for Bar {}
48+
impl IBar for Bar {}
49+
pub trait IBar: Sized + std::ops::Deref {}
50+
#[repr(transparent)]
51+
#[derive(Clone, Copy)]
52+
pub struct Baz(pub id);
53+
impl std::ops::Deref for Baz {
54+
type Target = objc::runtime::Object;
55+
fn deref(&self) -> &Self::Target {
56+
unsafe { &*self.0 }
57+
}
58+
}
59+
unsafe impl objc::Message for Baz {}
60+
impl Baz {
61+
pub fn alloc() -> Self {
62+
Self(unsafe { msg_send!(objc::class!(Baz), alloc) })
63+
}
64+
}
65+
impl IBar for Baz {}
66+
impl IFoo for Baz {}
67+
impl IBaz for Baz {}
68+
pub trait IBaz: Sized + std::ops::Deref {}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 Foo(pub id);
18+
impl std::ops::Deref for Foo {
19+
type Target = objc::runtime::Object;
20+
fn deref(&self) -> &Self::Target {
21+
unsafe { &*self.0 }
22+
}
23+
}
24+
unsafe impl objc::Message for Foo {}
25+
impl Foo {
26+
pub fn alloc() -> Self {
27+
Self(unsafe { msg_send!(objc::class!(Foo), alloc) })
28+
}
29+
}
30+
impl IFoo for Foo {}
31+
pub trait IFoo: Sized + std::ops::Deref {}
32+
#[repr(transparent)]
33+
#[derive(Clone, Copy)]
34+
pub struct Bar(pub id);
35+
impl std::ops::Deref for Bar {
36+
type Target = objc::runtime::Object;
37+
fn deref(&self) -> &Self::Target {
38+
unsafe { &*self.0 }
39+
}
40+
}
41+
unsafe impl objc::Message for Bar {}
42+
impl Bar {
43+
pub fn alloc() -> Self {
44+
Self(unsafe { msg_send!(objc::class!(Bar), alloc) })
45+
}
46+
}
47+
impl IFoo for Bar {}
48+
impl IBar for Bar {}
49+
pub trait IBar: Sized + std::ops::Deref {}
50+
#[repr(transparent)]
51+
#[derive(Clone, Copy)]
52+
pub struct Baz(pub id);
53+
impl std::ops::Deref for Baz {
54+
type Target = objc::runtime::Object;
55+
fn deref(&self) -> &Self::Target {
56+
unsafe { &*self.0 }
57+
}
58+
}
59+
unsafe impl objc::Message for Baz {}
60+
impl Baz {
61+
pub fn alloc() -> Self {
62+
Self(unsafe { msg_send!(objc::class!(Baz), alloc) })
63+
}
64+
}
65+
impl IBar for Baz {}
66+
impl IFoo for Baz {}
67+
impl IBaz for Baz {}
68+
pub trait IBaz: Sized + std::ops::Deref {}

0 commit comments

Comments
 (0)