380f61ea2ccb8e4841f1c9337d6c513ae1451ea1
1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
24 # Path to the output file
25 var opt_output
= new OptionString("Output file", "-o")
27 private var nit_to_java_types
: Map[String, String] is lazy
do
28 var types
= new HashMap[String, String]
29 types
["char"] = "Byte"
30 types
["short"] = "Int"
31 types
["short int"] = "Int"
34 types
["long int"] = "Int"
35 types
["long long"] = "Int"
36 types
["long long int"] = "Int"
37 types
["float"] = "Float"
38 types
["double"] = "Float"
39 types
["long double"] = "Float"
41 types
["NSUInteger"] = "Int"
42 types
["BOOL"] = "Bool"
43 types
["id"] = "NSObject"
49 # Merge the calls to `alloc` and `init...` in a single constructor?
51 # If `true`, also the default behavior, initializing an extern Objective-C object looks like:
53 # var o = new NSArray.init_with_array(some_other_array)
56 # If `false`, the object must first be allocated and then initialized.
57 # This is closer to the Objective-C behavior:
60 # o.init_with_array(some_other_array)
62 var init_with_alloc
= true is writable
64 # Generate Nit code to wrap `classes`
65 fun generate
(classes
: Array[ObjcClass])
67 # Open specified path or stdin
69 var path
= opt_output
.value
71 if path
.file_extension
!= "nit" then
72 print_error
"Warning: output file path does not end with '.nit'"
75 file
= new FileWriter.open
(path
)
81 file
.write
"import cocoa::foundation\n\n"
82 for classe
in classes
do
83 write_class
(classe
, file
)
86 if path
!= null then file
.close
89 private fun write_class
(classe
: ObjcClass, file
: Writer)
91 var commented_methods
= new Array[ObjcMethod]
92 file
.write
"extern class " + classe
.name
+ """ in "ObjC" `{ """ + classe.name + """ * `}\n"""
93 for super_name
in classe
.super_names
do
94 file
.write
""" super """ + super_name
+ "\n"
96 if classe
.super_names
.is_empty
then file
.write
""" super NSObject\n"""
97 write_constructor
(classe
, file
)
99 for attribute
in classe
.attributes
do
100 write_attribute
(attribute
, file
)
102 for method
in classe
.methods
do
103 if method
.is_commented
then
104 commented_methods
.add
(method
)
106 if init_with_alloc
and method
.params
.first
.name
.has
("init") then continue
108 write_method
(method
, file
)
109 file
.write
""" in "ObjC" `{\n """
110 write_objc_method_call
(method
, file
)
112 if method
!= classe
.methods
.last
then file
.write
"\n\n"
115 for commented_method
in commented_methods
do
116 if commented_method
== commented_methods
.first
then file
.write
"\n"
118 write_method
(commented_method
, file
)
119 if commented_method
!= commented_methods
.last
then file
.write
"\n"
124 private fun write_constructor
(classe
: ObjcClass, file
: Writer)
126 if init_with_alloc
then
127 for method
in classe
.methods
do
128 if method
.params
.first
.name
.has
("init") and not method
.is_commented
then
130 if method
.params
.first
.name
== "init" then
133 write_method
(method
, file
)
135 file
.write
""" in "ObjC" `{\n"""
136 write_objc_init_call
(classe
.name
, method
, file
)
137 file
.write
""" `}\n"""
141 file
.write
"""\n new in "ObjC"`{\n"""
142 file
.write
""" return [""" + classe
.name
+ " alloc];\n"
143 file
.write
""" `}\n"""
147 private fun write_attribute
(attribute
: ObjcAttribute, file
: Writer)
149 write_attribute_getter
(attribute
, file
)
150 # TODO write_attribute_setter if there is no `readonly` annotation
154 private fun write_attribute_getter
(attribute
: ObjcAttribute, file
: Writer)
156 file
.write
""" fun """ + attribute
.name
.to_snake_case
+ ": " + attribute
.return_type
.to_nit_type
157 file
.write
""" in "ObjC" `{\n"""
158 file
.write
""" return [self """ + attribute
.name
+ "];\n"
159 file
.write
""" `}\n"""
162 private fun write_attribute_setter
(attribute
: ObjcAttribute, file
: Writer)
164 file
.write
""" fun """ + attribute
.name
.to_snake_case
+ "=(value: " + attribute
.return_type
.to_nit_type
+ ")"
165 file
.write
" in \"ObjC\
" `\{\n"
166 file
.write
""" self.""" + attribute
.name
+ " = value;\n"
167 file
.write
""" `}\n"""
170 private fun write_method
(method
: ObjcMethod, file
: Writer)
173 for param
in method
.params
do
174 name
+= param
.name
[0].to_upper
.to_s
+ param
.name
.substring_from
(1)
175 name
= name
.to_snake_case
177 if name
.has
("init") and init_with_alloc
then
180 if not init_with_alloc
and name
== "init" then name
= "init_0"
184 for param
in method
.params
do
185 if param
== method
.params
.first
and not param
.is_single
then
186 file
.write
"(" + param
.variable_name
+ ": " + param
.return_type
.to_nit_type
188 if param
!= method
.params
.first
and not param
.is_single
then
189 file
.write
", " + param
.variable_name
+ ": " + param
.return_type
.to_nit_type
191 if param
== method
.params
.last
and not param
.is_single
then
195 if method
.return_type
!= "void" and not method
.params
.first
.name
.has
("init") then
196 file
.write
": " + method
.return_type
.to_nit_type
200 private fun write_objc_init_call
(classe_name
: String, method
: ObjcMethod, file
: Writer)
202 file
.write
""" return [[""" + classe_name
+ " alloc] "
203 for param
in method
.params
do
204 if not param
.is_single
then
205 file
.write param
.name
+ ":" + param
.variable_name
206 if not param
== method
.params
.last
then file
.write
" "
208 file
.write param
.name
214 private fun write_objc_method_call
(method
: ObjcMethod, file
: Writer)
216 if method
.return_type
!= "void" then file
.write
"return "
218 for param
in method
.params
do
219 if not param
.is_single
then
220 file
.write param
.name
+ ":" + param
.variable_name
221 if not param
== method
.params
.last
then file
.write
" "
223 file
.write param
.name
231 # Nit equivalent to this type
232 private fun to_nit_type
: String
234 var types
= sys
.nit_to_java_types
236 if types
.has_key
(self) then