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 writable = 0
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
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
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
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 the public owner of 'self'.
217 fun public_owner
: MModule do
218 var public_owner
= self.intro_mmodule
.public_owner
219 if public_owner
== null then
220 return self.intro_mmodule
226 # Get direct parents of 'self'.
227 fun parents
: Set[MClass] do
228 var ret
= new HashSet[MClass]
229 for mclassdef
in mclassdefs
do
230 for mclasstype
in mclassdef
.supertypes
do
231 ret
.add
(mclasstype
.mclass
)
237 # Get all ancestors of 'self'.
238 fun ancestors
: Set[MClass] do
239 var lst
= new HashSet[MClass]
240 for mclassdef
in self.mclassdefs
do
241 for super_mclassdef
in mclassdef
.in_hierarchy
.greaters
do
242 if super_mclassdef
== mclassdef
then continue # skip self
243 lst
.add
(super_mclassdef
.mclass
)
249 # Get direct children of 'self'.
250 fun children
: Set[MClass] do
251 var lst
= new HashSet[MClass]
252 for mclassdef
in self.mclassdefs
do
253 for sub_mclassdef
in mclassdef
.in_hierarchy
.direct_smallers
do
254 if sub_mclassdef
== mclassdef
then continue # skip self
255 lst
.add
(sub_mclassdef
.mclass
)
261 # Get all children of 'self'.
262 fun descendants
: Set[MClass] do
263 var lst
= new HashSet[MClass]
264 for mclassdef
in self.mclassdefs
do
265 for sub_mclassdef
in mclassdef
.in_hierarchy
.smallers
do
266 if sub_mclassdef
== mclassdef
then continue # skip self
267 lst
.add
(sub_mclassdef
.mclass
)
273 # Get the list of constructors available for 'self'.
274 fun constructors
: Set[MMethod] do
275 var res
= new HashSet[MMethod]
276 for mclassdef
in mclassdefs
do
277 for mpropdef
in mclassdef
.mpropdefs
do
278 if mpropdef
isa MMethodDef then
279 if mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
286 # Get the list of methods introduced in 'self'.
287 fun intro_methods
: Set[MMethod] do
288 var res
= new HashSet[MMethod]
289 for mclassdef
in mclassdefs
do
290 for mpropdef
in mclassdef
.mpropdefs
do
291 if mpropdef
isa MMethodDef then
292 if mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
299 # the set of properties introduced in 'self'.
300 fun intro_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
301 var set
= new HashSet[MProperty]
302 for mclassdef
in mclassdefs
do
303 for mprop
in mclassdef
.intro_mproperties
do
304 if mprop
.visibility
< min_visibility
then continue
311 fun intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
312 var set
= new HashSet[MPropDef]
313 for mclassdef
in mclassdefs
do
314 for mpropdef
in mclassdef
.mpropdefs
do
315 if not mpropdef
.is_intro
then continue
316 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
323 # the set of locally refined properties in 'self'.
324 fun redef_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
325 var set
= new HashSet[MProperty]
326 for mclassdef
in mclassdefs
do
327 for mpropdef
in mclassdef
.mpropdefs
do
328 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
329 if mpropdef
.mproperty
.intro_mclassdef
.mclass
!= self then set
.add
(mpropdef
.mproperty
)
335 fun redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
336 var set
= new HashSet[MPropDef]
337 for mclassdef
in mclassdefs
do
338 for mpropdef
in mclassdef
.mpropdefs
do
339 if mpropdef
.is_intro
then continue
340 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
347 # the set of methods inherited by 'self'.
348 fun inherited_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
349 var set
= new HashSet[MProperty]
350 for parent
in in_hierarchy
(mainmodule
).direct_greaters
do
351 set
.add_all
(parent
.intro_mproperties
(min_visibility
))
352 set
.add_all
(parent
.inherited_mproperties
(mainmodule
, min_visibility
))
357 # the set of introduced and redefined mproperties
358 fun local_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
359 var set
= new HashSet[MProperty]
360 set
.add_all
(intro_mproperties
(min_visibility
))
361 set
.add_all
(redef_mproperties
(min_visibility
))
365 # the set of all accessible mproperties for this class
366 fun all_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
367 var set
= new HashSet[MProperty]
368 set
.add_all
(local_mproperties
(min_visibility
))
369 set
.add_all
(inherited_mproperties
(mainmodule
, min_visibility
))
373 # the set of all accessible mattributes for this class
374 fun all_mattributes
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MAttribute] do
375 var set
= new HashSet[MAttribute]
376 for mprop
in all_mproperties
(mainmodule
, min_visibility
) do
377 if mprop
isa MAttribute then set
.add
(mprop
)
382 # Get the list of locally refined methods in 'self'.
383 fun redef_methods
: Set[MMethod] do
384 var res
= new HashSet[MMethod]
385 for mclassdef
in mclassdefs
do
386 for mpropdef
in mclassdef
.mpropdefs
do
387 if mpropdef
isa MMethodDef then
388 if not mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
395 fun inherited_methods
: Set[MMethod] do
396 var res
= new HashSet[MMethod]
397 for s
in ancestors
do
398 for m
in s
.intro_methods
do
399 if not self.intro_methods
.has
(m
) and not self.redef_methods
.has
(m
) then res
.add
(m
)
405 # Get the list of all virtual types available in 'self'.
406 fun virtual_types
: Set[MVirtualTypeProp] do
407 var res
= new HashSet[MVirtualTypeProp]
408 for mclassdef
in mclassdefs
do
409 for mpropdef
in mclassdef
.mpropdefs
do
410 if mpropdef
isa MVirtualTypeDef then
411 res
.add
(mpropdef
.mproperty
)
415 for ancestor
in ancestors
do
416 for mclassdef
in ancestor
.mclassdefs
do
417 for mpropdef
in mclassdef
.mpropdefs
do
418 if mpropdef
isa MVirtualTypeDef then
419 res
.add
(mpropdef
.mproperty
)
427 # Get the list of all parameter types in 'self'.
428 fun parameter_types
: Map[String, MType] do
429 var res
= new HashMap[String, MType]
430 for i
in [0..intro
.parameter_names
.length
[ do
431 res
[intro
.parameter_names
[i
]] = intro
.bound_mtype
.arguments
[i
]
436 fun is_class
: Bool do
437 return self.kind
== concrete_kind
or self.kind
== abstract_kind
440 fun is_interface
: Bool do
441 return self.kind
== interface_kind
445 return self.kind
== enum_kind
448 fun is_abstract
: Bool do
449 return self.kind
== abstract_kind
453 redef class MAttribute
454 # Is this attribute nullable for sure?
456 # This mean that its introduction is declarred with a nullable static type
457 # since attributes are invariant this will work on most cases
458 # attributes with static type anchored with a virtual type are not "nullable for-sure"
459 # because this type can be redefined in subclasses
460 fun is_nullable
: Bool do return intro
.static_mtype
isa MNullableType
463 redef class MClassDef
464 # modifiers are keywords like redef, private etc.
465 fun modifiers
: Array[String] do
466 var res
= new Array[String]
470 res
.add mclass
.visibility
.to_s
472 res
.add mclass
.kind
.to_s
476 fun collect_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
477 var res
= new HashSet[MPropDef]
478 for mpropdef
in mpropdefs
do
479 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
485 fun collect_intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
486 var res
= new HashSet[MPropDef]
487 for mpropdef
in mpropdefs
do
488 if not mpropdef
.is_intro
then continue
489 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
495 fun collect_redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
496 var res
= new HashSet[MPropDef]
497 for mpropdef
in mpropdefs
do
498 if mpropdef
.is_intro
then continue
499 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
507 # modifiers are keywords like redef, private etc.
508 fun modifiers
: Array[String] do
509 var res
= new Array[String]
513 res
.add mproperty
.visibility
.to_s
516 if mprop
isa MVirtualTypeDef then
518 else if mprop
isa MMethodDef then
519 if mprop
.is_abstract
then
521 else if mprop
.is_intern
then
524 if mprop
.mproperty
.is_init
then
536 # Sort mentities by their name
537 class MEntityNameSorter
538 super AbstractSorter[MEntity]
539 redef fun compare
(a
, b
) do return a
.name
<=> b
.name
543 # Sort MConcerns based on the module importation hierarchy ranking
544 # see also: `MConcern::concern_rank` and `MConcern::booster_rank`
546 # Comparison is made with the formula:
548 # a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
550 # If both `a` and `b` have the same ranking,
551 # ordering is based on lexicographic comparison of `a.name` and `b.name`
552 class MConcernRankSorter
553 super AbstractSorter[MConcern]
557 redef fun compare
(a
, b
) do
558 if a
.concern_rank
== b
.concern_rank
then
559 return a
.name
<=> b
.name
561 return a
.concern_rank
+ a
.booster_rank
<=> b
.concern_rank
+ b
.booster_rank