model_utils: add MAttribute::is_nullable
[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 # Get the list of mclasses refined in 'self'.
24 fun redef_mclasses: Set[MClass] do
25 var mclasses = new HashSet[MClass]
26 for c in mclassdefs do
27 if not c.is_intro then mclasses.add(c.mclass)
28 end
29 return mclasses
30 end
31
32 # Get the list of all mclasses imported by 'self'.
33 fun imported_mclasses: Set[MClass] do
34 var mclasses = new HashSet[MClass]
35 for m in in_importation.greaters do
36 if m == self then continue
37 for c in m.mclassdefs do mclasses.add(c.mclass)
38 end
39 return mclasses
40 end
41 end
42
43 redef class MClass
44
45 # Get the public owner of 'self'.
46 fun public_owner: MModule do
47 var public_owner = self.intro_mmodule.public_owner
48 if public_owner == null then
49 return self.intro_mmodule
50 else
51 return public_owner
52 end
53 end
54
55 # Get direct parents of 'self'.
56 fun parents: Set[MClass] do
57 var ret = new HashSet[MClass]
58 for mclassdef in mclassdefs do
59 for mclasstype in mclassdef.supertypes do
60 ret.add(mclasstype.mclass)
61 end
62 end
63 return ret
64 end
65
66 # Get all ancestors of 'self'.
67 fun ancestors: Set[MClass] do
68 var lst = new HashSet[MClass]
69 for mclassdef in self.mclassdefs do
70 for super_mclassdef in mclassdef.in_hierarchy.greaters do
71 if super_mclassdef == mclassdef then continue # skip self
72 lst.add(super_mclassdef.mclass)
73 end
74 end
75 return lst
76 end
77
78 # Get direct children of 'self'.
79 fun children: Set[MClass] do
80 var lst = new HashSet[MClass]
81 for mclassdef in self.mclassdefs do
82 for sub_mclassdef in mclassdef.in_hierarchy.direct_smallers do
83 if sub_mclassdef == mclassdef then continue # skip self
84 lst.add(sub_mclassdef.mclass)
85 end
86 end
87 return lst
88 end
89
90 # Get all children of 'self'.
91 fun descendants: Set[MClass] do
92 var lst = new HashSet[MClass]
93 for mclassdef in self.mclassdefs do
94 for sub_mclassdef in mclassdef.in_hierarchy.smallers do
95 if sub_mclassdef == mclassdef then continue # skip self
96 lst.add(sub_mclassdef.mclass)
97 end
98 end
99 return lst
100 end
101
102 # Get the list of constructors available for 'self'.
103 fun constructors: Set[MMethod] do
104 var res = new HashSet[MMethod]
105 for mclassdef in mclassdefs do
106 for mpropdef in mclassdef.mpropdefs do
107 if mpropdef isa MMethodDef then
108 if mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
109 end
110 end
111 end
112 return res
113 end
114
115 # Get the list of methods introduced in 'self'.
116 fun intro_methods: Set[MMethod] do
117 var res = new HashSet[MMethod]
118 for mclassdef in mclassdefs do
119 for mpropdef in mclassdef.mpropdefs do
120 if mpropdef isa MMethodDef then
121 if mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
122 end
123 end
124 end
125 return res
126 end
127
128 # the set of properties introduced in 'self'.
129 fun intro_mproperties(min_visibility: MVisibility): Set[MProperty] do
130 var set = new HashSet[MProperty]
131 for mclassdef in mclassdefs do
132 for mprop in mclassdef.intro_mproperties do
133 if mprop.visibility < min_visibility then continue
134 set.add(mprop)
135 end
136 end
137 return set
138 end
139
140 # the set of locally refined properties in 'self'.
141 fun redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
142 var set = new HashSet[MProperty]
143 for mclassdef in mclassdefs do
144 for mpropdef in mclassdef.mpropdefs do
145 if mpropdef.mproperty.visibility < min_visibility then continue
146 if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
147 end
148 end
149 return set
150 end
151
152 # the set of methods inherited by 'self'.
153 fun inherited_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
154 var set = new HashSet[MProperty]
155 for parent in in_hierarchy(mainmodule).direct_greaters do
156 set.add_all(parent.intro_mproperties(min_visibility))
157 set.add_all(parent.inherited_mproperties(mainmodule, min_visibility))
158 end
159 return set
160 end
161
162 # the set of introduced and redefined mproperties
163 fun local_mproperties(min_visibility: MVisibility): Set[MProperty] do
164 var set = new HashSet[MProperty]
165 set.add_all(intro_mproperties(min_visibility))
166 set.add_all(redef_mproperties(min_visibility))
167 return set
168 end
169
170 # the set of all accessible mproperties for this class
171 fun all_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do
172 var set = new HashSet[MProperty]
173 set.add_all(local_mproperties(min_visibility))
174 set.add_all(inherited_mproperties(mainmodule, min_visibility))
175 return set
176 end
177
178 # the set of all accessible mattributes for this class
179 fun all_mattributes(mainmodule: MModule, min_visibility: MVisibility): Set[MAttribute] do
180 var set = new HashSet[MAttribute]
181 for mprop in all_mproperties(mainmodule, min_visibility) do
182 if mprop isa MAttribute then set.add(mprop)
183 end
184 return set
185 end
186
187 # Get the list of locally refined methods in 'self'.
188 fun redef_methods: Set[MMethod] do
189 var res = new HashSet[MMethod]
190 for mclassdef in mclassdefs do
191 for mpropdef in mclassdef.mpropdefs do
192 if mpropdef isa MMethodDef then
193 if not mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty)
194 end
195 end
196 end
197 return res
198 end
199
200 fun inherited_methods: Set[MMethod] do
201 var res = new HashSet[MMethod]
202 for s in ancestors do
203 for m in s.intro_methods do
204 if not self.intro_methods.has(m) and not self.redef_methods.has(m) then res.add(m)
205 end
206 end
207 return res
208 end
209
210 # Get the list of all virtual types available in 'self'.
211 fun virtual_types: Set[MVirtualTypeProp] do
212 var res = new HashSet[MVirtualTypeProp]
213 for mclassdef in mclassdefs do
214 for mpropdef in mclassdef.mpropdefs do
215 if mpropdef isa MVirtualTypeDef then
216 res.add(mpropdef.mproperty)
217 end
218 end
219 end
220 for ancestor in ancestors do
221 for mclassdef in ancestor.mclassdefs do
222 for mpropdef in mclassdef.mpropdefs do
223 if mpropdef isa MVirtualTypeDef then
224 res.add(mpropdef.mproperty)
225 end
226 end
227 end
228 end
229 return res
230 end
231
232 # Get the list of all parameter types in 'self'.
233 fun parameter_types: Map[String, MType] do
234 var res = new HashMap[String, MType]
235 for i in [0..intro.parameter_names.length[ do
236 res[intro.parameter_names[i]] = intro.bound_mtype.arguments[i]
237 end
238 return res
239 end
240
241 fun is_class: Bool do
242 return self.kind == concrete_kind or self.kind == abstract_kind
243 end
244
245 fun is_interface: Bool do
246 return self.kind == interface_kind
247 end
248
249 fun is_enum: Bool do
250 return self.kind == enum_kind
251 end
252
253 fun is_abstract: Bool do
254 return self.kind == abstract_kind
255 end
256 end
257
258 redef class MAttribute
259 # Is this attribute nullable for sure?
260 #
261 # This mean that its introduction is declarred with a nullable static type
262 # since attributes are invariant this will work on most cases
263 # attributes with static type anchored with a virtual type are not "nullable for-sure"
264 # because this type can be redefined in subclasses
265 fun is_nullable: Bool do return intro.static_mtype isa MNullableType
266 end
267
268 # Sorters
269
270 # Sort mmodules by their name
271 class MModuleNameSorter
272 super AbstractSorter[MModule]
273 redef fun compare(a, b) do return a.name <=> b.name
274 init do end
275 end
276
277 # Sort mclasses by their name
278 class MClassNameSorter
279 super AbstractSorter[MClass]
280 redef fun compare(a, b) do return a.name <=> b.name
281 init do end
282 end
283
284 # Sort mclassdefs by their name
285 class MClassDefNameSorter
286 super AbstractSorter[MClassDef]
287 redef fun compare(a, b) do return a.mclass.name <=> b.mclass.name
288 init do end
289 end
290
291 # Sort mproperties by their name
292 class MPropertyNameSorter
293 super AbstractSorter[MProperty]
294 redef fun compare(a, b) do return a.name <=> b.name
295 init do end
296 end
297
298 # Sort mpropdefs by their name
299 class MPropDefNameSorter
300 super AbstractSorter[MPropDef]
301 redef fun compare(a, b) do return a.mproperty.name <=> b.mproperty.name
302 init do end
303 end