X-Git-Url: http://nitlanguage.org diff --git a/contrib/objcwrapper/src/objc_generator.nit b/contrib/objcwrapper/src/objc_generator.nit index db273cb..408d731 100644 --- a/contrib/objcwrapper/src/objc_generator.nit +++ b/contrib/objcwrapper/src/objc_generator.nit @@ -42,7 +42,7 @@ redef class Sys "Wrap `init...` constructors as Nit methods instead of Nit constructors", "--init-as-methods") - private var nit_to_java_types: Map[String, String] is lazy do + private var objc_to_nit_types: Map[String, String] is lazy do var types = new HashMap[String, String] types["char"] = "Byte" types["short"] = "Int" @@ -59,14 +59,30 @@ redef class Sys types["NSUInteger"] = "Int" types["BOOL"] = "Bool" types["id"] = "NSObject" + types["constid"] = "NSObject" + types["SEL"] = "NSObject" + types["void"] = "Pointer" + return types end end +redef class ObjcModel + redef fun knows_type(objc_type) do return super or + objc_to_nit_types.keys.has(objc_type) +end + +# Wrapper generator class CodeGenerator + + # `ObjcModel` to wrap + var model: ObjcModel + # Generate Nit code to wrap `classes` - fun generate(classes: Array[ObjcClass]) + fun generate do + var classes = model.classes + # Open specified path or stdin var file var path = opt_output.value @@ -81,7 +97,7 @@ class CodeGenerator end # Generate code - file.write "import cocoa::foundation\n\n" + file.write "import cocoa::foundation\n" for classe in classes do write_class(classe, file) end @@ -105,8 +121,6 @@ extern class {{{classe.name}}} in "ObjC" `{ {{{classe.name}}} * `} super NSObject """ - file.write "\n" - # Constructor or constructors write_constructors(classe, file) @@ -115,10 +129,12 @@ extern class {{{classe.name}}} in "ObjC" `{ {{{classe.name}}} * `} write_attribute(attribute, file) end - # Methods + # Instance methods '-' for method in classe.methods do + if not model.knows_all_types(method) then method.is_commented = true if not opt_init_as_methods.value and method.is_init then continue + if method.is_class_property then continue write_method_signature(method, file) write_objc_method_call(method, file) @@ -127,6 +143,14 @@ extern class {{{classe.name}}} in "ObjC" `{ {{{classe.name}}} * `} file.write """ end """ + + # Class methods '+' + for method in classe.methods do + if not method.is_class_property then continue + + write_method_signature(method, file) + write_objc_method_call(method, file) + end end private fun write_constructors(classe: ObjcClass, file: Writer) @@ -134,10 +158,10 @@ end if opt_init_as_methods.value then # A single constructor for `alloc` file.write """ + new in "ObjC" `{ return [{{{classe.name}}} alloc]; `} - """ return end @@ -146,14 +170,18 @@ end for method in classe.methods do if not method.is_init then continue + if not model.knows_all_types(method) then method.is_commented = true + write_method_signature(method, file) - write_objc_init_call(classe.name, method, file) + write_objc_init_call(classe.name, method, file) end end private fun write_attribute(attribute: ObjcAttribute, file: Writer) do + if not model.knows_type(attribute.return_type) then attribute.is_commented = true + write_attribute_getter(attribute, file) # TODO write_attribute_setter if there is no `readonly` annotation end @@ -161,30 +189,32 @@ end private fun write_attribute_getter(attribute: ObjcAttribute, file: Writer) do var nit_attr_name = attribute.name.to_snake_case - var nit_attr_type = attribute.return_type.to_nit_type + var nit_attr_type = attribute.return_type.objc_to_nit_type var c = attribute.comment_str file.write """ + +{{{attribute.doc}}} {{{c}}} fun {{{nit_attr_name}}}: {{{nit_attr_type}}} in "ObjC" `{ {{{c}}} return [self {{{attribute.name}}}]; {{{c}}} `} - """ end private fun write_attribute_setter(attribute: ObjcAttribute, file: Writer) do var nit_attr_name = attribute.name.to_snake_case - var nit_attr_type = attribute.return_type.to_nit_type + var nit_attr_type = attribute.return_type.objc_to_nit_type var c = attribute.comment_str file.write """ + +{{{attribute.doc}}} {{{c}}} fun {{{nit_attr_name}}}=(value: {{{nit_attr_type}}}) in "ObjC" `{ {{{c}}} return self.{{{attribute.name}}} = value; {{{c}}} `} - """ end @@ -201,6 +231,9 @@ end if name == "init" then name = "" + # If class method, prefix with class name + if method.is_class_property then name = "{method.objc_class.name.to_snake_case}_{name}" + # Kind of method var fun_keyword = "fun" if not opt_init_as_methods.value and method.is_init then @@ -211,7 +244,7 @@ end var params = new Array[String] for param in method.params do if param.is_single then break - params.add "{param.variable_name}: {param.return_type.to_nit_type}" + params.add "{param.variable_name}: {param.return_type.objc_to_nit_type}" end var params_with_par = "" @@ -220,11 +253,13 @@ end # Return var ret = "" if method.return_type != "void" and fun_keyword != "new" then - ret = ": {method.return_type.to_nit_type}" + ret = ": {method.return_type.objc_to_nit_type}" end file.write """ -{{{c}}} {{{fun_keyword}}} {{{name}}}{{{params_with_par}}}{{{ret}}} in "ObjC" `{ + +{{{method.doc}}} +{{{c}}}{{{fun_keyword}}} {{{name}}}{{{params_with_par}}}{{{ret}}} in "ObjC" `{ """ end @@ -242,9 +277,8 @@ end var c = method.comment_str file.write """ -{{{c}}} return [[{{{class_name}}} alloc] {{{params.join(" ")}}}]; -{{{c}}} `} - +{{{c}}} return [[{{{class_name}}} alloc] {{{params.join(" ")}}}]; +{{{c}}}`} """ end @@ -262,21 +296,24 @@ end else params.add param.name end + # Receiver, instance or class + var recv = "self" + if method.is_class_property then recv = method.objc_class.name + var c = method.comment_str file.write """ -{{{c}}} {{{ret}}}[self {{{params.join(" ")}}}]; -{{{c}}} `} - +{{{c}}} {{{ret}}}[{{{recv}}} {{{params.join(" ")}}}]; +{{{c}}}`} """ end end redef class Text # Nit equivalent to this type - private fun to_nit_type: String + private fun objc_to_nit_type: String do - var types = sys.nit_to_java_types + var types = sys.objc_to_nit_types if types.has_key(self) then return types[self] @@ -286,8 +323,27 @@ redef class Text end end -redef class Property +redef class ObjcProperty private fun comment_str: String do if is_commented then return "#" else return "" + + # Full documentation to be generated for the Nit code + private fun doc: String is abstract +end + +redef class ObjcMethod + private fun indent: String do return if is_class_property then "" else "\t" + + redef fun comment_str do return indent + super + + redef fun doc + do + var recv = if is_class_property then objc_class.name else "self" + return "{indent}# Wraps: `[{recv} {params.join(" ")}]`" + end +end + +redef class ObjcAttribute + redef fun doc do return "\t# Wraps: `{objc_class.name}.{name}`" end