contrib/jwrapper: support wildcards with a default bound
[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 redef class Nwildcard
210 # TODO use the lower bound
211 redef fun accept_visitor(v) do v.add_identifier "Object"
212 end
213
214 # #
215 # C L A S S H E A D E R #
216 # #
217
218 redef class Nclass_declaration
219 redef fun accept_visitor(v)
220 do
221 v.java_class = new JavaClass
222 v.model.classes.add v.java_class
223 v.class_type = new JavaType(v.converter)
224
225 v.declaration_type = "class_header"
226 v.declaration_element = "id"
227 super
228
229 # Exit class declaration
230 v.declaration_type = null
231 v.declaration_element = null
232
233 v.java_class.class_type = v.class_type
234 end
235 end
236
237 # Extends declaration in the class header
238 redef class Nextends_declaration
239 redef fun accept_visitor(v)
240 do
241 v.declaration_element = "extends"
242 super
243 v.declaration_element = null
244 end
245 end
246
247 # Implements declaration in the class header
248 redef class Nimplements_declaration
249 redef fun accept_visitor(v)
250 do
251 v.declaration_element = "implements"
252 super
253 v.declaration_element = null
254 end
255 end
256
257 # #
258 # P R O P E R T Y D E C L A R A T I O N S #
259 # #
260
261 # Method declaration
262 redef class Nproperty_declaration_method
263 redef fun accept_visitor(v)
264 do
265 v.declaration_type = "method"
266 v.declaration_element = null
267 super
268 v.declaration_type = null
269
270 if v.method_return_type.has_unresolved_types then v.method_return_type.resolve_types(v.generic_map)
271
272 var method = new JavaMethod(v.method_return_type, v.method_params.clone)
273 v.java_class.methods[v.method_id].add method
274
275 v.method_params.clear
276 v.method_id = ""
277 v.method_return_type = new JavaType(v.converter)
278 end
279 end
280
281 # Constructor declaration
282 redef class Nproperty_declaration_constructor
283 redef fun accept_visitor(v)
284 do
285 v.declaration_type = "constructor"
286 super
287 v.declaration_type = null
288 end
289 end
290
291 # Variable property declaration
292 redef class Nproperty_declaration_attribute
293 redef fun accept_visitor(v)
294 do
295 v.declaration_type = "variable"
296 super
297 v.declaration_type = null
298
299 v.java_class.attributes[v.variable_id] = v.variable_type
300
301 v.variable_id = ""
302 v.variable_type = new JavaType(v.converter)
303 end
304 end
305
306 # Static property declaration
307 redef class Nproperty_declaration_static
308 redef fun accept_visitor(v)
309 do
310 v.declaration_type = "static"
311 super
312 v.declaration_type = null
313 end
314 end
315
316 # Identifier of a variable
317 redef class Nattribute_id
318 redef fun accept_visitor(v)
319 do
320 v.declaration_element = "id"
321 super
322 v.declaration_element = null
323 end
324 end
325
326 # Identifier of the method
327 redef class Nmethod_id
328 redef fun accept_visitor(v)
329 do
330 v.declaration_element = "id"
331 super
332 v.declaration_element = null
333 end
334 end
335
336 redef class Ntype
337 redef fun accept_visitor(v)
338 do
339 if v.declaration_type == "variable" and v.declaration_element != "id" then
340 v.declaration_element = "type"
341 end
342
343 if v.declaration_type == "method" and v.declaration_element == null then
344 # Makes sure it is not the generic return type definition
345 if not (v.method_return_type.identifier.is_empty and v.is_generic_param) then
346 v.declaration_element = "return_type"
347 end
348 end
349
350 super
351
352 if v.declaration_element == "variable" then
353 v.declaration_element = null
354 end
355 end
356 end
357
358 redef class Ngeneric_param
359 redef fun accept_visitor(v)
360 do
361 # Ignore the weird generic return type declaration
362 if v.declaration_type == "method" then
363 if v.declaration_element == null then
364 v.is_generic_param = true
365 else
366 v.is_generic_param = true
367 v.gen_params_index = 0
368
369 if v.declaration_element == "return_type" then
370 v.method_return_type.generic_params = new Array[JavaType]
371 else if v.declaration_element == "parameter_list" then
372 v.method_params[v.param_index].generic_params = new Array[JavaType]
373 end
374 end
375 else if v.declaration_type == "variable" then
376 if v.declaration_element == "type" then
377 v.is_generic_param = true
378 v.gen_params_index = 0
379 v.variable_type.generic_params = new Array[JavaType]
380 end
381 end
382
383 super
384
385 v.declaration_element = null
386 v.is_generic_param = false
387 end
388 end
389
390 redef class Ngeneric_identifier
391 redef fun accept_visitor(v)
392 do
393 if v.declaration_type == "method" then
394 if v.declaration_element == null then
395 v.is_generic_id = true
396 end
397 end
398
399 super
400
401 v.is_generic_id = false
402
403 end
404 end
405
406 redef class Nparameter_list
407 redef fun accept_visitor(v)
408 do
409 v.declaration_element = "parameter_list"
410 v.param_index = 0
411 super
412 v.declaration_element = null
413 v.param_index = 0
414 end
415 end
416
417 redef class Nparameter
418 redef fun accept_visitor(v)
419 do
420 if v.declaration_type == "method" then
421 if v.declaration_element == "parameter_list" then
422 if v.is_generic_param then
423 v.method_params[v.param_index].generic_params.add(new JavaType(v.converter))
424
425 super
426
427 v.gen_params_index += 1
428 else
429 v.method_params.add(new JavaType(v.converter))
430
431 super
432
433 v.param_index += 1
434 end
435 else if v.declaration_element == "return_type" and v.is_generic_param then
436
437 v.method_return_type.generic_params.add(new JavaType(v.converter))
438
439 super
440
441 v.gen_params_index += 1
442
443 # For generic return type definition
444 else if v.declaration_element == null then
445 super
446 end
447 else if v.declaration_type == "variable" then
448 if v.declaration_element == "type" and v.is_generic_param then
449 v.variable_type.generic_params.add(new JavaType(v.converter))
450
451 super
452
453 v.gen_params_index += 1
454 end
455 else
456 super
457 end
458 end
459 end