3651aa70f42e78d9dc0320c497086db2b4f04641
1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 Alexandre Terrasa <alexandre@moz-code.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.
17 # Collect common metrics about mclasses
18 module mclasses_metrics
25 redef class ToolContext
26 var mclasses_metrics_phase
= new MClassesMetricsPhase(self, null)
29 # Extract metrics about mclasses from model.
30 private class MClassesMetricsPhase
32 redef fun process_mainmodule
(mainmodule
)
34 if not toolcontext
.opt_mclasses
.value
and not toolcontext
.opt_all
.value
then return
36 print
"\n# MClasses metrics".yellow
.bold
38 var metrics
= new MClassMetricSet
39 metrics
.register
(new CNOA, new CNOP, new CNOC, new CNOD, new CDIT)
40 metrics
.register
(new CNBIP, new CNBRP, new CNBHP)
41 #TODO metrics.register(new CNBI) # nb init
42 #TODO metrics.register(new CNBA) # nb attrs
43 #TODO metrics.register(new CNBM) # nb methods
44 #TODO metrics.register(new CNBV) # nb vtypes
46 var model
= toolcontext
.modelbuilder
.model
47 var mclasses
= new HashSet[MClass]
48 for mproject
in model
.mprojects
do
50 print
"\n ## project {mproject}".bold
52 for mgroup
in mproject
.mgroups
do
53 if mgroup
.mmodules
.is_empty
then continue
56 print
" `- group {mgroup.full_name}"
58 var mod_mclasses
= new HashSet[MClass]
59 for mmodule
in mgroup
.mmodules
do mod_mclasses
.add_all
(mmodule
.intro_mclasses
)
60 if mod_mclasses
.is_empty
then continue
61 mclasses
.add_all
(mod_mclasses
)
62 metrics
.collect
(new HashSet[MClass].from
(mod_mclasses
), mainmodule
)
63 for name
, metric
in metrics
.metrics
do
64 print
"\t{name}: {metric.desc}".green
65 print
"\t avg: {metric.avg}".light_gray
67 print
"\t max: {max.first} ({max.second})".light_gray
69 print
"\t min: {min.first} ({min.second})".light_gray
73 if not mclasses
.is_empty
then
75 print
"\n ## global metrics".bold
77 metrics
.collect
(mclasses
, mainmodule
)
78 for name
, metric
in metrics
.metrics
do
79 print
"\t{name}: {metric.desc}".green
80 print
"\t avg: {metric.avg}".light_gray
82 print
"\t max: {max.first} ({max.second})".light_gray
84 print
"\t min: {min.first} ({min.second})".light_gray
90 # An MetricSet for MClasses metrics
93 redef type METRIC: MClassMetric
95 # Collect all the metrics on the set of MClasses
96 fun collect
(mclasses
: Set[MClass], mainmodule
: MModule) do
98 for metric
in metrics
.values
do
99 for mclass
in mclasses
do
100 metric
.collect
(mclass
, mainmodule
)
106 # An abstract metric about MClass
107 abstract class MClassMetric
108 super IntMetric[MClass]
109 # Collect the metric value for this mclass
110 fun collect
(mclass
: MClass, mainmodule
: MModule) is abstract
113 # Class Metric: Number of Ancestors
116 redef fun name
do return "cnoa"
117 redef fun desc
do return "number of ancestor classes"
119 redef fun collect
(mclass
, mainmodule
) do
120 values
[mclass
] = mclass
.in_hierarchy
(mainmodule
).greaters
.length
- 1
124 # Class Metric: Number of Parents
127 redef fun name
do return "cnop"
128 redef fun desc
do return "number of parent classes"
130 redef fun collect
(mclass
, mainmodule
) do
131 values
[mclass
] = mclass
.in_hierarchy
(mainmodule
).direct_greaters
.length
135 # Class Metric: Number of Children
138 redef fun name
do return "cnoc"
139 redef fun desc
do return "number of child classes"
141 redef fun collect
(mclass
, mainmodule
) do
142 values
[mclass
] = mclass
.in_hierarchy
(mainmodule
).direct_smallers
.length
146 # Class Metric: Number of Descendants
149 redef fun name
do return "cnod"
150 redef fun desc
do return "number of descendant classes"
152 redef fun collect
(mclass
, mainmodule
) do
153 values
[mclass
] = mclass
.in_hierarchy
(mainmodule
).smallers
.length
- 1
157 # Class Metric: Depth in Inheritance Tree
160 redef fun name
do return "cdit"
161 redef fun desc
do return "depth in class tree"
163 redef fun collect
(mclass
, mainmodule
) do
164 values
[mclass
] = mclass
.in_hierarchy
(mainmodule
).depth
168 # Class Metric: Number of Introduced MProperties
171 redef fun name
do return "cnbip"
172 redef fun desc
do return "number of introduced properties"
174 redef fun collect
(mclass
, mainmodule
) do
175 values
[mclass
] = mclass
.intro_mproperties
.length
179 # Class Metric: Number of Refined MProperties
182 redef fun name
do return "cnbrp"
183 redef fun desc
do return "number of redefined properties"
185 redef fun collect
(mclass
, mainmodule
) do
186 values
[mclass
] = mclass
.redef_mproperties
.length
190 # Class Metric: Number of Inherited MProperties
193 redef fun name
do return "cnbhp"
194 redef fun desc
do return "number of inherited properties"
196 redef fun collect
(mclass
, mainmodule
) do
197 values
[mclass
] = mclass
.inherited_mproperties2
(mainmodule
).length
202 # FIXME wait for cleaning in model_utils
203 redef fun intro_mproperties
: Set[MProperty] do
204 var set
= new HashSet[MProperty]
205 for mclassdef
in mclassdefs
do
206 set
.add_all
(mclassdef
.intro_mproperties
)
211 # FIXME wait for cleaning in model_utils
212 redef fun redef_mproperties
: Set[MProperty] do
213 var set
= new HashSet[MProperty]
214 for mclassdef
in mclassdefs
do
215 for mpropdef
in mclassdef
.mpropdefs
do
216 if mpropdef
.mproperty
.intro_mclassdef
.mclass
!= self then set
.add
(mpropdef
.mproperty
)
222 # FIXME wait for cleaning in model_utils
223 fun inherited_mproperties2
(mainmodule
: MModule): Set[MProperty] do
224 var set
= new HashSet[MProperty]
225 for parent
in in_hierarchy
(mainmodule
).direct_greaters
do
226 set
.add_all
(parent
.intro_mproperties
)
227 set
.add_all
(parent
.inherited_mproperties2
(mainmodule
))