1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2008 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 # Collect things from a `ModelView`
19 # This module introduce several usefull methods to list and count things from a
22 # First setup you view from a Model:
25 # var view = new ModelView(model)
28 # Then ask question using the view:
31 # print number of parents for `{my_class}`
32 # print my_class.collect_parents(view).count
37 # `model_collect` offers a flattened view of the model without considering any
39 # For this reason, `model_collect` lists all the definitions reachable from all
42 # This is usefull for tools that need a global view of a model like `nitdoc`,
43 # `nitx`, `nitmetrics` or `nituml`.
44 # It should not be used for compiling stuffs like computing VFT, where the listed
45 # entities could not be reachable depending on the modules really imported.
52 # FIXME used to bypass RTA limitation on type resolution
55 # Collect modifier keywords like `redef`, `private` etc
56 fun collect_modifiers
: Array[String] do return new Array[String]
58 # Collect `self` linearization anchored on `mainmodule`
59 fun collect_linearization
(mainmodule
: MModule): nullable Array[MEntity] do
63 # Collect `self` ancestors (direct and indirect)
65 # The concept of ancestor is abstract at this stage.
66 fun collect_ancestors
(view
: ModelView): Set[MENTITY] do
67 var done
= new HashSet[MENTITY]
68 var todo
= new Array[MENTITY]
70 todo
.add_all collect_parents
(view
)
71 while todo
.not_empty
do
72 var mentity
= todo
.pop
73 if mentity
== self or done
.has
(mentity
) then continue
75 todo
.add_all mentity
.collect_parents
(view
)
80 # Collect `self` parents (direct ancestors)
82 # The concept of parent is abstract at this stage.
83 fun collect_parents
(view
: ModelView): Set[MENTITY] is abstract
85 # Collect `self` children (direct descendants)
87 # The concept of child is abstract at this stage.
88 fun collect_children
(view
: ModelView): Set[MENTITY] is abstract
90 # Collect `self` descendants (direct and direct)
92 # The concept of descendant is abstract at this stage.
93 fun collect_descendants
(view
: ModelView): Set[MENTITY] do
94 var done
= new HashSet[MENTITY]
95 var todo
= new Array[MENTITY]
97 todo
.add_all collect_children
(view
)
98 while todo
.not_empty
do
99 var mentity
= todo
.pop
100 if mentity
== self or done
.has
(mentity
) then continue
102 todo
.add_all mentity
.collect_children
(view
)
107 # Build a poset representing `self` in it's own hierarchy
109 # The notion of hierarchy depends on the type of MEntity.
112 # * `MPackage`: package dependencies
113 # * `MGroup`: group dependencies
114 # * `MModule`: modules imports
115 # * `MClass`: class inheritance (all classdefs flattened)
116 # * `MClassDef`: classdef inheritance
117 # * `MProperty`: property definitions graph (all propdefs flattened)
118 # * `MPropDef`: property definitions graph
119 fun hierarchy_poset
(view
: ModelView): POSet[MENTITY] do
120 var done
= new HashSet[MENTITY]
121 var mentities
= new Array[MENTITY]
123 var poset
= new POSet[MENTITY]
124 while mentities
.not_empty
do
125 var mentity
= mentities
.pop
126 if done
.has
(mentity
) then continue
128 poset
.add_node mentity
129 for parent
in mentity
.collect_parents
(view
) do
130 poset
.add_edge
(mentity
, parent
)
133 for child
in mentity
.collect_children
(view
) do
134 poset
.add_edge
(child
, mentity
)
143 redef fun collect_modifiers
do
149 # Collect all packages directly imported by `self`
150 redef fun collect_parents
(view
) do
151 var res
= new HashSet[MENTITY]
152 for mgroup
in mgroups
do
153 for parent
in mgroup
.collect_parents
(view
) do
154 var mpackage
= parent
.mpackage
155 if mpackage
== self or not view
.accept_mentity
(mpackage
) then continue
162 # Collect all packages that directly depends on `self`
163 redef fun collect_children
(view
) do
164 var res
= new HashSet[MENTITY]
165 for mpackage
in view
.mpackages
do
166 if mpackage
.collect_parents
(view
).has
(self) then res
.add mpackage
171 # Collect all modules contained in `self`
172 fun collect_mmodules
(view
: ModelView): HashSet[MModule] do
173 var res
= new HashSet[MModule]
174 for mgroup
in mgroups
do
175 for mmodule
in mgroup
.mmodules
do
176 if not view
.accept_mentity
(mmodule
) then continue
185 redef fun collect_modifiers
do
191 # Collect all groups directly import by `self`
192 redef fun collect_parents
(view
) do
193 var res
= new HashSet[MENTITY]
194 for mmodule
in mmodules
do
195 for parent
in mmodule
.collect_parents
(view
) do
196 var mgroup
= parent
.mgroup
197 if mgroup
== null or mgroup
== self then continue
198 if not view
.accept_mentity
(mgroup
) then continue
205 # Collect all group that directly import `self`
206 redef fun collect_children
(view
) do
207 var res
= new HashSet[MENTITY]
208 for mgroup
in view
.mgroups
do
209 if mgroup
== self or not view
.accept_mentity
(mgroup
) then continue
210 if mgroup
.collect_parents
(view
).has
(self) then res
.add mgroup
218 redef fun collect_modifiers
do
224 # Collect all module ancestors of `self` (direct and transitive imports)
225 redef fun collect_ancestors
(view
) do
226 var res
= new HashSet[MENTITY]
227 for mentity
in in_importation
.greaters
do
228 if mentity
== self then continue
229 if not view
.accept_mentity
(mentity
) then continue
235 # Collect all modules directly imported by `self`
236 redef fun collect_parents
(view
) do
237 var res
= new HashSet[MENTITY]
238 for mentity
in in_importation
.direct_greaters
do
239 if mentity
== self then continue
240 if not view
.accept_mentity
(mentity
) then continue
246 # Collect all modules that directly import `self`
247 redef fun collect_children
(view
) do
248 var res
= new HashSet[MENTITY]
249 for mentity
in in_importation
.direct_smallers
do
250 if mentity
== self then continue
251 if not view
.accept_mentity
(mentity
) then continue
257 # Collect all module descendants of `self` (direct and transitive imports)
258 redef fun collect_descendants
(view
) do
259 var res
= new HashSet[MENTITY]
260 for mentity
in in_importation
.smallers
do
261 if mentity
== self then continue
262 if not view
.accept_mentity
(mentity
) then continue
268 # Collect all class definitions introduced in `self`
269 fun collect_intro_mclassdefs
(view
: ModelView): Set[MClassDef] do
270 var res
= new HashSet[MClassDef]
271 for mclassdef
in mclassdefs
do
272 if not mclassdef
.is_intro
then continue
273 if not view
.accept_mentity
(mclassdef
) then continue
279 # Collect all class definitions refined in `self`
280 fun collect_redef_mclassdefs
(view
: ModelView): Set[MClassDef] do
281 var res
= new HashSet[MClassDef]
282 for mclassdef
in mclassdefs
do
283 if mclassdef
.is_intro
then continue
284 if not view
.accept_mentity
(mclassdef
) then continue
290 # Collect all classes introduced in `self`
291 fun collect_intro_mclasses
(view
: ModelView): Set[MClass] do
292 var res
= new HashSet[MClass]
293 for mclass
in intro_mclasses
do
294 if not view
.accept_mentity
(mclass
) then continue
300 # Collect all classes refined in `self`
301 fun collect_redef_mclasses
(view
: ModelView): Set[MClass] do
302 var mclasses
= new HashSet[MClass]
303 for mclassdef
in mclassdefs
do
304 if not view
.accept_mentity
(mclassdef
) then continue
305 if not mclassdef
.is_intro
then mclasses
.add
(mclassdef
.mclass
)
313 redef fun collect_modifiers
do return intro
.collect_modifiers
315 redef fun collect_linearization
(mainmodule
) do
316 var mclassdefs
= self.mclassdefs
.to_a
317 mainmodule
.linearize_mclassdefs
(mclassdefs
)
321 # Collect all direct parents of `self`
323 # This method uses a flattened hierarchy containing all the mclassdefs.
324 redef fun collect_parents
(view
) do
325 var res
= new HashSet[MENTITY]
326 for mclassdef
in mclassdefs
do
327 for parent
in mclassdef
.collect_parents
(view
) do
328 var mclass
= parent
.mclass
329 if mclass
== self or not view
.accept_mentity
(parent
) then continue
336 # Collect all ancestors of `self`
337 redef fun collect_ancestors
(view
) do
338 var res
= new HashSet[MENTITY]
339 for mclassdef
in mclassdefs
do
340 for parent
in mclassdef
.collect_parents
(view
) do
341 if not view
.accept_mentity
(parent
) then continue
342 res
.add parent
.mclass
348 # Collect all direct children of `self`
350 # This method uses a flattened hierarchy containing all the mclassdefs.
351 redef fun collect_children
(view
) do
352 var res
= new HashSet[MENTITY]
353 for mclassdef
in mclassdefs
do
354 for child
in mclassdef
.collect_children
(view
) do
355 var mclass
= child
.mclass
356 if mclass
== self or not view
.accept_mentity
(child
) then continue
363 # Collect all properties introduced in `self`
364 fun collect_intro_mproperties
(view
: ModelView): Set[MProperty] do
365 var set
= new HashSet[MProperty]
366 for mclassdef
in mclassdefs
do
367 for mprop
in mclassdef
.intro_mproperties
do
368 if not view
.accept_mentity
(mprop
) then continue
375 # Collect all properties redefined in `self`
376 fun collect_redef_mproperties
(view
: ModelView): Set[MProperty] do
377 var set
= new HashSet[MProperty]
378 for mclassdef
in mclassdefs
do
379 for mpropdef
in mclassdef
.mpropdefs
do
380 if mpropdef
.mproperty
.intro_mclassdef
.mclass
== self then continue
381 if not view
.accept_mentity
(mpropdef
) then continue
382 set
.add
(mpropdef
.mproperty
)
388 # Collect all properties introduced and redefined in `self`
389 fun collect_local_mproperties
(view
: ModelView): Set[MProperty] do
390 var set
= new HashSet[MProperty]
391 set
.add_all collect_intro_mproperties
(view
)
392 set
.add_all collect_redef_mproperties
(view
)
396 # Collect all properties inehrited by `self`
397 fun collect_inherited_mproperties
(view
: ModelView): Set[MProperty] do
398 var set
= new HashSet[MProperty]
399 for parent
in collect_parents
(view
) do
400 set
.add_all
(parent
.collect_intro_mproperties
(view
))
401 set
.add_all
(parent
.collect_inherited_mproperties
(view
))
406 # Collect all properties accessible by `self`
408 # This include introduced, redefined, inherited properties.
409 fun collect_accessible_mproperties
(view
: ModelView): Set[MProperty] do
410 var set
= new HashSet[MProperty]
411 set
.add_all
(collect_intro_mproperties
(view
))
412 set
.add_all
(collect_redef_mproperties
(view
))
413 set
.add_all
(collect_inherited_mproperties
(view
))
417 # Collect all methods introduced in `self`
418 fun collect_intro_mmethods
(view
: ModelView): Set[MMethod] do
419 var res
= new HashSet[MMethod]
420 for mproperty
in collect_intro_mproperties
(view
) do
421 if mproperty
isa MMethod then res
.add
(mproperty
)
426 # Collect all methods redefined in `self`
427 fun collect_redef_mmethods
(view
: ModelView): Set[MMethod] do
428 var res
= new HashSet[MMethod]
429 for mproperty
in collect_redef_mproperties
(view
) do
430 if mproperty
isa MMethod then res
.add
(mproperty
)
435 # Collect all methods introduced and redefined in `self`
436 fun collect_local_mmethods
(view
: ModelView): Set[MMethod] do
437 var set
= new HashSet[MMethod]
438 set
.add_all collect_intro_mmethods
(view
)
439 set
.add_all collect_redef_mmethods
(view
)
443 # Collect all methods inherited by `self`
444 fun collect_inherited_mmethods
(view
: ModelView): Set[MMethod] do
445 var res
= new HashSet[MMethod]
446 for mproperty
in collect_inherited_mproperties
(view
) do
447 if mproperty
isa MMethod then res
.add
(mproperty
)
452 # Collect all methods accessible by `self`
454 # This include introduced, redefined, inherited methods.
455 fun collect_accessible_mmethods
(view
: ModelView): Set[MMethod] do
456 var set
= new HashSet[MMethod]
457 set
.add_all
(collect_intro_mmethods
(view
))
458 set
.add_all
(collect_redef_mmethods
(view
))
459 set
.add_all
(collect_inherited_mmethods
(view
))
463 # Collect all attributes introduced in `self`
464 fun collect_intro_mattributes
(view
: ModelView): Set[MAttribute] do
465 var res
= new HashSet[MAttribute]
466 for mproperty
in collect_intro_mproperties
(view
) do
467 if mproperty
isa MAttribute then res
.add
(mproperty
)
472 # Collect all attributes redefined in `self`
473 fun collect_redef_mattributes
(view
: ModelView): Set[MAttribute] do
474 var res
= new HashSet[MAttribute]
475 for mproperty
in collect_redef_mproperties
(view
) do
476 if mproperty
isa MAttribute then res
.add
(mproperty
)
481 # Collect all attributes introduced and redefined in `self`
482 fun collect_local_mattributes
(view
: ModelView): Set[MAttribute] do
483 var set
= new HashSet[MAttribute]
484 set
.add_all collect_intro_mattributes
(view
)
485 set
.add_all collect_redef_mattributes
(view
)
489 # Collect all attributes inherited by `self`
490 fun collect_inherited_mattributes
(view
: ModelView): Set[MAttribute] do
491 var res
= new HashSet[MAttribute]
492 for mproperty
in collect_inherited_mproperties
(view
) do
493 if mproperty
isa MAttribute then res
.add
(mproperty
)
498 # Collect all attributes accessible by `self`
500 # This include introduced, redefined, inherited mattributes.
501 fun collect_accessible_mattributes
(view
: ModelView): Set[MAttribute] do
502 var set
= new HashSet[MAttribute]
503 set
.add_all
(collect_intro_mattributes
(view
))
504 set
.add_all
(collect_redef_mattributes
(view
))
505 set
.add_all
(collect_inherited_mattributes
(view
))
509 # Collect all init methods introduced in `self`
510 fun collect_intro_inits
(view
: ModelView): Set[MMethod] do
511 var res
= new HashSet[MMethod]
512 for mproperty
in collect_intro_mmethods
(view
) do
513 if mproperty
.is_init
then res
.add
(mproperty
)
518 # Collect all init methods redefined in `self`
519 fun collect_redef_inits
(view
: ModelView): Set[MMethod] do
520 var res
= new HashSet[MMethod]
521 for mproperty
in collect_redef_mmethods
(view
) do
522 if mproperty
.is_init
then res
.add
(mproperty
)
527 # Collect all init methods introduced and redefined in `self`
528 fun collect_local_inits
(view
: ModelView): Set[MMethod] do
529 var set
= new HashSet[MMethod]
530 set
.add_all collect_intro_inits
(view
)
531 set
.add_all collect_redef_inits
(view
)
535 # Collect all init methods inherited by `self`
536 fun collect_inherited_inits
(view
: ModelView): Set[MMethod] do
537 var res
= new HashSet[MMethod]
538 for mproperty
in collect_inherited_mmethods
(view
) do
539 if mproperty
.is_init
then res
.add
(mproperty
)
544 # Collect all init methods accessible by `self`
546 # This include introduced, redefined, inherited inits.
547 fun collect_accessible_inits
(view
: ModelView): Set[MMethod] do
548 var set
= new HashSet[MMethod]
549 set
.add_all
(collect_intro_inits
(view
))
550 set
.add_all
(collect_redef_inits
(view
))
551 set
.add_all
(collect_inherited_inits
(view
))
555 # Collect all virtual types accessible by `self`
557 # This include introduced, redefined, inherited virtual types.
558 fun collect_accessible_vts
(view
: ModelView): Set[MVirtualTypeProp] do
559 var set
= new HashSet[MVirtualTypeProp]
560 for mproperty
in collect_accessible_mproperties
(view
) do
561 if mproperty
isa MVirtualTypeProp then set
.add mproperty
567 redef class MClassDef
569 redef fun collect_linearization
(mainmodule
) do
570 var mclassdefs
= new Array[MClassDef]
571 for mclassdef
in in_hierarchy
.as(not null).greaters
do
572 if mclassdef
.mclass
== self.mclass
then mclassdefs
.add mclassdef
574 mainmodule
.linearize_mclassdefs
(mclassdefs
)
578 redef fun collect_ancestors
(view
) do
579 var res
= new HashSet[MENTITY]
580 var hierarchy
= self.in_hierarchy
581 if hierarchy
== null then return res
582 for parent
in hierarchy
.greaters
do
583 if parent
== self or not view
.accept_mentity
(parent
) then continue
589 redef fun collect_parents
(view
) do
590 var res
= new HashSet[MENTITY]
591 var hierarchy
= self.in_hierarchy
592 if hierarchy
== null then return res
593 for parent
in hierarchy
.direct_greaters
do
594 if parent
== self or not view
.accept_mentity
(parent
) then continue
600 redef fun collect_children
(view
) do
601 var res
= new HashSet[MENTITY]
602 var hierarchy
= self.in_hierarchy
603 if hierarchy
== null then return res
604 for child
in hierarchy
.direct_smallers
do
605 if child
== self or not view
.accept_mentity
(child
) then continue
611 # Collect all property definitions in `self`
612 fun collect_mpropdefs
(view
: ModelView): Set[MPropDef] do
613 var res
= new HashSet[MPropDef]
614 for mpropdef
in mpropdefs
do
615 if not view
.accept_mentity
(mpropdef
) then continue
621 # Collect all property definitions that are introduction in `self`
622 fun collect_intro_mpropdefs
(view
: ModelView): Set[MPropDef] do
623 var res
= new HashSet[MPropDef]
624 for mpropdef
in mpropdefs
do
625 if not mpropdef
.is_intro
then continue
626 if not view
.accept_mentity
(mpropdef
) then continue
632 # Collect all property definitions that are redefinition in `self`
633 fun collect_redef_mpropdefs
(view
: ModelView): Set[MPropDef] do
634 var res
= new HashSet[MPropDef]
635 for mpropdef
in mpropdefs
do
636 if mpropdef
.is_intro
then continue
637 if not view
.accept_mentity
(mpropdef
) then continue
643 redef fun collect_modifiers
do
648 res
.add mclass
.visibility
.to_s
650 res
.add mclass
.kind
.to_s
655 redef class MProperty
656 redef fun collect_modifiers
do return intro
.collect_modifiers
658 redef fun collect_linearization
(mainmodule
) do
659 var mpropdefs
= self.mpropdefs
.to_a
660 mainmodule
.linearize_mpropdefs
(mpropdefs
)
664 # Collect all property definitions of `self`
665 fun collect_mpropdefs
(view
: ModelView): Set[MPropDef] do
666 var res
= new HashSet[MPropDef]
667 for mpropdef
in mpropdefs
do
668 if not view
.accept_mentity
(mpropdef
) then continue
674 # Collect all direct super definitions of `self`
675 redef fun collect_parents
(view
) do
676 var res
= new HashSet[MENTITY]
677 for mpropdef
in mpropdefs
do
678 for parent
in mpropdef
.collect_parents
(view
) do
679 if not view
.accept_mentity
(parent
) then continue
680 res
.add parent
.mproperty
686 # Collection all definitions that have `self` as a direct super definition
687 redef fun collect_children
(view
) do
688 var res
= new HashSet[MENTITY]
689 for mpropdef
in mpropdefs
do
690 for child
in mpropdef
.collect_parents
(view
) do
691 if not view
.accept_mentity
(child
) then continue
692 res
.add child
.mproperty
701 redef fun collect_modifiers
do
706 res
.add mproperty
.visibility
.to_s
709 if mprop
isa MVirtualTypeDef then
711 else if mprop
isa MMethodDef then
712 if mprop
.is_abstract
then
714 else if mprop
.is_intern
then
717 if mprop
.mproperty
.is_init
then
722 else if mprop
isa MAttributeDef then
728 redef fun collect_linearization
(mainmodule
) do
729 var mpropdefs
= new Array[MPropDef]
731 while not mentity
.is_intro
do
732 mpropdefs
.add mentity
733 mentity
= mentity
.lookup_next_definition
(mainmodule
, mentity
.mclassdef
.bound_mtype
)
735 mpropdefs
.add mentity
736 mainmodule
.linearize_mpropdefs
(mpropdefs
)
740 # Collect only the next definition of `self`
741 redef fun collect_parents
(view
) do
742 var res
= new HashSet[MENTITY]
744 while not mpropdef
.is_intro
do
745 mpropdef
= mpropdef
.lookup_next_definition
(mclassdef
.mmodule
, mclassdef
.bound_mtype
)
751 # Collect all children definitions that directly depend on `self`
752 redef fun collect_children
(view
) do
753 var res
= new HashSet[MENTITY]
754 for mpropdef
in mproperty
.collect_mpropdefs
(view
) do
755 if mpropdef
.collect_parents
(view
).has
(self) then res
.add mpropdef