metrics: factorize `mainmodule` and `model_view` for all MModule metrics
[nit.git] / src / metrics / mmodules_metrics.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 # Collect common metrics about modules
18 module mmodules_metrics
19
20 import metrics_base
21 import model::model_collect
22
23 redef class ToolContext
24
25 # MModules related metrics phase
26 var mmodules_metrics_phase: Phase = new MModulesMetricsPhase(self, null)
27 end
28
29 # Extract metrics about modules from the model.
30 private class MModulesMetricsPhase
31 super Phase
32 redef fun process_mainmodule(mainmodule, given_mmodules)
33 do
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"
37 out.mkdir
38
39 var model = toolcontext.modelbuilder.model
40 var model_view = model.private_view
41
42 print toolcontext.format_h1("\n# MModules metrics")
43
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))
55
56 var mmodules = new HashSet[MModule]
57 for mpackage in model.mpackages do
58
59 print toolcontext.format_h2("\n ## package {mpackage}")
60 for mgroup in mpackage.mgroups do
61 if mgroup.mmodules.is_empty then continue
62
63 # Scalar metrics
64 print toolcontext.format_h3(" `- group {mgroup.full_name}")
65 mmodules.add_all(mgroup.mmodules)
66 metrics.clear
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")
70 end
71 end
72 if not mmodules.is_empty then
73 # Global metrics
74 print toolcontext.format_h2("\n ## global metrics")
75 metrics.clear
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")
79 end
80 end
81 end
82
83 # A metric about MModule
84 abstract class MModuleMetric
85 super Metric
86 redef type ELM: MModule
87
88 # Main module used for linearization
89 var mainmodule: MModule
90
91 # Model view used to collect and filter entities
92 var model_view: ModelView
93 end
94
95 # Module Metric: Number of Ancestors
96 class MNOA
97 super MModuleMetric
98 super IntMetric
99 redef fun name do return "mnoa"
100 redef fun desc do return "number of ancestor modules"
101
102 redef fun collect(mmodules) do
103 for mmodule in mmodules do
104 values[mmodule] = mmodule.in_importation.greaters.length - 1
105 end
106 end
107 end
108
109 # Module Metric: Number of Parents
110 class MNOP
111 super MModuleMetric
112 super IntMetric
113 redef fun name do return "mnop"
114 redef fun desc do return "number of parent modules"
115
116 redef fun collect(mmodules) do
117 for mmodule in mmodules do
118 values[mmodule] = mmodule.in_importation.direct_greaters.length
119 end
120 end
121 end
122
123 # Module Metric: Number of Children
124 class MNOC
125 super MModuleMetric
126 super IntMetric
127 redef fun name do return "mnoc"
128 redef fun desc do return "number of child modules"
129
130 redef fun collect(mmodules) do
131 for mmodule in mmodules do
132 values[mmodule] = mmodule.in_importation.direct_smallers.length
133 end
134 end
135 end
136
137 # Module Metric: Number of Descendants
138 class MNOD
139 super MModuleMetric
140 super IntMetric
141 redef fun name do return "mnod"
142 redef fun desc do return "number of descendant modules"
143
144 redef fun collect(mmodules) do
145 for mmodule in mmodules do
146 values[mmodule] = mmodule.in_importation.smallers.length - 1
147 end
148 end
149 end
150
151 # Module Metric: Depth in Tree
152 class MDIT
153 super MModuleMetric
154 super IntMetric
155 redef fun name do return "mdit"
156 redef fun desc do return "depth in module tree"
157
158 redef fun collect(mmodules) do
159 for mmodule in mmodules do
160 values[mmodule] = mmodule.in_importation.depth
161 end
162 end
163 end
164
165 # Module Metric: Number of Introduction (of all kind)
166 #
167 # count all mclasses introduced by the module
168 class MNBI
169 super MModuleMetric
170 super IntMetric
171 redef fun name do return "mnbi"
172 redef fun desc do return "number of introduction in module"
173
174 redef fun collect(mmodules) do
175 for mmodule in mmodules do
176 values[mmodule] = mmodule.intro_mclasses.length
177 end
178 end
179 end
180
181 # Module Metric: Number of Refinement
182 #
183 # count all mclasses refined in the module
184 class MNBR
185 super MModuleMetric
186 super IntMetric
187 redef fun name do return "mnbr"
188 redef fun desc do return "number of refinement in module"
189
190 redef fun collect(mmodules) do
191 for mmodule in mmodules do
192 var value = 0
193 for mclassdef in mmodule.mclassdefs do
194 if not mclassdef.is_intro then value += 1
195 end
196 values[mmodule] = value
197 end
198 end
199 end
200
201 # Module Metric: Number of Concrete Class in module (intro + redef)
202 class MNBCC
203 super MModuleMetric
204 super IntMetric
205 redef fun name do return "mnbcc"
206 redef fun desc do return "number of concrete class in module (intro + redef)"
207
208 redef fun collect(mmodules) do
209 for mmodule in mmodules do
210 var value = 0
211 for mclassdef in mmodule.mclassdefs do
212 if mclassdef.mclass.kind == concrete_kind then value += 1
213 end
214 values[mmodule] = value
215 end
216 end
217 end
218
219 # Module Metric: Number of Abstract Class in module (intro + redef)
220 class MNBAC
221 super MModuleMetric
222 super IntMetric
223 redef fun name do return "mnbac"
224 redef fun desc do return "number of abstract class in module (intro + redef)"
225
226 redef fun collect(mmodules) do
227 for mmodule in mmodules do
228 var value = 0
229 for mclassdef in mmodule.mclassdefs do
230 if mclassdef.mclass.kind == abstract_kind then value += 1
231 end
232 values[mmodule] = value
233 end
234 end
235 end
236
237 # Module Metric: Number of Interface in module (intro + redef)
238 class MNBIC
239 super MModuleMetric
240 super IntMetric
241 redef fun name do return "mnbic"
242 redef fun desc do return "number of interface in module (intro + redef)"
243
244 redef fun collect(mmodules) do
245 for mmodule in mmodules do
246 var value = 0
247 for mclassdef in mmodule.mclassdefs do
248 if mclassdef.mclass.kind == interface_kind then value += 1
249 end
250 values[mmodule] = value
251 end
252 end
253 end
254
255 # Module Metric: Number of Enum in module (intro + redef)
256 class MNBEC
257 super MModuleMetric
258 super IntMetric
259 redef fun name do return "mnbec"
260 redef fun desc do return "number of enum in module (intro + redef)"
261
262 redef fun collect(mmodules) do
263 for mmodule in mmodules do
264 var value = 0
265 for mclassdef in mmodule.mclassdefs do
266 if mclassdef.mclass.kind == enum_kind then value += 1
267 end
268 values[mmodule] = value
269 end
270 end
271 end