2bb61cb98d50728f32305cbf40ffbb7b61292603
1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 # Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
18 # Helpers for various statistics tools.
26 redef class ToolContext
29 var opt_all
= new OptionBool("Compute all metrics", "--all")
32 var opt_mmodules
= new OptionBool("Compute metrics about mmodules", "--mmodules")
34 var opt_mclasses
= new OptionBool("Compute metrics about mclasses", "--mclasses")
37 var opt_inheritance
= new OptionBool("Compute metrics about inheritance usage", "--inheritance")
39 var opt_refinement
= new OptionBool("Compute metrics about refinement usage", "--refinement")
41 var opt_self
= new OptionBool("Compute metrics about the usage of explicit and implicit self", "--self")
43 var opt_ast
= new OptionBool("Compute metrics about the usage of nodes and identifiers in the AST", "--ast")
45 var opt_nullables
= new OptionBool("Compute metrics on nullables send", "--nullables")
47 var opt_static_types
= new OptionBool("Compute explicit static types metrics", "--static-types")
49 var opt_tables
= new OptionBool("Compute tables metrics", "--tables")
51 var opt_rta
= new OptionBool("Compute RTA metrics", "--rta")
53 var opt_generate_csv
= new OptionBool("Generate CVS format metrics", "--generate-csv")
55 var opt_generate_hyperdoc
= new OptionBool("Generate Hyperdoc", "--generate_hyperdoc")
57 var opt_poset
= new OptionBool("Complete metrics on posets", "--poset")
60 var opt_nocolors
= new OptionBool("Disable colors in console outputs", "--no-colors")
63 var opt_dir
= new OptionString("Directory where some statistics files are generated", "-d", "--dir")
64 var output_dir
: String = "."
69 self.option_context
.add_option
(opt_all
)
70 self.option_context
.add_option
(opt_mmodules
)
71 self.option_context
.add_option
(opt_mclasses
)
72 self.option_context
.add_option
(opt_inheritance
)
73 self.option_context
.add_option
(opt_refinement
)
74 self.option_context
.add_option
(opt_self
)
75 self.option_context
.add_option
(opt_ast
)
76 self.option_context
.add_option
(opt_nullables
)
77 self.option_context
.add_option
(opt_static_types
)
78 self.option_context
.add_option
(opt_tables
)
79 self.option_context
.add_option
(opt_rta
)
80 self.option_context
.add_option
(opt_generate_csv
)
81 self.option_context
.add_option
(opt_generate_hyperdoc
)
82 self.option_context
.add_option
(opt_poset
)
83 self.option_context
.add_option
(opt_dir
)
84 self.option_context
.add_option
(opt_nocolors
)
87 redef fun process_options
90 var val
= self.opt_dir
.value
92 val
= val
.simplify_path
98 # colorize heading 1 for console output
99 fun format_h1
(str
: String): String do
100 if opt_nocolors
.value
then return str
101 return str
.yellow
.bold
104 fun format_h2
(str
: String): String do
105 if opt_nocolors
.value
then return str
109 fun format_h3
(str
: String): String do
110 if opt_nocolors
.value
then return str
114 fun format_h4
(str
: String): String do
115 if opt_nocolors
.value
then return str
119 fun format_p
(str
: String): String do
120 if opt_nocolors
.value
then return str
121 return str
.light_gray
127 # is the class imported from standard lib?
128 fun is_standard
: Bool do
129 return self.intro_mmodule
.mgroup
.mproject
.name
== "standard"
134 # is the module imported from standard lib?
135 fun is_standard
: Bool do
136 return self.mgroup
.mproject
.name
== "standard"
140 # A Metric is used to collect data about things
142 # The concept is reified here for a better organization and documentation
146 type RES: Map[ELM, VAL]
148 fun name
: String is abstract
149 fun desc
: String is abstract
151 # Clear all results for this metric
152 fun clear
is abstract
154 # Values for each element
155 fun values
: RES is abstract
157 # Collect metric values on elements
158 fun collect
(elements
: Set[ELM]) is abstract
160 # The value calculated for the element
161 fun [](element
: ELM): VAL do return values
[element
]
163 # Does the element have a value for this metric?
164 fun has_element
(element
: ELM): Bool do return values
.has_key
(element
)
167 fun avg
: Float is abstract
169 # Pretty print the metric results in console
170 fun to_console
(indent
: Int, colors
: Bool) do
174 print
"{"\t" * indent}{name}: {desc}".green
175 print
"{"\t" * indent} avg: {avg}".light_gray
176 print
"{"\t" * indent} max: {max} ({self[max]})".light_gray
177 print
"{"\t" * indent} min: {min} ({self[min]})".light_gray
178 print
"{"\t" * indent} std: {std_dev}".light_gray
180 print
"{"\t" * indent}{name}: {desc}"
181 print
"{"\t" * indent} avg: {avg}"
182 print
"{"\t" * indent} max: {max} ({self[max]})"
183 print
"{"\t" * indent} min: {min} ({self[min]})"
184 print
"{"\t" * indent} std: {std_dev}"
188 # The values standard derivation
189 fun std_dev
: Float is abstract
192 # A Metric that collects integer data
194 # Used to count things
199 redef type RES: Counter[ELM]
201 protected var values_cache
= new Counter[ELM]
202 redef fun values
do return values_cache
204 redef fun clear
do values_cache
.clear
206 # Return the couple with the highest value
207 fun max
: Couple[ELM, Int] do
208 assert not values_cache
.is_empty
209 var elem
= values_cache
.max
.as(not null)
210 var value
= values_cache
[elem
]
211 return new Couple[ELM, Int](elem
, value
)
214 # Return the couple with the lowest value
215 fun min
: Couple[ELM, Int] do
216 assert not values_cache
.is_empty
217 var elem
= values_cache
.min
.as(not null)
218 var value
= values_cache
[elem
]
219 return new Couple[ELM, Int](elem
, value
)
223 redef fun avg
: Float do return values_cache
.avg
225 redef fun std_dev
: Float do return values_cache
.std_dev
228 # A Metric that collects float datas
230 # Used sor summarization
234 redef type VAL: Float
236 protected var values_cache
= new HashMap[ELM, VAL]
237 redef fun values
do return values_cache
239 redef fun clear
do values_cache
.clear
241 # Return the couple with the highest value
242 fun max
: Couple[ELM, Float] do
243 assert not values
.is_empty
244 var max
: nullable Float = null
245 var elem
: nullable ELM = null
246 for e
, v
in values
do
247 if max
== null or v
> max
then
252 return new Couple[ELM, Float](elem
.as(not null), max
.as(not null))
255 # Return the couple with the lowest value
256 fun min
: Couple[ELM, Float] do
257 assert not values
.is_empty
258 var min
: nullable Float = null
259 var elem
: nullable ELM = null
260 for e
, v
in values
do
261 if min
== null or v
< min
then
266 return new Couple[ELM, Float](elem
.as(not null), min
.as(not null))
270 if values
.is_empty
then return 0.0
272 for value
in values
.values
do
275 return sum
/ values
.length
.to_f
278 redef fun std_dev
: Float do
280 for value
in values
.values
do
281 sum
+= (value
- avg
).pow
(2.to_f
)
283 return (sum
/ values
.length
.to_f
).sqrt
287 # A MetricSet is a metric holder
289 # It purpose is to be extended with a metric collect service
294 var metrics
: Set[Metric] = new HashSet[Metric]
296 # Add a metric to the set
297 fun register
(metrics
: Metric...) do for metric
in metrics
do self.metrics
.add
(metric
)
299 # Clear all results for all metrics
300 fun clear
do for metric
in metrics
do metric
.clear
302 # Collect all metrics for this set of class
303 fun collect
(elements
: Set[ELM]) do
304 for metric
in metrics
do metric
.collect
(elements
)
307 # Pretty print the resuls in console
308 fun to_console
(indent
: Int, colors
: Bool) do
309 for metric
in metrics
do metric
.to_console
(indent
, colors
)