modelbuilder: `resolve_mtype` require a MClassDef instead of a AClassdef
[nit.git] / src / metrics / mclasses_metrics.nit
index 5babf79..ffdf69c 100644 (file)
@@ -23,24 +23,35 @@ import phase
 import frontend
 
 redef class ToolContext
 import frontend
 
 redef class ToolContext
-       var mclasses_metrics_phase = new MClassesMetricsPhase(self, null)
+       var mclasses_metrics_phase: Phase = new MClassesMetricsPhase(self, null)
 end
 
 # Extract metrics about mclasses from model.
 private class MClassesMetricsPhase
        super Phase
 end
 
 # Extract metrics about mclasses from model.
 private class MClassesMetricsPhase
        super Phase
-       redef fun process_mainmodule(mainmodule)
+       redef fun process_mainmodule(mainmodule, given_mmodules)
        do
                if not toolcontext.opt_mclasses.value and not toolcontext.opt_all.value then return
        do
                if not toolcontext.opt_mclasses.value and not toolcontext.opt_all.value then return
+               var csv = toolcontext.opt_csv.value
+               var out = "{toolcontext.opt_dir.value or else "metrics"}/mclasses"
+               out.mkdir
+
 
                print toolcontext.format_h1("\n# MClasses metrics")
 
 
                print toolcontext.format_h1("\n# MClasses metrics")
 
-               var metrics = new MClassMetricSet
+               var metrics = new MetricSet
                var min_vis = private_visibility
                var min_vis = private_visibility
-               metrics.register(new CNOA, new CNOP, new CNOC, new CNOD, new CDIT)
-               metrics.register(new CNBIP(min_vis), new CNBRP(min_vis), new CNBHP(min_vis))
+               metrics.register(new CNOA(mainmodule))
+               metrics.register(new CNOP(mainmodule))
+               metrics.register(new CNOC(mainmodule))
+               metrics.register(new CNOD(mainmodule))
+               metrics.register(new CDIT(mainmodule))
+               metrics.register(new CNBP(mainmodule, min_vis))
+               metrics.register(new CNBA(mainmodule, min_vis))
+               metrics.register(new CNBIP(mainmodule, min_vis))
+               metrics.register(new CNBRP(mainmodule, min_vis))
+               metrics.register(new CNBHP(mainmodule, min_vis))
                #TODO metrics.register(new CNBI) # nb init
                #TODO metrics.register(new CNBI) # nb init
-               #TODO metrics.register(new CNBA) # nb attrs
                #TODO metrics.register(new CNBM) # nb methods
                #TODO metrics.register(new CNBV) # nb vtypes
 
                #TODO metrics.register(new CNBM) # nb methods
                #TODO metrics.register(new CNBV) # nb vtypes
 
@@ -52,159 +63,249 @@ private class MClassesMetricsPhase
 
                        for mgroup in mproject.mgroups do
                                if mgroup.mmodules.is_empty then continue
 
                        for mgroup in mproject.mgroups do
                                if mgroup.mmodules.is_empty then continue
+                               metrics.clear
 
                                # Scalar metrics
                                print toolcontext.format_h3("  `- group {mgroup.full_name}")
 
                                # Scalar metrics
                                print toolcontext.format_h3("  `- group {mgroup.full_name}")
-
                                var mod_mclasses = new HashSet[MClass]
                                for mmodule in mgroup.mmodules do mod_mclasses.add_all(mmodule.intro_mclasses)
                                if mod_mclasses.is_empty then continue
                                mclasses.add_all(mod_mclasses)
                                var mod_mclasses = new HashSet[MClass]
                                for mmodule in mgroup.mmodules do mod_mclasses.add_all(mmodule.intro_mclasses)
                                if mod_mclasses.is_empty then continue
                                mclasses.add_all(mod_mclasses)
-                               metrics.collect(new HashSet[MClass].from(mod_mclasses), mainmodule)
-                               for name, metric in metrics.metrics do
-                                       print toolcontext.format_h4("\t{name}: {metric.desc}")
-                                       print toolcontext.format_p("\t    avg: {metric.avg}")
-                                       var max = metric.max
-                                       print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                                       var min = metric.min
-                                       print toolcontext.format_p("\t    min: {min.first} ({min.second})")
-                               end
+                               metrics.collect(new HashSet[MClass].from(mod_mclasses))
+                               metrics.to_console(1, not toolcontext.opt_nocolors.value)
+                               if csv then metrics.to_csv.save("{out}/{mgroup}.csv")
                        end
                end
                if not mclasses.is_empty then
                        end
                end
                if not mclasses.is_empty then
