tests: update sav/test_parser* because AST changes
[nit.git] / contrib / objcwrapper / src / objc_generator.nit
index d50795b..cdb2fae 100644 (file)
@@ -16,6 +16,7 @@
 module objc_generator
 
 import opts
+import gen_nit
 
 import objc_model
 
@@ -57,7 +58,10 @@ redef class Sys
                types["long double"] = "Float"
 
                types["NSUInteger"] = "Int"
+               types["NSInteger"] = "Int"
+               types["CGFloat"] = "Float"
                types["BOOL"] = "Bool"
+
                types["id"] = "NSObject"
                types["constid"] = "NSObject"
                types["SEL"] = "NSObject"
@@ -97,6 +101,12 @@ class CodeGenerator
                end
 
                # Generate code
+               file.write """
+# File generated by objcwrapper with the following command:
+# {{{program_name}}} {{{args.join(" ")}}}
+
+"""
+
                file.write "import cocoa::foundation\n"
                for classe in classes do
                        write_class(classe, file)
@@ -107,17 +117,21 @@ class CodeGenerator
 
        private fun write_class(classe: ObjcClass, file: Writer)
        do
+               # FIXME remove the redef when the base lib is generated by objcwrapper
+               var r = ""
+               if classe.name == "NSObject" then r = "redef "
+
                # Class header
                file.write """
 
-extern class {{{classe.name}}} in "ObjC" `{ {{{classe.name}}} * `}
+{{{r}}}extern class {{{classe.name}}} in "ObjC" `{ {{{classe.name}}} * `}
 """
 
                # Supers
                for super_name in classe.super_names do file.write """
        super {{{super_name}}}
 """
-               if classe.super_names.is_empty then file.write """
+               if classe.super_names.is_empty and classe.name != "NSObject" then file.write """
        super NSObject
 """
 
@@ -195,6 +209,7 @@ end
 
                file.write """
 
+{{{attribute.doc}}}
 {{{c}}}        fun {{{nit_attr_name}}}: {{{nit_attr_type}}} in "ObjC" `{
 {{{c}}}                return [self {{{attribute.name}}}];
 {{{c}}}        `}
@@ -210,6 +225,7 @@ end
 
                file.write """
 
+{{{attribute.doc}}}
 {{{c}}}        fun {{{nit_attr_name}}}=(value: {{{nit_attr_type}}}) in "ObjC" `{
 {{{c}}}                return self.{{{attribute.name}}} = value;
 {{{c}}}        `}
@@ -229,6 +245,8 @@ end
 
                if name == "init" then name = ""
 
+               name = name.to_nit_name(property=true, pointer=true)
+
                # If class method, prefix with class name
                if method.is_class_property then name = "{method.objc_class.name.to_snake_case}_{name}"
 
@@ -242,7 +260,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.objc_to_nit_type}"
+                       params.add "{param.nit_variable_name}: {param.return_type.objc_to_nit_type}"
                end
 
                var params_with_par = ""
@@ -256,6 +274,7 @@ end
 
                file.write """
 
+{{{method.doc}}}
 {{{c}}}{{{fun_keyword}}} {{{name}}}{{{params_with_par}}}{{{ret}}} in "ObjC" `{
 """
        end
@@ -267,7 +286,7 @@ end
                var params = new Array[String]
                for param in method.params do
                        if not param.is_single then
-                               params.add "{param.name}: {param.variable_name}"
+                               params.add "{param.name}: {param.nit_variable_name}"
                        else params.add param.name
                end
 
@@ -289,7 +308,7 @@ end
                var params = new Array[String]
                for param in method.params do
                        if not param.is_single then
-                               params.add "{param.name}: {param.variable_name}"
+                               params.add "{param.name}: {param.nit_variable_name}"
                        else params.add param.name
                end
 
@@ -318,16 +337,52 @@ redef class Text
                        return to_s
                end
        end
+
+       # Convert to a safe Nit name for a `property`, a property in a subclass of `pointer` or a variable
+       private fun to_nit_name(property, pointer: nullable Bool): String
+       do
+               var name = to_s
+               name = name.to_snake_case
+
+               while not name.is_empty and name.chars.first == '_' do name = name.substring_from(1)
+
+               if keywords.has(name) then name = name + "0"
+
+               if property == true then
+                       if methods_in_object.has(name) then name = name + "0"
+                       if pointer == true and methods_in_pointer.has(name) then name = name + "0"
+               end
+
+               return name.to_s
+       end
 end
 
 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
+
+redef class ObjcParam
+       # `variable_name` mangled for the Nit language
+       private fun nit_variable_name: String do return variable_name.to_nit_name
 end