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
= new ModelView(model
, mainmodule
)
42 print toolcontext
.format_h1
("\n# MModules metrics")
44 var metrics
= new MetricSet
45 metrics
.register
(new MNOA(model_view
))
46 metrics
.register
(new MNOP(model_view
))
47 metrics
.register
(new MNOC(model_view
))
48 metrics
.register
(new MNOD(model_view
))
49 metrics
.register
(new MDIT(model_view
))
50 metrics
.register
(new MNBI(model_view
))
51 metrics
.register
(new MNBR(model_view
))
52 metrics
.register
(new MNBCC(model_view
))
53 metrics
.register
(new MNBAC(model_view
))
54 metrics
.register
(new MNBIC(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 # Model view used to collect and filter entities
89 var model_view
: ModelView
92 # Module Metric: Number of Ancestors
96 redef fun name
do return "mnoa"
97 redef fun desc
do return "number of ancestor modules"
99 redef fun collect
(mmodules
) do
100 for mmodule
in mmodules
do
101 values
[mmodule
] = mmodule
.in_importation
.greaters
.length
- 1
106 # Module Metric: Number of Parents
110 redef fun name
do return "mnop"
111 redef fun desc
do return "number of parent modules"
113 redef fun collect
(mmodules
) do
114 for mmodule
in mmodules
do
115 values
[mmodule
] = mmodule
.in_importation
.direct_greaters
.length
120 # Module Metric: Number of Children
124 redef fun name
do return "mnoc"
125 redef fun desc
do return "number of child modules"
127 redef fun collect
(mmodules
) do
128 for mmodule
in mmodules
do
129 values
[mmodule
] = mmodule
.in_importation
.direct_smallers
.length
134 # Module Metric: Number of Descendants
138 redef fun name
do return "mnod"
139 redef fun desc
do return "number of descendant modules"
141 redef fun collect
(mmodules
) do
142 for mmodule
in mmodules
do
143 values
[mmodule
] = mmodule
.in_importation
.smallers
.length
- 1
148 # Module Metric: Depth in Tree
152 redef fun name
do return "mdit"
153 redef fun desc
do return "depth in module tree"
155 redef fun collect
(mmodules
) do
156 for mmodule
in mmodules
do
157 values
[mmodule
] = mmodule
.in_importation
.depth
162 # Module Metric: Number of Accessible Definitions (of all kind)
164 # count all mclasses accessible by the module
168 redef fun name
do return "mnbd"
169 redef fun desc
do return "number of definition accessibles in module"
171 redef fun collect
(mmodules
) do
172 for mmodule
in mmodules
do
174 for a
in mmodule
.collect_ancestors
(model_view
) do
175 values
[mmodule
] += a
.intro_mclasses
.length
181 # Module Metric: Number of Introduction (of all kind)
183 # count all mclasses introduced by the module
187 redef fun name
do return "mnbi"
188 redef fun desc
do return "number of introduction in module"
190 redef fun collect
(mmodules
) do
191 for mmodule
in mmodules
do
192 values
[mmodule
] = mmodule
.intro_mclasses
.length
197 # Module Metric: Number of Refinement
199 # count all mclasses refined in the module
203 redef fun name
do return "mnbr"
204 redef fun desc
do return "number of refinement in module"
206 redef fun collect
(mmodules
) do
207 for mmodule
in mmodules
do
209 for mclassdef
in mmodule
.mclassdefs
do
210 if not mclassdef
.is_intro
then value
+= 1
212 values
[mmodule
] = value
217 # Module Metric: Number of Concrete Class in module (intro + redef)
221 redef fun name
do return "mnbcc"
222 redef fun desc
do return "number of concrete class in module (intro + redef)"
224 redef fun collect
(mmodules
) do
225 for mmodule
in mmodules
do
227 for mclassdef
in mmodule
.mclassdefs
do
228 if mclassdef
.mclass
.kind
== concrete_kind
then value
+= 1
230 values
[mmodule
] = value
235 # Module Metric: Number of Abstract Class in module (intro + redef)
239 redef fun name
do return "mnbac"
240 redef fun desc
do return "number of abstract class in module (intro + redef)"
242 redef fun collect
(mmodules
) do
243 for mmodule
in mmodules
do
245 for mclassdef
in mmodule
.mclassdefs
do
246 if mclassdef
.mclass
.kind
== abstract_kind
then value
+= 1
248 values
[mmodule
] = value
253 # Module Metric: Number of Interface in module (intro + redef)
257 redef fun name
do return "mnbic"
258 redef fun desc
do return "number of interface in module (intro + redef)"
260 redef fun collect
(mmodules
) do
261 for mmodule
in mmodules
do
263 for mclassdef
in mmodule
.mclassdefs
do
264 if mclassdef
.mclass
.kind
== interface_kind
then value
+= 1
266 values
[mmodule
] = value
271 # Module Metric: Number of Enum in module (intro + redef)
275 redef fun name
do return "mnbec"
276 redef fun desc
do return "number of enum in module (intro + redef)"
278 redef fun collect
(mmodules
) do
279 for mmodule
in mmodules
do
281 for mclassdef
in mmodule
.mclassdefs
do
282 if mclassdef
.mclass
.kind
== enum_kind
then value
+= 1
284 values
[mmodule
] = value