+                       metrics.clear
                        # Global metrics
                        print toolcontext.format_h2("\n ## global metrics")
                        # Global metrics
                        print toolcontext.format_h2("\n ## global metrics")
-
-                       metrics.collect(mclasses, mainmodule)
-                       for name, metric in metrics.metrics do
-                               print toolcontext.format_h4("\t{name}: {metric.desc}")
-                               print toolcontext.format_p("\t    avg: {metric.avg}")
-                               var max = metric.max
-                               print toolcontext.format_p("\t    max: {max.first} ({max.second})")
-                               var min = metric.min
-                               print toolcontext.format_p("\t    min: {min.first} ({min.second})")
-                       end
+                       metrics.collect(mclasses)
+                       metrics.to_console(1, not toolcontext.opt_nocolors.value)
+                       if csv then metrics.to_csv.save("{out}/summary.csv")
                end
        end
 end
 
                end
        end
 end
 
-# An MetricSet for MClasses metrics
-class MClassMetricSet
-       super MetricSet
-       redef type METRIC: MClassMetric
-
-       # Collect all the metrics on the set of MClasses
-       fun collect(mclasses: Set[MClass], mainmodule: MModule) do
-               clear
-               for metric in metrics.values do
-                       for mclass in mclasses do
-                               metric.collect(mclass, mainmodule)
-                       end
-               end
-       end
-end
-
-# An abstract metric about MClass
-abstract class MClassMetric
-       super IntMetric[MClass]
-       # Collect the metric value for this mclass
-       fun collect(mclass: MClass, mainmodule: MModule) is abstract
+# A metric about MClass
+interface MClassMetric
+       super Metric
+       redef type ELM: MClass
 end
 
 # Class Metric: Number of Ancestors
 class CNOA
        super MClassMetric
 end
 
 # Class Metric: Number of Ancestors
 class CNOA
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnoa"
        redef fun desc do return "number of ancestor classes"
 
        redef fun name do return "cnoa"
        redef fun desc do return "number of ancestor classes"
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.in_hierarchy(mainmodule).greaters.length - 1
+       var mainmodule: MModule
+       init(mainmodule: MModule) do self.mainmodule = mainmodule
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.in_hierarchy(mainmodule).greaters.length - 1
+               end
        end
 end
 
 # Class Metric: Number of Parents
 class CNOP
        super MClassMetric
        end
 end
 
 # Class Metric: Number of Parents
 class CNOP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnop"
        redef fun desc do return "number of parent classes"
 
        redef fun name do return "cnop"
        redef fun desc do return "number of parent classes"
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.in_hierarchy(mainmodule).direct_greaters.length
+       var mainmodule: MModule
+       init(mainmodule: MModule) do self.mainmodule = mainmodule
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.in_hierarchy(mainmodule).direct_greaters.length
+               end
        end
 end
 
 # Class Metric: Number of Children
 class CNOC
        super MClassMetric
        end
 end
 
 # Class Metric: Number of Children
 class CNOC
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnoc"
        redef fun desc do return "number of child classes"
 
        redef fun name do return "cnoc"
        redef fun desc do return "number of child classes"
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.in_hierarchy(mainmodule).direct_smallers.length
+       var mainmodule: MModule
+       init(mainmodule: MModule) do self.mainmodule = mainmodule
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.in_hierarchy(mainmodule).direct_smallers.length
+               end
        end
 end
 
 # Class Metric: Number of Descendants
 class CNOD
        super MClassMetric
        end
 end
 
 # Class Metric: Number of Descendants
 class CNOD
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnod"
        redef fun desc do return "number of descendant classes"
 
        redef fun name do return "cnod"
        redef fun desc do return "number of descendant classes"
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.in_hierarchy(mainmodule).smallers.length - 1
+       var mainmodule: MModule
+       init(mainmodule: MModule) do self.mainmodule = mainmodule
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.in_hierarchy(mainmodule).smallers.length - 1
+               end
        end
 end
 
 # Class Metric: Depth in Inheritance Tree
 class CDIT
        super MClassMetric
        end
 end
 
 # Class Metric: Depth in Inheritance Tree
 class CDIT
        super MClassMetric
