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
213 # Find all mmodules nested in `self` if `self` is the default module of a `MGroup`.
214 fun nested_mmodules
: Array[MModule] do
215 var res
= new Array[MModule]
217 if mgroup
== null or self != mgroup
.default_mmodule
then return res
218 for mmodule
in mgroup
.mmodules
do
219 if mmodule
== self then continue
222 for nested
in mgroup
.in_nesting
.direct_smallers
do
223 var default
= nested
.default_mmodule
224 if default
== null then continue
233 # Get direct parents of 'self'.
234 fun parents
: Set[MClass] do
235 var ret
= new HashSet[MClass]
236 for mclassdef
in mclassdefs
do
237 for mclasstype
in mclassdef
.supertypes
do
238 ret
.add
(mclasstype
.mclass
)
244 # Get all ancestors of 'self'.
245 fun ancestors
: Set[MClass] do
246 var lst
= new HashSet[MClass]
247 for mclassdef
in self.mclassdefs
do
248 for super_mclassdef
in mclassdef
.in_hierarchy
.greaters
do
249 if super_mclassdef
== mclassdef
then continue # skip self
250 lst
.add
(super_mclassdef
.mclass
)
256 # Get direct children of 'self'.
257 fun children
: Set[MClass] do
258 var lst
= new HashSet[MClass]
259 for mclassdef
in self.mclassdefs
do
260 for sub_mclassdef
in mclassdef
.in_hierarchy
.direct_smallers
do
261 if sub_mclassdef
== mclassdef
then continue # skip self
262 lst
.add
(sub_mclassdef
.mclass
)
268 # Get all children of 'self'.
269 fun descendants
: Set[MClass] do
270 var lst
= new HashSet[MClass]
271 for mclassdef
in self.mclassdefs
do
272 for sub_mclassdef
in mclassdef
.in_hierarchy
.smallers
do
273 if sub_mclassdef
== mclassdef
then continue # skip self
274 lst
.add
(sub_mclassdef
.mclass
)
280 # Get the list of constructors available for 'self'.
281 fun constructors
: Set[MMethod] do
282 var res
= new HashSet[MMethod]
283 for mclassdef
in mclassdefs
do
284 for mpropdef
in mclassdef
.mpropdefs
do
285 if mpropdef
isa MMethodDef then
286 if mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
293 # Get the list of methods introduced in 'self'.
294 fun intro_methods
: Set[MMethod] do
295 var res
= new HashSet[MMethod]
296 for mclassdef
in mclassdefs
do
297 for mpropdef
in mclassdef
.mpropdefs
do
298 if mpropdef
isa MMethodDef then
299 if mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
306 # the set of properties introduced in 'self'.
307 fun intro_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
308 var set
= new HashSet[MProperty]
309 for mclassdef
in mclassdefs
do
310 for mprop
in mclassdef
.intro_mproperties
do
311 if mprop
.visibility
< min_visibility
then continue
318 fun intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
319 var set
= new HashSet[MPropDef]
320 for mclassdef
in mclassdefs
do
321 for mpropdef
in mclassdef
.mpropdefs
do
322 if not mpropdef
.is_intro
then continue
323 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
330 # the set of locally refined properties in 'self'.
331 fun redef_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
332 var set
= new HashSet[MProperty]
333 for mclassdef
in mclassdefs
do
334 for mpropdef
in mclassdef
.mpropdefs
do
335 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
336 if mpropdef
.mproperty
.intro_mclassdef
.mclass
!= self then set
.add
(mpropdef
.mproperty
)
342 fun redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
343 var set
= new HashSet[MPropDef]
344 for mclassdef
in mclassdefs
do
345 for mpropdef
in mclassdef
.mpropdefs
do
346 if mpropdef
.is_intro
then continue
347 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
354 # the set of methods inherited by 'self'.
355 fun inherited_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
356 var set
= new HashSet[MProperty]
357 for parent
in in_hierarchy
(mainmodule
).direct_greaters
do
358 set
.add_all
(parent
.intro_mproperties
(min_visibility
))
359 set
.add_all
(parent
.inherited_mproperties
(mainmodule
, min_visibility
))
364 # the set of introduced and redefined mproperties
365 fun local_mproperties
(min_visibility
: MVisibility): Set[MProperty] do
366 var set
= new HashSet[MProperty]
367 set
.add_all
(intro_mproperties
(min_visibility
))
368 set
.add_all
(redef_mproperties
(min_visibility
))
372 # the set of all accessible mproperties for this class
373 fun all_mproperties
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MProperty] do
374 var set
= new HashSet[MProperty]
375 set
.add_all
(local_mproperties
(min_visibility
))
376 set
.add_all
(inherited_mproperties
(mainmodule
, min_visibility
))
380 # the set of all accessible mattributes for this class
381 fun all_mattributes
(mainmodule
: MModule, min_visibility
: MVisibility): Set[MAttribute] do
382 var set
= new HashSet[MAttribute]
383 for mprop
in all_mproperties
(mainmodule
, min_visibility
) do
384 if mprop
isa MAttribute then set
.add
(mprop
)
389 # Get the list of locally refined methods in 'self'.
390 fun redef_methods
: Set[MMethod] do
391 var res
= new HashSet[MMethod]
392 for mclassdef
in mclassdefs
do
393 for mpropdef
in mclassdef
.mpropdefs
do
394 if mpropdef
isa MMethodDef then
395 if not mpropdef
.is_intro
and not mpropdef
.mproperty
.is_init
then res
.add
(mpropdef
.mproperty
)
402 fun inherited_methods
: Set[MMethod] do
403 var res
= new HashSet[MMethod]
404 for s
in ancestors
do
405 for m
in s
.intro_methods
do
406 if not self.intro_methods
.has
(m
) and not self.redef_methods
.has
(m
) then res
.add
(m
)
412 # Get the list of all virtual types available in 'self'.
413 fun virtual_types
: Set[MVirtualTypeProp] do
414 var res
= new HashSet[MVirtualTypeProp]
415 for mclassdef
in mclassdefs
do
416 for mpropdef
in mclassdef
.mpropdefs
do
417 if mpropdef
isa MVirtualTypeDef then
418 res
.add
(mpropdef
.mproperty
)
422 for ancestor
in ancestors
do
423 for mclassdef
in ancestor
.mclassdefs
do
424 for mpropdef
in mclassdef
.mpropdefs
do
425 if mpropdef
isa MVirtualTypeDef then
426 res
.add
(mpropdef
.mproperty
)
434 # Get the list of all parameter types in 'self'.
435 fun parameter_types
: Map[String, MType] do
436 var res
= new HashMap[String, MType]
437 for p
in mparameters
do
443 fun is_class
: Bool do
444 return self.kind
== concrete_kind
or self.kind
== abstract_kind
447 fun is_interface
: Bool do
448 return self.kind
== interface_kind
452 return self.kind
== enum_kind
455 fun is_abstract
: Bool do
456 return self.kind
== abstract_kind
460 redef class MAttribute
461 # Is this attribute nullable for sure?
463 # This mean that its introduction is declarred with a nullable static type
464 # since attributes are invariant this will work on most cases
465 # attributes with static type anchored with a virtual type are not "nullable for-sure"
466 # because this type can be redefined in subclasses
467 fun is_nullable
: Bool do return intro
.static_mtype
isa MNullableType
470 redef class MClassDef
471 # modifiers are keywords like redef, private etc.
472 fun modifiers
: Array[String] do
473 var res
= new Array[String]
477 res
.add mclass
.visibility
.to_s
479 res
.add mclass
.kind
.to_s
483 fun collect_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
484 var res
= new HashSet[MPropDef]
485 for mpropdef
in mpropdefs
do
486 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
492 fun collect_intro_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
493 var res
= new HashSet[MPropDef]
494 for mpropdef
in mpropdefs
do
495 if not mpropdef
.is_intro
then continue
496 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
502 fun collect_redef_mpropdefs
(min_visibility
: MVisibility): Set[MPropDef] do
503 var res
= new HashSet[MPropDef]
504 for mpropdef
in mpropdefs
do
505 if mpropdef
.is_intro
then continue
506 if mpropdef
.mproperty
.visibility
< min_visibility
then continue
514 # modifiers are keywords like redef, private etc.
515 fun modifiers
: Array[String] do
516 var res
= new Array[String]
520 res
.add mproperty
.visibility
.to_s
523 if mprop
isa MVirtualTypeDef then
525 else if mprop
isa MMethodDef then
526 if mprop
.is_abstract
then
528 else if mprop
.is_intern
then
531 if mprop
.mproperty
.is_init
then
543 # Sort mentities by their name
544 class MEntityNameSorter
546 redef type COMPARED: MEntity
547 redef fun compare
(a
, b
) do return a
.name
<=> b
.name
550 # Sort MConcerns based on the module importation hierarchy ranking
551 # see also: `MConcern::concern_rank` and `MConcern::booster_rank`
553 # Comparison is made with the formula:
556 # a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
559 # If both `a` and `b` have the same ranking,
560 # ordering is based on lexicographic comparison of `a.name` and `b.name`
561 class MConcernRankSorter
563 redef type COMPARED: MConcern
565 redef fun compare
(a
, b
) do
566 if a
.concern_rank
== b
.concern_rank
then
567 return a
.name
<=> b
.name
569 return a
.concern_rank
+ a
.booster_rank
<=> b
.concern_rank
+ b
.booster_rank