modelbuilder: add parameter `given_mmodules` to `Phase::process_mainmodule`
[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, given_mmodules)
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
83 # dump type and method infos
84 if csv then
85 analysis.live_types_to_csv.save("{out}/rta_types.csv")
86 analysis.live_methods_to_tree.write_to_file("{out}/rta_methods.dat")
87 end
88 end
89 end
90
91 # Summary metrics
92
93 # MModule Metric: Number of Live Types
94 class MNLI
95 super MModuleMetric
96 super IntMetric
97 redef fun name do return "mnli"
98 redef fun desc do return "number of live instances in a mmodule"
99
100 var modelbuilder: ModelBuilder
101 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
102
103 redef fun collect(mainmodules) do
104 for mainmodule in mainmodules do
105 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
106 analysis.run_analysis
107 values[mainmodule] = analysis.tnli.sum
108 end
109 end
110 end
111
112 # MModule Metric: Number of Live Types
113 class MNLT
114 super MModuleMetric
115 super IntMetric
116 redef fun name do return "mnlt"
117 redef fun desc do return "number of live mtypes in a mmodule"
118
119 var modelbuilder: ModelBuilder
120 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
121
122 redef fun collect(mainmodules) do
123 for mainmodule in mainmodules do
124 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
125 analysis.run_analysis
126 values[mainmodule] = analysis.live_types.length
127 end
128 end
129 end
130
131 # MModule Metric: Number of Live Cast Types
132 class MNCT
133 super MModuleMetric
134 super IntMetric
135 redef fun name do return "mnct"
136 redef fun desc do return "number of live cast mtypes in a mmodule"
137
138 var modelbuilder: ModelBuilder
139 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
140
141 redef fun collect(mainmodules) do
142 for mainmodule in mainmodules do
143 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
144 analysis.run_analysis
145 values[mainmodule] = analysis.live_cast_types.length
146 end
147 end
148 end
149
150 # MModule Metric: Number of Live Classes
151 class MNLC
152 super MModuleMetric
153 super IntMetric
154 redef fun name do return "mnlc"
155 redef fun desc do return "number of live mclasses in a mmodule"
156
157 var modelbuilder: ModelBuilder
158 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
159
160 redef fun collect(mainmodules) do
161 for mainmodule in mainmodules do
162 var live = new HashSet[MClass]
163 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
164 analysis.run_analysis
165 for mtype in analysis.live_types do
166 live.add(mtype.mclass)
167 end
168 values[mainmodule] = live.length
169 end
170 end
171 end
172
173 # MModule Metric: Number of Live Methods
174 class MNLM
175 super MModuleMetric
176 super IntMetric
177 redef fun name do return "mnlm"
178 redef fun desc do return "number of live methods in a mmodule"
179
180 var modelbuilder: ModelBuilder
181 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
182
183 redef fun collect(mainmodules) do
184 for mainmodule in mainmodules do
185 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
186 analysis.run_analysis
187 values[mainmodule] = analysis.live_methods.length
188 end
189 end
190 end
191
192 # MModule Metric: Number of Live MethodDefs
193 class MNLMD
194 super MModuleMetric
195 super IntMetric
196 redef fun name do return "mnlmd"
197 redef fun desc do return "number of live method definitions in a mmodule"
198
199 var modelbuilder: ModelBuilder
200 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
201
202 redef fun collect(mainmodules) do
203 for mainmodule in mainmodules do
204 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
205 analysis.run_analysis
206 values[mainmodule] = analysis.live_methoddefs.length
207 end
208 end
209 end
210
211 # MModule Metric: Number of Dead MethodDefs
212 class MNLDD
213 super MModuleMetric
214 super IntMetric
215 redef fun name do return "mnldd"
216 redef fun desc do return "number of dead method definitions in a mmodule"
217
218 var modelbuilder: ModelBuilder
219 init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
220
221 redef fun collect(mainmodules) do
222 for mainmodule in mainmodules do
223 var dead = 0
224 var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
225 analysis.run_analysis
226 for mmethod in analysis.live_methods do
227 for mdef in mmethod.mpropdefs do
228 if analysis.live_methoddefs.has(mdef) or mdef.is_abstract then continue
229 dead += 1
230 end
231 end
232 values[mainmodule] = dead
233 end
234 end
235 end
236
237 # MClass metrics
238
239 # Class Metric: Number of Live Instances
240 #
241 # count all the `new` made on each mclass
242 class CNLI
243 super MClassMetric
244 super IntMetric
245 redef fun name do return "cnli"
246 redef fun desc do return "number of live instances for a mclass"
247
248 redef fun collect(mclasses) do end
249 end
250
251 # Class Metric: Number of Live Cast
252 #
253 # count all the cast made on each mclass type
254 class CNLC
255 super MClassMetric
256 super IntMetric
257 redef fun name do return "cnlc"
258 redef fun desc do return "number of live cast for a mclass type"
259
260 redef fun collect(mclasses) do end
261 end
262
263 # MType metrics
264
265 # A metric about MType
266 interface MTypeMetric
267 super Metric
268 redef type ELM: MType
269 end
270
271 # Type Metric: Number of Live Instances
272 #
273 # count all the `new` made on each types
274 class TNLI
275 super MTypeMetric
276 super IntMetric
277 redef fun name do return "tnli"
278 redef fun desc do return "number of live instances for a mtype"
279
280 redef fun collect(mtypes) do end
281 end
282
283 # Type Metric: Number of Live Cast
284 #
285 # count all the cast made to each types
286 class TNLC
287 super MTypeMetric
288 super IntMetric
289 redef fun name do return "tnlc"
290 redef fun desc do return "number of live casts to a mtype"
291
292 redef fun collect(mtypes) do end
293 end
294
295 # Type Metric: Arity of Generic Signature
296 #
297 # tags(List[X]) = 1
298 # tags(Map[X, Y]) = 2
299 class TAGS
300 super MTypeMetric
301 super IntMetric
302 redef fun name do return "tags"
303 redef fun desc do return "arity of generic signature"
304
305 redef fun collect(mtypes) do
306 for mtype in mtypes do
307 if mtype isa MGenericType then
308 values[mtype] = mtype.arguments.length
309 else
310 values[mtype] = 0
311 end
312 end
313 end
314 end
315
316 # Type Metric: Depth of Generic Signature
317 #
318 # tdgs(List[X]) = 1
319 # tdgs(Map[X, List[Y]]) = 2
320 class TDGS
321 super MTypeMetric
322 super IntMetric
323 redef fun name do return "tdos"
324 redef fun desc do return "depth of generic signature"
325
326 redef fun collect(mtypes) do
327 for mtype in mtypes do
328 values[mtype] = mtype.signature_depth
329 end
330 end
331 end
332
333 # rta redef
334
335 redef class RapidTypeAnalysis
336 var cnli = new CNLI
337 var cnlc = new CNLC
338 var tnli = new TNLI
339 var tnlc = new TNLC
340
341 redef fun add_new(recv, mtype) do
342 super
343 tnli.values.inc(mtype)
344 cnli.values.inc(mtype.mclass)
345 end
346
347 redef fun add_cast(mtype) do
348 super
349 tnlc.values.inc(mtype)
350
351 if mtype isa MNullableType then mtype = mtype.mtype
352 if mtype isa MClassType then
353 cnlc.values.inc(mtype.mclass)
354 end
355 end
356 end
357
358 # model redefs
359
360 redef class MType
361 private fun signature_depth: Int do
362 var mtype = self
363 if mtype isa MNullableType then mtype = mtype.mtype
364 if not mtype isa MGenericType then return 0
365
366 var depth = 0
367 for ft in mtype.arguments do
368 var ftd = ft.signature_depth
369 if ftd > depth then depth = ftd
370 end
371 return depth + 1
372 end
373 end
374