+       super IntMetric
        redef fun name do return "cdit"
        redef fun desc do return "depth in class tree"
 
        redef fun name do return "cdit"
        redef fun desc do return "depth in class tree"
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.in_hierarchy(mainmodule).depth
+       var mainmodule: MModule
+       init(mainmodule: MModule) do self.mainmodule = mainmodule
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.in_hierarchy(mainmodule).depth
+               end
+       end
+end
+
+# Class Metric: Number of MProperties
+class CNBP
+       super MClassMetric
+       super IntMetric
+       redef fun name do return "cnbp"
+       redef fun desc do return "number of accessible properties (inherited + local)"
+
+       var mainmodule: MModule
+       var min_visibility: MVisibility
+
+       init(mainmodule: MModule, min_visibility: MVisibility) do
+               self.mainmodule = mainmodule
+               self.min_visibility = min_visibility
+       end
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.all_mproperties(mainmodule, min_visibility).length
+               end
+       end
+end
+
+# Class Metric: Number of MAttributes
+class CNBA
+       super MClassMetric
+       super IntMetric
+       redef fun name do return "cnba"
+       redef fun desc do return "number of accessible attributes (inherited + local)"
+
+       var mainmodule: MModule
+       var min_visibility: MVisibility
+
+       init(mainmodule: MModule, min_visibility: MVisibility) do
+               self.mainmodule = mainmodule
+               self.min_visibility = min_visibility
+       end
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.all_mattributes(mainmodule, min_visibility).length
+               end
        end
 end
 
 # Class Metric: Number of Introduced MProperties
 class CNBIP
        super MClassMetric
        end
 end
 
 # Class Metric: Number of Introduced MProperties
 class CNBIP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnbip"
        redef fun desc do return "number of introduced properties"
 
        redef fun name do return "cnbip"
        redef fun desc do return "number of introduced properties"
 
+       var mainmodule: MModule
        var min_visibility: MVisibility
        var min_visibility: MVisibility
-       init(min_visibility: MVisibility) do self.min_visibility = min_visibility
 
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.intro_mproperties(min_visibility).length
+       init(mainmodule: MModule, min_visibility: MVisibility) do
+               self.mainmodule = mainmodule
+               self.min_visibility = min_visibility
+       end
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.intro_mproperties(min_visibility).length
+               end
        end
 end
 
 # Class Metric: Number of Refined MProperties
 class CNBRP
        super MClassMetric
        end
 end
 
 # Class Metric: Number of Refined MProperties
 class CNBRP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnbrp"
        redef fun desc do return "number of redefined properties"
 
        redef fun name do return "cnbrp"
        redef fun desc do return "number of redefined properties"
 
+       var mainmodule: MModule
        var min_visibility: MVisibility
        var min_visibility: MVisibility
-       init(min_visibility: MVisibility) do self.min_visibility = min_visibility
 
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.redef_mproperties(min_visibility).length
+       init(mainmodule: MModule, min_visibility: MVisibility) do
+               self.mainmodule = mainmodule
+               self.min_visibility = min_visibility
+       end
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.redef_mproperties(min_visibility).length
+               end
        end
 end
 
 # Class Metric: Number of Inherited MProperties
 class CNBHP
        super MClassMetric
        end
 end
 
 # Class Metric: Number of Inherited MProperties
 class CNBHP
        super MClassMetric
+       super IntMetric
        redef fun name do return "cnbhp"
        redef fun desc do return "number of inherited properties"
 
        redef fun name do return "cnbhp"
        redef fun desc do return "number of inherited properties"
 
+       var mainmodule: MModule
        var min_visibility: MVisibility
        var min_visibility: MVisibility
-       init(min_visibility: MVisibility) do self.min_visibility = min_visibility
 
 
-       redef fun collect(mclass, mainmodule) do
-               values[mclass] = mclass.inherited_mproperties(mainmodule, min_visibility).length
+       init(mainmodule: MModule, min_visibility: MVisibility) do
+               self.mainmodule = mainmodule
+               self.min_visibility = min_visibility
+       end
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.inherited_mproperties(mainmodule, min_visibility).length
+               end
        end
 end
 
        end
 end
 
+# Class Metric: Number of Local MProperties (Intro + Redef)
+class CNBLP
+       super MClassMetric
+       super IntMetric
+       redef fun name do return "cnblp"
+       redef fun desc do return "number of local properties (intro + redef)"
+
+       var mainmodule: MModule
+       var min_visibility: MVisibility
+
+       init(mainmodule: MModule, min_visibility: MVisibility) do
+               self.mainmodule = mainmodule
+               self.min_visibility = min_visibility
+       end
+
+       redef fun collect(mclasses) do
+               for mclass in mclasses do
+                       values[mclass] = mclass.local_mproperties(min_visibility).length
+               end
+       end
+end