Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / metrics / mmodules_metrics.nit
index fc3a781..b740912 100644 (file)
 # Collect common metrics about modules
 module mmodules_metrics
 
 # Collect common metrics about modules
 module mmodules_metrics
 
-import model
 import metrics_base
 import metrics_base
-import phase
-import frontend
+import model::model_collect
 
 redef class ToolContext
 
 redef class ToolContext
-       var mmodules_metrics_phase = new MModulesMetricsPhase(self, null)
+
+       # MModules related metrics phase
+       var mmodules_metrics_phase: Phase = new MModulesMetricsPhase(self, null)
 end
 
 # Extract metrics about modules from the model.
 private class MModulesMetricsPhase
        super Phase
 end
 
 # Extract metrics about modules from the model.
 private class MModulesMetricsPhase
        super Phase
-       redef fun process_mainmodule(mainmodule)
+       redef fun process_mainmodule(mainmodule, given_mmodules)
        do
                if not toolcontext.opt_mmodules.value and not toolcontext.opt_all.value then return
        do
                if not toolcontext.opt_mmodules.value and not toolcontext.opt_all.value then return
+               var csv = toolcontext.opt_csv.value
+               var out = "{toolcontext.opt_dir.value or else "metrics"}/mmodules"
+               out.mkdir
+
+               var model = toolcontext.modelbuilder.model
 
                print toolcontext.format_h1("\n# MModules metrics")
 
 
                print toolcontext.format_h1("\n# MModules metrics")
 
-               var metrics = new MModuleMetricSet
-               metrics.register(new MNOA, new MNOP, new MNOC, new MNOD, new MDIT)
-               metrics.register(new MNBI, new MNBR, new MNBCC, new MNBAC, new MNBIC)
+               var metrics = new MetricSet
+               metrics.register(new MNOA(model, mainmodule))
+               metrics.register(new MNOP(model, mainmodule))
+               metrics.register(new MNOC(model, mainmodule))
+               metrics.register(new MNOD(model, mainmodule))
+               metrics.register(new MDIT(model, mainmodule))
+               metrics.register(new MNBI(model, mainmodule))
+               metrics.register(new MNBR(model, mainmodule))
+               metrics.register(new MNBCC(model, mainmodule))
+               metrics.register(new MNBAC(model, mainmodule))
+               metrics.register(new MNBIC(model, mainmodule))
 
 
-               var model = toolcontext.modelbuilder.model
                var mmodules = new HashSet[MModule]
                var mmodules = new HashSet[MModule]
-               for mproject in model.mprojects do
-
-                       print  toolcontext.format_h2("\n ## project {mproject}")
+               for mpackage in model.mpackages do
 
 
-                       for mgroup in mproject.mgroups do
+                       print  toolcontext.format_h2("\n ## package {mpackage}")
+                       for mgroup in mpackage.mgroups do
                                if mgroup.mmodules.is_empty then continue
 
                                # Scalar metrics
                                print  toolcontext.format_h3("  `- group {mgroup.full_name}")
                                if mgroup.mmodules.is_empty then continue
 
                                # Scalar metrics
                                print  toolcontext.format_h3("  `- group {mgroup.full_name}")
-
                                mmodules.add_all(mgroup.mmodules)
                                mmodules.add_all(mgroup.mmodules)
