1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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.
20 private import rapid_type_analysis
22 import mmodules_metrics
23 import mclasses_metrics
25 redef class ToolContext
27 # RTA related metrics phase
28 var rta_metrics_phase
: Phase = new RTAMetricsPhase(self, null)
31 private class RTAMetricsPhase
33 redef fun process_mainmodule
(mainmodule
, given_mmodules
)
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"
40 var model
= toolcontext
.modelbuilder
.model
41 var model_view
= model
.protected_view
43 print toolcontext
.format_h1
("\n# RTA metrics")
45 print toolcontext
.format_h2
("\n ## Live instances by mainmodules")
46 var mmetrics
= new MetricSet
47 mmetrics
.register
(new MNLC(mainmodule
, model_view
, toolcontext
.modelbuilder
))
48 mmetrics
.register
(new MNLT(mainmodule
, model_view
, toolcontext
.modelbuilder
))
49 mmetrics
.register
(new MNCT(mainmodule
, model_view
, toolcontext
.modelbuilder
))
50 mmetrics
.register
(new MNLI(mainmodule
, model_view
, toolcontext
.modelbuilder
))
51 mmetrics
.register
(new MNLM(mainmodule
, model_view
, toolcontext
.modelbuilder
))
52 mmetrics
.register
(new MNLMD(mainmodule
, model_view
, toolcontext
.modelbuilder
))
53 mmetrics
.register
(new MNLDD(mainmodule
, model_view
, toolcontext
.modelbuilder
))
54 mmetrics
.collect
(new HashSet[MModule].from
([mainmodule
]))
55 mmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
56 if csv
then mmetrics
.to_csv
.write_to_file
("{out}/{mainmodule}.csv")
58 var mtypes
= new HashSet[MType]
59 var analysis
= new RapidTypeAnalysis(toolcontext
.modelbuilder
, mainmodule
)
61 mtypes
.add_all
(analysis
.live_types
)
62 mtypes
.add_all
(analysis
.live_cast_types
)
64 print toolcontext
.format_h2
("\n ## Total live instances by mclasses")
65 var cmetrics
= new MetricSet
66 cmetrics
.register
(analysis
.cnli
)
67 cmetrics
.register
(analysis
.cnlc
)
68 cmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
69 if csv
then cmetrics
.to_csv
.write_to_file
("{out}/mclasses.csv")
71 print toolcontext
.format_h2
("\n ## Total live instances by mtypes")
72 var tmetrics
= new MetricSet
73 tmetrics
.register
(analysis
.tnli
)
74 tmetrics
.register
(analysis
.tnlc
)
75 tmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
76 if csv
then tmetrics
.to_csv
.write_to_file
("{out}/mtypes.csv")
78 print toolcontext
.format_h2
("\n ## MType complexity")
79 var gmetrics
= new MetricSet
80 gmetrics
.register
(new TAGS)
81 gmetrics
.register
(new TDGS)
82 gmetrics
.collect
(mtypes
)
83 gmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
84 if csv
then gmetrics
.to_csv
.write_to_file
("{out}/complexity.csv")
86 callsite_info
(analysis
)
88 # dump type and method infos
90 analysis
.live_types_to_csv
.write_to_file
("{out}/rta_types.csv")
91 analysis
.live_methods_to_tree
.write_to_file
("{out}/rta_methods.dat")
95 fun callsite_info
(rta
: RapidTypeAnalysis)
97 print toolcontext
.format_h2
("\n ## Callsites")
98 print
"* {rta.live_callsites.length} live callsites"
100 var csep
= new Counter[MPropDef]
101 var cglo
= new Counter[MPropDef]
102 var morphisme
= new Counter[Int]
103 for cs
in rta
.live_callsites
do
104 csep
.inc
(cs
.mpropdef
)
105 var targets
= rta
.live_targets
(cs
)
109 morphisme
.inc
(targets
.length
)
112 print toolcontext
.format_h3
("MMethodDef locally designated (by number of CallSites)")
114 csep
.print_elements
(5)
116 print toolcontext
.format_h3
("MMethodDef possibly invoked at runtime (by number of CallSites)")
118 cglo
.print_elements
(5)
124 # RTA related metric that needs a `modelbuilder`
128 # Modelbuilder used to access AST
129 var modelbuilder
: ModelBuilder
132 # MModule Metric: Number of Live Types
136 redef fun name
do return "mnli"
137 redef fun desc
do return "number of live instances in a mmodule"
140 redef fun collect
(mainmodules
) do
141 for mainmodule
in mainmodules
do
142 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
143 analysis
.run_analysis
144 values
[mainmodule
] = analysis
.tnli
.sum
149 # MModule Metric: Number of Live Types
153 redef fun name
do return "mnlt"
154 redef fun desc
do return "number of live mtypes in a mmodule"
156 redef fun collect
(mainmodules
) do
157 for mainmodule
in mainmodules
do
158 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
159 analysis
.run_analysis
160 values
[mainmodule
] = analysis
.live_types
.length
165 # MModule Metric: Number of Live Cast Types
169 redef fun name
do return "mnct"
170 redef fun desc
do return "number of live cast mtypes in a mmodule"
172 redef fun collect
(mainmodules
) do
173 for mainmodule
in mainmodules
do
174 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
175 analysis
.run_analysis
176 values
[mainmodule
] = analysis
.live_cast_types
.length
181 # MModule Metric: Number of Live Classes
185 redef fun name
do return "mnlc"
186 redef fun desc
do return "number of live mclasses in a mmodule"
188 redef fun collect
(mainmodules
) do
189 for mainmodule
in mainmodules
do
190 var live
= new HashSet[MClass]
191 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
192 analysis
.run_analysis
193 for mtype
in analysis
.live_types
do
194 live
.add
(mtype
.mclass
)
196 values
[mainmodule
] = live
.length
201 # MModule Metric: Number of Live Methods
205 redef fun name
do return "mnlm"
206 redef fun desc
do return "number of live methods in a mmodule"
208 redef fun collect
(mainmodules
) do
209 for mainmodule
in mainmodules
do
210 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
211 analysis
.run_analysis
212 values
[mainmodule
] = analysis
.live_methods
.length
217 # MModule Metric: Number of Live MethodDefs
221 redef fun name
do return "mnlmd"
222 redef fun desc
do return "number of live method definitions in a mmodule"
224 redef fun collect
(mainmodules
) do
225 for mainmodule
in mainmodules
do
226 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
227 analysis
.run_analysis
228 values
[mainmodule
] = analysis
.live_methoddefs
.length
233 # MModule Metric: Number of Dead MethodDefs
237 redef fun name
do return "mnldd"
238 redef fun desc
do return "number of dead method definitions in a mmodule"
240 redef fun collect
(mainmodules
) do
241 for mainmodule
in mainmodules
do
243 var analysis
= new RapidTypeAnalysis(modelbuilder
, mainmodule
)
244 analysis
.run_analysis
245 for mmethod
in analysis
.live_methods
do
246 for mdef
in mmethod
.mpropdefs
do
247 if analysis
.live_methoddefs
.has
(mdef
) or mdef
.is_abstract
then continue
251 values
[mainmodule
] = dead
258 # Class Metric: Number of Live Instances
260 # count all the `new` made on each mclass
264 redef fun name
do return "cnli"
265 redef fun desc
do return "number of live instances for a mclass"
267 redef fun collect
(mclasses
) do end
270 # Class Metric: Number of Live Cast
272 # count all the cast made on each mclass type
276 redef fun name
do return "cnlc"
277 redef fun desc
do return "number of live cast for a mclass type"
279 redef fun collect
(mclasses
) do end
284 # A metric about MType
285 interface MTypeMetric
287 redef type ELM: MType
290 # Type Metric: Number of Live Instances
292 # count all the `new` made on each types
296 redef fun name
do return "tnli"
297 redef fun desc
do return "number of live instances for a mtype"
299 redef fun collect
(mtypes
) do end
302 # Type Metric: Number of Live Cast
304 # count all the cast made to each types
308 redef fun name
do return "tnlc"
309 redef fun desc
do return "number of live casts to a mtype"
311 redef fun collect
(mtypes
) do end
314 # Type Metric: Arity of Generic Signature
317 # tags(Map[X, Y]) = 2
321 redef fun name
do return "tags"
322 redef fun desc
do return "arity of generic signature"
324 redef fun collect
(mtypes
) do
325 for mtype
in mtypes
do
326 if mtype
isa MGenericType then
327 values
[mtype
] = mtype
.arguments
.length
335 # Type Metric: Depth of Generic Signature
338 # tdgs(Map[X, List[Y]]) = 2
342 redef fun name
do return "tdos"
343 redef fun desc
do return "depth of generic signature"
345 redef fun collect
(mtypes
) do
346 for mtype
in mtypes
do
347 values
[mtype
] = mtype
.signature_depth
354 redef class RapidTypeAnalysis
356 # Class Live Instances
357 var cnli
: CNLI is lazy
do return new CNLI(mainmodule
, modelbuilder
.model
.protected_view
)
360 var cnlc
: CNLC is lazy
do return new CNLC(mainmodule
, modelbuilder
.model
.protected_view
)
362 # Type Live Instances
368 redef fun add_new
(recv
, mtype
) do
370 tnli
.values
.inc
(mtype
)
371 cnli
.values
.inc
(mtype
.mclass
)
374 redef fun add_cast
(mtype
) do
376 tnlc
.values
.inc
(mtype
)
378 mtype
= mtype
.undecorate
379 if mtype
isa MClassType then
380 cnlc
.values
.inc
(mtype
.mclass
)
388 private fun signature_depth
: Int do
389 var mtype
= self.undecorate
390 if not mtype
isa MGenericType then return 0
393 for ft
in mtype
.arguments
do
394 var ftd
= ft
.signature_depth
395 if ftd
> depth
then depth
= ftd