model_utils: collect mmodules in mproject and mgroups
[nit.git] / src / model_utils.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
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 # Model exploration and traversing facilities
18 module model_utils
19
20 import modelbuilder
21
22 redef class MGroup
23 fun in_nesting_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
24 var res = new HashSet[MClass]
25 var lst = in_nesting.direct_smallers
26 for mmodule in mmodules do res.add_all mmodule.intro_mclasses
27 for mgrp in lst do res.add_all mgrp.in_nesting_intro_mclasses(min_visibility)
28 return res
29 end
30
31 fun in_nesting_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
32 var res = new HashSet[MClass]
33 var lst = in_nesting.direct_smallers
34 for mmodule in mmodules do res.add_all mmodule.redef_mclasses
35 for mgrp in lst do res.add_all mgrp.in_nesting_redef_mclasses(min_visibility)
36 return res
37 end
38
39 fun in_nesting_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
40 var res = new HashSet[MClassDef]
41 var lst = in_nesting.direct_smallers
42 for mmodule in mmodules do res.add_all mmodule.intro_mclassdefs(min_visibility)
43 for mgrp in lst do res.add_all mgrp.in_nesting_intro_mclassdefs(min_visibility)
44 return res
45 end
46
47 fun in_nesting_redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
48 var res = new HashSet[MClassDef]
49 var lst = in_nesting.direct_smallers
50 for mmodule in mmodules do res.add_all mmodule.redef_mclassdefs(min_visibility)
51 for mgrp in lst do res.add_all mgrp.in_nesting_redef_mclassdefs(min_visibility)
52 return res
53 end
54
55 # Collect nested modules
56 fun collect_mmodules: Set[MModule] do
57 var res = new HashSet[MModule]
58 res.add_all mmodules
59 for mgroup in in_nesting.direct_smallers do
60 res.add_all mgroup.collect_mmodules
61 end
62 return res
63 end
64 end
65
66 redef class MModule
67
68 # The list of intro mclassdef in the module.
69 # with visibility >= to min_visibility
70 fun intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
71 var res = new HashSet[MClassDef]
72 for mclassdef in mclassdefs do
73 if not mclassdef.is_intro then continue
74 if mclassdef.mclass.visibility < min_visibility then continue
75 res.add mclassdef
76 end
77 return res
78 end
79
80 # The list of redef mclassdef in the module.
81 # with visibility >= to min_visibility
82 fun redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
83 var res = new HashSet[MClassDef]
84 for mclassdef in mclassdefs do
85 if mclassdef.is_intro then continue
86 if mclassdef.mclass.visibility < min_visibility then continue
87 res.add mclassdef
88 end
89 return res
90 end
91
92 # Get the list of mclasses refined in 'self'.
93 fun redef_mclasses: Set[MClass] do
94 var mclasses = new HashSet[MClass]
95 for c in mclassdefs do
96 if not c.is_intro then mclasses.add(c.mclass)
97 end
98 return mclasses
99 end
100
101 # Get the list of all mclasses imported by 'self'.
102 fun imported_mclasses: Set[MClass] do
103 var mclasses = new HashSet[MClass]
104 for m in in_importation.greaters do
105 if m == self then continue
106 for c in m.mclassdefs do mclasses.add(c.mclass)
107 end
108 return mclasses
109 end
110
111 fun in_nesting_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
112 var res = new HashSet[MClass]
113 for mmodule in in_nesting.greaters do
114 for mclass in mmodule.intro_mclasses do
115 if mclass.visibility < min_visibility then continue
116 res.add mclass
117 end
118 end
119 return res
120 end
121
122 fun in_nesting_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
123 var res = new HashSet[MClass]
124 for mmodule in self.in_nesting.greaters do
125 for mclass in mmodule.redef_mclasses do
126 if mclass.visibility < min_visibility then continue
127 res.add mclass
128 end
129 end
130 return res
131 end
132
133 fun in_nesting_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
134 var res = new HashSet[MClassDef]
135 for mmodule in in_nesting.greaters do
136 res.add_all mmodule.intro_mclassdefs(min_visibility)
137 end
138 return res
139 end
140
141 fun in_nesting_redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
142 var res = new HashSet[MClassDef]
143 for mmodule in self.in_nesting.greaters do
144 res.add_all mmodule.redef_mclassdefs(min_visibility)
145 end
146 return res
147 end
148 end
149
150 redef class MClass
151
152 # Get the public owner of 'self'.
153 fun public_owner: MModule do
154 var public_owner = self.intro_mmodule.public_owner
155 if public_owner == null then
156 return self.intro_mmodule
157 else
158 return public_owner
159 end
160 end
161
162 # Get direct parents of 'self'.
163 fun parents: Set[MClass] do
164 var ret = new HashSet[MClass]
165 for mclassdef in mclassdefs do
166 for mclasstype in mclassdef.supertypes do
167 ret.add(mclasstype.mclass)
168 end
169 end
170 return ret
171 end
172
173 # Get all ancestors of 'self'.
174 fun ancestors: Set[MClass] do
175 var lst = new HashSet[MClass]
176 for mclassdef in self.mclassdefs do
177 for super_mclassdef in mclassdef.in_hierarchy.greaters do
178 if super_mclassdef == mclassdef then continue # skip self
179 lst.add(super_mclassdef.mclass)
180 end
181 end
182 return lst
183 end
184
185 # Get direct children of 'self'.
186 fun children: Set[MClass] do
187 var lst = new HashSet[MClass]
188 for mclassdef in self.mclassdefs do
189 for sub_mclassdef in mclassdef.in_hierarchy.direct_smallers do
190 if sub_mclassdef == mclassdef then continue # skip self
191 lst.add(sub_mclassdef.mclass)
192 end
193 end
194 return lst
195 end
196
197 # Get all children of 'self'.
198 fun descendants: Set[MClass] do
199 var lst = new HashSet[MClass]
200 for mclassdef in self.mclassdefs do
201 for sub_mclassdef in mclassdef.in_hierarchy.smallers do
202 if sub_mclassdef == mclassdef then continue # skip self
203 lst.add(sub_mclassdef.mclass)
204 end
205 end
206 return lst
207 end
208
209 # Get the list of constructors available for 'self'.
210 fun constructors: Set[MMethod] do
211 var res = new HashSet[MMethod]
212 for mclassdef in mclassdefs do
213 for mpropdef in mclassdef.mpropdefs do
214 if mpropdef isa MMethodDef then
215 if mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
216 end
217 end
218 end
219 return res
220 end
221
222 # Get the list of methods introduced in 'self'.
223 fun intro_methods: Set[MMethod] do
224 var res = new HashSet[MMethod]
225 for mclassdef in mclassdefs do
226 for mpropdef in mclassdef.mpropdefs do
227 if mpropdef isa MMethodDef then
228 if mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
229 end
230 end
231 end
232 return res
233 end
234
235 # the set of properties introduced in 'self'.
236 fun intro_mproperties(min_visibility: MVisibility): Set[MProperty] do
237 var set = new HashSet[MProperty]
238 for mclassdef in mclassdefs do
239 for mprop in mclassdef.intro_mproperties do
240 if mprop.visibility < min_visibility then continue
241 set.add(mprop)
242 end
243 end
244 return set
245 end
246
247 fun intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
248 var set = new HashSet[MPropDef]
249 for mclassdef in mclassdefs do
250 for mpropdef in mclassdef.mpropdefs do
251 if not mpropdef.is_intro then continue
252 if mpropdef.mproperty.visibility < min_visibility then continue
253 set.add(mpropdef)
254 end
255 end
256 return set
257 end
258
259 # the set of locally refined properties in 'self'.
260 fun redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
261 var set = new HashSet[MProperty]
262 for mclassdef in mclassdefs do
263 for mpropdef in mclassdef.mpropdefs do
264 if mpropdef.mproperty.visibility < min_visibility then continue
265 if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
266 end
267 end
268 return set
269 end
270
271 fun redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
272 var set = new HashSet[MPropDef]
273 for mclassdef in mclassdefs do
274 for mpropdef in mclassdef.mpropdefs do
275 if mpropdef.is_intro then continue
276 if mpropdef.mproperty.visibility < min_visibility then continue
277 set.add(mpropdef)
278 end
279 end
280 return set
281 end
282
283 # the set of methods inherited by 'self'.
284 fun inherited_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
285 var set = new HashSet[MProperty]
286 for parent in in_hierarchy(mainmodule).direct_greaters do
287 set.add_all(parent.intro_mproperties(min_visibility))
288 set.add_all(parent.inherited_mproperties(mainmodule, min_visibility))
289 end
290 return set
291 end
292
293 # the set of introduced and redefined mproperties
294 fun local_mproperties(min_visibility: MVisibility): Set[MProperty] do
295 var set = new HashSet[MProperty]
296 set.add_all(intro_mproperties(min_visibility))
297 set.add_all(redef_mproperties(min_visibility))
298 return set
299 end
300
301 # the set of all accessible mproperties for this class
302 fun all_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
303 var set = new HashSet[MProperty]
304 set.add_all(local_mproperties(min_visibility))
305 set.add_all(inherited_mproperties(mainmodule, min_visibility))
306 return set
307 end
308
309 # the set of all accessible mattributes for this class
310 fun all_mattributes(mainmodule: MModule, min_visibility: MVisibility): Set[MAttribute] do
311 var set = new HashSet[MAttribute]
312 for mprop in all_mproperties(mainmodule, min_visibility) do
313 if mprop isa MAttribute then set.add(mprop)
314 end
315 return set
316 end
317
318 # Get the list of locally refined methods in 'self'.
319 fun redef_methods: Set[MMethod] do
320 var res = new HashSet[MMethod]
321 for mclassdef in mclassdefs do
322 for mpropdef in mclassdef.mpropdefs do
323 if mpropdef isa MMethodDef then
324 if not mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
325 end
326 end
327 end
328 return res
329 end
330
331 fun inherited_methods: Set[MMethod] do
332 var res = new HashSet[MMethod]
333 for s in ancestors do
334 for m in s.intro_methods do
335 if not self.intro_methods.has(m) and not self.redef_methods.has(m) then res.add(m)
336 end
337 end
338 return res
339 end
340
341 # Get the list of all virtual types available in 'self'.
342 fun virtual_types: Set[MVirtualTypeProp] do
343 var res = new HashSet[MVirtualTypeProp]
344 for mclassdef in mclassdefs do
345 for mpropdef in mclassdef.mpropdefs do
346 if mpropdef isa MVirtualTypeDef then
347 res.add(mpropdef.mproperty)
348 end
349 end
350 end
351 for ancestor in ancestors do
352 for mclassdef in ancestor.mclassdefs do
353 for mpropdef in mclassdef.mpropdefs do
354 if mpropdef isa MVirtualTypeDef then
355 res.add(mpropdef.mproperty)
356 end
357 end
358 end
359 end
360 return res
361 end
362
363 # Get the list of all parameter types in 'self'.
364 fun parameter_types: Map[String, MType] do
365 var res = new HashMap[String, MType]
366 for i in [0..intro.parameter_names.length[ do
367 res[intro.parameter_names[i]] = intro.bound_mtype.arguments[i]
368 end
369 return res
370 end
371
372 fun is_class: Bool do
373 return self.kind == concrete_kind or self.kind == abstract_kind
374 end
375
376 fun is_interface: Bool do
377 return self.kind == interface_kind
378 end
379
380 fun is_enum: Bool do
381 return self.kind == enum_kind
382 end
383
384 fun is_abstract: Bool do
385 return self.kind == abstract_kind
386 end
387 end
388
389 redef class MAttribute
390 # Is this attribute nullable for sure?
391 #
392 # This mean that its introduction is declarred with a nullable static type
393 # since attributes are invariant this will work on most cases
394 # attributes with static type anchored with a virtual type are not "nullable for-sure"
395 # because this type can be redefined in subclasses
396 fun is_nullable: Bool do return intro.static_mtype isa MNullableType
397 end
398
399 redef class MClassDef
400 # modifiers are keywords like redef, private etc.
401 fun modifiers: Array[String] do
402 var res = new Array[String]
403 if not is_intro then
404 res.add "redef"
405 else
406 res.add mclass.visibility.to_s
407 end
408 res.add mclass.kind.to_s
409 return res
410 end
411 end
412
413 redef class MPropDef
414 # modifiers are keywords like redef, private etc.
415 fun modifiers: Array[String] do
416 var res = new Array[String]
417 if not is_intro then
418 res.add "redef"
419 else
420 res.add mproperty.visibility.to_s
421 end
422 var mprop = self
423 if mprop isa MVirtualTypeDef then
424 res.add "type"
425 else if mprop isa MMethodDef then
426 if mprop.is_abstract then
427 res.add "abstract"
428 else if mprop.is_intern then
429 res.add "intern"
430 end
431 if mprop.mproperty.is_init then
432 res.add "init"
433 else
434 res.add "fun"
435 end
436 end
437 return res
438 end
439 end
440
441
442 # Sorters
443
444 # Sort mmodules by their name
445 class MModuleNameSorter
446 super AbstractSorter[MModule]
447 redef fun compare(a, b) do return a.name <=> b.name
448 init do end
449 end
450
451 # Sort mclasses by their name
452 class MClassNameSorter
453 super AbstractSorter[MClass]
454 redef fun compare(a, b) do return a.name <=> b.name
455 init do end
456 end
457
458 # Sort mclassdefs by their name
459 class MClassDefNameSorter
460 super AbstractSorter[MClassDef]
461 redef fun compare(a, b) do return a.mclass.name <=> b.mclass.name
462 init do end
463 end
464
465 # Sort mproperties by their name
466 class MPropertyNameSorter
467 super AbstractSorter[MProperty]
468 redef fun compare(a, b) do return a.name <=> b.name
469 init do end
470 end
471
472 # Sort mpropdefs by their name
473 class MPropDefNameSorter
474 super AbstractSorter[MPropDef]
475 redef fun compare(a, b) do return a.mproperty.name <=> b.mproperty.name
476 init do end
477 end