1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
4 # Copyright 2015 Alexis Laferrière <alexis.laf@xymus.net>
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
18 # Services to generate extern class `in "Java"`
25 # Path to the output file
28 # Model of Java class being wrapped
31 # Comment out methods with unknown (unwrapped) types
32 var comment_unknown_types
: Bool
34 # Generate stub classes for unknown types used in the generated module
35 var stub_for_unknown_types
: Bool
38 var file_out
: Writer = new FileWriter.open
(file_name
) is lazy
, writable
40 # Name of the Nit module to generate
41 var module_name
: nullable String is lazy
do
42 if file_name
.file_extension
== "nit" then
43 # Output file ends with .nit, we expect it to be a valid name
44 return file_name
.basename
(".nit")
48 # Generate the Nit module into `file_out`
52 file_out
.write license
55 var module_name
= module_name
56 if module_name
!= null then file_out
.write
"module {module_name}\n"
60 var imports
= new HashSet[String]
61 imports
.add
"import mnit_android\n"
62 for jclass
in model
.classes
do
63 for import_
in jclass
.imports
do imports
.add
"import android::{import_}\n"
65 file_out
.write imports
.join
("\n")
67 for jclass
in model
.classes
do
69 file_out
.write gen_class_header
(jclass
.class_type
)
71 for id
, signatures
in jclass
.methods
do
73 for signature
in signatures
do
75 if c
> 0 then nid
+= c
.to_s
78 file_out
.write gen_method
(jclass
, id
, nid
, signature
.return_type
, signature
.params
)
82 file_out
.write
"end\n\n"
85 if stub_for_unknown_types
then
86 for jtype
in model
.unknown_types
do
87 file_out
.write gen_unknown_class_header
(jtype
)
93 # License for the header of the generated Nit module
95 # This file is part of NIT (http://www.nitlanguage.org).
97 # Licensed under the Apache License, Version 2.0 (the "License");
98 # you may not use this file except in compliance with the License.
99 # You may obtain a copy of the License at
101 # http://www.apache.org/licenses/LICENSE-2.0
103 # Unless required by applicable law or agreed to in writing, software
104 # distributed under the License is distributed on an "AS IS" BASIS,
105 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106 # See the License for the specific language governing permissions and
107 # limitations under the License.
109 # This code has been generated using `jwrapper`
112 fun gen_class_header
(jtype
: JavaType): String
114 var temp
= new Array[String]
115 var nit_type
= jtype
.to_nit_type
116 temp
.add
"# Java class: {jtype.to_package_name}\n"
117 temp
.add
"extern class {nit_type} in \"Java\
" `\{ {jtype.to_package_name} `\}\n"
118 temp
.add
"\tsuper JavaObject\n\n"
123 fun gen_unknown_class_header
(jtype
: JavaType): String
125 var nit_type
: NitType
126 if jtype
.extern_name
.has_generic_params
then
127 nit_type
= jtype
.extern_name
.generic_params
.first
129 nit_type
= jtype
.extern_name
132 var temp
= new Array[String]
133 temp
.add
("extern class {nit_type} in \"Java\
" `\{ {jtype.to_package_name} `\}\n")
134 temp
.add
("\tsuper JavaObject\n\nend\n")
139 fun gen_method
(java_class
: JavaClass, jmethod_id
, nmethod_id
: String, jreturn_type
: JavaType, jparam_list
: Array[JavaType]): String
145 var nit_types
= new Array[NitType]
149 for i
in [0..jparam_list
.length
[ do
150 var jparam
= jparam_list
[i
]
151 var nit_type
= jparam
.to_nit_type
153 if not nit_type
.is_complete
then
154 if jparam
.is_wrapped
then
155 java_class
.imports
.add nit_type
.mod
.as(not null)
157 model
.unknown_types
.add jparam
158 if comment_unknown_types
then
161 nit_type
= jparam
.extern_name
168 if not jparam
.is_collection
then cast
= jparam
.param_cast
170 nit_types
.add
(nit_type
)
171 nit_type
.arg_id
= "{nit_id}{nit_id_no}"
173 if i
== jparam_list
.length
- 1 then
174 java_params
+= "{cast}{nit_id}{nit_id_no}"
175 nit_params
+= "{nit_id}{nit_id_no}: {nit_type}"
177 java_params
+= "{cast}{nit_id}{nit_id_no}" + ", "
178 nit_params
+= "{nit_id}{nit_id_no}: {nit_type}, "
184 # Method documentation
185 var doc
= "\t# Java implementation: {java_class}.{jmethod_id}\n"
188 var method_id
= nmethod_id
.to_nit_method_name
189 var nit_signature
= new Array[String]
191 nit_signature
.add
"\tfun {method_id}"
193 if not jparam_list
.is_empty
then
194 nit_signature
.add
"({nit_params})"
197 var return_type
= null
199 if not jreturn_type
.is_void
then
200 return_type
= jreturn_type
.to_nit_type
202 if not return_type
.is_complete
then
203 if jreturn_type
.is_wrapped
then
204 java_class
.imports
.add return_type
.mod
.as(not null)
206 model
.unknown_types
.add jreturn_type
207 if comment_unknown_types
then
210 return_type
= jreturn_type
.extern_name
215 nit_signature
.add
": {return_type} "
218 var temp
= new Array[String]
221 temp
.add
(comment
+ nit_signature
.join
)
223 if comment
== "#" then
224 temp
.add
(" in \"Java\
" `\{\n{comment}\t\tself.{jmethod_id}({java_params});\n{comment}\t`\}\n")
225 # Methods with return type
226 else if return_type
!= null then
227 temp
.add
(" in \"Java\
" `\{\n{comment}\t\treturn {jreturn_type.return_cast}self.{jmethod_id}({java_params});\n{comment}\t`\}\n")
228 # Methods without return type
229 else if jreturn_type
.is_void
then
230 temp
.add
(" in \"Java\
" `\{\n{comment}\t\tself.{jmethod_id}({java_params});\n{comment}\t`\}\n")
233 temp
.add
(" in \"Java\
" `\{\n{comment}\t\tself.{jmethod_id}({java_params});\n{comment}\t`\}\n")
241 # List of Nit keywords
243 # These may also be keywords in Java, but there they would be used capitalized.
244 private var nit_keywords
: Array[String] = ["abort", "abstract", "and", "assert",
245 "break", "class", "continue", "do", "else", "end", "enum", "extern", "implies",
246 "import", "init", "interface", "intrude", "if", "in", "is", "isa", "for", "label",
247 "loop", "module", "new", "not", "null", "nullable", "or", "package", "private",
248 "protected", "public", "return", "self", "super", "then", "type", "var", "while"]
253 # Convert the Java method name `self` to the Nit style
255 # * Converts to snake case
256 # * Strips `Get` and `Set`
257 # * Add suffix `=` to setters
258 fun to_nit_method_name
: String
260 var name
= self.to_snake_case
261 if name
.has_prefix
("get_") then
262 name
= name
.substring_from
(4)
263 else if name
.has_prefix
("set_") then
264 name
= name
.substring_from
(4)
265 if nit_keywords
.has
(name
) then name
+= "_"
269 # Strip the '_' prefix
270 while name
.has_prefix
("_") do name
= name
.substring
(1, name
.length-1
)
272 # Escape Nit keywords
273 if nit_keywords
.has
(name
) then name
+= "_"
275 # If the name starts by something other than a letter, prefix with `java_`
276 if not name
.chars
.first
.is_letter
then name
= "java_" + name
278 name
= name
.replace
("$", "_")