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