summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs11
-rw-r--r--src/ir/objc.rs33
-rw-r--r--src/ir/ty.rs27
3 files changed, 62 insertions, 9 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index aab59946..46b0a3e7 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -647,6 +647,9 @@ impl CodeGenerator for Type {
TypeKind::Enum(ref ei) => {
ei.codegen(ctx, result, whitelisted_items, item)
}
+ TypeKind::ObjCId | TypeKind::ObjCSel => {
+ result.saw_objc();
+ }
TypeKind::ObjCInterface(ref interface) => {
interface.codegen(ctx, result, whitelisted_items, item)
}
@@ -2276,6 +2279,8 @@ impl ToRustTy for Type {
let ident = ctx.rust_ident(&name);
quote_ty!(ctx.ext_cx(), $ident)
}
+ TypeKind::ObjCSel => quote_ty!(ctx.ext_cx(), objc::runtime::Sel),
+ TypeKind::ObjCId |
TypeKind::ObjCInterface(..) => quote_ty!(ctx.ext_cx(), id),
ref u @ TypeKind::UnresolvedTypeRef(..) => {
unreachable!("Should have been resolved after parsing {:?}!", u)
@@ -2461,10 +2466,12 @@ impl CodeGenerator for ObjCInterface {
}
+ let trait_name = self.rust_name();
+
let trait_block = aster::AstBuilder::new()
.item()
.pub_()
- .trait_(self.name())
+ .trait_(&trait_name)
.with_items(trait_items)
.build();
@@ -2473,7 +2480,7 @@ impl CodeGenerator for ObjCInterface {
.item()
.impl_()
.trait_()
- .id(self.name())
+ .id(&trait_name)
.build()
.with_items(impl_items)
.build_ty(ty_for_impl);
diff --git a/src/ir/objc.rs b/src/ir/objc.rs
index b3c3688b..ff36c7b6 100644
--- a/src/ir/objc.rs
+++ b/src/ir/objc.rs
@@ -4,17 +4,21 @@ use super::context::BindgenContext;
use super::function::FunctionSig;
use clang;
use clang_sys::CXChildVisit_Continue;
+use clang_sys::CXCursor_ObjCCategoryDecl;
+use clang_sys::CXCursor_ObjCClassRef;
use clang_sys::CXCursor_ObjCInstanceMethodDecl;
/// Objective C interface as used in TypeKind
///
-/// Also protocols are parsed as this type
+/// Also protocols and categories are parsed as this type
#[derive(Debug)]
pub struct ObjCInterface {
/// The name
/// like, NSObject
name: String,
+ category: Option<String>,
+
/// List of the methods defined in this interfae
methods: Vec<ObjCInstanceMethod>,
}
@@ -37,6 +41,7 @@ impl ObjCInterface {
fn new(name: &str) -> ObjCInterface {
ObjCInterface {
name: name.to_owned(),
+ category: None,
methods: Vec::new(),
}
}
@@ -47,6 +52,16 @@ impl ObjCInterface {
self.name.as_ref()
}
+ /// Formats the name for rust
+ /// Can be like NSObject, but with categories might be like NSObject_NSCoderMethods
+ pub fn rust_name(&self) -> String {
+ if let Some(ref cat) = self.category {
+ format!("{}_{}", self.name(), cat)
+ } else {
+ self.name().to_owned()
+ }
+ }
+
/// List of the methods defined in this interfae
pub fn methods(&self) -> &Vec<ObjCInstanceMethod> {
&self.methods
@@ -59,12 +74,20 @@ impl ObjCInterface {
let name = cursor.spelling();
let mut interface = Self::new(&name);
- cursor.visit(|cursor| {
- match cursor.kind() {
+ cursor.visit(|c| {
+ match c.kind() {
+ CXCursor_ObjCClassRef => {
+ if cursor.kind() == CXCursor_ObjCCategoryDecl {
+ // We are actually a category extension, and we found the reference
+ // to the original interface, so name this interface approriately
+ interface.name = c.spelling();
+ interface.category = Some(cursor.spelling());
+ }
+ }
CXCursor_ObjCInstanceMethodDecl => {
- let name = cursor.spelling();
+ let name = c.spelling();
let signature =
- FunctionSig::from_ty(&cursor.cur_type(), &cursor, ctx)
+ FunctionSig::from_ty(&c.cur_type(), &c, ctx)
.expect("Invalid function sig");
let method = ObjCInstanceMethod::new(&name, signature);
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 44a88744..5491ceaf 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -358,6 +358,8 @@ impl Type {
TypeKind::NullPtr |
TypeKind::BlockPointer |
TypeKind::Pointer(..) |
+ TypeKind::ObjCId |
+ TypeKind::ObjCSel |
TypeKind::ObjCInterface(..) => Some(self),
TypeKind::ResolvedTypeRef(inner) |
@@ -433,6 +435,8 @@ impl DotAttributes for TypeKind {
TypeKind::TemplateInstantiation(..) => "TemplateInstantiation",
TypeKind::ResolvedTypeRef(..) => "ResolvedTypeRef",
TypeKind::Named => "Named",
+ TypeKind::ObjCId => "ObjCId",
+ TypeKind::ObjCSel => "ObjCSel",
TypeKind::ObjCInterface(..) => "ObjCInterface",
TypeKind::UnresolvedTypeRef(..) => {
unreachable!("there shouldn't be any more of these anymore")
@@ -516,6 +520,8 @@ impl TemplateDeclaration for TypeKind {
TypeKind::UnresolvedTypeRef(..) |
TypeKind::Named |
TypeKind::Alias(_) |
+ TypeKind::ObjCId |
+ TypeKind::ObjCSel |
TypeKind::ObjCInterface(_) => None,
}
}
@@ -562,6 +568,8 @@ impl CanDeriveDefault for Type {
TypeKind::NullPtr |
TypeKind::Pointer(..) |
TypeKind::BlockPointer |
+ TypeKind::ObjCId |
+ TypeKind::ObjCSel |
TypeKind::ObjCInterface(..) |
TypeKind::Enum(..) => false,
TypeKind::Function(..) |
@@ -707,6 +715,12 @@ pub enum TypeKind {
/// Objective C interface. Always referenced through a pointer
ObjCInterface(ObjCInterface),
+
+ /// Objective C 'id' type, points to any object
+ ObjCId,
+
+ /// Objective C selector type
+ ObjCSel,
}
impl Type {
@@ -738,6 +752,8 @@ impl Type {
TypeKind::Reference(..) |
TypeKind::NullPtr |
TypeKind::BlockPointer |
+ TypeKind::ObjCId |
+ TypeKind::ObjCSel |
TypeKind::Pointer(..) => false,
TypeKind::ObjCInterface(..) => true, // dunno?
@@ -787,8 +803,10 @@ impl Type {
// Parse objc protocols as if they were interfaces
let mut ty_kind = ty.kind();
if let Some(loc) = location {
- if loc.kind() == CXCursor_ObjCProtocolDecl {
- ty_kind = CXType_ObjCInterface;
+ match loc.kind() {
+ CXCursor_ObjCProtocolDecl |
+ CXCursor_ObjCCategoryDecl => ty_kind = CXType_ObjCInterface,
+ _ => {}
}
}
@@ -1146,6 +1164,9 @@ impl Type {
parent_id,
ctx);
}
+ CXType_ObjCId => TypeKind::ObjCId,
+ CXType_ObjCSel => TypeKind::ObjCSel,
+ CXType_ObjCClass |
CXType_ObjCInterface => {
let interface = ObjCInterface::from_ty(&location.unwrap(), ctx)
.expect("Not a valid objc interface?");
@@ -1214,6 +1235,8 @@ impl Trace for Type {
TypeKind::Int(_) |
TypeKind::Float(_) |
TypeKind::Complex(_) |
+ TypeKind::ObjCId |
+ TypeKind::ObjCSel |
TypeKind::BlockPointer => {}
}
}