nitmetrics: refactor static types metrics computation
[nit.git] / src / metrics / static_types_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 on the usage of explicit static types.
18 module static_types_metrics
19
20 private import metrics_base
21 import modelbuilder
22
23 # The job of this visitor is to resolve all types found
24 private class ATypeCounterVisitor
25 super Visitor
26 var modelbuilder: ModelBuilder
27 var nclassdef: AClassdef
28
29 var typecount: Counter[MType]
30
31 # Get a new visitor on a classef to add type count in `typecount'.
32 init(modelbuilder: ModelBuilder, nclassdef: AClassdef, typecount: Counter[MType])
33 do
34 self.modelbuilder = modelbuilder
35 self.nclassdef = nclassdef
36 self.typecount = typecount
37 end
38
39 redef fun visit(n)
40 do
41 if n isa AType then
42 var mtype = modelbuilder.resolve_mtype(self.nclassdef, n)
43 if mtype != null then
44 self.typecount.inc(mtype)
45 end
46 end
47 n.visit_all(self)
48 end
49 end
50
51 # Visit the AST and print metrics on the usage of explicit static types.
52 fun compute_static_types_metrics(modelbuilder: ModelBuilder)
53 do
54 # Count each occurence of a specific static type
55 var typecount = new Counter[MType]
56
57 # Visit all the source code to collect data
58 for nmodule in modelbuilder.nmodules do
59 for nclassdef in nmodule.n_classdefs do
60 var visitor = new ATypeCounterVisitor(modelbuilder, nclassdef, typecount)
61 visitor.enter_visit(nclassdef)
62 end
63 end
64
65 # Display data
66 print "--- Metrics of the explitic static types ---"
67 print "Total number of explicit static types: {typecount.total}"
68 if typecount.total == 0 then return
69
70 # types sorted by usage
71 var types = typecount.sort
72
73 # Display most used types (ie the last of `types')
74 print "Most used types: "
75 var min = 10
76 if types.length < min then min = types.length
77 for i in [0..min[ do
78 var t = types[types.length-i-1]
79 print " {t}: {typecount[t]}"
80 end
81
82 # Compute the distribution of type usage
83 print "Distribution of type usage:"
84 var count = 0
85 var sum = 0
86 var limit = 1
87 for t in types do
88 if typecount[t] > limit then
89 print " <={limit}: {count} ({div(count*100,types.length)}% of types; {div(sum*100,typecount.total)}% of usage)"
90 count = 0
91 sum = 0
92 while typecount[t] > limit do limit = limit * 2
93 end
94 count += 1
95 sum += typecount[t]
96 end
97 print " <={limit}: {count} ({div(count*100,types.length)}% of types; {div(sum*100,typecount.total)}% of usage)"
98 end