model_collect: allow collect by full namespace
[nit.git] / src / model / model_collect.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 # Collect things from a `Model`.
18 #
19 # **Warning**
20 #
21 # `model_collect` offers a flattened view of the model without considering any
22 # main module.
23 # For this reason, `model_collect` lists all the definitions reachable from all
24 # modules
25 #
26 # This is usefull for tools that need a global view of a model like `nitdoc`,
27 # `nitx` or `nituml`.
28 # It shoul not be used for compiling stuffs like computing VFT, where the listed
29 # entities could not be reachable depending on the modules really imported.
30 module model_collect
31
32 import model
33
34 redef class MEntity
35
36 # Collect mentities with a fully qualified `namespace`.
37 fun collect_by_namespace(namespace: String): Array[MEntity] is abstract
38
39 private fun lookup_in(mentities: Collection[MEntity], namespace: String, res: Array[MEntity]) do
40 var parts = namespace.split_once_on("::")
41 var name = parts.shift
42 for mentity in mentities do
43 if mentity.name != name then continue
44 if parts.is_empty then
45 res.add mentity
46 else
47 res.add_all mentity.collect_by_namespace(parts.first)
48 end
49 end
50 end
51 end
52
53 redef class Model
54 redef fun collect_by_namespace(namespace) do
55 var res = new Array[MEntity]
56 var parts = namespace.split_once_on("::")
57 var name = parts.shift
58 for mentity in mpackages do
59 if mentity.name != name then continue
60 if parts.is_empty then
61 res.add mentity
62 else
63 res.add_all mentity.collect_by_namespace(parts.first)
64 end
65 end
66 return res
67 end
68 end
69
70 redef class MPackage
71 redef fun collect_by_namespace(namespace) do
72 var res = new Array[MEntity]
73 var root = self.root
74 if root == null then return res
75 lookup_in([root], namespace, res)
76 return res
77 end
78 end
79
80 redef class MGroup
81 redef fun collect_by_namespace(namespace) do
82 var res = new Array[MEntity]
83 lookup_in(in_nesting.direct_smallers, namespace, res)
84 lookup_in(mmodules, namespace, res)
85 return res
86 end
87 end
88
89 redef class MModule
90
91 redef fun collect_by_namespace(namespace) do
92 var res = new Array[MEntity]
93 lookup_in(mclassdefs, namespace, res)
94 return res
95 end
96
97 # Collect mclassdefs introduced in `self` with `visibility >= to min_visibility`.
98 fun collect_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
99 var res = new HashSet[MClassDef]
100 for mclassdef in mclassdefs do
101 if not mclassdef.is_intro then continue
102 if mclassdef.mclass.visibility < min_visibility then continue
103 res.add mclassdef
104 end
105 return res
106 end
107
108 # Collect mclassdefs redefined in `self` with `visibility >= to min_visibility`.
109 fun collect_redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do
110 var res = new HashSet[MClassDef]
111 for mclassdef in mclassdefs do
112 if mclassdef.is_intro then continue
113 if mclassdef.mclass.visibility < min_visibility then continue
114 res.add mclassdef
115 end
116 return res
117 end
118
119 # Collect mclasses introduced in `self` with `visibility >= to min_visibility`.
120 fun collect_intro_mclasses(min_visibility: MVisibility): Set[MClass] do
121 var res = new HashSet[MClass]
122 for mclass in intro_mclasses do
123 if mclass.visibility < min_visibility then continue
124 res.add mclass
125 end
126 return res
127 end
128
129 # Collect mclasses redefined in `self` with `visibility >= to min_visibility`.
130 fun collect_redef_mclasses(min_visibility: MVisibility): Set[MClass] do
131 var mclasses = new HashSet[MClass]
132 for c in mclassdefs do
133 if c.mclass.visibility < min_visibility then continue
134 if not c.is_intro then mclasses.add(c.mclass)
135 end
136 return mclasses
137 end
138 end
139
140 redef class MClass
141
142 # Collect direct parents of `self` with `visibility >= to min_visibility`.
143 fun collect_parents(min_visibility: MVisibility): Set[MClass] do
144 var res = new HashSet[MClass]
145 for mclassdef in mclassdefs do
146 for mclasstype in mclassdef.supertypes do
147 var mclass = mclasstype.mclass
148 if mclass.visibility < min_visibility then continue
149 res.add(mclass)
150 end
151 end
152 return res
153 end
154
155 # Collect all ancestors of `self` with `visibility >= to min_visibility`.
156 fun collect_ancestors(min_visibility: MVisibility): Set[MClass] do
157 var res = new HashSet[MClass]
158 for mclassdef in self.mclassdefs do
159 for super_mclassdef in mclassdef.in_hierarchy.greaters do
160 if super_mclassdef == mclassdef then continue # skip self
161 var mclass = super_mclassdef.mclass
162 if mclass.visibility < min_visibility then continue
163 res.add(mclass)
164 end
165 end
166 return res
167 end
168
169 # Collect direct children of `self` with `visibility >= to min_visibility`.
170 fun collect_children(min_visibility: MVisibility): Set[MClass] do
171 var res = new HashSet[MClass]
172 for mclassdef in self.mclassdefs do
173 for sub_mclassdef in mclassdef.in_hierarchy.direct_smallers do
174 if sub_mclassdef == mclassdef then continue # skip self
175 var mclass = sub_mclassdef.mclass
176 if mclass.visibility < min_visibility then continue
177 res.add(mclass)
178 end
179 end
180 return res
181 end
182
183 # Collect all descendants of `self` with `visibility >= to min_visibility`.
184 fun descendants(min_visibility: MVisibility): Set[MClass] do
185 var res = new HashSet[MClass]
186 for mclassdef in self.mclassdefs do
187 for sub_mclassdef in mclassdef.in_hierarchy.smallers do
188 if sub_mclassdef == mclassdef then continue # skip self
189 var mclass = sub_mclassdef.mclass
190 if mclass.visibility < min_visibility then continue
191 res.add(mclass)
192 end
193 end
194 return res
195 end
196
197 # Collect all mproperties introduced in 'self' with `visibility >= min_visibility`.
198 fun collect_intro_mproperties(min_visibility: MVisibility): Set[MProperty] do
199 var set = new HashSet[MProperty]
200 for mclassdef in mclassdefs do
201 for mprop in mclassdef.intro_mproperties do
202 if mprop.visibility < min_visibility then continue
203 set.add(mprop)
204 end
205 end
206 return set
207 end
208
209 # Collect all mproperties redefined in 'self' with `visibility >= min_visibility`.
210 fun collect_redef_mproperties(min_visibility: MVisibility): Set[MProperty] do
211 var set = new HashSet[MProperty]
212 for mclassdef in mclassdefs do
213 for mpropdef in mclassdef.mpropdefs do
214 if mpropdef.mproperty.visibility < min_visibility then continue
215 if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty)
216 end
217 end
218 return set
219 end
220
221 # Collect mproperties introduced and redefined in 'self' with `visibility >= min_visibility`.
222 fun collect_local_mproperties(min_visibility: MVisibility): Set[MProperty] do
223 var set = new HashSet[MProperty]
224 set.add_all collect_intro_mproperties(min_visibility)
225 set.add_all collect_redef_mproperties(min_visibility)
226 return set
227 end
228
229 # Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`.
230 fun collect_inherited_mproperties(min_visibility: MVisibility): Set[MProperty] do
231 var set = new HashSet[MProperty]
232 for parent in collect_parents(min_visibility) do
233 set.add_all(parent.collect_intro_mproperties(min_visibility))
234 set.add_all(parent.collect_inherited_mproperties(min_visibility))
235 end
236 return set
237 end
238
239 # Collect all mproperties accessible by 'self' with `visibility >= min_visibility`.
240 #
241 # This include introduced, redefined, inherited mproperties.
242 fun collect_accessible_mproperties(min_visibility: MVisibility): Set[MProperty] do
243 var set = new HashSet[MProperty]
244 set.add_all(collect_intro_mproperties(min_visibility))
245 set.add_all(collect_redef_mproperties(min_visibility))
246 set.add_all(collect_inherited_mproperties(min_visibility))
247 return set
248 end
249
250 # Collect mmethods introduced in 'self' with `visibility >= min_visibility`.
251 fun collect_intro_mmethods(min_visibility: MVisibility): Set[MMethod] do
252 var res = new HashSet[MMethod]
253 for mproperty in collect_intro_mproperties(min_visibility) do
254 if mproperty isa MMethod then res.add(mproperty)
255 end
256 return res
257 end
258
259 # Collect mmethods redefined in 'self' with `visibility >= min_visibility`.
260 fun collect_redef_mmethods(min_visibility: MVisibility): Set[MMethod] do
261 var res = new HashSet[MMethod]
262 for mproperty in collect_redef_mproperties(min_visibility) do
263 if mproperty isa MMethod then res.add(mproperty)
264 end
265 return res
266 end
267
268 # Collect mmethods introduced and redefined in 'self' with `visibility >= min_visibility`.
269 fun collect_local_mmethods(min_visibility: MVisibility): Set[MMethod] do
270 var set = new HashSet[MMethod]
271 set.add_all collect_intro_mmethods(min_visibility)
272 set.add_all collect_redef_mmethods(min_visibility)
273 return set
274 end
275
276 # Collect mattributes introduced in 'self' with `visibility >= min_visibility`.
277 fun collect_intro_mattributes(min_visibility: MVisibility): Set[MAttribute] do
278 var res = new HashSet[MAttribute]
279 for mproperty in collect_intro_mproperties(min_visibility) do
280 if mproperty isa MAttribute then res.add(mproperty)
281 end
282 return res
283 end
284
285 # Collect mattributes redefined in 'self' with `visibility >= min_visibility`.
286 fun collect_redef_mattributes(min_visibility: MVisibility): Set[MAttribute] do
287 var res = new HashSet[MAttribute]
288 for mproperty in collect_redef_mproperties(min_visibility) do
289 if mproperty isa MAttribute then res.add(mproperty)
290 end
291 return res
292 end
293
294 # Collect mattributes introduced and redefined in 'self' with `visibility >= min_visibility`.
295 fun collect_local_mattributes(min_visibility: MVisibility): Set[MAttribute] do
296 var set = new HashSet[MAttribute]
297 set.add_all collect_intro_mattributes(min_visibility)
298 set.add_all collect_redef_mattributes(min_visibility)
299 return set
300 end
301
302 # Collect mattributes inherited by 'self' with `visibility >= min_visibility`.
303 fun collect_inherited_mattributes(min_visibility: MVisibility): Set[MAttribute] do
304 var res = new HashSet[MAttribute]
305 for mproperty in collect_inherited_mproperties(min_visibility) do
306 if mproperty isa MAttribute then res.add(mproperty)
307 end
308 return res
309 end
310
311 # Collect all mattributes accessible by 'self' with `visibility >= min_visibility`.
312 #
313 # This include introduced, redefined, inherited mattributes.
314 fun collect_accessible_mattributes(min_visibility: MVisibility): Set[MAttribute] do
315 var set = new HashSet[MAttribute]
316 set.add_all(collect_intro_mattributes(min_visibility))
317 set.add_all(collect_redef_mattributes(min_visibility))
318 set.add_all(collect_inherited_mattributes(min_visibility))
319 return set
320 end
321 end
322
323 redef class MClassDef
324
325 redef fun collect_by_namespace(namespace) do
326 var res = new Array[MEntity]
327 lookup_in(mpropdefs, namespace, res)
328 return res
329 end
330
331 # Collect mpropdefs in 'self' with `visibility >= min_visibility`.
332 fun collect_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
333 var res = new HashSet[MPropDef]
334 for mpropdef in mpropdefs do
335 if mpropdef.mproperty.visibility < min_visibility then continue
336 res.add mpropdef
337 end
338 return res
339 end
340
341 # Collect mpropdefs introduced in 'self' with `visibility >= min_visibility`.
342 fun collect_intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
343 var res = new HashSet[MPropDef]
344 for mpropdef in mpropdefs do
345 if not mpropdef.is_intro then continue
346 if mpropdef.mproperty.visibility < min_visibility then continue
347 res.add mpropdef
348 end
349 return res
350 end
351
352 # Collect mpropdefs redefined in 'self' with `visibility >= min_visibility`.
353 fun collect_redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do
354 var res = new HashSet[MPropDef]
355 for mpropdef in mpropdefs do
356 if mpropdef.is_intro then continue
357 if mpropdef.mproperty.visibility < min_visibility then continue
358 res.add mpropdef
359 end
360 return res
361 end
362
363 # Collect modifiers like redef, private etc.
364 fun collect_modifiers: Array[String] do
365 var res = new Array[String]
366 if not is_intro then
367 res.add "redef"
368 else
369 res.add mclass.visibility.to_s
370 end
371 res.add mclass.kind.to_s
372 return res
373 end
374 end
375
376 redef class MPropDef
377 # Collect modifiers like redef, private, abstract, intern, fun etc.
378 fun collect_modifiers: Array[String] do
379 var res = new Array[String]
380 if not is_intro then
381 res.add "redef"
382 else
383 res.add mproperty.visibility.to_s
384 end
385 var mprop = self
386 if mprop isa MVirtualTypeDef then
387 res.add "type"
388 else if mprop isa MMethodDef then
389 if mprop.is_abstract then
390 res.add "abstract"
391 else if mprop.is_intern then
392 res.add "intern"
393 end
394 if mprop.mproperty.is_init then
395 res.add "init"
396 else
397 res.add "fun"
398 end
399 end
400 return res
401 end
402 end