model_utils: extract modifier list from mclassdef
[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 end
67
68 redef class MClass
69
70 # Get the public owner of 'self'.
71 fun public_owner: MModule do
72 var public_owner = self.intro_mmodule.public_owner
73 if public_owner == null then
74 return self.intro_mmodule
75 else
76 return public_owner
77 end
78 end
79
80 # Get direct parents of 'self'.
81 fun parents: Set[MClass] do
82 var ret = new HashSet[MClass]
83 for mclassdef in mclassdefs do
84 for mclasstype in mclassdef.supertypes do
85 ret.add(mclasstype.mclass)
86 end
87 end
88 return ret
89 end
90
91 # Get all ancestors of 'self'.
92 fun ancestors: Set[MClass] do
93 var lst = new HashSet[MClass]
94 for mclassdef in self.mclassdefs do
95 for super_mclassdef in mclassdef.in_hierarchy.greaters do
96 if super_mclassdef == mclassdef then continue # skip self
97 lst.add(super_mclassdef.mclass)
98 end
99 end
100 return lst
101 end
102
103 # Get direct children of 'self'.
104 fun children: Set[MClass] do
105 var lst = new HashSet[MClass]
106 for mclassdef in self.mclassdefs do
107 for sub_mclassdef in mclassdef.in_hierarchy.direct_smallers do
108 if sub_mclassdef == mclassdef then continue # skip self
109 lst.add(sub_mclassdef.mclass)
110 end
111 end
112 return lst
113 end
114
115 # Get all children of 'self'.
116 fun descendants: Set[MClass] do
117 var lst = new HashSet[MClass]
118 for mclassdef in self.mclassdefs do
119 for sub_mclassdef in mclassdef.in_hierarchy.smallers do
120 if sub_mclassdef == mclassdef then continue # skip self
121 lst.add(sub_mclassdef.mclass)
122 end
123 end
124 return lst
125 end
126
127 # Get the list of constructors available for 'self'.
128 fun constructors: Set[MMethod] do
129 var res = new HashSet[MMethod]
130 for mclassdef in mclassdefs do
131 for mpropdef in mclassdef.mpropdefs do
132 if mpropdef isa MMethodDef then
133 if mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
134 end
135 end
136 end
137 return res
138 end
139
140 # Get the list of methods introduced in 'self'.
141 fun intro_methods: Set[MMethod] do
142 var res = new HashSet[MMethod]
143 for mclassdef in mclassdefs do
144 for mpropdef in mclassdef.mpropdefs do
145 if mpropdef isa MMethodDef then
146 if mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
147 end
148 end
149 end
150 return res
151 end
152
153 # the set of properties introduced in 'self'.
154 fun intro_mproperties(min_visibility: MVisibility): Set[MProperty] do
155 var set = new HashSet[MProperty]
156 for mclassdef in mclassdefs do
157 for mprop in mclassdef.intro_mproperties do
158 if mprop.visibility < min_visibility then continue
159 set.add(mprop)
160 end
161 end
162 return set
163 end
164
165 # the set of locally refined properties in 'self'.
166 fun redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
167 var set = new HashSet[MProperty]
168 for mclassdef in mclassdefs do
169 for mpropdef in mclassdef.mpropdefs do
170 if mpropdef.mproperty.visibility < min_visibility then continue
171 if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
172 end
173 end
174 return set
175 end
176
177 # the set of methods inherited by 'self'.
178 fun inherited_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
179 var set = new HashSet[MProperty]
180 for parent in in_hierarchy(mainmodule).direct_greaters do
181 set.add_all(parent.intro_mproperties(min_visibility))
182 set.add_all(parent.inherited_mproperties(mainmodule, min_visibility))
183 end
184 return set
185 end
186
187 # the set of introduced and redefined mproperties
188 fun local_mproperties(min_visibility: MVisibility): Set[MProperty] do
189 var set = new HashSet[MProperty]
190 set.add_all(intro_mproperties(min_visibility))
191 set.add_all(redef_mproperties(min_visibility))
192 return set
193 end
194
195 # the set of all accessible mproperties for this class
196 fun all_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
197 var set = new HashSet[MProperty]
198 set.add_all(local_mproperties(min_visibility))
199 set.add_all(inherited_mproperties(mainmodule, min_visibility))
200 return set
201 end
202
203 # the set of all accessible mattributes for this class
204 fun all_mattributes(mainmodule: MModule, min_visibility: MVisibility): Set[MAttribute] do
205 var set = new HashSet[MAttribute]
206 for mprop in all_mproperties(mainmodule, min_visibility) do
207 if mprop isa MAttribute then set.add(mprop)
208 end
209 return set
210 end
211
212 # Get the list of locally refined methods in 'self'.
213 fun redef_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 not 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 fun inherited_methods: Set[MMethod] do
226 var res = new HashSet[MMethod]
227 for s in ancestors do
228 for m in s.intro_methods do
229 if not self.intro_methods.has(m) and not self.redef_methods.has(m) then res.add(m)
230 end
231 end
232 return res
233 end
234
235 # Get the list of all virtual types available in 'self'.
236 fun virtual_types: Set[MVirtualTypeProp] do
237 var res = new HashSet[MVirtualTypeProp]
238 for mclassdef in mclassdefs do
239 for mpropdef in mclassdef.mpropdefs do
240 if mpropdef isa MVirtualTypeDef then
241 res.add(mpropdef.mproperty)
242 end
243 end
244 end
245 for ancestor in ancestors do
246 for mclassdef in ancestor.mclassdefs do
247 for mpropdef in mclassdef.mpropdefs do
248 if mpropdef isa MVirtualTypeDef then
249 res.add(mpropdef.mproperty)
250 end
251 end
252 end
253 end
254 return res
255 end
256
257 # Get the list of all parameter types in 'self'.
258 fun parameter_types: Map[String, MType] do
259 var res = new HashMap[String, MType]
260 for i in [0..intro.parameter_names.length[ do
261 res[intro.parameter_names[i]] = intro.bound_mtype.arguments[i]
262 end
263 return res
264 end
265
266 fun is_class: Bool do
267 return self.kind == concrete_kind or self.kind == abstract_kind
268 end
269
270 fun is_interface: Bool do
271 return self.kind == interface_kind
272 end
273
274 fun is_enum: Bool do
275 return self.kind == enum_kind
276 end
277
278 fun is_abstract: Bool do
279 return self.kind == abstract_kind
280 end
281 end
282
283 redef class MAttribute
284 # Is this attribute nullable for sure?
285 #
286 # This mean that its introduction is declarred with a nullable static type
287 # since attributes are invariant this will work on most cases
288 # attributes with static type anchored with a virtual type are not "nullable for-sure"
289 # because this type can be redefined in subclasses
290 fun is_nullable: Bool do return intro.static_mtype isa MNullableType
291 end
292
293 redef class MClassDef
294 # modifiers are keywords like redef, private etc.
295 fun modifiers: Array[String] do
296 var res = new Array[String]
297 if not is_intro then
298 res.add "redef"
299 else
300 res.add mclass.visibility.to_s
301 end
302 res.add mclass.kind.to_s
303 return res
304 end
305 end
306
307 # Sorters
308
309 # Sort mmodules by their name
310 class MModuleNameSorter
311 super AbstractSorter[MModule]
312 redef fun compare(a, b) do return a.name <=> b.name
313 init do end
314 end
315
316 # Sort mclasses by their name
317 class MClassNameSorter
318 super AbstractSorter[MClass]
319 redef fun compare(a, b) do return a.name <=> b.name
320 init do end
321 end
322
323 # Sort mclassdefs by their name
324 class MClassDefNameSorter
325 super AbstractSorter[MClassDef]
326 redef fun compare(a, b) do return a.mclass.name <=> b.mclass.name
327 init do end
328 end
329
330 # Sort mproperties by their name
331 class MPropertyNameSorter
332 super AbstractSorter[MProperty]
333 redef fun compare(a, b) do return a.name <=> b.name
334 init do end
335 end
336
337 # Sort mpropdefs by their name
338 class MPropDefNameSorter
339 super AbstractSorter[MPropDef]
340 redef fun compare(a, b) do return a.mproperty.name <=> b.mproperty.name
341 init do end
342 end