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