metrics: extract mmodule_metrics in its own module
authorAlexandre Terrasa <alexandre@moz-code.org>
Tue, 25 Feb 2014 06:33:51 +0000 (01:33 -0500)
committerAlexandre Terrasa <alexandre@moz-code.org>
Fri, 28 Feb 2014 18:35:15 +0000 (13:35 -0500)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/metrics/metrics.nit
src/metrics/metrics_base.nit
src/metrics/mmodules_metrics.nit [new file with mode: 0644]
tests/sav/nitmetrics.res

index c1f1830..9ccd25d 100644 (file)
@@ -18,6 +18,7 @@
 module metrics
 
 import metrics_base
+import mmodules_metrics
 import inheritance_metrics
 import refinement_metrics
 import static_types_metrics
index e2c39f7..647f1a1 100644 (file)
@@ -27,6 +27,8 @@ redef class ToolContext
        # --all
        var opt_all = new OptionBool("Compute all metrics", "--all")
 
+       # --mmodules
+       var opt_mmodules = new OptionBool("Compute metrics about mmodules", "--mmodules")
        # --inheritance
        var opt_inheritance = new OptionBool("Compute metrics about inheritance usage", "--inheritance")
        # --genericity
@@ -57,6 +59,7 @@ redef class ToolContext
        do
                super
                self.option_context.add_option(opt_all)
+               self.option_context.add_option(opt_mmodules)
                self.option_context.add_option(opt_inheritance)
                self.option_context.add_option(opt_refinement)
                self.option_context.add_option(opt_self)
diff --git a/src/metrics/mmodules_metrics.nit b/src/metrics/mmodules_metrics.nit
new file mode 100644 (file)
index 0000000..f729c75
--- /dev/null
@@ -0,0 +1,248 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Collect common metrics about modules
+module mmodules_metrics
+
+import model
+import metrics_base
+import phase
+import frontend
+
+redef class ToolContext
+       var mmodules_metrics_phase = new MModulesMetricsPhase(self, null)
+end
+
+# Extract metrics about modules from the model.
+private class MModulesMetricsPhase
+       super Phase
+       redef fun process_mainmodule(mainmodule)
+       do
+               if not toolcontext.opt_mmodules.value and not toolcontext.opt_all.value then return
+
+               print "\n# MModules metrics".yellow.bold
+
+               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 model = toolcontext.modelbuilder.model
+               var mmodules = new HashSet[MModule]
+               for mproject in model.mprojects do
+
+                       print "\n ## project {mproject}".bold
+
+                       for mgroup in mproject.mgroups do
+                               if mgroup.mmodules.is_empty then continue
+
+                               # Scalar metrics
+                               print "  `- group {mgroup.full_name}"
+
+                               mmodules.add_all(mgroup.mmodules)
+                               metrics.collect(new HashSet[MModule].from(mgroup.mmodules), mainmodule)
+                               for name, metric in metrics.metrics do
+                                       print "\t{name}: {metric.desc}".green
+                                       print "\t    avg: {metric.avg}".light_gray
+                                       var max = metric.max
+                                       print "\t    max: {max.first} ({max.second})".light_gray
+                                       var min = metric.min
+                                       print "\t    min: {min.first} ({min.second})".light_gray
+                               end
+                       end
+               end
+               if not mmodules.is_empty then
+                       # Global metrics
+                       print "\n ## global metrics".bold
+
+                       metrics.collect(mmodules, mainmodule)
+                       for name, metric in metrics.metrics do
+                               print "\t{name}: {metric.desc}".green
+                               print "\t    avg: {metric.avg}".light_gray
+                               var max = metric.max
+                               print "\t    max: {max.first} ({max.second})".light_gray
+                               var min = metric.min
+                               print "\t    min: {min.first} ({min.second})".light_gray
+                       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
+               end
+       end
+end
+
+# An abstract Metric on MModules
+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
+end
+
+# Module Metric: Number of Ancestors
+class MNOA
+       super MModuleMetric
+       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
+       end
+end
+
+# Module Metric: Number of Parents
+class MNOP
+       super MModuleMetric
+       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
+       end
+end
+
+# Module Metric: Number of Children
+class MNOC
+       super MModuleMetric
+       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
+       end
+end
+
+# Module Metric: Number of Descendants
+class MNOD
+       super MModuleMetric
+       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
+       end
+end
+
+# Module Metric: Depth in Tree
+class MDIT
+       super MModuleMetric
+       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
+       end
+end
+
+# Module Metric: Number of Introduction (of all kind)
+#
+# count all mclasses introduced by the module
+class MNBI
+       super MModuleMetric
+       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
+       end
+end
+
+# Module Metric: Number of Refinement
+#
+# count all mclasses refined in the module
+class MNBR
+       super MModuleMetric
+       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)
+               end
+       end
+end
+
+# Module Metric: Number of Concrete Class in module (intro + redef)
+class MNBCC
+       super MModuleMetric
+       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)
+               end
+       end
+end
+
+# Module Metric: Number of Abstract Class in module (intro + redef)
+class MNBAC
+       super MModuleMetric
+       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)
+               end
+       end
+end
+
+# Module Metric: Number of Interface in module (intro + redef)
+class MNBIC
+       super MModuleMetric
+       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)
+               end
+       end
+end
+
+# Module Metric: Number of Enum in module (intro + redef)
+class MNBEC
+       super MModuleMetric
+       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)
+               end
+       end
+end
+
+
index 8ba93ce..3c7bc97 100644 (file)
@@ -11,6 +11,7 @@
   --only-parse            Only proceed to parse step of loaders
   --only-metamodel        Stop after meta-model processing
   --all                   Compute all metrics
+  --mmodules              Compute metrics about mmodules
   --inheritance           Compute metrics about inheritance usage
   --refinement            Compute metrics about refinement usage
   --self                  Compute metrics about the usage of explicit and implicit self