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