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 Introduction (of all kind)
167 # count all mclasses introduced by the module
171 redef fun name
do return "mnbi"
172 redef fun desc
do return "number of introduction in module"
174 redef fun collect
(mmodules
) do
175 for mmodule
in mmodules
do
176 values
[mmodule
] = mmodule
.intro_mclasses
.length
181 # Module Metric: Number of Refinement
183 # count all mclasses refined in the module
187 redef fun name
do return "mnbr"
188 redef fun desc
do return "number of refinement in module"
190 redef fun collect
(mmodules
) do
191 for mmodule
in mmodules
do
193 for mclassdef
in mmodule
.mclassdefs
do
194 if not mclassdef
.is_intro
then value
+= 1
196 values
[mmodule
] = value
201 # Module Metric: Number of Concrete Class in module (intro + redef)
205 redef fun name
do return "mnbcc"
206 redef fun desc
do return "number of concrete class in module (intro + redef)"
208 redef fun collect
(mmodules
) do
209 for mmodule
in mmodules
do
211 for mclassdef
in mmodule
.mclassdefs
do
212 if mclassdef
.mclass
.kind
== concrete_kind
then value
+= 1
214 values
[mmodule
] = value
219 # Module Metric: Number of Abstract Class in module (intro + redef)
223 redef fun name
do return "mnbac"
224 redef fun desc
do return "number of abstract class in module (intro + redef)"
226 redef fun collect
(mmodules
) do
227 for mmodule
in mmodules
do
229 for mclassdef
in mmodule
.mclassdefs
do
230 if mclassdef
.mclass
.kind
== abstract_kind
then value
+= 1
232 values
[mmodule
] = value
237 # Module Metric: Number of Interface in module (intro + redef)
241 redef fun name
do return "mnbic"
242 redef fun desc
do return "number of interface in module (intro + redef)"
244 redef fun collect
(mmodules
) do
245 for mmodule
in mmodules
do
247 for mclassdef
in mmodule
.mclassdefs
do
248 if mclassdef
.mclass
.kind
== interface_kind
then value
+= 1
250 values
[mmodule
] = value
255 # Module Metric: Number of Enum in module (intro + redef)
259 redef fun name
do return "mnbec"
260 redef fun desc
do return "number of enum in module (intro + redef)"
262 redef fun collect
(mmodules
) do
263 for mmodule
in mmodules
do
265 for mclassdef
in mmodule
.mclassdefs
do
266 if mclassdef
.mclass
.kind
== enum_kind
then value
+= 1
268 values
[mmodule
] = value