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 fun in_nesting_intro_mclasses
(min_visibility
: MVisibility): Set[MClass] do
167 var res
= new HashSet[MClass]
168 for mmodule
in in_nesting
.greaters
do
169 for mclass
in mmodule
.filter_intro_mclasses
(min_visibility
) do
170 if mclass
.visibility
< min_visibility
then continue
177 fun in_nesting_redef_mclasses
(min_visibility
: MVisibility): Set[MClass] do
178 var res
= new HashSet[MClass]
179 for mmodule
in self.in_nesting
.greaters
do
180 for mclass
in mmodule
.filter_redef_mclasses
(min_visibility
) do
181 if mclass
.visibility
< min_visibility
then continue
188 fun in_nesting_intro_mclassdefs
(min_visibility
: MVisibility): Set[MClassDef] do
189 var res
= new HashSet[MClassDef]
190 for mmodule
in in_nesting
.greaters
do
191 res
.add_all mmodule
.intro_mclassdefs
(min_visibility
)
196 fun in_nesting_redef_mclassdefs
(min_visibility
: MVisibility): Set[MClassDef] do
197 var res
= new HashSet[MClassDef]
198 for mmodule
in self.in_nesting
.greaters
do
199 res
.add_all mmodule
.redef_mclassdefs
(min_visibility
)
204 redef fun concern_rank
is cached
do
206 for p
in in_importation
.direct_greaters
do
207 var pmax
= p
.concern_rank
208 if pmax
> max
then max
= pmax
216 # Get direct parents of 'self'.
217 fun parents
: Set[MClass] do
218 var ret
= new HashSet[MClass]
219 for mclassdef
in mclassdefs
do
220 for mclasstype
in mclassdef
.supertypes
do
221 ret
.add
(mclasstype
.mclass
)
227 # Get all ancestors of 'self'.
228 fun ancestors
: Set[MClass] do
229 var lst
= new HashSet[MClass]
230 for mclassdef
in self.mclassdefs
do
231 for super_mclassdef
in mclassdef
.in_hierarchy
.greaters
do
232 if super_mclassdef
== mclassdef
then continue # skip self
233 lst
.add
(super_mclassdef
.mclass
)
239 # Get direct children of 'self'.
240 fun children
: Set[MClass] do
241 var lst
= new HashSet[MClass]
242 for mclassdef
in self.mclassdefs
do
243 for sub_mclassdef
in mclassdef
.in_hierarchy
.direct_smallers
do
244 if sub_mclassdef
== mclassdef
then continue # skip self
245 lst
.add
(sub_mclassdef
.mclass
)
251 # Get all children of 'self'.
252 fun descendants
: Set[MClass] do
253 var lst
= new HashSet[MClass]
254 for mclassdef
in self.mclassdefs
do
255 for sub_mclassdef
in mclassdef
.in_hierarchy
.smallers
do
256 if sub_mclassdef
== mclassdef
then continue # skip self
257 lst
.add
(sub_mclassdef
.mclass
)
263 # Get the list of constructors available for 'self'.
264 fun constructors
: Set[MMethod] do
265 var res
= new HashSet[MMethod]
266 for mclassdef
in mclassdefs
do
267 for mpropdef
in mclassdef
.mpropdefs
do
268 if mpropdef
isa MMethodDef then
269 if mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
276 # Get the list of methods introduced in 'self'.
277 fun intro_methods
: Set[MMethod] do
278 var res
= new HashSet[MMethod]
279 for mclassdef
in mclassdefs
do
280 for mpropdef
in mclassdef
.mpropdefs
do
281 if mpropdef
isa MMethodDef then
282 if mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
289 # the set of properties introduced in 'self'.
290 fun intro_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
291 var set
= new HashSet[MProperty]
292 for mclassdef
in mclassdefs
do
293 for mprop
in mclassdef
.intro_mproperties
do
294 if mprop
.visibility
< min_visibility
then continue
301 fun intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
302 var set
= new HashSet[MPropDef]
303 for mclassdef
in mclassdefs
do
304 for mpropdef
in mclassdef
.mpropdefs
do
305 if not mpropdef
.is_intro
then continue
306 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
313 # the set of locally refined properties in 'self'.
314 fun redef_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
315 var set
= new HashSet[MProperty]
316 for mclassdef
in mclassdefs
do
317 for mpropdef
in mclassdef
.mpropdefs
do
318 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
319 if mpropdef
.mproperty
.intro_mclassdef
.mclass
!= self then set
.add
(mpropdef
.mproperty
)
325 fun redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
326 var set
= new HashSet[MPropDef]
327 for mclassdef
in mclassdefs
do
328 for mpropdef
in mclassdef
.mpropdefs
do
329 if mpropdef
.is_intro
then continue
330 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
337 # the set of methods inherited by 'self'.
338 fun inherited_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
339 var set
= new HashSet[MProperty]
340 for parent
in in_hierarchy
(mainmodule
).direct_greaters
do
341 set
.add_all
(parent
.intro_mproperties
(min_visibility
))
342 set
.add_all
(parent
.inherited_mproperties
(mainmodule
, min_visibility
))
347 # the set of introduced and redefined mproperties
348 fun local_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
349 var set
= new HashSet[MProperty]
350 set
.add_all
(intro_mproperties
(min_visibility
))
351 set
.add_all
(redef_mproperties
(min_visibility
))
355 # the set of all accessible mproperties for this class
356 fun all_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
357 var set
= new HashSet[MProperty]
358 set
.add_all
(local_mproperties
(min_visibility
))
359 set
.add_all
(inherited_mproperties
(mainmodule
, min_visibility
))
363 # the set of all accessible mattributes for this class
364 fun all_mattributes
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MAttribute] do
365 var set
= new HashSet[MAttribute]
366 for mprop
in all_mproperties
(mainmodule
, min_visibility
) do
367 if mprop
isa MAttribute then set
.add
(mprop
)
372 # Get the list of locally refined methods in 'self'.
373 fun redef_methods
: Set[MMethod] do
374 var res
= new HashSet[MMethod]
375 for mclassdef
in mclassdefs
do
376 for mpropdef
in mclassdef
.mpropdefs
do
377 if mpropdef
isa MMethodDef then
378 if not mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
385 fun inherited_methods
: Set[MMethod] do
386 var res
= new HashSet[MMethod]
387 for s
in ancestors
do
388 for m
in s
.intro_methods
do
389 if not self.intro_methods
.has
(m
) and not self.redef_methods
.has
(m
) then res
.add
(m
)
395 # Get the list of all virtual types available in 'self'.
396 fun virtual_types
: Set[MVirtualTypeProp] do
397 var res
= new HashSet[MVirtualTypeProp]
398 for mclassdef
in mclassdefs
do
399 for mpropdef
in mclassdef
.mpropdefs
do
400 if mpropdef
isa MVirtualTypeDef then
401 res
.add
(mpropdef
.mproperty
)
405 for ancestor
in ancestors
do
406 for mclassdef
in ancestor
.mclassdefs
do
407 for mpropdef
in mclassdef
.mpropdefs
do
408 if mpropdef
isa MVirtualTypeDef then
409 res
.add
(mpropdef
.mproperty
)
417 # Get the list of all parameter types in 'self'.
418 fun parameter_types
: Map[String, MType] do
419 var res
= new HashMap[String, MType]
420 for p
in mparameters
do
426 fun is_class
: Bool do
427 return self.kind
== concrete_kind
or self.kind
== abstract_kind
430 fun is_interface
: Bool do
431 return self.kind
== interface_kind
435 return self.kind
== enum_kind
438 fun is_abstract
: Bool do
439 return self.kind
== abstract_kind
443 redef class MAttribute
444 # Is this attribute nullable for sure?
446 # This mean that its introduction is declarred with a nullable static type
447 # since attributes are invariant this will work on most cases
448 # attributes with static type anchored with a virtual type are not "nullable for-sure"
449 # because this type can be redefined in subclasses
450 fun is_nullable
: Bool do return intro
.static_mtype
isa MNullableType
453 redef class MClassDef
454 # modifiers are keywords like redef, private etc.
455 fun modifiers
: Array[String] do
456 var res
= new Array[String]
460 res
.add mclass
.visibility
.to_s
462 res
.add mclass
.kind
.to_s
466 fun collect_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
467 var res
= new HashSet[MPropDef]
468 for mpropdef
in mpropdefs
do
469 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
475 fun collect_intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
476 var res
= new HashSet[MPropDef]
477 for mpropdef
in mpropdefs
do
478 if not mpropdef
.is_intro
then continue
479 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
485 fun collect_redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
486 var res
= new HashSet[MPropDef]
487 for mpropdef
in mpropdefs
do
488 if mpropdef
.is_intro
then continue
489 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
497 # modifiers are keywords like redef, private etc.
498 fun modifiers
: Array[String] do
499 var res
= new Array[String]
503 res
.add mproperty
.visibility
.to_s
506 if mprop
isa MVirtualTypeDef then
508 else if mprop
isa MMethodDef then
509 if mprop
.is_abstract
then
511 else if mprop
.is_intern
then
514 if mprop
.mproperty
.is_init
then
526 # Sort mentities by their name
527 class MEntityNameSorter
529 redef type COMPARED: MEntity
530 redef fun compare
(a
, b
) do return a
.name
<=> b
.name
533 # Sort MConcerns based on the module importation hierarchy ranking
534 # see also: `MConcern::concern_rank` and `MConcern::booster_rank`
536 # Comparison is made with the formula:
538 # a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
540 # If both `a` and `b` have the same ranking,
541 # ordering is based on lexicographic comparison of `a.name` and `b.name`
542 class MConcernRankSorter
544 redef type COMPARED: MConcern
546 redef fun compare
(a
, b
) do
547 if a
.concern_rank
== b
.concern_rank
then
548 return a
.name
<=> b
.name
550 return a
.concern_rank
+ a
.booster_rank
<=> b
.concern_rank
+ b
.booster_rank