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 # Model exploration and traversing facilities
24 # Boost a MConcern rank
25 # see: `MConcernRankSorter`
26 # Use a positive booster to push down a result in the list
27 # A negative booster can be used to push up the result
28 var booster_rank
: Int = 0 is writable
30 # Concern ranking used for ordering
31 # see: `MConcernRankSorter`
32 # Rank can be positive or negative
33 fun concern_rank
: Int is abstract
37 redef fun concern_rank
is cached
do
39 for mgroup
in mgroups
do
40 var mmax
= mgroup
.concern_rank
41 if mmax
> max
then max
= mmax
48 fun in_nesting_intro_mclasses
(min_visibility
: MVisibility): Set[MClass] do
49 var res
= new HashSet[MClass]
50 var lst
= in_nesting
.direct_smallers
51 for mmodule
in mmodules
do res
.add_all mmodule
.filter_intro_mclasses
(min_visibility
)
52 for mgrp
in lst
do res
.add_all mgrp
.in_nesting_intro_mclasses
(min_visibility
)
56 fun in_nesting_redef_mclasses
(min_visibility
: MVisibility): Set[MClass] do
57 var res
= new HashSet[MClass]
58 var lst
= in_nesting
.direct_smallers
59 for mmodule
in mmodules
do res
.add_all mmodule
.filter_redef_mclasses
(min_visibility
)
60 for mgrp
in lst
do res
.add_all mgrp
.in_nesting_redef_mclasses
(min_visibility
)
64 fun in_nesting_intro_mclassdefs
(min_visibility
: MVisibility): Set[MClassDef] do
65 var res
= new HashSet[MClassDef]
66 var lst
= in_nesting
.direct_smallers
67 for mmodule
in mmodules
do res
.add_all mmodule
.intro_mclassdefs
(min_visibility
)
68 for mgrp
in lst
do res
.add_all mgrp
.in_nesting_intro_mclassdefs
(min_visibility
)
72 fun in_nesting_redef_mclassdefs
(min_visibility
: MVisibility): Set[MClassDef] do
73 var res
= new HashSet[MClassDef]
74 var lst
= in_nesting
.direct_smallers
75 for mmodule
in mmodules
do res
.add_all mmodule
.redef_mclassdefs
(min_visibility
)
76 for mgrp
in lst
do res
.add_all mgrp
.in_nesting_redef_mclassdefs
(min_visibility
)
80 # Collect nested modules
81 fun collect_mmodules
: Set[MModule] do
82 var res
= new HashSet[MModule]
84 for mgroup
in in_nesting
.direct_smallers
do
85 res
.add_all mgroup
.collect_mmodules
90 redef fun concern_rank
is cached
do
92 for mmodule
in collect_mmodules
do
93 var mmax
= mmodule
.concern_rank
94 if mmax
> max
then max
= mmax
102 # The list of intro mclassdef in the module.
103 # with visibility >= to min_visibility
104 fun intro_mclassdefs
(min_visibility
: MVisibility): Set[MClassDef] do
105 var res
= new HashSet[MClassDef]
106 for mclassdef
in mclassdefs
do
107 if not mclassdef
.is_intro
then continue
108 if mclassdef
.mclass
.visibility
< min_visibility
then continue
114 # The list of redef mclassdef in the module.
115 # with visibility >= to min_visibility
116 fun redef_mclassdefs
(min_visibility
: MVisibility): Set[MClassDef] do
117 var res
= new HashSet[MClassDef]
118 for mclassdef
in mclassdefs
do
119 if mclassdef
.is_intro
then continue
120 if mclassdef
.mclass
.visibility
< min_visibility
then continue
126 # The list of intro mclass in the module.
127 # with visibility >= to min_visibility
128 fun filter_intro_mclasses
(min_visibility
: MVisibility): Set[MClass] do
129 var res
= new HashSet[MClass]
130 for mclass
in intro_mclasses
do
131 if mclass
.visibility
< min_visibility
then continue
137 # Get the list of mclasses refined in 'self'.
138 fun redef_mclasses
: Set[MClass] do
139 var mclasses
= new HashSet[MClass]
140 for c
in mclassdefs
do
141 if not c
.is_intro
then mclasses
.add
(c
.mclass
)
146 # Get the list of mclasses refined in 'self'.
147 fun filter_redef_mclasses
(min_visibility
: MVisibility): Set[MClass] do
148 var mclasses
= new HashSet[MClass]
149 for c
in mclassdefs
do
150 if c
.mclass
.visibility
< min_visibility
then continue
151 if not c
.is_intro
then mclasses
.add
(c
.mclass
)
156 # Get the list of all mclasses imported by 'self'.
157 fun imported_mclasses
: Set[MClass] do
158 var mclasses
= new HashSet[MClass]
159 for m
in in_importation
.greaters
do
160 if m
== self then continue
161 for c
in m
.mclassdefs
do mclasses
.add
(c
.mclass
)
166 redef fun concern_rank
is cached
do
168 for p
in in_importation
.direct_greaters
do
169 var pmax
= p
.concern_rank
170 if pmax
> max
then max
= pmax
175 # Find all mmodules nested in `self` if `self` is the default module of a `MGroup`.
176 fun nested_mmodules
: Array[MModule] do
177 var res
= new Array[MModule]
179 if mgroup
== null or self != mgroup
.default_mmodule
then return res
180 for mmodule
in mgroup
.mmodules
do
181 if mmodule
== self then continue
184 for nested
in mgroup
.in_nesting
.direct_smallers
do
185 var default
= nested
.default_mmodule
186 if default
== null then continue
195 # Get direct parents of 'self'.
196 fun parents
: Set[MClass] do
197 var ret
= new HashSet[MClass]
198 for mclassdef
in mclassdefs
do
199 for mclasstype
in mclassdef
.supertypes
do
200 ret
.add
(mclasstype
.mclass
)
206 # Get all ancestors of 'self'.
207 fun ancestors
: Set[MClass] do
208 var lst
= new HashSet[MClass]
209 for mclassdef
in self.mclassdefs
do
210 for super_mclassdef
in mclassdef
.in_hierarchy
.greaters
do
211 if super_mclassdef
== mclassdef
then continue # skip self
212 lst
.add
(super_mclassdef
.mclass
)
218 # Get direct children of 'self'.
219 fun children
: Set[MClass] do
220 var lst
= new HashSet[MClass]
221 for mclassdef
in self.mclassdefs
do
222 for sub_mclassdef
in mclassdef
.in_hierarchy
.direct_smallers
do
223 if sub_mclassdef
== mclassdef
then continue # skip self
224 lst
.add
(sub_mclassdef
.mclass
)
230 # Get all children of 'self'.
231 fun descendants
: Set[MClass] do
232 var lst
= new HashSet[MClass]
233 for mclassdef
in self.mclassdefs
do
234 for sub_mclassdef
in mclassdef
.in_hierarchy
.smallers
do
235 if sub_mclassdef
== mclassdef
then continue # skip self
236 lst
.add
(sub_mclassdef
.mclass
)
242 # Get the list of constructors available for 'self'.
243 fun constructors
: Set[MMethod] do
244 var res
= new HashSet[MMethod]
245 for mclassdef
in mclassdefs
do
246 for mpropdef
in mclassdef
.mpropdefs
do
247 if mpropdef
isa MMethodDef then
248 if mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
255 # Get the list of methods introduced in 'self'.
256 fun intro_methods
: Set[MMethod] do
257 var res
= new HashSet[MMethod]
258 for mclassdef
in mclassdefs
do
259 for mpropdef
in mclassdef
.mpropdefs
do
260 if mpropdef
isa MMethodDef then
261 if mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
268 # the set of properties introduced in 'self'.
269 fun intro_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
270 var set
= new HashSet[MProperty]
271 for mclassdef
in mclassdefs
do
272 for mprop
in mclassdef
.intro_mproperties
do
273 if mprop
.visibility
< min_visibility
then continue
280 fun intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
281 var set
= new HashSet[MPropDef]
282 for mclassdef
in mclassdefs
do
283 for mpropdef
in mclassdef
.mpropdefs
do
284 if not mpropdef
.is_intro
then continue
285 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
292 # the set of locally refined properties in 'self'.
293 fun redef_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
294 var set
= new HashSet[MProperty]
295 for mclassdef
in mclassdefs
do
296 for mpropdef
in mclassdef
.mpropdefs
do
297 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
298 if mpropdef
.mproperty
.intro_mclassdef
.mclass
!= self then set
.add
(mpropdef
.mproperty
)
304 fun redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
305 var set
= new HashSet[MPropDef]
306 for mclassdef
in mclassdefs
do
307 for mpropdef
in mclassdef
.mpropdefs
do
308 if mpropdef
.is_intro
then continue
309 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
316 # the set of methods inherited by 'self'.
317 fun inherited_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
318 var set
= new HashSet[MProperty]
319 for parent
in in_hierarchy
(mainmodule
).direct_greaters
do
320 set
.add_all
(parent
.intro_mproperties
(min_visibility
))
321 set
.add_all
(parent
.inherited_mproperties
(mainmodule
, min_visibility
))
326 # the set of introduced and redefined mproperties
327 fun local_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
328 var set
= new HashSet[MProperty]
329 set
.add_all
(intro_mproperties
(min_visibility
))
330 set
.add_all
(redef_mproperties
(min_visibility
))
334 # the set of all accessible mproperties for this class
335 fun all_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
336 var set
= new HashSet[MProperty]
337 set
.add_all
(local_mproperties
(min_visibility
))
338 set
.add_all
(inherited_mproperties
(mainmodule
, min_visibility
))
342 # the set of all accessible mattributes for this class
343 fun all_mattributes
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MAttribute] do
344 var set
= new HashSet[MAttribute]
345 for mprop
in all_mproperties
(mainmodule
, min_visibility
) do
346 if mprop
isa MAttribute then set
.add
(mprop
)
351 # Get the list of locally refined methods in 'self'.
352 fun redef_methods
: Set[MMethod] do
353 var res
= new HashSet[MMethod]
354 for mclassdef
in mclassdefs
do
355 for mpropdef
in mclassdef
.mpropdefs
do
356 if mpropdef
isa MMethodDef then
357 if not mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
364 fun inherited_methods
: Set[MMethod] do
365 var res
= new HashSet[MMethod]
366 for s
in ancestors
do
367 for m
in s
.intro_methods
do
368 if not self.intro_methods
.has
(m
) and not self.redef_methods
.has
(m
) then res
.add
(m
)
374 # Get the list of all virtual types available in 'self'.
375 fun virtual_types
: Set[MVirtualTypeProp] do
376 var res
= new HashSet[MVirtualTypeProp]
377 for mclassdef
in mclassdefs
do
378 for mpropdef
in mclassdef
.mpropdefs
do
379 if mpropdef
isa MVirtualTypeDef then
380 res
.add
(mpropdef
.mproperty
)
384 for ancestor
in ancestors
do
385 for mclassdef
in ancestor
.mclassdefs
do
386 for mpropdef
in mclassdef
.mpropdefs
do
387 if mpropdef
isa MVirtualTypeDef then
388 res
.add
(mpropdef
.mproperty
)
396 # Get the list of all parameter types in 'self'.
397 fun parameter_types
: Map[String, MType] do
398 var res
= new HashMap[String, MType]
399 for p
in mparameters
do
405 fun is_class
: Bool do
406 return self.kind
== concrete_kind
or self.kind
== abstract_kind
409 fun is_interface
: Bool do
410 return self.kind
== interface_kind
414 return self.kind
== enum_kind
417 fun is_abstract
: Bool do
418 return self.kind
== abstract_kind
422 redef class MAttribute
423 # Is this attribute nullable for sure?
425 # This mean that its introduction is declarred with a nullable static type
426 # since attributes are invariant this will work on most cases
427 # attributes with static type anchored with a virtual type are not "nullable for-sure"
428 # because this type can be redefined in subclasses
429 fun is_nullable
: Bool do return intro
.static_mtype
isa MNullableType
432 redef class MClassDef
433 # modifiers are keywords like redef, private etc.
434 fun modifiers
: Array[String] do
435 var res
= new Array[String]
439 res
.add mclass
.visibility
.to_s
441 res
.add mclass
.kind
.to_s
445 fun collect_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
446 var res
= new HashSet[MPropDef]
447 for mpropdef
in mpropdefs
do
448 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
454 fun collect_intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
455 var res
= new HashSet[MPropDef]
456 for mpropdef
in mpropdefs
do
457 if not mpropdef
.is_intro
then continue
458 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
464 fun collect_redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
465 var res
= new HashSet[MPropDef]
466 for mpropdef
in mpropdefs
do
467 if mpropdef
.is_intro
then continue
468 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
476 # modifiers are keywords like redef, private etc.
477 fun modifiers
: Array[String] do
478 var res
= new Array[String]
482 res
.add mproperty
.visibility
.to_s
485 if mprop
isa MVirtualTypeDef then
487 else if mprop
isa MMethodDef then
488 if mprop
.is_abstract
then
490 else if mprop
.is_intern
then
493 if mprop
.mproperty
.is_init
then
505 # Sort mentities by their name
506 class MEntityNameSorter
508 redef type COMPARED: MEntity
509 redef fun compare
(a
, b
) do return a
.name
<=> b
.name
512 # Sort MConcerns based on the module importation hierarchy ranking
513 # see also: `MConcern::concern_rank` and `MConcern::booster_rank`
515 # Comparison is made with the formula:
518 # a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
521 # If both `a` and `b` have the same ranking,
522 # ordering is based on lexicographic comparison of `a.name` and `b.name`
523 class MConcernRankSorter
525 redef type COMPARED: MConcern
527 redef fun compare
(a
, b
) do
528 if a
.concern_rank
== b
.concern_rank
then
529 return a
.name
<=> b
.name
531 return a
.concern_rank
+ a
.booster_rank
<=> b
.concern_rank
+ b
.booster_rank