-
Notifications
You must be signed in to change notification settings - Fork 356
Support 'swift_name' attributes on generated functions #449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,17 +23,20 @@ use crate::bindgen::writer::{Source, SourceWriter}; | |
| #[derive(Debug, Clone)] | ||
| pub struct Function { | ||
| pub path: Path, | ||
| pub self_type_path: Option<Path>, | ||
| pub ret: Type, | ||
| pub args: Vec<(String, Type)>, | ||
| pub extern_decl: bool, | ||
| pub cfg: Option<Cfg>, | ||
| pub annotations: AnnotationSet, | ||
| pub documentation: Documentation, | ||
| pub attributes: Vec<String>, | ||
|
||
| } | ||
|
|
||
| impl Function { | ||
| pub fn load( | ||
| path: Path, | ||
| self_type_path: Option<Path>, | ||
| sig: &syn::Signature, | ||
| extern_decl: bool, | ||
| attrs: &[syn::Attribute], | ||
|
|
@@ -53,15 +56,52 @@ impl Function { | |
|
|
||
| Ok(Function { | ||
| path, | ||
| self_type_path, | ||
| ret, | ||
| args, | ||
| extern_decl, | ||
| cfg: Cfg::append(mod_cfg, Cfg::load(attrs)), | ||
| annotations: AnnotationSet::load(attrs)?, | ||
| documentation: Documentation::load(attrs), | ||
| attributes: Vec::new(), | ||
| }) | ||
| } | ||
|
|
||
| pub fn swift_name(&self) -> String { | ||
| // If the symbol name starts with the type name, separate the two components with '.' | ||
| // so that Swift recognises the association between the method and the type | ||
| let (ref type_prefix, ref type_name) = if let Some(type_name) = &self.self_type_path { | ||
| let type_name = type_name.to_string(); | ||
| if !self.path.name().starts_with(&type_name) { | ||
| return self.path.to_string(); | ||
| } | ||
| (format!("{}.", type_name), type_name) | ||
| } else { | ||
| ("".to_string(), "".to_string()) | ||
| }; | ||
|
|
||
| let item_name = self.path | ||
| .name() | ||
| .trim_start_matches(type_name) | ||
| .trim_start_matches('_'); | ||
|
|
||
| let item_args = { | ||
| let mut items = vec![]; | ||
| for (arg, _) in self.args.iter() { | ||
| match arg.as_str() { | ||
|
||
| "self" => { | ||
| items.push("self:".to_string()); | ||
| } | ||
| other => { | ||
| items.push(format!("{}:", other)); | ||
| } | ||
| } | ||
| } | ||
| items.join("") | ||
| }; | ||
| format!("{}{}({})", type_prefix, item_name, item_args) | ||
| } | ||
|
|
||
| pub fn path(&self) -> &Path { | ||
| &self.path | ||
| } | ||
|
|
@@ -160,12 +200,22 @@ impl Source for Function { | |
| } | ||
| } | ||
| cdecl::write_func(out, &func, false, void_prototype); | ||
|
|
||
| if !func.extern_decl { | ||
| if let Some(ref postfix) = postfix { | ||
| out.write(" "); | ||
| write!(out, "{}", postfix); | ||
| } | ||
| } | ||
|
|
||
| if let Some(ref swift_name_macro) = config.function.swift_name_macro { | ||
| let swift_name = func.swift_name(); | ||
| if !swift_name.is_empty() { | ||
|
||
| out.write(" "); | ||
|
||
| write!(out, "{}({})", swift_name_macro, func.swift_name()); | ||
| } | ||
| } | ||
|
|
||
| out.write(";"); | ||
|
|
||
| condition.write_after(config, out); | ||
|
|
@@ -203,6 +253,15 @@ impl Source for Function { | |
| write!(out, "{}", postfix); | ||
| } | ||
| } | ||
|
|
||
| if let Some(ref swift_name_macro) = config.function.swift_name_macro { | ||
| let swift_name = func.swift_name(); | ||
| if !swift_name.is_empty() { | ||
| out.write(" "); | ||
| write!(out, "{}({})", swift_name_macro, func.swift_name()); | ||
| } | ||
| } | ||
|
|
||
| out.write(";"); | ||
|
|
||
| condition.write_after(config, out); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,6 +57,20 @@ impl SynItemFnHelpers for syn::ItemFn { | |
| } | ||
| } | ||
|
|
||
| impl SynItemFnHelpers for syn::ImplItemMethod { | ||
| fn exported_name(&self) -> Option<String> { | ||
| self.attrs | ||
| .attr_name_value_lookup("export_name") | ||
| .or_else(|| { | ||
| if self.is_no_mangle() { | ||
| Some(self.sig.ident.to_string()) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this really work for impl items? Like, does |
||
| } else { | ||
| None | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| pub trait SynItemHelpers { | ||
| /// Searches for attributes like `#[test]`. | ||
| /// Example: | ||
|
|
@@ -138,6 +152,7 @@ impl_syn_item_helper!(syn::ItemUse); | |
| impl_syn_item_helper!(syn::ItemStatic); | ||
| impl_syn_item_helper!(syn::ItemConst); | ||
| impl_syn_item_helper!(syn::ItemFn); | ||
| impl_syn_item_helper!(syn::ImplItemMethod); | ||
| impl_syn_item_helper!(syn::ItemMod); | ||
| impl_syn_item_helper!(syn::ItemForeignMod); | ||
| impl_syn_item_helper!(syn::ItemType); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #define CF_SWIFT_NAME(_name) __attribute__((swift_name(#_name))) | ||
|
|
||
| #include <stdarg.h> | ||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
| #include <stdlib.h> | ||
|
|
||
| typedef struct Foo Foo; | ||
|
|
||
| typedef struct FooRef { | ||
| Foo *ptr; | ||
| } FooRef; | ||
|
|
||
| FooRef FooRef_create(void) CF_SWIFT_NAME(FooRef.create()); | ||
|
|
||
| int32_t FooRef_doThing(FooRef self) /*a comment!*/ CF_SWIFT_NAME(FooRef.doThing(self:)); | ||
|
|
||
| int32_t FooRef_getBar(FooRef self) CF_SWIFT_NAME(FooRef.getBar(self:)); | ||
|
|
||
| void FooRef_setBar(FooRef self, int32_t bar) CF_SWIFT_NAME(FooRef.setBar(self:bar:)); | ||
|
|
||
| void do_the_thing(void) CF_SWIFT_NAME(do_the_thing()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment saying something like "If we're a method, this will be
Some, and the path will be the path of the type in theimplblock" or such.It'd be nice to make something more similar to what associated constants do, but it may be overkill for this.