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