-                               metrics.collect(new HashSet[MModule].from(mgroup.mmodules), 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.clear
+                               metrics.collect(new HashSet[MModule].from(mgroup.mmodules))
+                               metrics.to_console(1, not toolcontext.opt_nocolors.value)
+                               if csv then metrics.to_csv.write_to_file("{out}/{mgroup}.csv")
                        end
                end
                if not mmodules.is_empty then
                        # Global metrics
                        print  toolcontext.format_h2("\n ## global metrics")
                        end
                end
                if not mmodules.is_empty then
                        # Global metrics
                        print  toolcontext.format_h2("\n ## global metrics")
-
-                       metrics.collect(mmodules, 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
-               end
-       end
-end
-
-# A MetricSet for metrics about MModules
-class MModuleMetricSet
-       super MetricSet
-       redef type METRIC: MModuleMetric
-
-       # Collect all the metrics on the set of MModules
-       fun collect(mmodules: Set[MModule], mainmodule: MModule) do
-               clear
-               for metric in metrics.values do
-                       for mmodule in mmodules do
-                               metric.collect(mmodule, mainmodule)
-                       end
+                       metrics.clear
+                       metrics.collect(mmodules)
+                       metrics.to_console(1, not toolcontext.opt_nocolors.value)
+                       if csv then metrics.to_csv.write_to_file("{out}/summary.csv")
                end
        end
 end
 
                end
        end
 end
 
-# An abstract Metric on MModules
+# A metric about MModule
 abstract class MModuleMetric
 abstract class MModuleMetric
-       super IntMetric[MModule]
-       # Collect the metric on the MModule
-       #
-       # Results are stored in the property `values`
-       fun collect(mmodule: MModule, mainmodule: MModule) is abstract
+       super Metric
+       redef type ELM: MModule
+
+       # Model view used to collect and filter entities
+       var model: Model
+
+       # Mainmodule used for linearization
+       var mainmodule: MModule
+
+       # Filter to apply on model if any
+       var filter: nullable ModelFilter
 end
 
 # Module Metric: Number of Ancestors
 class MNOA
        super MModuleMetric
 end
 
 # Module Metric: Number of Ancestors
 class MNOA
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnoa"
        redef fun desc do return "number of ancestor modules"
 
        redef fun name do return "mnoa"
        redef fun desc do return "number of ancestor modules"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = mmodule.in_importation.greaters.length - 1
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       values[mmodule] = mmodule.in_importation.greaters.length - 1
+               end
        end
 end
 
 # Module Metric: Number of Parents
 class MNOP
        super MModuleMetric
        end
 end
 
 # Module Metric: Number of Parents
 class MNOP
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnop"
        redef fun desc do return "number of parent modules"
 
        redef fun name do return "mnop"
        redef fun desc do return "number of parent modules"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = mmodule.in_importation.direct_greaters.length
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       values[mmodule] = mmodule.in_importation.direct_greaters.length
+               end
        end
 end
 
 # Module Metric: Number of Children
 class MNOC
        super MModuleMetric
        end
 end
 
 # Module Metric: Number of Children
 class MNOC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnoc"
        redef fun desc do return "number of child modules"
 
        redef fun name do return "mnoc"
        redef fun desc do return "number of child modules"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = mmodule.in_importation.direct_smallers.length
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       values[mmodule] = mmodule.in_importation.direct_smallers.length
+               end
        end
 end
 
 # Module Metric: Number of Descendants
 class MNOD
        super MModuleMetric
        end
 end
 
 # Module Metric: Number of Descendants
 class MNOD
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnod"
        redef fun desc do return "number of descendant modules"
 
        redef fun name do return "mnod"
        redef fun desc do return "number of descendant modules"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = mmodule.in_importation.smallers.length - 1
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       values[mmodule] = mmodule.in_importation.smallers.length - 1
+               end
        end
 end
 
 # Module Metric: Depth in Tree
 class MDIT
        super MModuleMetric
        end
 end
 
 # Module Metric: Depth in Tree
 class MDIT
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mdit"
        redef fun desc do return "depth in module tree"
 
        redef fun name do return "mdit"
        redef fun desc do return "depth in module tree"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = mmodule.in_importation.depth
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       values[mmodule] = mmodule.in_importation.depth
+               end
+       end
+end
+
+# Module Metric: Number of Accessible Definitions (of all kind)
+#
+# count all mclasses accessible by the module
+class MNBD
+       super MModuleMetric
+       super IntMetric
+       redef fun name do return "mnbd"
+       redef fun desc do return "number of definition accessibles in module"
+
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       values[mmodule] = 0
+                       for a in mmodule.collect_ancestors(mainmodule, filter) do
+                               values[mmodule] += a.intro_mclasses.length
+                       end
+               end
        end
 end
 
        end
 end
 
@@ -165,11 +188,14 @@ end
 # count all mclasses introduced by the module
 class MNBI
        super MModuleMetric
 # count all mclasses introduced by the module
 class MNBI
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbi"
        redef fun desc do return "number of introduction in module"
 
        redef fun name do return "mnbi"
        redef fun desc do return "number of introduction in module"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = mmodule.intro_mclasses.length
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       values[mmodule] = mmodule.intro_mclasses.length
+               end
        end
 end
 
        end
 end
 
@@ -178,13 +204,17 @@ end
 # count all mclasses refined in the module
 class MNBR
        super MModuleMetric
 # count all mclasses refined in the module
 class MNBR
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbr"
        redef fun desc do return "number of refinement in module"
 
        redef fun name do return "mnbr"
        redef fun desc do return "number of refinement in module"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = 0
-               for mclassdef in mmodule.mclassdefs do
-                       if not mclassdef.is_intro then values.inc(mmodule)
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       var value = 0
+                       for mclassdef in mmodule.mclassdefs do
+                               if not mclassdef.is_intro then value += 1
+                       end
+                       values[mmodule] = value
                end
        end
 end
                end
        end
 end
@@ -192,13 +222,17 @@ end
 # Module Metric: Number of Concrete Class in module (intro + redef)
 class MNBCC
        super MModuleMetric
 # Module Metric: Number of Concrete Class in module (intro + redef)
 class MNBCC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbcc"
        redef fun desc do return "number of concrete class in module (intro + redef)"
 
        redef fun name do return "mnbcc"
        redef fun desc do return "number of concrete class in module (intro + redef)"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = 0
-               for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == concrete_kind then values.inc(mmodule)
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       var value = 0
+                       for mclassdef in mmodule.mclassdefs do
+                               if mclassdef.mclass.kind == concrete_kind then value += 1
+                       end
+                       values[mmodule] = value
                end
        end
 end
                end
        end
 end
@@ -206,13 +240,17 @@ end
 # Module Metric: Number of Abstract Class in module (intro + redef)
 class MNBAC
        super MModuleMetric
 # Module Metric: Number of Abstract Class in module (intro + redef)
 class MNBAC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbac"
        redef fun desc do return "number of abstract class in module (intro + redef)"
 
        redef fun name do return "mnbac"
        redef fun desc do return "number of abstract class in module (intro + redef)"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = 0
-               for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == abstract_kind then values.inc(mmodule)
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       var value = 0
+                       for mclassdef in mmodule.mclassdefs do
+                               if mclassdef.mclass.kind == abstract_kind then value += 1
+                       end
+                       values[mmodule] = value
                end
        end
 end
                end
        end
 end
@@ -220,13 +258,17 @@ end
 # Module Metric: Number of Interface in module (intro + redef)
 class MNBIC
        super MModuleMetric
 # Module Metric: Number of Interface in module (intro + redef)
 class MNBIC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbic"
        redef fun desc do return "number of interface in module (intro + redef)"
 
        redef fun name do return "mnbic"
        redef fun desc do return "number of interface in module (intro + redef)"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = 0
-               for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == interface_kind then values.inc(mmodule)
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       var value = 0
+                       for mclassdef in mmodule.mclassdefs do
+                               if mclassdef.mclass.kind == interface_kind then value += 1
+                       end
+                       values[mmodule] = value
                end
        end
 end
                end
        end
 end
@@ -234,15 +276,17 @@ end
 # Module Metric: Number of Enum in module (intro + redef)
 class MNBEC
        super MModuleMetric
 # Module Metric: Number of Enum in module (intro + redef)
 class MNBEC
        super MModuleMetric
+       super IntMetric
        redef fun name do return "mnbec"
        redef fun desc do return "number of enum in module (intro + redef)"
 
        redef fun name do return "mnbec"
        redef fun desc do return "number of enum in module (intro + redef)"
 
-       redef fun collect(mmodule, main) do
-               values[mmodule] = 0
-               for mclassdef in mmodule.mclassdefs do
-                       if mclassdef.mclass.kind == enum_kind then values.inc(mmodule)
+       redef fun collect(mmodules) do
+               for mmodule in mmodules do
+                       var value = 0
+                       for mclassdef in mmodule.mclassdefs do
+                               if mclassdef.mclass.kind == enum_kind then value += 1
+                       end
+                       values[mmodule] = value
                end
        end
 end
                end
        end
 end
-
-