model_collect: Fix a spelling mistake
[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 should 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_views
33
34 redef class MEntity
35
36 # FIXME used to bypass RTA limitation on type resolution.
37 type MENTITY: SELF
38
39 # Collect modifier keywords like `redef`, `private` etc.
40 fun collect_modifiers: Array[String] do
41 return new Array[String]
42 end
43
44 # Collect `self` linearization anchored on `mainmodule`.
45 fun collect_linearization(mainmodule: MModule): nullable Array[MEntity] do
46 return null
47 end
48
49 # Collect `self` ancestors (direct and indirect).
50 #
51 # The concept of ancestor is abstract at this stage.
52 fun collect_ancestors(view: ModelView): Set[MENTITY] do
53 var done = new HashSet[MENTITY]
54 var todo = new Array[MENTITY]
55
56 todo.add_all collect_parents(view)
57 while todo.not_empty do
58 var mentity = todo.pop
59 if mentity == self or done.has(mentity) then continue
60 print "{mentity} == {self}"
61 done.add mentity
62 todo.add_all mentity.collect_parents(view)
63 end
64 return done
65 end
66
67 # Collect `self` parents (direct ancestors).
68 #
69 # The concept of parent is abstract at this stage.
70 fun collect_parents(view: ModelView): Set[MENTITY] is abstract
71
72 # Collect `self` children (direct descendants).
73 #
74 # The concept of child is abstract at this stage.
75 fun collect_children(view: ModelView): Set[MENTITY] is abstract
76
77 # Collect `self` descendants (direct and direct).
78 #
79 # The concept of descendant is abstract at this stage.
80 fun collect_descendants(view: ModelView): Set[MENTITY] do
81 var done = new HashSet[MENTITY]
82 var todo = new Array[MENTITY]
83
84 todo.add_all collect_children(view)
85 while todo.not_empty do
86 var mentity = todo.pop
87 if mentity == self or done.has(mentity) then continue
88 done.add mentity
89 todo.add_all mentity.collect_children(view)
90 end
91 return done
92 end
93
94 # Build a poset representing `self` in it's own hierarchy.
95 #
96 # The notion of hierarchy depends on the type of MEntity.
97 #
98 # Here a recap:
99 # * MPackage: package dependencies
100 # * MGroup: group dependencies
101 # * MModule: modules imports
102 # * MClass: class inheritance (all classdefs flattened)
103 # * MClassDef: classdef inheritance
104 # * MProperty: property definitions graph (all propdefs flattened)
105 # * MPropDef: property definitions graph
106 fun hierarchy_poset(view: ModelView): POSet[MENTITY] do
107 var done = new HashSet[MENTITY]
108 var mentities = new Array[MENTITY]
109 mentities.add self
110 var poset = new POSet[MENTITY]
111 while mentities.not_empty do
112 var mentity = mentities.pop
113 if done.has(mentity) then continue
114 done.add mentity
115 poset.add_node mentity
116 for parent in mentity.collect_parents(view) do
117 poset.add_edge(mentity, parent)
118 mentities.add parent
119 end
120 for child in mentity.collect_children(view) do
121 poset.add_edge(child, mentity)
122 mentities.add child
123 end
124 end
125 return poset
126 end
127 end
128
129 redef class MPackage
130 redef fun collect_modifiers do
131 var res = super
132 res.add "package"
133 return res
134 end
135
136 # `MPackage` parents are its direct dependencies.
137 redef fun collect_parents(view) do
138 var res = new HashSet[MENTITY]
139 for mgroup in mgroups do
140 for parent in mgroup.collect_parents(view) do
141 var mpackage = parent.mpackage
142 if mpackage == self or not view.accept_mentity(mpackage) then continue
143 res.add(mpackage)
144 end
145 end
146 return res
147 end
148
149 # `MPackage` children are packages that directly depends on `self`.
150 redef fun collect_children(view) do
151 var res = new HashSet[MENTITY]
152 for mpackage in view.mpackages do
153 if mpackage.collect_parents(view).has(self) then res.add mpackage
154 end
155 return res
156 end
157 end
158
159 redef class MGroup
160 redef fun collect_modifiers do
161 var res = super
162 res.add "group"
163 return res
164 end
165
166 # `MGroup` parents are its direct dependencies.
167 redef fun collect_parents(view) do
168 var res = new HashSet[MENTITY]
169 for mmodule in mmodules do
170 for parent in mmodule.collect_parents(view) do
171 var mgroup = parent.mgroup
172 if mgroup == null or mgroup == self then continue
173 if not view.accept_mentity(mgroup) then continue
174 res.add(mgroup)
175 end
176 end
177 return res
178 end
179
180 # `MGroup` children are mgroups that directly depends on `self`.
181 redef fun collect_children(view) do
182 var res = new HashSet[MENTITY]
183 for mgroup in view.mgroups do
184 if mgroup == self or not view.accept_mentity(mgroup) then continue
185 if mgroup.collect_parents(view).has(self) then res.add mgroup
186 end
187 return res
188 end
189 end
190
191 redef class MModule
192
193 redef fun collect_modifiers do
194 var res = super
195 res.add "module"
196 return res
197 end
198
199 # `MModule` ancestors are all its transitive imports.
200 redef fun collect_ancestors(view) do
201 var res = new HashSet[MENTITY]
202 for mentity in in_importation.greaters do
203 if mentity == self then continue
204 if not view.accept_mentity(mentity) then continue
205 res.add mentity
206 end
207 return res
208 end
209
210 # `MModule` parents are all its direct imports.
211 redef fun collect_parents(view) do
212 var res = new HashSet[MENTITY]
213 for mentity in in_importation.direct_greaters do
214 if mentity == self then continue
215 if not view.accept_mentity(mentity) then continue
216 res.add mentity
217 end
218 return res
219 end
220
221 # `MModule` children are modules that directly import `self`.
222 redef fun collect_children(view) do
223 var res = new HashSet[MENTITY]
224 for mentity in in_importation.direct_smallers do
225 if mentity == self then continue
226 if not view.accept_mentity(mentity) then continue
227 res.add mentity
228 end
229 return res
230 end
231
232 # `MModule` children are modules that transitively import `self`.
233 redef fun collect_descendants(view) do
234 var res = new HashSet[MENTITY]
235 for mentity in in_importation.smallers do
236 if mentity == self then continue
237 if not view.accept_mentity(mentity) then continue
238 res.add mentity
239 end
240 return res
241 end
242
243 # Collect mclassdefs introduced in `self` with `visibility >= to min_visibility`.
244 fun collect_intro_mclassdefs(view: ModelView): Set[MClassDef] do
245 var res = new HashSet[MClassDef]
246 for mclassdef in mclassdefs do
247 if not mclassdef.is_intro then continue
248 if not view.accept_mentity(mclassdef) then continue
249 res.add mclassdef
250 end
251 return res
252 end
253
254 # Collect mclassdefs redefined in `self` with `visibility >= to min_visibility`.
255 fun collect_redef_mclassdefs(view: ModelView): Set[MClassDef] do
256 var res = new HashSet[MClassDef]
257 for mclassdef in mclassdefs do
258 if mclassdef.is_intro then continue
259 if not view.accept_mentity(mclassdef) then continue
260 res.add mclassdef
261 end
262 return res
263 end
264
265 # Collect mclasses introduced in `self` with `visibility >= to min_visibility`.
266 fun collect_intro_mclasses(view: ModelView): Set[MClass] do
267 var res = new HashSet[MClass]
268 for mclass in intro_mclasses do
269 if not view.accept_mentity(mclass) then continue
270 res.add mclass
271 end
272 return res
273 end
274
275 # Collect mclasses redefined in `self` with `visibility >= to min_visibility`.
276 fun collect_redef_mclasses(view: ModelView): Set[MClass] do
277 var mclasses = new HashSet[MClass]
278 for mclassdef in mclassdefs do
279 if not view.accept_mentity(mclassdef) then continue
280 if not mclassdef.is_intro then mclasses.add(mclassdef.mclass)
281 end
282 return mclasses
283 end
284 end
285
286 redef class MClass
287
288 redef fun collect_modifiers do return intro.collect_modifiers
289
290 redef fun collect_linearization(mainmodule) do
291 var mclassdefs = self.mclassdefs.to_a
292 mainmodule.linearize_mclassdefs(mclassdefs)
293 return mclassdefs
294 end
295
296 # `MClass` parents are the direct parents of `self`.
297 #
298 # This method uses a flattened hierarchy containing all the mclassdefs.
299 redef fun collect_parents(view) do
300 var res = new HashSet[MENTITY]
301 for mclassdef in mclassdefs do
302 for parent in mclassdef.collect_parents(view) do
303 var mclass = parent.mclass
304 if mclass == self or not view.accept_mentity(parent) then continue
305 res.add mclass
306 end
307 end
308 return res
309 end
310
311 # Collect all ancestors of `self` with `visibility >= to min_visibility`.
312 redef fun collect_ancestors(view) do
313 var res = new HashSet[MENTITY]
314 for mclassdef in mclassdefs do
315 for parent in mclassdef.collect_parents(view) do
316 if not view.accept_mentity(parent) then continue
317 res.add parent.mclass
318 end
319 end
320 return res
321 end
322
323 # `MClass` parents are the direct parents of `self`.
324 #
325 # This method uses a flattened hierarchy containing all the mclassdefs.
326 redef fun collect_children(view) do
327 var res = new HashSet[MENTITY]
328 for mclassdef in mclassdefs do
329 for child in mclassdef.collect_children(view) do
330 var mclass = child.mclass
331 if mclass == self or not view.accept_mentity(child) then continue
332 res.add mclass
333 end
334 end
335 return res
336 end
337
338 # Collect all mproperties introduced in 'self' with `visibility >= min_visibility`.
339 fun collect_intro_mproperties(view: ModelView): Set[MProperty] do
340 var set = new HashSet[MProperty]
341 for mclassdef in mclassdefs do
342 for mprop in mclassdef.intro_mproperties do
343 if not view.accept_mentity(mprop) then continue
344 set.add(mprop)
345 end
346 end
347 return set
348 end
349
350 # Collect all mproperties redefined in 'self' with `visibility >= min_visibility`.
351 fun collect_redef_mproperties(view: ModelView): Set[MProperty] do
352 var set = new HashSet[MProperty]
353 for mclassdef in mclassdefs do
354 for mpropdef in mclassdef.mpropdefs do
355 if mpropdef.mproperty.intro_mclassdef.mclass == self then continue
356 if not view.accept_mentity(mpropdef) then continue
357 set.add(mpropdef.mproperty)
358 end
359 end
360 return set
361 end
362
363 # Collect mproperties introduced and redefined in 'self' with `visibility >= min_visibility`.
364 fun collect_local_mproperties(view: ModelView): Set[MProperty] do
365 var set = new HashSet[MProperty]
366 set.add_all collect_intro_mproperties(view)
367 set.add_all collect_redef_mproperties(view)
368 return set
369 end
370
371 # Collect all mproperties inehrited by 'self' with `visibility >= min_visibility`.
372 fun collect_inherited_mproperties(view: ModelView): Set[MProperty] do
373 var set = new HashSet[MProperty]
374 for parent in collect_parents(view) do
375 set.add_all(parent.collect_intro_mproperties(view))
376 set.add_all(parent.collect_inherited_mproperties(view))
377 end
378 return set
379 end
380
381 # Collect all mproperties accessible by 'self' with `visibility >= min_visibility`.
382 #
383 # This include introduced, redefined, inherited mproperties.
384 fun collect_accessible_mproperties(view: ModelView): Set[MProperty] do
385 var set = new HashSet[MProperty]
386 set.add_all(collect_intro_mproperties(view))
387 set.add_all(collect_redef_mproperties(view))
388 set.add_all(collect_inherited_mproperties(view))
389 return set
390 end
391
392 # Collect mmethods introduced in 'self' with `visibility >= min_visibility`.
393 fun collect_intro_mmethods(view: ModelView): Set[MMethod] do
394 var res = new HashSet[MMethod]
395 for mproperty in collect_intro_mproperties(view) do
396 if mproperty isa MMethod then res.add(mproperty)
397 end
398 return res
399 end
400
401 # Collect mmethods redefined in 'self' with `visibility >= min_visibility`.
402 fun collect_redef_mmethods(view: ModelView): Set[MMethod] do
403 var res = new HashSet[MMethod]
404 for mproperty in collect_redef_mproperties(view) do
405 if mproperty isa MMethod then res.add(mproperty)
406 end
407 return res
408 end
409
410 # Collect mmethods introduced and redefined in 'self' with `visibility >= min_visibility`.
411 fun collect_local_mmethods(view: ModelView): Set[MMethod] do
412 var set = new HashSet[MMethod]
413 set.add_all collect_intro_mmethods(view)
414 set.add_all collect_redef_mmethods(view)
415 return set
416 end
417
418 # Collect mmethods inherited by 'self' if accepted by `view`.
419 fun collect_inherited_mmethods(view: ModelView): Set[MMethod] do
420 var res = new HashSet[MMethod]
421 for mproperty in collect_inherited_mproperties(view) do
422 if mproperty isa MMethod then res.add(mproperty)
423 end
424 return res
425 end
426
427 # Collect mattributes introduced in 'self' with `visibility >= min_visibility`.
428 fun collect_intro_mattributes(view: ModelView): Set[MAttribute] do
429 var res = new HashSet[MAttribute]
430 for mproperty in collect_intro_mproperties(view) do
431 if mproperty isa MAttribute then res.add(mproperty)
432 end
433 return res
434 end
435
436 # Collect mattributes redefined in 'self' with `visibility >= min_visibility`.
437 fun collect_redef_mattributes(view: ModelView): Set[MAttribute] do
438 var res = new HashSet[MAttribute]
439 for mproperty in collect_redef_mproperties(view) do
440 if mproperty isa MAttribute then res.add(mproperty)
441 end
442 return res
443 end
444
445 # Collect mattributes introduced and redefined in 'self' with `visibility >= min_visibility`.
446 fun collect_local_mattributes(view: ModelView): Set[MAttribute] do
447 var set = new HashSet[MAttribute]
448 set.add_all collect_intro_mattributes(view)
449 set.add_all collect_redef_mattributes(view)
450 return set
451 end
452
453 # Collect mattributes inherited by 'self' with `visibility >= min_visibility`.
454 fun collect_inherited_mattributes(view: ModelView): Set[MAttribute] do
455 var res = new HashSet[MAttribute]
456 for mproperty in collect_inherited_mproperties(view) do
457 if mproperty isa MAttribute then res.add(mproperty)
458 end
459 return res
460 end
461
462 # Collect all mattributes accessible by 'self' with `visibility >= min_visibility`.
463 #
464 # This include introduced, redefined, inherited mattributes.
465 fun collect_accessible_mattributes(view: ModelView): Set[MAttribute] do
466 var set = new HashSet[MAttribute]
467 set.add_all(collect_intro_mattributes(view))
468 set.add_all(collect_redef_mattributes(view))
469 set.add_all(collect_inherited_mattributes(view))
470 return set
471 end
472
473 # Collect init mmethods introduced in 'self' if accepted by `view`.
474 fun collect_intro_inits(view: ModelView): Set[MMethod] do
475 var res = new HashSet[MMethod]
476 for mproperty in collect_intro_mmethods(view) do
477 if mproperty.is_init then res.add(mproperty)
478 end
479 return res
480 end
481
482 # Collect init mmethods redefined in 'self' if accepted by `view`.
483 fun collect_redef_inits(view: ModelView): Set[MMethod] do
484 var res = new HashSet[MMethod]
485 for mproperty in collect_redef_mmethods(view) do
486 if mproperty.is_init then res.add(mproperty)
487 end
488 return res
489 end
490
491 # Collect init mmethods introduced and redefined in 'self' if accepted by `view`.
492 fun collect_local_inits(view: ModelView): Set[MMethod] do
493 var set = new HashSet[MMethod]
494 set.add_all collect_intro_inits(view)
495 set.add_all collect_redef_inits(view)
496 return set
497 end
498
499 # Collect init mmethods inherited by 'self' if accepted by `view`.
500 fun collect_inherited_inits(view: ModelView): Set[MMethod] do
501 var res = new HashSet[MMethod]
502 for mproperty in collect_inherited_mmethods(view) do
503 if mproperty.is_init then res.add(mproperty)
504 end
505 return res
506 end
507
508 # Collect all init mmethods accessible by 'self' if accepted by `view`.
509 #
510 # This include introduced, redefined, inherited inits.
511 fun collect_accessible_inits(view: ModelView): Set[MMethod] do
512 var set = new HashSet[MMethod]
513 set.add_all(collect_intro_inits(view))
514 set.add_all(collect_redef_inits(view))
515 set.add_all(collect_inherited_inits(view))
516 return set
517 end
518 end
519
520 redef class MClassDef
521
522 redef fun collect_linearization(mainmodule) do
523 var mclassdefs = new Array[MClassDef]
524 for mclassdef in in_hierarchy.as(not null).greaters do
525 if mclassdef.mclass == self.mclass then mclassdefs.add mclassdef
526 end
527 mainmodule.linearize_mclassdefs(mclassdefs)
528 return mclassdefs
529 end
530
531 # `MClassDef` ancestors are its direct and transitive super classes.
532 redef fun collect_ancestors(view) do
533 var res = new HashSet[MENTITY]
534 var hierarchy = self.in_hierarchy
535 if hierarchy == null then return res
536 for parent in hierarchy.greaters do
537 if parent == self or not view.accept_mentity(parent) then continue
538 res.add parent
539 end
540 return res
541 end
542
543 # `MClassDef` parents are its direct super classes.
544 redef fun collect_parents(view) do
545 var res = new HashSet[MENTITY]
546 var hierarchy = self.in_hierarchy
547 if hierarchy == null then return res
548 for parent in hierarchy.direct_greaters do
549 if parent == self or not view.accept_mentity(parent) then continue
550 res.add parent
551 end
552 return res
553 end
554
555 # `MClassDef` children are its direct subclasses.
556 redef fun collect_children(view) do
557 var res = new HashSet[MENTITY]
558 var hierarchy = self.in_hierarchy
559 if hierarchy == null then return res
560 for child in hierarchy.direct_smallers do
561 if child == self or not view.accept_mentity(child) then continue
562 res.add child
563 end
564 return res
565 end
566
567 # Collect mpropdefs in 'self' with `visibility >= min_visibility`.
568 fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
569 var res = new HashSet[MPropDef]
570 for mpropdef in mpropdefs do
571 if not view.accept_mentity(mpropdef) then continue
572 res.add mpropdef
573 end
574 return res
575 end
576
577 # Collect mpropdefs introduced in 'self' with `visibility >= min_visibility`.
578 fun collect_intro_mpropdefs(view: ModelView): Set[MPropDef] do
579 var res = new HashSet[MPropDef]
580 for mpropdef in mpropdefs do
581 if not mpropdef.is_intro then continue
582 if not view.accept_mentity(mpropdef) then continue
583 res.add mpropdef
584 end
585 return res
586 end
587
588 # Collect mpropdefs redefined in 'self' with `visibility >= min_visibility`.
589 fun collect_redef_mpropdefs(view: ModelView): Set[MPropDef] do
590 var res = new HashSet[MPropDef]
591 for mpropdef in mpropdefs do
592 if mpropdef.is_intro then continue
593 if not view.accept_mentity(mpropdef) then continue
594 res.add mpropdef
595 end
596 return res
597 end
598
599 redef fun collect_modifiers do
600 var res = super
601 if not is_intro then
602 res.add "redef"
603 else
604 res.add mclass.visibility.to_s
605 end
606 res.add mclass.kind.to_s
607 return res
608 end
609 end
610
611 redef class MProperty
612 redef fun collect_modifiers do return intro.collect_modifiers
613
614 redef fun collect_linearization(mainmodule) do
615 var mpropdefs = self.mpropdefs.to_a
616 mainmodule.linearize_mpropdefs(mpropdefs)
617 return mpropdefs
618 end
619
620 # Collect mpropdefs in 'self' with `visibility >= min_visibility`.
621 fun collect_mpropdefs(view: ModelView): Set[MPropDef] do
622 var res = new HashSet[MPropDef]
623 for mpropdef in mpropdefs do
624 if not view.accept_mentity(mpropdef) then continue
625 res.add mpropdef
626 end
627 return res
628 end
629
630 # `MProperty` parents are all direct super definition of `self`.
631 #
632 # This method uses a flattened hierarchy containing all the mpropdefs.
633 redef fun collect_parents(view) do
634 var res = new HashSet[MENTITY]
635 for mpropdef in mpropdefs do
636 for parent in mpropdef.collect_parents(view) do
637 if not view.accept_mentity(parent) then continue
638 res.add parent.mproperty
639 end
640 end
641 return res
642 end
643
644 # `MProperty` parents are all direct sub definition of `self`.
645 #
646 # This method uses a flattened hierarchy containing all the mpropdefs.
647 redef fun collect_children(view) do
648 var res = new HashSet[MENTITY]
649 for mpropdef in mpropdefs do
650 for child in mpropdef.collect_parents(view) do
651 if not view.accept_mentity(child) then continue
652 res.add child.mproperty
653 end
654 end
655 return res
656 end
657 end
658
659 redef class MPropDef
660 redef fun collect_modifiers do
661 var res = super
662 if not is_intro then
663 res.add "redef"
664 else
665 res.add mproperty.visibility.to_s
666 end
667 var mprop = self
668 if mprop isa MVirtualTypeDef then
669 res.add "type"
670 else if mprop isa MMethodDef then
671 if mprop.is_abstract then
672 res.add "abstract"
673 else if mprop.is_intern then
674 res.add "intern"
675 end
676 if mprop.mproperty.is_init then
677 res.add "init"
678 else
679 res.add "fun"
680 end
681 else if mprop isa MAttributeDef then
682 res.add "var"
683 end
684 return res
685 end
686
687 redef fun collect_linearization(mainmodule) do
688 var mpropdefs = new Array[MPropDef]
689 var mentity = self
690 while not mentity.is_intro do
691 mpropdefs.add mentity
692 mentity = mentity.lookup_next_definition(mainmodule, mentity.mclassdef.bound_mtype)
693 end
694 mpropdefs.add mentity
695 mainmodule.linearize_mpropdefs(mpropdefs)
696 return mpropdefs
697 end
698
699 # `MPropDef` parents include only the next definition of `self`.
700 redef fun collect_parents(view) do
701 var res = new HashSet[MENTITY]
702 var mpropdef = self
703 while not mpropdef.is_intro do
704 mpropdef = mpropdef.lookup_next_definition(mclassdef.mmodule, mclassdef.bound_mtype)
705 res.add mpropdef
706 end
707 return res
708 end
709
710 # `MPropdef` children are definitions that directly depends on `self`.
711 redef fun collect_children(view) do
712 var res = new HashSet[MENTITY]
713 for mpropdef in mproperty.collect_mpropdefs(view) do
714 if mpropdef.collect_parents(view).has(self) then res.add mpropdef
715 end
716 return res
717 end
718 end