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