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