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 filter
= new ModelFilter(min_visibility
= protected_visibility
)
42 var model_view
= new ModelView(model
, mainmodule
, filter
)
44 print toolcontext
.format_h1
("\n# RTA metrics")
46 print toolcontext
.format_h2
("\n ## Live instances by mainmodules")
47 var mmetrics
= new MetricSet
48 mmetrics
.register
(new MNLC(model_view
, toolcontext
.modelbuilder
))
49 mmetrics
.register
(new MNLT(model_view
, toolcontext
.modelbuilder
))
50 mmetrics
.register
(new MNCT(model_view
, toolcontext
.modelbuilder
))
51 mmetrics
.register
(new MNLI(model_view
, toolcontext
.modelbuilder
))
52 mmetrics
.register
(new MNLM(model_view
, toolcontext
.modelbuilder
))
53 mmetrics
.register
(new MNLMD(model_view
, toolcontext
.modelbuilder
))
54 mmetrics
.register
(new MNLDD(model_view
, toolcontext
.modelbuilder
))
55 mmetrics
.collect
(new HashSet[MModule].from
([mainmodule
]))
56 mmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
57 if csv
then mmetrics
.to_csv
.write_to_file
("{out}/{mainmodule}.csv")
59 var mtypes
= new HashSet[MType]
60 var analysis
= new MetricsRapidTypeAnalysis(toolcontext
.modelbuilder
, mainmodule
, model_view
)
62 mtypes
.add_all
(analysis
.live_types
)
63 mtypes
.add_all
(analysis
.live_cast_types
)
65 print toolcontext
.format_h2
("\n ## Total live instances by mclasses")
66 var cmetrics
= new MetricSet
67 cmetrics
.register
(analysis
.cnli
)
68 cmetrics
.register
(analysis
.cnlc
)
69 cmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
70 if csv
then cmetrics
.to_csv
.write_to_file
("{out}/mclasses.csv")
72 print toolcontext
.format_h2
("\n ## Total live instances by mtypes")
73 var tmetrics
= new MetricSet
74 tmetrics
.register
(analysis
.tnli
)
75 tmetrics
.register
(analysis
.tnlc
)
76 tmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
77 if csv
then tmetrics
.to_csv
.write_to_file
("{out}/mtypes.csv")
79 print toolcontext
.format_h2
("\n ## MType complexity")
80 var gmetrics
= new MetricSet
81 gmetrics
.register
(new TAGS)
82 gmetrics
.register
(new TDGS)
83 gmetrics
.collect
(mtypes
)
84 gmetrics
.to_console
(1, not toolcontext
.opt_nocolors
.value
)
85 if csv
then gmetrics
.to_csv
.write_to_file
("{out}/complexity.csv")
87 callsite_info
(analysis
)
89 # dump type and method infos
91 analysis
.live_types_to_csv
.write_to_file
("{out}/rta_types.csv")
92 analysis
.live_methods_to_tree
.write_to_file
("{out}/rta_methods.dat")
96 fun callsite_info
(rta
: RapidTypeAnalysis)
98 print toolcontext
.format_h2
("\n ## Callsites")
99 print
"* {rta.live_callsites.length} live callsites"
101 var csep
= new Counter[MPropDef]
102 var cglo
= new Counter[MPropDef]
103 var morphisme
= new Counter[Int]
104 for cs
in rta
.live_callsites
do
105 csep
.inc
(cs
.mpropdef
)
106 var targets
= rta
.live_targets
(cs
)
110 morphisme
.inc
(targets
.length
)
113 print toolcontext
.format_h3
("MMethodDef locally designated (by number of CallSites)")
115 csep
.print_elements
(5)
117 print toolcontext
.format_h3
("MMethodDef possibly invoked at runtime (by number of CallSites)")
119 cglo
.print_elements
(5)
125 # RTA related metric that needs a `modelbuilder`
129 # Modelbuilder used to access AST
130 var modelbuilder
: ModelBuilder
133 # MModule Metric: Number of Live Types
137 redef fun name
do return "mnli"
138 redef fun desc
do return "number of live instances in a mmodule"
141 redef fun collect
(mainmodules
) do
142 for mainmodule
in mainmodules
do
143 var analysis
= new MetricsRapidTypeAnalysis(modelbuilder
, mainmodule
, model_view
)
144 analysis
.run_analysis
145 values
[mainmodule
] = analysis
.tnli
.sum
150 # MModule Metric: Number of Live Types
154 redef fun name
do return "mnlt"
155 redef fun desc
do return "number of live mtypes in a mmodule"
157 redef fun collect
(mainmodules
) do
158 for mainmodule
in mainmodules
do
159 var analysis
= new MetricsRapidTypeAnalysis(modelbuilder
, mainmodule
, model_view
)
160 analysis
.run_analysis
161 values
[mainmodule
] = analysis
.live_types
.length
166 # MModule Metric: Number of Live Cast Types
170 redef fun name
do return "mnct"
171 redef fun desc
do return "number of live cast mtypes in a mmodule"
173 redef fun collect
(mainmodules
) do
174 for mainmodule
in mainmodules
do
175 var analysis
= new MetricsRapidTypeAnalysis(modelbuilder
, mainmodule
, model_view
)
176 analysis
.run_analysis
177 values
[mainmodule
] = analysis
.live_cast_types
.length
182 # MModule Metric: Number of Live Classes
186 redef fun name
do return "mnlc"
187 redef fun desc
do return "number of live mclasses in a mmodule"
189 redef fun collect
(mainmodules
) do
190 for mainmodule
in mainmodules
do
191 var live
= new HashSet[MClass]
192 var analysis
= new MetricsRapidTypeAnalysis(modelbuilder
, mainmodule
, model_view
)
193 analysis
.run_analysis
194 for mtype
in analysis
.live_types
do
195 live
.add
(mtype
.mclass
)
197 values
[mainmodule
] = live
.length
202 # MModule Metric: Number of Live Methods
206 redef fun name
do return "mnlm"
207 redef fun desc
do return "number of live methods in a mmodule"
209 redef fun collect
(mainmodules
) do
210 for mainmodule
in mainmodules
do
211 var analysis
= new MetricsRapidTypeAnalysis(modelbuilder
, mainmodule
, model_view
)
212 analysis
.run_analysis
213 values
[mainmodule
] = analysis
.live_methods
.length
218 # MModule Metric: Number of Live MethodDefs
222 redef fun name
do return "mnlmd"
223 redef fun desc
do return "number of live method definitions in a mmodule"
225 redef fun collect
(mainmodules
) do
226 for mainmodule
in mainmodules
do
227 var analysis
= new MetricsRapidTypeAnalysis(modelbuilder
, mainmodule
, model_view
)
228 analysis
.run_analysis
229 values
[mainmodule
] = analysis
.live_methoddefs
.length
234 # MModule Metric: Number of Dead MethodDefs
238 redef fun name
do return "mnldd"
239 redef fun desc
do return "number of dead method definitions in a mmodule"
241 redef fun collect
(mainmodules
) do
242 for mainmodule
in mainmodules
do
244 var analysis
= new MetricsRapidTypeAnalysis(modelbuilder
, mainmodule
, model_view
)
245 analysis
.run_analysis
246 for mmethod
in analysis
.live_methods
do
247 for mdef
in mmethod
.mpropdefs
do
248 if analysis
.live_methoddefs
.has
(mdef
) or mdef
.is_abstract
then continue
252 values
[mainmodule
] = dead
259 # Class Metric: Number of Live Instances
261 # count all the `new` made on each mclass
265 redef fun name
do return "cnli"
266 redef fun desc
do return "number of live instances for a mclass"
268 redef fun collect
(mclasses
) do end
271 # Class Metric: Number of Live Cast
273 # count all the cast made on each mclass type
277 redef fun name
do return "cnlc"
278 redef fun desc
do return "number of live cast for a mclass type"
280 redef fun collect
(mclasses
) do end
285 # A metric about MType
286 interface MTypeMetric
288 redef type ELM: MType
291 # Type Metric: Number of Live Instances
293 # count all the `new` made on each types
297 redef fun name
do return "tnli"
298 redef fun desc
do return "number of live instances for a mtype"
300 redef fun collect
(mtypes
) do end
303 # Type Metric: Number of Live Cast
305 # count all the cast made to each types
309 redef fun name
do return "tnlc"
310 redef fun desc
do return "number of live casts to a mtype"
312 redef fun collect
(mtypes
) do end
315 # Type Metric: Arity of Generic Signature
318 # tags(Map[X, Y]) = 2
322 redef fun name
do return "tags"
323 redef fun desc
do return "arity of generic signature"
325 redef fun collect
(mtypes
) do
326 for mtype
in mtypes
do
327 if mtype
isa MGenericType then
328 values
[mtype
] = mtype
.arguments
.length
336 # Type Metric: Depth of Generic Signature
339 # tdgs(Map[X, List[Y]]) = 2
343 redef fun name
do return "tdos"
344 redef fun desc
do return "depth of generic signature"
346 redef fun collect
(mtypes
) do
347 for mtype
in mtypes
do
348 values
[mtype
] = mtype
.signature_depth
355 # Custom RTA analyzer
356 class MetricsRapidTypeAnalysis
357 super RapidTypeAnalysis
359 # Model view used to linearize classes
362 # Class Live Instances
363 var cnli
: CNLI is lazy
do return new CNLI(view
)
366 var cnlc
: CNLC is lazy
do return new CNLC(view
)
368 # Type Live Instances
374 redef fun add_new
(recv
, mtype
) do
376 tnli
.values
.inc
(mtype
)
377 cnli
.values
.inc
(mtype
.mclass
)
380 redef fun add_cast
(mtype
) do
382 tnlc
.values
.inc
(mtype
)
384 mtype
= mtype
.undecorate
385 if mtype
isa MClassType then
386 cnlc
.values
.inc
(mtype
.mclass
)
394 private fun signature_depth
: Int do
395 var mtype
= self.undecorate
396 if not mtype
isa MGenericType then return 0
399 for ft
in mtype
.arguments
do
400 var ftd
= ft
.signature_depth
401 if ftd
> depth
then depth
= ftd