diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-05-03 14:48:02 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-03 14:48:02 -0500 |
commit | 765671df1a6b93fccf7460043be865055de7ceb2 (patch) | |
tree | 83f2d370b530749c21eb9e16d6866ae4237dd0ee | |
parent | 8e9b3884961802a8c5c102ecfff06419e9695199 (diff) | |
parent | 335e5c726608e73af062315bcd76cf639e27330c (diff) |
Auto merge of #673 - scoopr:objc, r=emilio
objc: Fixes to properly parse most of Foundation
I had half of these just lying around in my commit queue for a while, having problems with the template param thing. Incidentally, either some other fixes made it work, or I had accidentally built against clang 4.0, which I guess doesn't work with the current approach.
With these I'm able to parse and generate code for Foundation.framework, with regex ^NS.* (and skipping that one id redefine). Also needed --no-doc-comments, that I guess generated comment for an enum in the wrong place, didn't look at that.
-rw-r--r-- | src/codegen/mod.rs | 28 | ||||
-rw-r--r-- | src/ir/function.rs | 4 | ||||
-rw-r--r-- | src/ir/ty.rs | 18 | ||||
-rw-r--r-- | src/options.rs | 4 | ||||
-rw-r--r-- | tests/expectations/tests/objc_method_clash.rs | 22 | ||||
-rw-r--r-- | tests/expectations/tests/objc_property_fnptr.rs | 35 | ||||
-rw-r--r-- | tests/expectations/tests/objc_template.rs | 18 | ||||
-rw-r--r-- | tests/headers/objc_method_clash.h | 7 | ||||
-rw-r--r-- | tests/headers/objc_property_fnptr.h | 8 | ||||
-rw-r--r-- | tests/headers/objc_template.h | 6 |
10 files changed, 141 insertions, 9 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 39b115fa..697c140f 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2805,7 +2805,8 @@ impl CodeGenerator for Function { fn objc_method_codegen(ctx: &BindgenContext, method: &ObjCMethod, - class_name: Option<&str>) + class_name: Option<&str>, + prefix: &str) -> (ast::ImplItem, ast::TraitItem) { let signature = method.signature(); let fn_args = utils::fnsig_arguments(ctx, signature); @@ -2864,9 +2865,11 @@ fn objc_method_codegen(ctx: &BindgenContext, let attrs = vec![]; + let method_name = format!("{}{}", prefix, method.rust_name()); + let impl_item = ast::ImplItem { id: ast::DUMMY_NODE_ID, - ident: ctx.rust_ident(method.rust_name()), + ident: ctx.rust_ident(&method_name), vis: ast::Visibility::Inherited, // Public, attrs: attrs.clone(), node: ast::ImplItemKind::Method(sig.clone(), P(block)), @@ -2876,7 +2879,7 @@ fn objc_method_codegen(ctx: &BindgenContext, let trait_item = ast::TraitItem { id: ast::DUMMY_NODE_ID, - ident: ctx.rust_ident(method.rust_name()), + ident: ctx.rust_ident(&method_name), attrs: attrs, node: ast::TraitItemKind::Method(sig, None), span: ctx.span(), @@ -2898,14 +2901,23 @@ impl CodeGenerator for ObjCInterface { for method in self.methods() { let (impl_item, trait_item) = - objc_method_codegen(ctx, method, None); + objc_method_codegen(ctx, method, None, ""); impl_items.push(impl_item); trait_items.push(trait_item) } + let instance_method_names : Vec<_> = self.methods().iter().map( { |m| m.rust_name() } ).collect(); + for class_method in self.class_methods() { + + let ambiquity = instance_method_names.contains(&class_method.rust_name()); + let prefix = if ambiquity { + "class_" + } else { + "" + }; let (impl_item, trait_item) = - objc_method_codegen(ctx, class_method, Some(self.name())); + objc_method_codegen(ctx, class_method, Some(self.name()), prefix); impl_items.push(impl_item); trait_items.push(trait_item) } @@ -2982,13 +2994,13 @@ mod utils { result: &mut Vec<P<ast::Item>>) { let use_objc = if ctx.options().objc_extern_crate { quote_item!(ctx.ext_cx(), - use objc; + #[macro_use] + extern crate objc; ) .unwrap() } else { quote_item!(ctx.ext_cx(), - #[macro_use] - extern crate objc; + use objc; ) .unwrap() }; diff --git a/src/ir/function.rs b/src/ir/function.rs index 23503b05..01689734 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -284,7 +284,9 @@ impl FunctionSig { let ty_ret_type = if cursor.kind() == CXCursor_ObjCInstanceMethodDecl || cursor.kind() == CXCursor_ObjCClassMethodDecl { - try!(cursor.ret_type().ok_or(ParseError::Continue)) + try!(ty.ret_type() + .or_else(|| cursor.ret_type()) + .ok_or(ParseError::Continue)) } else { try!(ty.ret_type().ok_or(ParseError::Continue)) }; diff --git a/src/ir/ty.rs b/src/ir/ty.rs index c3f26572..a9054e98 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -836,6 +836,24 @@ impl Type { _ => {} } + // Objective C template type parameter + // FIXME: This is probably wrong, we are attempting to find the + // objc template params, which seem to manifest as a typedef. + // We are rewriting them as id to suppress multiple conflicting + // typedefs at root level + if ty_kind == CXType_Typedef { + let is_template_type_param = ty.declaration().kind() == CXCursor_TemplateTypeParameter; + let is_canonical_objcpointer = canonical_ty.kind() == CXType_ObjCObjectPointer; + + // We have found a template type for objc interface + if is_canonical_objcpointer && is_template_type_param { + // Objective-C generics are just ids with fancy name. + // To keep it simple, just name them ids + name = "id".to_owned(); + } + + } + if location.kind() == CXCursor_ClassTemplatePartialSpecialization { // Sorry! (Not sorry) warn!("Found a partial template specialization; bindgen does not \ diff --git a/src/options.rs b/src/options.rs index ca54dbc6..bbf9c0dd 100644 --- a/src/options.rs +++ b/src/options.rs @@ -341,6 +341,10 @@ pub fn builder_from_flags<I> builder = builder.whitelist_recursively(false); } + if matches.is_present("objc-extern-crate") { + builder = builder.objc_extern_crate(true); + } + if let Some(opaque_types) = matches.values_of("opaque-type") { for ty in opaque_types { builder = builder.opaque_type(ty); diff --git a/tests/expectations/tests/objc_method_clash.rs b/tests/expectations/tests/objc_method_clash.rs new file mode 100644 index 00000000..07dedc4c --- /dev/null +++ b/tests/expectations/tests/objc_method_clash.rs @@ -0,0 +1,22 @@ +/* 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 Foo { + unsafe fn foo(self); + unsafe fn class_foo(); +} +impl Foo for id { + unsafe fn foo(self) { msg_send!(self , foo) } + unsafe fn class_foo() { + msg_send!(objc :: runtime :: Class :: get ( "Foo" ) . expect ( + "Couldn\'t find Foo" ) , foo) + } +} diff --git a/tests/expectations/tests/objc_property_fnptr.rs b/tests/expectations/tests/objc_property_fnptr.rs new file mode 100644 index 00000000..044f25d1 --- /dev/null +++ b/tests/expectations/tests/objc_property_fnptr.rs @@ -0,0 +1,35 @@ +/* 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 Foo { + unsafe fn func(self) + -> ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_int>; + unsafe fn setFunc_(self, + func: + ::std::option::Option<unsafe extern "C" fn() + -> + ::std::os::raw::c_int>); +} +impl Foo for id { + unsafe fn func(self) + -> + ::std::option::Option<unsafe extern "C" fn() + -> ::std::os::raw::c_int> { + msg_send!(self , func) + } + unsafe fn setFunc_(self, + func: + ::std::option::Option<unsafe extern "C" fn() + -> + ::std::os::raw::c_int>) { + msg_send!(self , setFunc:func ) + } +} diff --git a/tests/expectations/tests/objc_template.rs b/tests/expectations/tests/objc_template.rs new file mode 100644 index 00000000..e5a874c6 --- /dev/null +++ b/tests/expectations/tests/objc_template.rs @@ -0,0 +1,18 @@ +/* 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 Foo { + unsafe fn get(self) + -> id; +} +impl Foo for id { + unsafe fn get(self) -> id { msg_send!(self , get) } +} diff --git a/tests/headers/objc_method_clash.h b/tests/headers/objc_method_clash.h new file mode 100644 index 00000000..a56e39db --- /dev/null +++ b/tests/headers/objc_method_clash.h @@ -0,0 +1,7 @@ +// bindgen-flags: --objc-extern-crate -- -x objective-c +// bindgen-osx-only + +@interface Foo ++ (void)foo; +- (void)foo; +@end diff --git a/tests/headers/objc_property_fnptr.h b/tests/headers/objc_property_fnptr.h new file mode 100644 index 00000000..8312ba4a --- /dev/null +++ b/tests/headers/objc_property_fnptr.h @@ -0,0 +1,8 @@ +// bindgen-flags: --objc-extern-crate -- -x objective-c +// bindgen-osx-only + +@interface Foo +// FIXME: We are not generating valid code for this +// but at least we should not die +@property int (*func)(char, short, float); +@end diff --git a/tests/headers/objc_template.h b/tests/headers/objc_template.h new file mode 100644 index 00000000..62398eb7 --- /dev/null +++ b/tests/headers/objc_template.h @@ -0,0 +1,6 @@ +// bindgen-flags: --objc-extern-crate -- -x objective-c +// bindgen-osx-only + +@interface Foo<__covariant ObjectType> +- (ObjectType)get; +@end |