6fcd361352b9732d1a5ff2a6683478af97d13fc4
[nit.git] / contrib / jwrapper / src / javap_visitor.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
4 # Copyright 2015 Alexis Laferrière <alexis.laf@xymus.net>
5 #
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
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
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.
17
18 # Uses a visitor to extract data from the javap output AST
19 # It sends the data to `code_generator` module
20 module javap_visitor
21
22 import javap_test_parser
23 import code_generator
24 import jtype_converter
25 intrude import model
26
27 class JavaVisitor
28 super Visitor
29
30 var converter: JavaTypeConverter
31
32 var java_class = new JavaClass
33 var declaration_type: nullable String = null
34 var declaration_element: nullable String = null
35 var class_type = new JavaType(self.converter) is lazy
36
37 var variable_id = ""
38 var variable_type = new JavaType(self.converter) is lazy
39
40 var is_generic_param = false
41 var is_generic_id = false
42 var generic_id = ""
43 var gen_params_index = 0
44
45 # Used to resolve generic return types (T -> foo.faz.Bar)
46 var generic_map = new HashMap[String, Array[String]]
47
48 var is_primitive_array = false
49
50 var method_id = ""
51 var method_return_type = new JavaType(self.converter) is lazy
52 var method_params = new Array[JavaType]
53 var param_index = 0
54
55 redef fun visit(n) do n.accept_visitor(self)
56
57 # Add the identifier from `token` to the current context
58 fun add_identifier(token: NToken)
59 do
60 if declaration_type == "variable" then
61 if declaration_element == "type" then
62 variable_type.identifier.add(token.text)
63 end
64 else if declaration_type == "method" then
65 if declaration_element == "return_type" then
66 method_return_type.identifier.add(token.text)
67 else if declaration_element == "parameter_list" then
68 method_params[param_index].identifier.add(token.text)
69 end
70 end
71 end
72 end
73
74 redef class Node
75 fun accept_visitor(v: JavaVisitor) do visit_children(v)
76 end
77
78 redef class Nidentifier
79 redef fun accept_visitor(v)
80 do
81 if v.declaration_type == "class_header" then
82
83 if v.declaration_element == "id" then
84 v.class_type.identifier.add(self.text)
85 end
86
87 else if v.declaration_type == "variable" then
88
89 if v.declaration_element == "id" then
90 v.variable_id += self.text
91 else if v.declaration_element == "type" then
92 if v.is_generic_param then
93 v.variable_type.generic_params[v.gen_params_index].identifier.add(self.text)
94 else
95 v.variable_type.identifier.add(self.text)
96 end
97 end
98
99 else if v.declaration_type == "method" then
100
101 if v.declaration_element == "id" then
102 v.method_id = self.text
103 else if v.declaration_element == "return_type" then
104 if self.text == "void" then
105 v.method_return_type.is_void = true
106 else if v.is_generic_param then
107 v.method_return_type.generic_params[v.gen_params_index].identifier.add(self.text)
108 else
109 v.method_return_type.identifier.add(self.text)
110 end
111 else if v.declaration_element == "parameter_list" then
112 if v.is_generic_param then
113 v.method_params[v.param_index].generic_params[v.gen_params_index].identifier.add(self.text)
114 else
115 v.method_params[v.param_index].identifier.add(self.text)
116 end
117
118 # Creates a map to resolve generic return types
119 # Exemple : public **<T extends android/os/Bundle>** T foo();
120 else if v.is_generic_param then
121 if v.is_generic_id then
122 v.generic_id = self.text
123 v.generic_map[self.text] = new Array[String]
124
125 if not v.method_return_type.has_unresolved_types then v.method_return_type.has_unresolved_types = true
126 else
127 v.generic_map[v.generic_id].add(self.text)
128 end
129 end
130
131 end
132
133 super
134 end
135 end
136
137 # Primitive array node
138 redef class Nbrackets
139 redef fun accept_visitor(v)
140 do
141 if v.declaration_type == "variable" then
142 if v.declaration_element == "type" then
143 if v.is_generic_param then
144 v.variable_type.generic_params[v.gen_params_index].array_dimension += 1
145 else
146 v.variable_type.array_dimension += 1
147 end
148 end
149
150 else if v.declaration_type == "method" then
151
152 if v.declaration_element == "return_type" then
153 if v.is_generic_param then
154 v.method_return_type.generic_params[v.gen_params_index].array_dimension += 1
155 else
156 v.method_return_type.array_dimension += 1
157 end
158 else if v.declaration_element == "parameter_list" then
159 if v.is_generic_param then
160 v.method_params[v.param_index].generic_params[v.gen_params_index].array_dimension += 1
161 else
162 v.method_params[v.param_index].array_dimension += 1
163 end
164 end
165
166 end
167
168 super
169 end
170 end
171
172 redef class N_39dchar_39d
173 redef fun accept_visitor(v) do v.add_identifier self
174 end
175
176 redef class N_39dboolean_39d
177 redef fun accept_visitor(v) do v.add_identifier self
178 end
179
180 redef class N_39dfloat_39d
181 redef fun accept_visitor(v) do v.add_identifier self
182 end
183
184 redef class N_39ddouble_39d
185 redef fun accept_visitor(v) do v.add_identifier self
186 end
187
188 redef class N_39dbyte_39d
189 redef fun accept_visitor(v) do v.add_identifier self
190 end
191
192 redef class N_39dshort_39d
193 redef fun accept_visitor(v) do v.add_identifier self
194 end
195
196 redef class N_39dint_39d
197 redef fun accept_visitor(v) do v.add_identifier self
198 end
199
200 redef class N_39dlong_39d
201 redef fun accept_visitor(v) do v.add_identifier self
202 end
203
204 # #
205 # C L A S S H E A D E R #
206 # #
207
208 redef class Nclass_declaration
209 redef fun accept_visitor(v)
210 do
211 v.declaration_type = "class_header"
212 v.declaration_element = "id"
213 super
214
215 # Exit class declaration
216 v.declaration_type = null
217 v.declaration_element = null
218
219 v.java_class.class_type = v.class_type
220 end
221 end
222
223 # Extends declaration in the class header
224 redef class Nextends_declaration
225 redef fun accept_visitor(v)
226 do
227 v.declaration_element = "extends"
228 super
229 v.declaration_element = null
230 end
231 end
232
233 # Implements declaration in the class header
234 redef class Nimplements_declaration
235 redef fun accept_visitor(v)
236 do
237 v.declaration_element = "implements"
238 super
239 v.declaration_element = null
240 end
241 end
242
243 # #
244 # P R O P E R T Y D E C L A R A T I O N S #
245 # #
246
247 # Method declaration
248 redef class Nproperty_declaration_method
249 redef fun accept_visitor(v)
250 do
251 v.declaration_type = "method"
252 v.declaration_element = null
253 super
254 v.declaration_type = null
255
256 if v.method_return_type.has_unresolved_types then v.method_return_type.resolve_types(v.generic_map)
257
258 var method = new JavaMethod(v.method_return_type, v.method_params.clone)
259 v.java_class.methods[v.method_id].add method
260
261 v.method_params.clear
262 v.method_id = ""
263 v.method_return_type = new JavaType(v.converter)
264 end
265 end
266
267 # Constructor declaration
268 redef class Nproperty_declaration_constructor
269 redef fun accept_visitor(v)
270 do
271 v.declaration_type = "constructor"
272 super
273 v.declaration_type = null
274 end
275 end
276
277 # Variable property declaration
278 redef class Nproperty_declaration_attribute
279 redef fun accept_visitor(v)
280 do
281 v.declaration_type = "variable"
282 super
283 v.declaration_type = null
284
285 v.java_class.attributes[v.variable_id] = v.variable_type
286
287 v.variable_id = ""
288 v.variable_type = new JavaType(v.converter)
289 end
290 end
291
292 # Static property declaration
293 redef class Nproperty_declaration_static
294 redef fun accept_visitor(v)
295 do
296 v.declaration_type = "static"
297 super
298 v.declaration_type = null
299 end
300 end
301
302 # Identifier of a variable
303 redef class Nattribute_id
304 redef fun accept_visitor(v)
305 do
306 v.declaration_element = "id"
307 super
308 v.declaration_element = null
309 end
310 end
311
312 # Identifier of the method
313 redef class Nmethod_id
314 redef fun accept_visitor(v)
315 do
316 v.declaration_element = "id"
317 super
318 v.declaration_element = null
319 end
320 end
321
322 redef class Ntype
323 redef fun accept_visitor(v)
324 do
325 if v.declaration_type == "variable" and v.declaration_element != "id" then
326 v.declaration_element = "type"
327 end
328
329 if v.declaration_type == "method" and v.declaration_element == null then
330 # Makes sure it is not the generic return type definition
331 if not (v.method_return_type.identifier.is_empty and v.is_generic_param) then
332 v.declaration_element = "return_type"
333 end
334 end
335
336 super
337
338 if v.declaration_element == "variable" then
339 v.declaration_element = null
340 end
341 end
342 end
343
344 redef class Ngeneric_param
345 redef fun accept_visitor(v)
346 do
347 # Ignore the weird generic return type declaration
348 if v.declaration_type == "method" then
349 if v.declaration_element == null then
350 v.is_generic_param = true
351 else
352 v.is_generic_param = true
353 v.gen_params_index = 0
354
355 if v.declaration_element == "return_type" then
356 v.method_return_type.generic_params = new Array[JavaType]
357 else if v.declaration_element == "parameter_list" then
358 v.method_params[v.param_index].generic_params = new Array[JavaType]
359 end
360 end
361 else if v.declaration_type == "variable" then
362 if v.declaration_element == "type" then
363 v.is_generic_param = true
364 v.gen_params_index = 0
365 v.variable_type.generic_params = new Array[JavaType]
366 end
367 end
368
369 super
370
371 v.declaration_element = null
372 v.is_generic_param = false
373 end
374 end
375
376 redef class Ngeneric_identifier
377 redef fun accept_visitor(v)
378 do
379 if v.declaration_type == "method" then
380 if v.declaration_element == null then
381 v.is_generic_id = true
382 end
383 end
384
385 super
386
387 v.is_generic_id = false
388
389 end
390 end
391
392 redef class Nparameter_list
393 redef fun accept_visitor(v)
394 do
395 v.declaration_element = "parameter_list"
396 v.param_index = 0
397 super
398 v.declaration_element = null
399 v.param_index = 0
400 end
401 end
402
403 redef class Nparameter
404 redef fun accept_visitor(v)
405 do
406 if v.declaration_type == "method" then
407 if v.declaration_element == "parameter_list" then
408 if v.is_generic_param then
409 v.method_params[v.param_index].generic_params.add(new JavaType(v.converter))
410
411 super
412
413 v.gen_params_index += 1
414 else
415 v.method_params.add(new JavaType(v.converter))
416
417 super
418
419 v.param_index += 1
420 end
421 else if v.declaration_element == "return_type" and v.is_generic_param then
422
423 v.method_return_type.generic_params.add(new JavaType(v.converter))
424
425 super
426
427 v.gen_params_index += 1
428
429 # For generic return type definition
430 else if v.declaration_element == null then
431 super
432 end
433 else if v.declaration_type == "variable" then
434 if v.declaration_element == "type" and v.is_generic_param then
435 v.variable_type.generic_params.add(new JavaType(v.converter))
436
437 super
438
439 v.gen_params_index += 1
440 end
441 else
442 super
443 end
444 end
445 end