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
21 import model
::model_collect
23 redef class ToolContext
25 # MModules related metrics phase
26 var mmodules_metrics_phase
: Phase = new MModulesMetricsPhase(self, null)
29 # Extract metrics about modules from the model.
30 private class MModulesMetricsPhase
32 redef fun process_mainmodule
(mainmodule
, given_mmodules
)
34 if not toolcontext
.opt_mmodules
.value
and not toolcontext
.opt_all
.value
then return
35 var csv
= toolcontext
.opt_csv
.value
36 var out
= "{toolcontext.opt_dir.value or else "metrics"}/mmodules"
39 var model
= toolcontext
.modelbuilder
.model
40 var model_view
= model
.private_view
42 print toolcontext
.format_h1
("\n# MModules metrics")
44 var metrics
= new MetricSet
45 metrics
.register
(new MNOA(mainmodule
, model_view
))
46 metrics
.register
(new MNOP(mainmodule
, model_view
))
47 metrics
.register
(new MNOC(mainmodule
, model_view
))
48 metrics
.register
(new MNOD(mainmodule
, model_view
))
49 metrics
.register
(new MDIT(mainmodule
, model_view
))
50 metrics
.register
(new MNBI(mainmodule
, model_view
))
51 metrics
.register
(new MNBR(mainmodule
, model_view
))
52 metrics
.register
(new MNBCC(mainmodule
, model_view
))
53 metrics
.register
(new MNBAC(mainmodule
, model_view
))
54 metrics
.register
(new MNBIC(mainmodule
, model_view
))
56 var mmodules
= new HashSet[MModule]
57 for mpackage
in model
.mpackages
do
59 print toolcontext
.format_h2
("\n ## package {mpackage}")
60 for mgroup
in mpackage
.mgroups
do
61 if mgroup
.mmodules
.is_empty
then continue
64 print toolcontext
.format_h3
(" `- group {mgroup.full_name}")
65 mmodules
.add_all
(mgroup
.mmodules
)
67 metrics
.collect
(new HashSet[MModule].from
(mgroup
.mmodules
))
68 metrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
69 if csv
then metrics
.to_csv
.write_to_file
("{out}/{mgroup}.csv")
72 if not mmodules
.is_empty
then
74 print toolcontext
.format_h2
("\n ## global metrics")
76 metrics
.collect
(mmodules
)
77 metrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
78 if csv
then metrics
.to_csv
.write_to_file
("{out}/summary.csv")
83 # A metric about MModule
84 abstract class MModuleMetric
86 redef type ELM: MModule
88 # Main module used for linearization
89 var mainmodule
: MModule
91 # Model view used to collect and filter entities
92 var model_view
: ModelView
95 # Module Metric: Number of Ancestors
99 redef fun name
do return "mnoa"
100 redef fun desc
do return "number of ancestor modules"
102 redef fun collect
(mmodules
) do
103 for mmodule
in mmodules
do
104 values
[mmodule
] = mmodule
.in_importation
.greaters
.length
- 1
109 # Module Metric: Number of Parents
113 redef fun name
do return "mnop"
114 redef fun desc
do return "number of parent modules"
116 redef fun collect
(mmodules
) do
117 for mmodule
in mmodules
do
118 values
[mmodule
] = mmodule
.in_importation
.direct_greaters
.length
123 # Module Metric: Number of Children
127 redef fun name
do return "mnoc"
128 redef fun desc
do return "number of child modules"
130 redef fun collect
(mmodules
) do
131 for mmodule
in mmodules
do
132 values
[mmodule
] = mmodule
.in_importation
.direct_smallers
.length
137 # Module Metric: Number of Descendants
141 redef fun name
do return "mnod"
142 redef fun desc
do return "number of descendant modules"
144 redef fun collect
(mmodules
) do
145 for mmodule
in mmodules
do
146 values
[mmodule
] = mmodule
.in_importation
.smallers
.length
- 1
151 # 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
(mmodules
) do
159 for mmodule
in mmodules
do
160 values
[mmodule
] = mmodule
.in_importation
.depth
165 # Module Metric: Number of Accessible Definitions (of all kind)
167 # count all mclasses accessible by the module
171 redef fun name
do return "mnbd"
172 redef fun desc
do return "number of definition accessibles in module"
174 redef fun collect
(mmodules
) do
175 for mmodule
in mmodules
do
177 for a
in mmodule
.collect_ancestors
(model_view
) do
178 values
[mmodule
] += a
.intro_mclasses
.length
184 # Module Metric: Number of Introduction (of all kind)
186 # count all mclasses introduced by the module
190 redef fun name
do return "mnbi"
191 redef fun desc
do return "number of introduction in module"
193 redef fun collect
(mmodules
) do
194 for mmodule
in mmodules
do
195 values
[mmodule
] = mmodule
.intro_mclasses
.length
200 # Module Metric: Number of Refinement
202 # count all mclasses refined in the module
206 redef fun name
do return "mnbr"
207 redef fun desc
do return "number of refinement in module"
209 redef fun collect
(mmodules
) do
210 for mmodule
in mmodules
do
212 for mclassdef
in mmodule
.mclassdefs
do
213 if not mclassdef
.is_intro
then value
+= 1
215 values
[mmodule
] = value
220 # Module Metric: Number of Concrete Class in module (intro + redef)
224 redef fun name
do return "mnbcc"
225 redef fun desc
do return "number of concrete class in module (intro + redef)"
227 redef fun collect
(mmodules
) do
228 for mmodule
in mmodules
do
230 for mclassdef
in mmodule
.mclassdefs
do
231 if mclassdef
.mclass
.kind
== concrete_kind
then value
+= 1
233 values
[mmodule
] = value
238 # Module Metric: Number of Abstract Class in module (intro + redef)
242 redef fun name
do return "mnbac"
243 redef fun desc
do return "number of abstract class in module (intro + redef)"
245 redef fun collect
(mmodules
) do
246 for mmodule
in mmodules
do
248 for mclassdef
in mmodule
.mclassdefs
do
249 if mclassdef
.mclass
.kind
== abstract_kind
then value
+= 1
251 values
[mmodule
] = value
256 # Module Metric: Number of Interface in module (intro + redef)
260 redef fun name
do return "mnbic"
261 redef fun desc
do return "number of interface in module (intro + redef)"
263 redef fun collect
(mmodules
) do
264 for mmodule
in mmodules
do
266 for mclassdef
in mmodule
.mclassdefs
do
267 if mclassdef
.mclass
.kind
== interface_kind
then value
+= 1
269 values
[mmodule
] = value
274 # Module Metric: Number of Enum in module (intro + redef)
278 redef fun name
do return "mnbec"
279 redef fun desc
do return "number of enum in module (intro + redef)"
281 redef fun collect
(mmodules
) do
282 for mmodule
in mmodules
do
284 for mclassdef
in mmodule
.mclassdefs
do
285 if mclassdef
.mclass
.kind
== enum_kind
then value
+= 1
287 values
[mmodule
] = value