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