1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 Alexandre Terrasa <alexandre@moz-code.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 common metrics about modules
18 module mmodules_metrics
25 redef class ToolContext
26 var mmodules_metrics_phase
= new MModulesMetricsPhase(self, null)
29 # Extract metrics about modules from the model.
30 private class MModulesMetricsPhase
32 redef fun process_mainmodule
(mainmodule
)
34 if not toolcontext
.opt_mmodules
.value
and not toolcontext
.opt_all
.value
then return
36 print toolcontext
.format_h1
("\n# MModules metrics")
38 var metrics
= new MModuleMetricSet
39 metrics
.register
(new MNOA, new MNOP, new MNOC, new MNOD, new MDIT)
40 metrics
.register
(new MNBI, new MNBR, new MNBCC, new MNBAC, new MNBIC)
42 var model
= toolcontext
.modelbuilder
.model
43 var mmodules
= new HashSet[MModule]
44 for mproject
in model
.mprojects
do
46 print toolcontext
.format_h2
("\n ## project {mproject}")
48 for mgroup
in mproject
.mgroups
do
49 if mgroup
.mmodules
.is_empty
then continue
52 print toolcontext
.format_h3
(" `- group {mgroup.full_name}")
54 mmodules
.add_all
(mgroup
.mmodules
)
55 metrics
.collect
(new HashSet[MModule].from
(mgroup
.mmodules
), mainmodule
)
56 for name
, metric
in metrics
.metrics
do
57 print toolcontext
.format_h4
("\t{name}: {metric.desc}")
58 print toolcontext
.format_p
("\t avg: {metric.avg}")
60 print toolcontext
.format_p
("\t max: {max.first} ({max.second})")
62 print toolcontext
.format_p
("\t min: {min.first} ({min.second})")
66 if not mmodules
.is_empty
then
68 print toolcontext
.format_h2
("\n ## global metrics")
70 metrics
.collect
(mmodules
, mainmodule
)
71 for name
, metric
in metrics
.metrics
do
72 print toolcontext
.format_h4
( "\t{name}: {metric.desc}")
73 print toolcontext
.format_p
("\t avg: {metric.avg}")
75 print toolcontext
.format_p
("\t max: {max.first} ({max.second})")
77 print toolcontext
.format_p
("\t min: {min.first} ({min.second})")
83 # A MetricSet for metrics about MModules
84 class MModuleMetricSet
86 redef type METRIC: MModuleMetric
88 # Collect all the metrics on the set of MModules
89 fun collect
(mmodules
: Set[MModule], mainmodule
: MModule) do
91 for metric
in metrics
.values
do
92 for mmodule
in mmodules
do
93 metric
.collect
(mmodule
, mainmodule
)
99 # An abstract Metric on MModules
100 abstract class MModuleMetric
101 super IntMetric[MModule]
102 # Collect the metric on the MModule
104 # Results are stored in the property `values`
105 fun collect
(mmodule
: MModule, mainmodule
: MModule) is abstract
108 # Module Metric: Number of Ancestors
111 redef fun name
do return "mnoa"
112 redef fun desc
do return "number of ancestor modules"
114 redef fun collect
(mmodule
, main
) do
115 values
[mmodule
] = mmodule
.in_importation
.greaters
.length
- 1
119 # Module Metric: Number of Parents
122 redef fun name
do return "mnop"
123 redef fun desc
do return "number of parent modules"
125 redef fun collect
(mmodule
, main
) do
126 values
[mmodule
] = mmodule
.in_importation
.direct_greaters
.length
130 # Module Metric: Number of Children
133 redef fun name
do return "mnoc"
134 redef fun desc
do return "number of child modules"
136 redef fun collect
(mmodule
, main
) do
137 values
[mmodule
] = mmodule
.in_importation
.direct_smallers
.length
141 # Module Metric: Number of Descendants
144 redef fun name
do return "mnod"
145 redef fun desc
do return "number of descendant modules"
147 redef fun collect
(mmodule
, main
) do
148 values
[mmodule
] = mmodule
.in_importation
.smallers
.length
- 1
152 # Module Metric: Depth in Tree
155 redef fun name
do return "mdit"
156 redef fun desc
do return "depth in module tree"
158 redef fun collect
(mmodule
, main
) do
159 values
[mmodule
] = mmodule
.in_importation
.depth
163 # Module Metric: Number of Introduction (of all kind)
165 # count all mclasses introduced by the module
168 redef fun name
do return "mnbi"
169 redef fun desc
do return "number of introduction in module"
171 redef fun collect
(mmodule
, main
) do
172 values
[mmodule
] = mmodule
.intro_mclasses
.length
176 # Module Metric: Number of Refinement
178 # count all mclasses refined in the module
181 redef fun name
do return "mnbr"
182 redef fun desc
do return "number of refinement in module"
184 redef fun collect
(mmodule
, main
) do
186 for mclassdef
in mmodule
.mclassdefs
do
187 if not mclassdef
.is_intro
then values
.inc
(mmodule
)
192 # Module Metric: Number of Concrete Class in module (intro + redef)
195 redef fun name
do return "mnbcc"
196 redef fun desc
do return "number of concrete class in module (intro + redef)"
198 redef fun collect
(mmodule
, main
) do
200 for mclassdef
in mmodule
.mclassdefs
do
201 if mclassdef
.mclass
.kind
== concrete_kind
then values
.inc
(mmodule
)
206 # Module Metric: Number of Abstract Class in module (intro + redef)
209 redef fun name
do return "mnbac"
210 redef fun desc
do return "number of abstract class in module (intro + redef)"
212 redef fun collect
(mmodule
, main
) do
214 for mclassdef
in mmodule
.mclassdefs
do
215 if mclassdef
.mclass
.kind
== abstract_kind
then values
.inc
(mmodule
)
220 # Module Metric: Number of Interface in module (intro + redef)
223 redef fun name
do return "mnbic"
224 redef fun desc
do return "number of interface in module (intro + redef)"
226 redef fun collect
(mmodule
, main
) do
228 for mclassdef
in mmodule
.mclassdefs
do
229 if mclassdef
.mclass
.kind
== interface_kind
then values
.inc
(mmodule
)
234 # Module Metric: Number of Enum in module (intro + redef)
237 redef fun name
do return "mnbec"
238 redef fun desc
do return "number of enum in module (intro + redef)"
240 redef fun collect
(mmodule
, main
) do
242 for mclassdef
in mmodule
.mclassdefs
do
243 if mclassdef
.mclass
.kind
== enum_kind
then values
.inc
(mmodule
)