1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Uses a visitor to extract data from the javap output AST
18 # It sends the data to `code_generator` module
21 import javap_test_parser
23 import jtype_converter
29 var converter
: JavaTypeConverter
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
37 var variable_type
: JavaType
39 var is_generic_param
= false
40 var is_generic_id
= false
42 var gen_params_index
= 0
44 # Used to resolve generic return types (T -> foo.faz.Bar)
45 var generic_map
= new HashMap[String, Array[String]]
47 var is_primitive_array
= false
50 var method_return_type
: JavaType
51 var method_params
= new Array[JavaType]
54 redef fun visit
(n
) do n
.accept_visitor
(self)
56 init(converter
: JavaTypeConverter)
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
)
65 # Add the identifier from `token` to the current context
66 fun add_identifier
(token
: NToken)
68 if declaration_type
== "variable" then
69 if declaration_element
== "type" then
70 variable_type
.identifier
.add
(token
.text
)
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
)
83 fun accept_visitor
(v
: JavaVisitor) do visit_children
(v
)
86 redef class Nidentifier
87 redef fun accept_visitor
(v
)
89 if v
.declaration_type
== "class_header" then
91 if v
.declaration_element
== "id" then
92 v
.class_type
.identifier
.add
(self.text
)
95 else if v
.declaration_type
== "variable" then
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
)
103 v
.variable_type
.identifier
.add
(self.text
)
107 else if v
.declaration_type
== "method" then
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
)
117 v
.method_return_type
.identifier
.add
(self.text
)
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
)
123 v
.method_params
[v
.param_index
].identifier
.add
(self.text
)
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]
133 if not v
.method_return_type
.has_unresolved_types
then v
.method_return_type
.has_unresolved_types
= true
135 v
.generic_map
[v
.generic_id
].add
(self.text
)
145 # Primitive array node
146 redef class Nbrackets
147 redef fun accept_visitor
(v
)
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
154 v
.variable_type
.array_dimension
+= 1
158 else if v
.declaration_type
== "method" then
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
164 v
.method_return_type
.array_dimension
+= 1
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
170 v
.method_params
[v
.param_index
].array_dimension
+= 1
180 redef class N_39dchar_39d
181 redef fun accept_visitor
(v
) do v
.add_identifier
self
184 redef class N_39dboolean_39d
185 redef fun accept_visitor
(v
) do v
.add_identifier
self
188 redef class N_39dfloat_39d
189 redef fun accept_visitor
(v
) do v
.add_identifier
self
192 redef class N_39ddouble_39d
193 redef fun accept_visitor
(v
) do v
.add_identifier
self
196 redef class N_39dbyte_39d
197 redef fun accept_visitor
(v
) do v
.add_identifier
self
200 redef class N_39dshort_39d
201 redef fun accept_visitor
(v
) do v
.add_identifier
self
204 redef class N_39dint_39d
205 redef fun accept_visitor
(v
) do v
.add_identifier
self
208 redef class N_39dlong_39d
209 redef fun accept_visitor
(v
) do v
.add_identifier
self
213 # C L A S S H E A D E R #
216 redef class Nclass_declaration
217 redef fun accept_visitor
(v
)
219 v
.declaration_type
= "class_header"
220 v
.declaration_element
= "id"
223 # Exit class declaration
224 v
.declaration_type
= null
225 v
.declaration_element
= null
227 v
.java_class
.class_type
= v
.class_type
231 # Extends declaration in the class header
232 redef class Nextends_declaration
233 redef fun accept_visitor
(v
)
235 v
.declaration_element
= "extends"
237 v
.declaration_element
= null
241 # Implements declaration in the class header
242 redef class Nimplements_declaration
243 redef fun accept_visitor
(v
)
245 v
.declaration_element
= "implements"
247 v
.declaration_element
= null
252 # P R O P E R T Y D E C L A R A T I O N S #
256 redef class Nproperty_declaration_method
257 redef fun accept_visitor
(v
)
259 v
.declaration_type
= "method"
260 v
.declaration_element
= null
262 v
.declaration_type
= null
264 if v
.method_return_type
.has_unresolved_types
then v
.method_return_type
.resolve_types
(v
.generic_map
)
265 v
.java_class
.add_method
(v
.method_id
, v
.method_return_type
, v
.method_params
)
267 v
.method_params
.clear
269 v
.method_return_type
= new JavaType(v
.converter
)
273 # Constructor declaration
274 redef class Nproperty_declaration_constructor
275 redef fun accept_visitor
(v
)
277 v
.declaration_type
= "constructor"
279 v
.declaration_type
= null
283 # Variable property declaration
284 redef class Nproperty_declaration_attribute
285 redef fun accept_visitor
(v
)
287 v
.declaration_type
= "variable"
289 v
.declaration_type
= null
291 v
.java_class
.attributes
[v
.variable_id
] = v
.variable_type
294 v
.variable_type
= new JavaType(v
.converter
)
298 # Static property declaration
299 redef class Nproperty_declaration_static
300 redef fun accept_visitor
(v
)
302 v
.declaration_type
= "static"
304 v
.declaration_type
= null
308 # Identifier of a variable
309 redef class Nattribute_id
310 redef fun accept_visitor
(v
)
312 v
.declaration_element
= "id"
314 v
.declaration_element
= null
318 # Identifier of the method
319 redef class Nmethod_id
320 redef fun accept_visitor
(v
)
322 v
.declaration_element
= "id"
324 v
.declaration_element
= null
329 redef fun accept_visitor
(v
)
331 if v
.declaration_type
== "variable" and v
.declaration_element
!= "id" then
332 v
.declaration_element
= "type"
335 if v
.declaration_type
== "method" and v
.declaration_element
== null then
336 # Makes sure it is not the generic return type definition
337 if not (v
.method_return_type
.identifier
.is_empty
and v
.is_generic_param
) then
338 v
.declaration_element
= "return_type"
344 if v
.declaration_element
== "variable" then
345 v
.declaration_element
= null
350 redef class Ngeneric_param
351 redef fun accept_visitor
(v
)
353 # Ignore the weird generic return type declaration
354 if v
.declaration_type
== "method" then
355 if v
.declaration_element
== null then
356 v
.is_generic_param
= true
358 v
.is_generic_param
= true
359 v
.gen_params_index
= 0
361 if v
.declaration_element
== "return_type" then
362 v
.method_return_type
.generic_params
= new Array[JavaType]
363 else if v
.declaration_element
== "parameter_list" then
364 v
.method_params
[v
.param_index
].generic_params
= new Array[JavaType]
367 else if v
.declaration_type
== "variable" then
368 if v
.declaration_element
== "type" then
369 v
.is_generic_param
= true
370 v
.gen_params_index
= 0
371 v
.variable_type
.generic_params
= new Array[JavaType]
377 v
.declaration_element
= null
378 v
.is_generic_param
= false
382 redef class Ngeneric_identifier
383 redef fun accept_visitor
(v
)
385 if v
.declaration_type
== "method" then
386 if v
.declaration_element
== null then
387 v
.is_generic_id
= true
393 v
.is_generic_id
= false
398 redef class Nparameter_list
399 redef fun accept_visitor
(v
)
401 v
.declaration_element
= "parameter_list"
404 v
.declaration_element
= null
409 redef class Nparameter
410 redef fun accept_visitor
(v
)
412 if v
.declaration_type
== "method" then
413 if v
.declaration_element
== "parameter_list" then
414 if v
.is_generic_param
then
415 v
.method_params
[v
.param_index
].generic_params
.add
(new JavaType(v
.converter
))
419 v
.gen_params_index
+= 1
421 v
.method_params
.add
(new JavaType(v
.converter
))
427 else if v
.declaration_element
== "return_type" and v
.is_generic_param
then
429 v
.method_return_type
.generic_params
.add
(new JavaType(v
.converter
))
433 v
.gen_params_index
+= 1
435 # For generic return type definition
436 else if v
.declaration_element
== null then
439 else if v
.declaration_type
== "variable" then
440 if v
.declaration_element
== "type" and v
.is_generic_param
then
441 v
.variable_type
.generic_params
.add
(new JavaType(v
.converter
))
445 v
.gen_params_index
+= 1