1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
4 # Copyright 2015 Alexis Laferrière <alexis.laf@xymus.net>
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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.
18 # Uses a visitor to extract data from the javap output AST
19 # It sends the data to `code_generator` module
22 import javap_test_parser
24 import jtype_converter
27 # Visitor of the AST generated from javap output
31 var converter
: JavaTypeConverter
33 # Model of all the analyzed classes
36 var java_class
: JavaClass is noinit
38 var declaration_type
: nullable String = null
39 var declaration_element
: nullable String = null
40 var class_type
: JavaType is noinit
43 var variable_type
= new JavaType(self.converter
) is lazy
45 var is_generic_param
= false
46 var is_generic_id
= false
48 var gen_params_index
= 0
50 # Used to resolve generic return types (T -> foo.faz.Bar)
51 var generic_map
= new HashMap[String, Array[String]]
53 var is_primitive_array
= false
56 var method_return_type
= new JavaType(self.converter
) is lazy
57 var method_params
= new Array[JavaType]
60 redef fun visit
(n
) do n
.accept_visitor
(self)
62 # Add the identifier from `token` to the current context
63 fun add_identifier
(token
: NToken)
65 if declaration_type
== "variable" then
66 if declaration_element
== "type" then
67 variable_type
.identifier
.add
(token
.text
)
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
)
80 fun accept_visitor
(v
: JavaVisitor) do visit_children
(v
)
83 redef class Nidentifier
84 redef fun accept_visitor
(v
)
86 if v
.declaration_type
== "class_header" then
88 if v
.declaration_element
== "id" then
89 v
.class_type
.identifier
.add
(self.text
)
92 else if v
.declaration_type
== "variable" then
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
)
100 v
.variable_type
.identifier
.add
(self.text
)
104 else if v
.declaration_type
== "method" then
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
)
114 v
.method_return_type
.identifier
.add
(self.text
)
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
)
120 v
.method_params
[v
.param_index
].identifier
.add
(self.text
)
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]
130 if not v
.method_return_type
.has_unresolved_types
then v
.method_return_type
.has_unresolved_types
= true
132 v
.generic_map
[v
.generic_id
].add
(self.text
)
142 # Primitive array node
143 redef class Nbrackets
144 redef fun accept_visitor
(v
)
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
151 v
.variable_type
.array_dimension
+= 1
155 else if v
.declaration_type
== "method" then
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
161 v
.method_return_type
.array_dimension
+= 1
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
167 v
.method_params
[v
.param_index
].array_dimension
+= 1
177 redef class N_39dchar_39d
178 redef fun accept_visitor
(v
) do v
.add_identifier
self
181 redef class N_39dboolean_39d
182 redef fun accept_visitor
(v
) do v
.add_identifier
self
185 redef class N_39dfloat_39d
186 redef fun accept_visitor
(v
) do v
.add_identifier
self
189 redef class N_39ddouble_39d
190 redef fun accept_visitor
(v
) do v
.add_identifier
self
193 redef class N_39dbyte_39d
194 redef fun accept_visitor
(v
) do v
.add_identifier
self
197 redef class N_39dshort_39d
198 redef fun accept_visitor
(v
) do v
.add_identifier
self
201 redef class N_39dint_39d
202 redef fun accept_visitor
(v
) do v
.add_identifier
self
205 redef class N_39dlong_39d
206 redef fun accept_visitor
(v
) do v
.add_identifier
self
209 redef class Nwildcard
210 # TODO use the lower bound
211 redef fun accept_visitor
(v
) do v
.add_identifier
"Object"
215 # C L A S S H E A D E R #
218 redef class Nclass_declaration
219 redef fun accept_visitor
(v
)
221 v
.java_class
= new JavaClass
222 v
.model
.classes
.add v
.java_class
223 v
.class_type
= new JavaType(v
.converter
)
225 v
.declaration_type
= "class_header"
226 v
.declaration_element
= "id"
229 # Exit class declaration
230 v
.declaration_type
= null
231 v
.declaration_element
= null
233 v
.java_class
.class_type
= v
.class_type
237 # Extends declaration in the class header
238 redef class Nextends_declaration
239 redef fun accept_visitor
(v
)
241 v
.declaration_element
= "extends"
243 v
.declaration_element
= null
247 # Implements declaration in the class header
248 redef class Nimplements_declaration
249 redef fun accept_visitor
(v
)
251 v
.declaration_element
= "implements"
253 v
.declaration_element
= null
258 # P R O P E R T Y D E C L A R A T I O N S #
262 redef class Nproperty_declaration_method
263 redef fun accept_visitor
(v
)
265 v
.declaration_type
= "method"
266 v
.declaration_element
= null
268 v
.declaration_type
= null
270 if v
.method_return_type
.has_unresolved_types
then v
.method_return_type
.resolve_types
(v
.generic_map
)
272 var method
= new JavaMethod(v
.method_return_type
, v
.method_params
.clone
)
273 v
.java_class
.methods
[v
.method_id
].add method
275 v
.method_params
.clear
277 v
.method_return_type
= new JavaType(v
.converter
)
281 # Constructor declaration
282 redef class Nproperty_declaration_constructor
283 redef fun accept_visitor
(v
)
285 v
.declaration_type
= "constructor"
287 v
.declaration_type
= null
291 # Variable property declaration
292 redef class Nproperty_declaration_attribute
293 redef fun accept_visitor
(v
)
295 v
.declaration_type
= "variable"
297 v
.declaration_type
= null
299 v
.java_class
.attributes
[v
.variable_id
] = v
.variable_type
302 v
.variable_type
= new JavaType(v
.converter
)
306 # Static property declaration
307 redef class Nproperty_declaration_static
308 redef fun accept_visitor
(v
)
310 v
.declaration_type
= "static"
312 v
.declaration_type
= null
316 # Identifier of a variable
317 redef class Nattribute_id
318 redef fun accept_visitor
(v
)
320 v
.declaration_element
= "id"
322 v
.declaration_element
= null
326 # Identifier of the method
327 redef class Nmethod_id
328 redef fun accept_visitor
(v
)
330 v
.declaration_element
= "id"
332 v
.declaration_element
= null
337 redef fun accept_visitor
(v
)
339 if v
.declaration_type
== "variable" and v
.declaration_element
!= "id" then
340 v
.declaration_element
= "type"
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"
352 if v
.declaration_element
== "variable" then
353 v
.declaration_element
= null
358 redef class Ngeneric_param
359 redef fun accept_visitor
(v
)
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
366 v
.is_generic_param
= true
367 v
.gen_params_index
= 0
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]
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]
385 v
.declaration_element
= null
386 v
.is_generic_param
= false
390 redef class Ngeneric_identifier
391 redef fun accept_visitor
(v
)
393 if v
.declaration_type
== "method" then
394 if v
.declaration_element
== null then
395 v
.is_generic_id
= true
401 v
.is_generic_id
= false
406 redef class Nparameter_list
407 redef fun accept_visitor
(v
)
409 v
.declaration_element
= "parameter_list"
412 v
.declaration_element
= null
417 redef class Nparameter
418 redef fun accept_visitor
(v
)
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
))
427 v
.gen_params_index
+= 1
429 v
.method_params
.add
(new JavaType(v
.converter
))
435 else if v
.declaration_element
== "return_type" and v
.is_generic_param
then
437 v
.method_return_type
.generic_params
.add
(new JavaType(v
.converter
))
441 v
.gen_params_index
+= 1
443 # For generic return type definition
444 else if v
.declaration_element
== null then
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
))
453 v
.gen_params_index
+= 1