45edb3d288e20cb94ab886791fde91b4882e5d12
[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 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Uses a visitor to extract data from the javap output AST
18 # It sends the data to `code_generator` module
19 module javap_visitor
20
21 import javap_test_parser
22 import code_generator
23 import jtype_converter
24 intrude import types
25
26 class JavaVisitor
27 super Visitor
28
29 var converter: JavaTypeConverter
30
31 var java_class = new JavaClass
32 var declaration_type: nullable String = null
33 var declaration_element: nullable String = null
34 var class_type: JavaType
35
36 var variable_id = ""
37 var variable_type: JavaType
38
39 var is_generic_param = false
40 var is_generic_id = false
41 var generic_id = ""
42 var gen_params_index = 0
43
44 # Used to resolve generic return types (T -> foo.faz.Bar)
45 var generic_map = new HashMap[String, Array[String]]
46
47 var is_primitive_array = false
48
49 var method_id = ""
50 var method_return_type: JavaType
51 var method_params = new Array[JavaType]
52 var param_index = 0
53
54 redef fun visit(n) do n.accept_visitor(self)
55
56 init(converter: JavaTypeConverter)
57 do
58 self.converter = converter
59 self.class_type = new JavaType(self.converter)
60 self.method_return_type = new JavaType(self.converter)
61 self.variable_type = new JavaType(self.converter)
62 super
63 end
64 end
65
66 redef class Node
67 fun accept_visitor(v: JavaVisitor) do visit_children(v)
68 end
69
70 redef class Nidentifier
71 redef fun accept_visitor(v)
72 do
73 if v.declaration_type == "class_header" then
74
75 if v.declaration_element == "id" then
76 v.class_type.identifier.add(self.text)
77 end
78
79 else if v.declaration_type == "variable" then
80
81 if v.declaration_element == "id" then
82 v.variable_id += self.text
83 else if v.declaration_element == "type" then
84 if v.is_generic_param then
85 v.variable_type.generic_params[v.gen_params_index].identifier.add(self.text)
86 else
87 v.variable_type.identifier.add(self.text)
88 end
89 end
90
91 else if v.declaration_type == "method" then
92
93 if v.declaration_element == "id" then
94 v.method_id = self.text
95 else if v.declaration_element == "return_type" then
96 if self.text == "void" then
97 v.method_return_type.is_void = true
98 else if v.is_generic_param then
99 v.method_return_type.generic_params[v.gen_params_index].identifier.add(self.text)
100 else
101 v.method_return_type.identifier.add(self.text)
102 end
103 else if v.declaration_element == "parameter_list" then
104 if v.is_generic_param then
105 v.method_params[v.param_index].generic_params[v.gen_params_index].identifier.add(self.text)
106 else
107 v.method_params[v.param_index].identifier.add(self.text)
108 end
109
110 # Creates a map to resolve generic return types
111 # Exemple : public **<T extends android/os/Bundle>** T foo();
112 else if v.is_generic_param then
113 if v.is_generic_id then
114 v.generic_id = self.text
115 v.generic_map[self.text] = new Array[String]
116
117 if not v.method_return_type.has_unresolved_types then v.method_return_type.has_unresolved_types = true
118 else
119 v.generic_map[v.generic_id].add(self.text)
120 end
121 end
122
123 end
124
125 super
126 end
127 end
128
129 # Primitive array node
130 redef class N_39d_91d_93d_39d
131 redef fun accept_visitor(v)
132 do
133 if v.declaration_type == "variable" then
134 if v.declaration_element == "type" then
135 if v.is_generic_param then
136 v.variable_type.generic_params[v.gen_params_index].array_dimension += 1
137 else
138 v.variable_type.array_dimension += 1
139 end
140 end
141
142 else if v.declaration_type == "method" then
143
144 if v.declaration_element == "return_type" then
145 if v.is_generic_param then
146 v.method_return_type.generic_params[v.gen_params_index].array_dimension += 1
147 else
148 v.method_return_type.array_dimension += 1
149 end
150 else if v.declaration_element == "parameter_list" then
151 if v.is_generic_param then
152 v.method_params[v.param_index].generic_params[v.gen_params_index].array_dimension += 1
153 else
154 v.method_params[v.param_index].array_dimension += 1
155 end
156 end
157
158 end
159
160 super
161 end
162 end
163
164 redef class N_39dchar_39d
165 redef fun accept_visitor(v)
166 do
167 if v.declaration_type == "variable" then
168 if v.declaration_element == "type" then
169 v.variable_type.identifier.add(self.text)
170 end
171 else if v.declaration_type == "method" then
172 if v.declaration_element == "return_type" then
173 v.method_return_type.identifier.add(self.text)
174 else if v.declaration_element == "parameter_list" then
175 v.method_params[v.param_index].identifier.add(self.text)
176 end
177 end
178 end
179 end
180
181 redef class N_39dboolean_39d
182 redef fun accept_visitor(v)
183 do
184 if v.declaration_type == "variable" then
185 if v.declaration_element == "type" then
186 v.variable_type.identifier.add(self.text)
187 end
188 else if v.declaration_type == "method" then
189 if v.declaration_element == "return_type" then
190 v.method_return_type.identifier.add(self.text)
191 else if v.declaration_element == "parameter_list" then
192 v.method_params[v.param_index].identifier.add(self.text)
193 end
194 end
195 end
196 end
197
198 redef class N_39dfloat_39d
199 redef fun accept_visitor(v)
200 do
201 if v.declaration_type == "variable" then
202 if v.declaration_element == "type" then
203 v.variable_type.identifier.add(self.text)
204 end
205 else if v.declaration_type == "method" then
206 if v.declaration_element == "return_type" then
207 v.method_return_type.identifier.add(self.text)
208 else if v.declaration_element == "parameter_list" then
209 v.method_params[v.param_index].identifier.add(self.text)
210 end
211 end
212 end
213 end
214
215 redef class N_39ddouble_39d
216 redef fun accept_visitor(v)
217 do
218 if v.declaration_type == "variable" then
219 if v.declaration_element == "type" then
220 v.variable_type.identifier.add(self.text)
221 end
222 else if v.declaration_type == "method" then
223 if v.declaration_element == "return_type" then
224 v.method_return_type.identifier.add(self.text)
225 else if v.declaration_element == "parameter_list" then
226 v.method_params[v.param_index].identifier.add(self.text)
227 end
228 end
229 end
230 end
231
232 redef class N_39dbyte_39d
233 redef fun accept_visitor(v)
234 do
235 if v.declaration_type == "variable" then
236 if v.declaration_element == "type" then
237 v.variable_type.identifier.add(self.text)
238 end
239 else if v.declaration_type == "method" then
240 if v.declaration_element == "return_type" then
241 v.method_return_type.identifier.add(self.text)
242 else if v.declaration_element == "parameter_list" then
243 v.method_params[v.param_index].identifier.add(self.text)
244 end
245 end
246 end
247 end
248
249 redef class N_39dshort_39d
250 redef fun accept_visitor(v)
251 do
252 if v.declaration_type == "variable" then
253 if v.declaration_element == "type" then
254 v.variable_type.identifier.add(self.text)
255 end
256 else if v.declaration_type == "method" then
257 if v.declaration_element == "return_type" then
258 v.method_return_type.identifier.add(self.text)
259 else if v.declaration_element == "parameter_list" then
260 v.method_params[v.param_index].identifier.add(self.text)
261 end
262 end
263 end
264 end
265
266 redef class N_39dint_39d
267 redef fun accept_visitor(v)
268 do
269 if v.declaration_type == "variable" then
270 if v.declaration_element == "type" then
271 v.variable_type.identifier.add(self.text)
272 end
273 else if v.declaration_type == "method" then
274 if v.declaration_element == "return_type" then
275 v.method_return_type.identifier.add(self.text)
276 else if v.declaration_element == "parameter_list" then
277 v.method_params[v.param_index].identifier.add(self.text)
278 end
279 end
280 end
281 end
282
283 redef class N_39dlong_39d
284 redef fun accept_visitor(v)
285 do
286 if v.declaration_type == "variable" then
287 if v.declaration_element == "type" then
288 v.variable_type.identifier.add(self.text)
289 end
290 else if v.declaration_type == "method" then
291 if v.declaration_element == "return_type" then
292 v.method_return_type.identifier.add(self.text)
293 else if v.declaration_element == "parameter_list" then
294 v.method_params[v.param_index].identifier.add(self.text)
295 end
296 end
297 end
298 end
299
300 # #
301 # C L A S S H E A D E R #
302 # #
303 redef class Nclass_header
304 redef fun accept_visitor(v)
305 do
306 v.declaration_type = "class_header"
307 v.declaration_element = "id"
308 super
309
310 # Exit class declaration
311 v.declaration_type = null
312 v.declaration_element = null
313
314 v.java_class.class_type = v.class_type
315 end
316 end
317
318 # Extends declaration in the class header
319 redef class Nextends_declaration
320 redef fun accept_visitor(v)
321 do
322 v.declaration_element = "extends"
323 super
324 v.declaration_element = null
325 end
326 end
327
328 # Implements declaration in the class header
329 redef class Nimplements_declaration
330 redef fun accept_visitor(v)
331 do
332 v.declaration_element = "implements"
333 super
334 v.declaration_element = null
335 end
336 end
337
338 # #
339 # F I E L D D E C L A R A T I O N S #
340 # #
341
342 # Method declaration in the field declarations
343 redef class Nmethod_declaration
344 redef fun accept_visitor(v)
345 do
346 v.declaration_type = "method"
347 super
348 v.declaration_type = null
349
350 if v.method_return_type.has_unresolved_types then v.method_return_type.resolve_types(v.generic_map)
351 v.java_class.add_method(v.method_id, v.method_return_type, v.method_params)
352
353 v.method_params.clear
354 v.method_id = ""
355 v.method_return_type = new JavaType(v.converter)
356 end
357 end
358
359 # Constructor declaration in the field declarations
360 redef class Nconstructor_declaration
361 redef fun accept_visitor(v)
362 do
363 v.declaration_type = "constructor"
364 super
365 v.declaration_type = null
366 end
367 end
368
369 # Variable declaration in the field declarations
370 redef class Nvariable_declaration
371 redef fun accept_visitor(v)
372 do
373 v.declaration_type = "variable"
374 super
375 v.declaration_type = null
376
377 v.java_class.attributes[v.variable_id] = v.variable_type
378
379 v.variable_id = ""
380 v.variable_type = new JavaType(v.converter)
381 end
382 end
383
384 # Static declaration in the field declarations
385 redef class Nstatic_declaration
386 redef fun accept_visitor(v)
387 do
388 v.declaration_type = "static"
389 super
390 v.declaration_type = null
391 end
392 end
393
394 # Identifier of the field
395 redef class Nvariable_id
396 redef fun accept_visitor(v)
397 do
398 v.declaration_element = "id"
399 super
400 v.declaration_element = null
401 end
402 end
403
404 # Identifier of the method
405 redef class Nmethod_id
406 redef fun accept_visitor(v)
407 do
408 v.declaration_element = "id"
409 super
410 v.declaration_element = null
411 end
412 end
413
414 redef class Ntype
415 redef fun accept_visitor(v)
416 do
417 if v.declaration_type == "variable" and v.declaration_element != "id" then
418 v.declaration_element = "type"
419 end
420
421 if v.declaration_type == "method" and v.declaration_element == null then
422 # Makes sure it is not the generic return type definition
423 if not (v.method_return_type.identifier.is_empty and v.is_generic_param) then
424 v.declaration_element = "return_type"
425 end
426 end
427
428 super
429
430 if v.declaration_element == "variable" then
431 v.declaration_element = null
432 end
433 end
434 end
435
436 redef class Ngeneric_param
437 redef fun accept_visitor(v)
438 do
439 # Ignore the weird generic return type declaration
440 if v.declaration_type == "method" then
441 if v.declaration_element == null then
442 v.is_generic_param = true
443 else
444 v.is_generic_param = true
445 v.gen_params_index = 0
446
447 if v.declaration_element == "return_type" then
448 v.method_return_type.generic_params = new Array[JavaType]
449 else if v.declaration_element == "parameter_list" then
450 v.method_params[v.param_index].generic_params = new Array[JavaType]
451 end
452 end
453 else if v.declaration_type == "variable" then
454 if v.declaration_element == "type" then
455 v.is_generic_param = true
456 v.gen_params_index = 0
457 v.variable_type.generic_params = new Array[JavaType]
458 end
459 end
460
461 super
462
463 v.declaration_element = null
464 v.is_generic_param = false
465 end
466 end
467
468 redef class Ngeneric_identifier
469 redef fun accept_visitor(v)
470 do
471 if v.declaration_type == "method" then
472 if v.declaration_element == null then
473 v.is_generic_id = true
474 end
475 end
476
477 super
478
479 v.is_generic_id = false
480
481 end
482 end
483
484 redef class Nparameter_list
485 redef fun accept_visitor(v)
486 do
487 v.declaration_element = "parameter_list"
488 v.param_index = 0
489 super
490 v.declaration_element = null
491 v.param_index = 0
492 end
493 end
494
495 redef class Nparameter
496 redef fun accept_visitor(v)
497 do
498 if v.declaration_type == "method" then
499 if v.declaration_element == "parameter_list" then
500 if v.is_generic_param then
501 v.method_params[v.param_index].generic_params.add(new JavaType(v.converter))
502
503 super
504
505 v.gen_params_index += 1
506 else
507 v.method_params.add(new JavaType(v.converter))
508
509 super
510
511 v.param_index += 1
512 end
513 else if v.declaration_element == "return_type" and v.is_generic_param then
514
515 v.method_return_type.generic_params.add(new JavaType(v.converter))
516
517 super
518
519 v.gen_params_index += 1
520
521 # For generic return type definition
522 else if v.declaration_element == null then
523 super
524 end
525 else if v.declaration_type == "variable" then
526 if v.declaration_element == "type" and v.is_generic_param then
527 v.variable_type.generic_params.add(new JavaType(v.converter))
528
529 super
530
531 v.gen_params_index += 1
532 end
533 else
534 super
535 end
536 end
537 end