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