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.
21 private import rapid_type_analysis
22 private import metrics_base
23 import mmodules_metrics
24 import mclasses_metrics
27 redef class ToolContext
28 var rta_metrics_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 print toolcontext
.format_h1
("\n# RTA metrics")
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")
55 var mtypes
= new HashSet[MType]
56 var analysis
= new RapidTypeAnalysis(toolcontext
.modelbuilder
, mainmodule
)
58 mtypes
.add_all
(analysis
.live_types
)
59 mtypes
.add_all
(analysis
.live_cast_types
)
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")
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")
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")
83 # dump type and method infos
85 analysis
.live_types_to_csv
.save
("{out}/rta_types.csv")
86 analysis
.live_methods_to_tree
.write_to_file
("{out}/rta_methods.dat")
93 # MModule Metric: Number of Live Types
97 redef fun name
do return "mnli"
98 redef fun desc
do return "number of live instances in a mmodule"
100 var modelbuilder
: ModelBuilder
101 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
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
112 # MModule Metric: Number of Live Types
116 redef fun name
do return "mnlt"
117 redef fun desc
do return "number of live mtypes in a mmodule"
119 var modelbuilder
: ModelBuilder
120 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
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
131 # MModule Metric: Number of Live Cast Types
135 redef fun name
do return "mnct"
136 redef fun desc
do return "number of live cast mtypes in a mmodule"
138 var modelbuilder
: ModelBuilder
139 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
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
150 # MModule Metric: Number of Live Classes
154 redef fun name
do return "mnlc"
155 redef fun desc
do return "number of live mclasses in a mmodule"
157 var modelbuilder
: ModelBuilder
158 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
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
)
168 values
[mainmodule
] = live
.length
173 # MModule Metric: Number of Live Methods
177 redef fun name
do return "mnlm"
178 redef fun desc
do return "number of live methods in a mmodule"
180 var modelbuilder
: ModelBuilder
181 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
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
192 # MModule Metric: Number of Live MethodDefs
196 redef fun name
do return "mnlmd"
197 redef fun desc
do return "number of live method definitions in a mmodule"
199 var modelbuilder
: ModelBuilder
200 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
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
211 # MModule Metric: Number of Dead MethodDefs
215 redef fun name
do return "mnldd"
216 redef fun desc
do return "number of dead method definitions in a mmodule"
218 var modelbuilder
: ModelBuilder
219 init(modelbuilder
: ModelBuilder) do self.modelbuilder
= modelbuilder
221 redef fun collect
(mainmodules
) do
222 for mainmodule
in mainmodules
do
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
232 values
[mainmodule
] = dead
239 # Class Metric: Number of Live Instances
241 # count all the `new` made on each mclass
245 redef fun name
do return "cnli"
246 redef fun desc
do return "number of live instances for a mclass"
248 redef fun collect
(mclasses
) do end
251 # Class Metric: Number of Live Cast
253 # count all the cast made on each mclass type
257 redef fun name
do return "cnlc"
258 redef fun desc
do return "number of live cast for a mclass type"
260 redef fun collect
(mclasses
) do end
265 # A metric about MType
266 interface MTypeMetric
268 redef type ELM: MType
271 # Type Metric: Number of Live Instances
273 # count all the `new` made on each types
277 redef fun name
do return "tnli"
278 redef fun desc
do return "number of live instances for a mtype"
280 redef fun collect
(mtypes
) do end
283 # Type Metric: Number of Live Cast
285 # count all the cast made to each types
289 redef fun name
do return "tnlc"
290 redef fun desc
do return "number of live casts to a mtype"
292 redef fun collect
(mtypes
) do end
295 # Type Metric: Arity of Generic Signature
298 # tags(Map[X, Y]) = 2
302 redef fun name
do return "tags"
303 redef fun desc
do return "arity of generic signature"
305 redef fun collect
(mtypes
) do
306 for mtype
in mtypes
do
307 if mtype
isa MGenericType then
308 values
[mtype
] = mtype
.arguments
.length
316 # Type Metric: Depth of Generic Signature
319 # tdgs(Map[X, List[Y]]) = 2
323 redef fun name
do return "tdos"
324 redef fun desc
do return "depth of generic signature"
326 redef fun collect
(mtypes
) do
327 for mtype
in mtypes
do
328 values
[mtype
] = mtype
.signature_depth
335 redef class RapidTypeAnalysis
341 redef fun add_new
(recv
, mtype
) do
343 tnli
.values
.inc
(mtype
)
344 cnli
.values
.inc
(mtype
.mclass
)
347 redef fun add_cast
(mtype
) do
349 tnlc
.values
.inc
(mtype
)
351 if mtype
isa MNullableType then mtype
= mtype
.mtype
352 if mtype
isa MClassType then
353 cnlc
.values
.inc
(mtype
.mclass
)
361 private fun signature_depth
: Int do
363 if mtype
isa MNullableType then mtype
= mtype
.mtype
364 if not mtype
isa MGenericType then return 0
367 for ft
in mtype
.arguments
do
368 var ftd
= ft
.signature_depth
369 if ftd
> depth
then depth
= ftd