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 # Model of all the analyzed classes
34 var java_class
: JavaClass is noinit
36 var declaration_type
: nullable String = null
37 var declaration_element
: nullable String = null
38 var class_type
: JavaType is noinit
41 var variable_type
= new JavaType is lazy
43 var is_generic_param
= false
44 var is_generic_id
= false
46 var gen_params_index
= 0
48 # Used to resolve generic return types (T -> foo.faz.Bar)
49 var generic_map
= new HashMap[String, Array[String]]
51 var is_primitive_array
= false
54 var method_return_type
= new JavaType is lazy
55 var method_params
= new Array[JavaType]
58 redef fun visit
(n
) do n
.accept_visitor
(self)
60 # Add the identifier from `token` to the current context
61 fun add_identifier
(token
: String)
63 if declaration_type
== "variable" then
64 if declaration_element
== "type" then
65 if is_generic_param
then
66 variable_type
.generic_params
[gen_params_index
].identifier
.add token
68 variable_type
.identifier
.add
(token
)
71 else if declaration_type
== "method" then
72 if declaration_element
== "return_type" then
73 if is_generic_param
then
74 method_return_type
.generic_params
[gen_params_index
].identifier
.add token
76 method_return_type
.identifier
.add
(token
)
78 else if declaration_element
== "parameter_list" then
79 if is_generic_param
then
80 method_params
[param_index
].generic_params
[gen_params_index
].identifier
.add token
82 method_params
[param_index
].identifier
.add
(token
)
90 fun accept_visitor
(v
: JavaVisitor) do visit_children
(v
)
93 redef class Nidentifier
94 redef fun accept_visitor
(v
)
96 if v
.declaration_type
== "class_header" then
98 if v
.declaration_element
== "id" then
99 v
.class_type
.identifier
.add text
103 else if v
.declaration_type
== "variable" then
104 # Attribute declaration
105 if v
.declaration_element
== "id" then
106 v
.variable_id
+= text
110 else if v
.declaration_type
== "method" then
112 if v
.declaration_element
== "id" then
114 v
.method_id
= self.text
116 else if v
.declaration_element
== "return_type" then
117 if self.text
== "void" then
119 v
.method_return_type
.is_void
= true
122 else if v
.declaration_element
== "parameter_list" then
123 # Parameters, leave it to add_identifier
125 else if v
.is_generic_param
then
126 # Creates a map to resolve generic return types
127 # Example : public **<T extends android/os/Bundle>** T foo();
128 if v
.is_generic_id
then
129 v
.generic_id
= self.text
130 v
.generic_map
[self.text
] = new Array[String]
132 if not v
.method_return_type
.has_unresolved_types
then v
.method_return_type
.has_unresolved_types
= true
134 v
.generic_map
[v
.generic_id
].add text
139 v
.add_identifier text
143 # Primitive array node
144 redef class Nbrackets
145 redef fun accept_visitor
(v
)
147 if v
.declaration_type
== "variable" then
148 if v
.declaration_element
== "type" then
149 if v
.is_generic_param
then
150 v
.variable_type
.generic_params
[v
.gen_params_index
].array_dimension
+= 1
152 v
.variable_type
.array_dimension
+= 1
156 else if v
.declaration_type
== "method" then
158 if v
.declaration_element
== "return_type" then
159 if v
.is_generic_param
then
160 v
.method_return_type
.generic_params
[v
.gen_params_index
].array_dimension
+= 1
162 v
.method_return_type
.array_dimension
+= 1
164 else if v
.declaration_element
== "parameter_list" then
165 if v
.is_generic_param
then
166 v
.method_params
[v
.param_index
].generic_params
[v
.gen_params_index
].array_dimension
+= 1
168 v
.method_params
[v
.param_index
].array_dimension
+= 1
178 redef class N_39dchar_39d
179 redef fun accept_visitor
(v
) do v
.add_identifier text
182 redef class N_39dboolean_39d
183 redef fun accept_visitor
(v
) do v
.add_identifier text
186 redef class N_39dfloat_39d
187 redef fun accept_visitor
(v
) do v
.add_identifier text
190 redef class N_39ddouble_39d
191 redef fun accept_visitor
(v
) do v
.add_identifier text
194 redef class N_39dbyte_39d
195 redef fun accept_visitor
(v
) do v
.add_identifier text
198 redef class N_39dshort_39d
199 redef fun accept_visitor
(v
) do v
.add_identifier text
202 redef class N_39dint_39d
203 redef fun accept_visitor
(v
) do v
.add_identifier text
206 redef class N_39dlong_39d
207 redef fun accept_visitor
(v
) do v
.add_identifier text
210 redef class Nwildcard
211 # TODO use the lower bound
212 redef fun accept_visitor
(v
) do v
.add_identifier
"Object"
216 # C L A S S H E A D E R #
219 redef class Nclass_declaration
220 redef fun accept_visitor
(v
)
222 v
.java_class
= new JavaClass
223 v
.model
.classes
.add v
.java_class
224 v
.class_type
= new JavaType
226 v
.declaration_type
= "class_header"
227 v
.declaration_element
= "id"
230 # Exit class declaration
231 v
.declaration_type
= null
232 v
.declaration_element
= null
234 v
.java_class
.class_type
= v
.class_type
238 # Extends declaration in the class header
239 redef class Nextends_declaration
240 redef fun accept_visitor
(v
)
242 v
.declaration_element
= "extends"
244 v
.declaration_element
= null
248 # Implements declaration in the class header
249 redef class Nimplements_declaration
250 redef fun accept_visitor
(v
)
252 v
.declaration_element
= "implements"
254 v
.declaration_element
= null
259 # P R O P E R T Y D E C L A R A T I O N S #
263 redef class Nproperty_declaration_method
264 redef fun accept_visitor
(v
)
266 v
.declaration_type
= "method"
267 v
.declaration_element
= null
269 v
.declaration_type
= null
271 if v
.method_return_type
.has_unresolved_types
then v
.method_return_type
.resolve_types
(v
.generic_map
)
273 var method
= new JavaMethod(v
.method_return_type
, v
.method_params
.clone
)
274 v
.java_class
.methods
[v
.method_id
].add method
276 v
.method_params
.clear
278 v
.method_return_type
= new JavaType
282 # Constructor declaration
283 redef class Nproperty_declaration_constructor
284 redef fun accept_visitor
(v
)
286 v
.declaration_type
= "constructor"
288 v
.declaration_type
= null
292 # Variable property declaration
293 redef class Nproperty_declaration_attribute
294 redef fun accept_visitor
(v
)
296 v
.declaration_type
= "variable"
298 v
.declaration_type
= null
300 v
.java_class
.attributes
[v
.variable_id
] = v
.variable_type
303 v
.variable_type
= new JavaType
307 # Static property declaration
308 redef class Nproperty_declaration_static
309 redef fun accept_visitor
(v
)
311 v
.declaration_type
= "static"
313 v
.declaration_type
= null
317 # Identifier of a variable
318 redef class Nattribute_id
319 redef fun accept_visitor
(v
)
321 v
.declaration_element
= "id"
323 v
.declaration_element
= null
327 # Identifier of the method
328 redef class Nmethod_id
329 redef fun accept_visitor
(v
)
331 v
.declaration_element
= "id"
333 v
.declaration_element
= null
338 redef fun accept_visitor
(v
)
340 if v
.declaration_type
== "variable" and v
.declaration_element
!= "id" then
341 v
.declaration_element
= "type"
344 if v
.declaration_type
== "method" and v
.declaration_element
== null then
345 # Makes sure it is not the generic return type definition
346 if not (v
.method_return_type
.identifier
.is_empty
and v
.is_generic_param
) then
347 v
.declaration_element
= "return_type"
353 if v
.declaration_element
== "variable" then
354 v
.declaration_element
= null
359 redef class Ngeneric_param
360 redef fun accept_visitor
(v
)
362 # Ignore the weird generic return type declaration
363 if v
.declaration_type
== "method" then
364 if v
.declaration_element
== null then
365 v
.is_generic_param
= true
367 v
.is_generic_param
= true
368 v
.gen_params_index
= 0
370 if v
.declaration_element
== "return_type" then
371 v
.method_return_type
.generic_params
= new Array[JavaType]
372 else if v
.declaration_element
== "parameter_list" then
373 v
.method_params
[v
.param_index
].generic_params
= new Array[JavaType]
376 else if v
.declaration_type
== "variable" then
377 if v
.declaration_element
== "type" then
378 v
.is_generic_param
= true
379 v
.gen_params_index
= 0
380 v
.variable_type
.generic_params
= new Array[JavaType]
386 v
.declaration_element
= null
387 v
.is_generic_param
= false
391 redef class Ngeneric_identifier
392 redef fun accept_visitor
(v
)
394 if v
.declaration_type
== "method" then
395 if v
.declaration_element
== null then
396 v
.is_generic_id
= true
402 v
.is_generic_id
= false
407 redef class Nparameter_list
408 redef fun accept_visitor
(v
)
410 v
.declaration_element
= "parameter_list"
413 v
.declaration_element
= null
418 redef class Nparameter
419 redef fun accept_visitor
(v
)
421 if v
.declaration_type
== "method" then
422 if v
.declaration_element
== "parameter_list" then
423 if v
.is_generic_param
then
424 v
.method_params
[v
.param_index
].generic_params
.add
new JavaType
428 v
.gen_params_index
+= 1
430 v
.method_params
.add
new JavaType
436 else if v
.declaration_element
== "return_type" and v
.is_generic_param
then
438 v
.method_return_type
.generic_params
.add
new JavaType
442 v
.gen_params_index
+= 1
444 # For generic return type definition
445 else if v
.declaration_element
== null then
448 else if v
.declaration_type
== "variable" then
449 if v
.declaration_element
== "type" and v
.is_generic_param
then
450 v
.variable_type
.generic_params
.add
new JavaType
454 v
.gen_params_index
+= 1