doc: modified comment for typing::AExpr::mtype
[nit.git] / src / metrics / rta_metrics.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.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 # Metrics from RTA
18 module rta_metrics
19
20 import modelbuilder
21 private import rapid_type_analysis
22 private import metrics_base
23 import mmodules_metrics
24 import mclasses_metrics
25 import frontend
26
27 redef class ToolContext
28 var rta_metrics_phase = new RTAMetricsPhase(self, null)
29 end
30
31 private class RTAMetricsPhase
32 super Phase
33 redef fun process_mainmodule(mainmodule)
34 do
35 if not toolcontext.opt_rta.value and not toolcontext.opt_all.value then return
36 var csv = toolcontext.opt_csv.value
37 var out = "{toolcontext.opt_dir.value or else "metrics"}/rta"
38 out.mkdir
39
40 print toolcontext.format_h1("\n# RTA metrics")
41
42 print toolcontext.format_h2("\n ## Live instances by mainmodules")
43 var mmetrics = new MetricSet
44 mmetrics.register(new MNLC(toolcontext.modelbuilder))
45 mmetrics.register(new MNLT(toolcontext.modelbuilder))
46 mmetrics.register(new MNCT(toolcontext.modelbuilder))
47 mmetrics.register(new MNLI(toolcontext.modelbuilder))
48 mmetrics.register(new MNLM(toolcontext.modelbuilder))
49 mmetrics.register(new MNLMD(toolcontext.modelbuilder))
50 mmetrics.register(new MNLDD(toolcontext.modelbuilder))
51 mmetrics.collect(new HashSet[MModule].from([mainmodule]))
52 mmetrics.to_console(1, not toolcontext.opt_nocolors.value)
53 if csv then mmetrics.to_csv.save("{out}/{mainmodule}.csv")
54
55 var mtypes = new HashSet[MType]
56 var analysis = new RapidTypeAnalysis(toolcontext.modelbuilder, mainmodule)
57 analysis.run_analysis
58 mtypes.add_all(analysis.live_types)
59 mtypes.add_all(analysis.live_cast_types)
60
61 print toolcontext.format_h2("\n ## Total live instances by mclasses")
62 var cmetrics = new MetricSet
63 cmetrics.register(analysis.cnli)
64 cmetrics.register(analysis.cnlc)
65 cmetrics.to_console(1, not toolcontext.opt_nocolors.value)
66 if csv then cmetrics.to_csv.save("{out}/mclasses.csv")
67
68 print toolcontext.format_h2("\n ## Total live instances by mtypes")
69 var tmetrics = new MetricSet
70 tmetrics.register(analysis.tnli)
71 tmetrics.register(analysis.tnlc)
72 tmetrics.to_console(1, not toolcontext.opt_nocolors.value)
73 if csv then tmetrics.to_csv.save("{out}/mtypes.csv")
74
75 print toolcontext.format_h2("\n ## MType complexity")
76 var gmetrics = new MetricSet
77 gmetrics.register(new TAGS)
78 gmetrics.register(new TDGS)
79 gmetrics.collect(mtypes)
80 gmetrics.to_console(1, not toolcontext.opt_nocolors.value)
81 if csv then gmetrics.to_csv.save("{out}/complexity.csv")
82 end
83 end
84
85 # Summary metrics
86
87 # MModule Metric: Number of Live Types
88 class MNLI
89 super MModuleMetric
90 super IntMetric
91 redef fun name do return "mnli"
92 redef fun desc do return "number of live instances in a mmodule"
93
94 var modelbuilder: ModelBuilder
95 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
96
97 redef fun collect(mainmodules) do
98 for mainmodule in mainmodules do
99 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
100 analysis.run_analysis
101 values[mainmodule] = analysis.tnli.sum
102 end
103 end
104 end
105
106 # MModule Metric: Number of Live Types
107 class MNLT
108 super MModuleMetric
109 super IntMetric
110 redef fun name do return "mnlt"
111 redef fun desc do return "number of live mtypes in a mmodule"
112
113 var modelbuilder: ModelBuilder
114 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
115
116 redef fun collect(mainmodules) do
117 for mainmodule in mainmodules do
118 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
119 analysis.run_analysis
120 values[mainmodule] = analysis.live_types.length
121 end
122 end
123 end
124
125 # MModule Metric: Number of Live Cast Types
126 class MNCT
127 super MModuleMetric
128 super IntMetric
129 redef fun name do return "mnct"
130 redef fun desc do return "number of live cast mtypes in a mmodule"
131
132 var modelbuilder: ModelBuilder
133 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
134
135 redef fun collect(mainmodules) do
136 for mainmodule in mainmodules do
137 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
138 analysis.run_analysis
139 values[mainmodule] = analysis.live_cast_types.length
140 end
141 end
142 end
143
144 # MModule Metric: Number of Live Classes
145 class MNLC
146 super MModuleMetric
147 super IntMetric
148 redef fun name do return "mnlc"
149 redef fun desc do return "number of live mclasses in a mmodule"
150
151 var modelbuilder: ModelBuilder
152 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
153
154 redef fun collect(mainmodules) do
155 for mainmodule in mainmodules do
156 var live = new HashSet[MClass]
157 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
158 analysis.run_analysis
159 for mtype in analysis.live_types do
160 live.add(mtype.mclass)
161 end
162 values[mainmodule] = live.length
163 end
164 end
165 end
166
167 # MModule Metric: Number of Live Methods
168 class MNLM
169 super MModuleMetric
170 super IntMetric
171 redef fun name do return "mnlm"
172 redef fun desc do return "number of live methods in a mmodule"
173
174 var modelbuilder: ModelBuilder
175 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
176
177 redef fun collect(mainmodules) do
178 for mainmodule in mainmodules do
179 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
180 analysis.run_analysis
181 values[mainmodule] = analysis.live_methods.length
182 end
183 end
184 end
185
186 # MModule Metric: Number of Live MethodDefs
187 class MNLMD
188 super MModuleMetric
189 super IntMetric
190 redef fun name do return "mnlmd"
191 redef fun desc do return "number of live method definitions in a mmodule"
192
193 var modelbuilder: ModelBuilder
194 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
195
196 redef fun collect(mainmodules) do
197 for mainmodule in mainmodules do
198 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
199 analysis.run_analysis
200 values[mainmodule] = analysis.live_methoddefs.length
201 end
202 end
203 end
204
205 # MModule Metric: Number of Dead MethodDefs
206 class MNLDD
207 super MModuleMetric
208 super IntMetric
209 redef fun name do return "mnldd"
210 redef fun desc do return "number of dead method definitions in a mmodule"
211
212 var modelbuilder: ModelBuilder
213 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
214
215 redef fun collect(mainmodules) do
216 for mainmodule in mainmodules do
217 var dead = 0
218 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
219 analysis.run_analysis
220 for mmethod in analysis.live_methods do
221 for mdef in mmethod.mpropdefs do
222 if analysis.live_methoddefs.has(mdef) or mdef.is_abstract then continue
223 dead += 1
224 end
225 end
226 values[mainmodule] = dead
227 end
228 end
229 end
230
231 # MClass metrics
232
233 # Class Metric: Number of Live Instances
234 #
235 # count all the `new` made on each mclass
236 class CNLI
237 super MClassMetric
238 super IntMetric
239 redef fun name do return "cnli"
240 redef fun desc do return "number of live instances for a mclass"
241
242 redef fun collect(mclasses) do end
243 end
244
245 # Class Metric: Number of Live Cast
246 #
247 # count all the cast made on each mclass type
248 class CNLC
249 super MClassMetric
250 super IntMetric
251 redef fun name do return "cnlc"
252 redef fun desc do return "number of live cast for a mclass type"
253
254 redef fun collect(mclasses) do end
255 end
256
257 # MType metrics
258
259 # A metric about MType
260 interface MTypeMetric
261 super Metric
262 redef type ELM: MType
263 end
264
265 # Type Metric: Number of Live Instances
266 #
267 # count all the `new` made on each types
268 class TNLI
269 super MTypeMetric
270 super IntMetric
271 redef fun name do return "tnli"
272 redef fun desc do return "number of live instances for a mtype"
273
274 redef fun collect(mtypes) do end
275 end
276
277 # Type Metric: Number of Live Cast
278 #
279 # count all the cast made to each types
280 class TNLC
281 super MTypeMetric
282 super IntMetric
283 redef fun name do return "tnlc"
284 redef fun desc do return "number of live casts to a mtype"
285
286 redef fun collect(mtypes) do end
287 end
288
289 # Type Metric: Arity of Generic Signature
290 #
291 # tags(List[X]) = 1
292 # tags(Map[X, Y]) = 2
293 class TAGS
294 super MTypeMetric
295 super IntMetric
296 redef fun name do return "tags"
297 redef fun desc do return "arity of generic signature"
298
299 redef fun collect(mtypes) do
300 for mtype in mtypes do
301 if mtype isa MGenericType then
302 values[mtype] = mtype.arguments.length
303 else
304 values[mtype] = 0
305 end
306 end
307 end
308 end
309
310 # Type Metric: Depth of Generic Signature
311 #
312 # tdgs(List[X]) = 1
313 # tdgs(Map[X, List[Y]]) = 2
314 class TDGS
315 super MTypeMetric
316 super IntMetric
317 redef fun name do return "tdos"
318 redef fun desc do return "depth of generic signature"
319
320 redef fun collect(mtypes) do
321 for mtype in mtypes do
322 values[mtype] = mtype.signature_depth
323 end
324 end
325 end
326
327 # rta redef
328
329 redef class RapidTypeAnalysis
330 var cnli = new CNLI
331 var cnlc = new CNLC
332 var tnli = new TNLI
333 var tnlc = new TNLC
334
335 redef fun add_new(recv, mtype) do
336 super
337 tnli.values.inc(mtype)
338 cnli.values.inc(mtype.mclass)
339 end
340
341 redef fun add_cast(mtype) do
342 super
343 tnlc.values.inc(mtype)
344
345 if mtype isa MNullableType then mtype = mtype.mtype
346 if mtype isa MClassType then
347 cnlc.values.inc(mtype.mclass)
348 end
349 end
350 end
351
352 # model redefs
353
354 redef class MType
355 private fun signature_depth: Int do
356 var mtype = self
357 if mtype isa MNullableType then mtype = mtype.mtype
358 if not mtype isa MGenericType then return 0
359
360 var depth = 0
361 for ft in mtype.arguments do
362 var ftd = ft.signature_depth
363 if ftd > depth then depth = ftd
364 end
365 return depth + 1
366 end
367 end
368