Merge: doc: fixed some typos and other misc. corrections
[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
41 print toolcontext.format_h1("\n# MModules metrics")
42
43 var metrics = new MetricSet
44 metrics.register(new MNOA(model, mainmodule))
45 metrics.register(new MNOP(model, mainmodule))
46 metrics.register(new MNOC(model, mainmodule))
47 metrics.register(new MNOD(model, mainmodule))
48 metrics.register(new MDIT(model, mainmodule))
49 metrics.register(new MNBI(model, mainmodule))
50 metrics.register(new MNBR(model, mainmodule))
51 metrics.register(new MNBCC(model, mainmodule))
52 metrics.register(new MNBAC(model, mainmodule))
53 metrics.register(new MNBIC(model, mainmodule))
54
55 var mmodules = new HashSet[MModule]
56 for mpackage in model.mpackages do
57
58 print toolcontext.format_h2("\n ## package {mpackage}")
59 for mgroup in mpackage.mgroups do
60 if mgroup.mmodules.is_empty then continue
61
62 # Scalar metrics
63 print toolcontext.format_h3(" `- group {mgroup.full_name}")
64 mmodules.add_all(mgroup.mmodules)
65 metrics.clear
66 metrics.collect(new HashSet[MModule].from(mgroup.mmodules))
67 metrics.to_console(1, not toolcontext.opt_nocolors.value)
68 if csv then metrics.to_csv.write_to_file("{out}/{mgroup}.csv")
69 end
70 end
71 if not mmodules.is_empty then
72 # Global metrics
73 print toolcontext.format_h2("\n ## global metrics")
74 metrics.clear
75 metrics.collect(mmodules)
76 metrics.to_console(1, not toolcontext.opt_nocolors.value)
77 if csv then metrics.to_csv.write_to_file("{out}/summary.csv")
78 end
79 end
80 end
81
82 # A metric about MModule
83 abstract class MModuleMetric
84 super Metric
85 redef type ELM: MModule
86
87 # Model view used to collect and filter entities
88 var model: Model
89
90 # Mainmodule used for linearization
91 var mainmodule: MModule
92
93 # Filter to apply on model if any
94 var filter: nullable ModelFilter
95 end
96
97 # Module Metric: Number of Ancestors
98 class MNOA
99 super MModuleMetric
100 super IntMetric
101 redef fun name do return "mnoa"
102 redef fun desc do return "number of ancestor modules"
103
104 redef fun collect(mmodules) do
105 for mmodule in mmodules do
106 values[mmodule] = mmodule.in_importation.greaters.length - 1
107 end
108 end
109 end
110
111 # Module Metric: Number of Parents
112 class MNOP
113 super MModuleMetric
114 super IntMetric
115 redef fun name do return "mnop"
116 redef fun desc do return "number of parent modules"
117
118 redef fun collect(mmodules) do
119 for mmodule in mmodules do
120 values[mmodule] = mmodule.in_importation.direct_greaters.length
121 end
122 end
123 end
124
125 # Module Metric: Number of Children
126 class MNOC
127 super MModuleMetric
128 super IntMetric
129 redef fun name do return "mnoc"
130 redef fun desc do return "number of child modules"
131
132 redef fun collect(mmodules) do
133 for mmodule in mmodules do
134 values[mmodule] = mmodule.in_importation.direct_smallers.length
135 end
136 end
137 end
138
139 # Module Metric: Number of Descendants
140 class MNOD
141 super MModuleMetric
142 super IntMetric
143 redef fun name do return "mnod"
144 redef fun desc do return "number of descendant modules"
145
146 redef fun collect(mmodules) do
147 for mmodule in mmodules do
148 values[mmodule] = mmodule.in_importation.smallers.length - 1
149 end
150 end
151 end
152
153 # Module Metric: Depth in Tree
154 class MDIT
155 super MModuleMetric
156 super IntMetric
157 redef fun name do return "mdit"
158 redef fun desc do return "depth in module tree"
159
160 redef fun collect(mmodules) do
161 for mmodule in mmodules do
162 values[mmodule] = mmodule.in_importation.depth
163 end
164 end
165 end
166
167 # Module Metric: Number of Accessible Definitions (of all kind)
168 #
169 # count all mclasses accessible by the module
170 class MNBD
171 super MModuleMetric
172 super IntMetric
173 redef fun name do return "mnbd"
174 redef fun desc do return "number of definition accessibles in module"
175
176 redef fun collect(mmodules) do
177 for mmodule in mmodules do
178 values[mmodule] = 0
179 for a in mmodule.collect_ancestors(mainmodule, filter) do
180 values[mmodule] += a.intro_mclasses.length
181 end
182 end
183 end
184 end
185
186 # Module Metric: Number of Introduction (of all kind)
187 #
188 # count all mclasses introduced by the module
189 class MNBI
190 super MModuleMetric
191 super IntMetric
192 redef fun name do return "mnbi"
193 redef fun desc do return "number of introduction in module"
194
195 redef fun collect(mmodules) do
196 for mmodule in mmodules do
197 values[mmodule] = mmodule.intro_mclasses.length
198 end
199 end
200 end
201
202 # Module Metric: Number of Refinement
203 #
204 # count all mclasses refined in the module
205 class MNBR
206 super MModuleMetric
207 super IntMetric
208 redef fun name do return "mnbr"
209 redef fun desc do return "number of refinement in module"
210
211 redef fun collect(mmodules) do
212 for mmodule in mmodules do
213 var value = 0
214 for mclassdef in mmodule.mclassdefs do
215 if not mclassdef.is_intro then value += 1
216 end
217 values[mmodule] = value
218 end
219 end
220 end
221
222 # Module Metric: Number of Concrete Class in module (intro + redef)
223 class MNBCC
224 super MModuleMetric
225 super IntMetric
226 redef fun name do return "mnbcc"
227 redef fun desc do return "number of concrete class in module (intro + redef)"
228
229 redef fun collect(mmodules) do
230 for mmodule in mmodules do
231 var value = 0
232 for mclassdef in mmodule.mclassdefs do
233 if mclassdef.mclass.kind == concrete_kind then value += 1
234 end
235 values[mmodule] = value
236 end
237 end
238 end
239
240 # Module Metric: Number of Abstract Class in module (intro + redef)
241 class MNBAC
242 super MModuleMetric
243 super IntMetric
244 redef fun name do return "mnbac"
245 redef fun desc do return "number of abstract class in module (intro + redef)"
246
247 redef fun collect(mmodules) do
248 for mmodule in mmodules do
249 var value = 0
250 for mclassdef in mmodule.mclassdefs do
251 if mclassdef.mclass.kind == abstract_kind then value += 1
252 end
253 values[mmodule] = value
254 end
255 end
256 end
257
258 # Module Metric: Number of Interface in module (intro + redef)
259 class MNBIC
260 super MModuleMetric
261 super IntMetric
262 redef fun name do return "mnbic"
263 redef fun desc do return "number of interface in module (intro + redef)"
264
265 redef fun collect(mmodules) do
266 for mmodule in mmodules do
267 var value = 0
268 for mclassdef in mmodule.mclassdefs do
269 if mclassdef.mclass.kind == interface_kind then value += 1
270 end
271 values[mmodule] = value
272 end
273 end
274 end
275
276 # Module Metric: Number of Enum in module (intro + redef)
277 class MNBEC
278 super MModuleMetric
279 super IntMetric
280 redef fun name do return "mnbec"
281 redef fun desc do return "number of enum in module (intro + redef)"
282
283 redef fun collect(mmodules) do
284 for mmodule in mmodules do
285 var value = 0
286 for mclassdef in mmodule.mclassdefs do
287 if mclassdef.mclass.kind == enum_kind then value += 1
288 end
289 values[mmodule] = value
290 end
291 end
292 end