model_utils: extract classes in mmodule nesting
[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 # the set of locally refined properties in 'self'.
204 fun redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
205 var set = new HashSet[MProperty]
206 for mclassdef in mclassdefs do
207 for mpropdef in mclassdef.mpropdefs do
208 if mpropdef.mproperty.visibility < min_visibility then continue
209 if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
210 end
211 end
212 return set
213 end
214
215 # the set of methods inherited by 'self'.
216 fun inherited_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
217 var set = new HashSet[MProperty]
218 for parent in in_hierarchy(mainmodule).direct_greaters do
219 set.add_all(parent.intro_mproperties(min_visibility))
220 set.add_all(parent.inherited_mproperties(mainmodule, min_visibility))
221 end
222 return set
223 end
224
225 # the set of introduced and redefined mproperties
226 fun local_mproperties(min_visibility: MVisibility): Set[MProperty] do
227 var set = new HashSet[MProperty]
228 set.add_all(intro_mproperties(min_visibility))
229 set.add_all(redef_mproperties(min_visibility))
230 return set
231 end
232
233 # the set of all accessible mproperties for this class
234 fun all_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
235 var set = new HashSet[MProperty]
236 set.add_all(local_mproperties(min_visibility))
237 set.add_all(inherited_mproperties(mainmodule, min_visibility))
238 return set
239 end
240
241 # the set of all accessible mattributes for this class
242 fun all_mattributes(mainmodule: MModule, min_visibility: MVisibility): Set[MAttribute] do
243 var set = new HashSet[MAttribute]
244 for mprop in all_mproperties(mainmodule, min_visibility) do
245 if mprop isa MAttribute then set.add(mprop)
246 end
247 return set
248 end
249
250 # Get the list of locally refined methods in 'self'.
251 fun redef_methods: Set[MMethod] do
252 var res = new HashSet[MMethod]
253 for mclassdef in mclassdefs do
254 for mpropdef in mclassdef.mpropdefs do
255 if mpropdef isa MMethodDef then
256 if not mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
257 end
258 end
259 end
260 return res
261 end
262
263 fun inherited_methods: Set[MMethod] do
264 var res = new HashSet[MMethod]
265 for s in ancestors do
266 for m in s.intro_methods do
267 if not self.intro_methods.has(m) and not self.redef_methods.has(m) then res.add(m)
268 end
269 end
270 return res
271 end
272
273 # Get the list of all virtual types available in 'self'.
274 fun virtual_types: Set[MVirtualTypeProp] do
275 var res = new HashSet[MVirtualTypeProp]
276 for mclassdef in mclassdefs do
277 for mpropdef in mclassdef.mpropdefs do
278 if mpropdef isa MVirtualTypeDef then
279 res.add(mpropdef.mproperty)
280 end
281 end
282 end
283 for ancestor in ancestors do
284 for mclassdef in ancestor.mclassdefs do
285 for mpropdef in mclassdef.mpropdefs do
286 if mpropdef isa MVirtualTypeDef then
287 res.add(mpropdef.mproperty)
288 end
289 end
290 end
291 end
292 return res
293 end
294
295 # Get the list of all parameter types in 'self'.
296 fun parameter_types: Map[String, MType] do
297 var res = new HashMap[String, MType]
298 for i in [0..intro.parameter_names.length[ do
299 res[intro.parameter_names[i]] = intro.bound_mtype.arguments[i]
300 end
301 return res
302 end
303
304 fun is_class: Bool do
305 return self.kind == concrete_kind or self.kind == abstract_kind
306 end
307
308 fun is_interface: Bool do
309 return self.kind == interface_kind
310 end
311
312 fun is_enum: Bool do
313 return self.kind == enum_kind
314 end
315
316 fun is_abstract: Bool do
317 return self.kind == abstract_kind
318 end
319 end
320
321 redef class MAttribute
322 # Is this attribute nullable for sure?
323 #
324 # This mean that its introduction is declarred with a nullable static type
325 # since attributes are invariant this will work on most cases
326 # attributes with static type anchored with a virtual type are not "nullable for-sure"
327 # because this type can be redefined in subclasses
328 fun is_nullable: Bool do return intro.static_mtype isa MNullableType
329 end
330
331 redef class MClassDef
332 # modifiers are keywords like redef, private etc.
333 fun modifiers: Array[String] do
334 var res = new Array[String]
335 if not is_intro then
336 res.add "redef"
337 else
338 res.add mclass.visibility.to_s
339 end
340 res.add mclass.kind.to_s
341 return res
342 end
343 end
344
345 redef class MPropDef
346 # modifiers are keywords like redef, private etc.
347 fun modifiers: Array[String] do
348 var res = new Array[String]
349 if not is_intro then
350 res.add "redef"
351 else
352 res.add mproperty.visibility.to_s
353 end
354 var mprop = self
355 if mprop isa MVirtualTypeDef then
356 res.add "type"
357 else if mprop isa MMethodDef then
358 if mprop.is_abstract then
359 res.add "abstract"
360 else if mprop.is_intern then
361 res.add "intern"
362 end
363 if mprop.mproperty.is_init then
364 res.add "init"
365 else
366 res.add "fun"
367 end
368 end
369 return res
370 end
371 end
372
373
374 # Sorters
375
376 # Sort mmodules by their name
377 class MModuleNameSorter
378 super AbstractSorter[MModule]
379 redef fun compare(a, b) do return a.name <=> b.name
380 init do end
381 end
382
383 # Sort mclasses by their name
384 class MClassNameSorter
385 super AbstractSorter[MClass]
386 redef fun compare(a, b) do return a.name <=> b.name
387 init do end
388 end
389
390 # Sort mclassdefs by their name
391 class MClassDefNameSorter
392 super AbstractSorter[MClassDef]
393 redef fun compare(a, b) do return a.mclass.name <=> b.mclass.name
394 init do end
395 end
396
397 # Sort mproperties by their name
398 class MPropertyNameSorter
399 super AbstractSorter[MProperty]
400 redef fun compare(a, b) do return a.name <=> b.name
401 init do end
402 end
403
404 # Sort mpropdefs by their name
405 class MPropDefNameSorter
406 super AbstractSorter[MPropDef]
407 redef fun compare(a, b) do return a.mproperty.name <=> b.mproperty.name
408 init do end
409 end