Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / metrics / rta_metrics.nit
index 99c0cb4..dc3077e 100644 (file)
 # Metrics from RTA
 module rta_metrics
 
-import modelbuilder
 private import rapid_type_analysis
-private import metrics_base
+import metrics_base
 import mmodules_metrics
 import mclasses_metrics
-import frontend
 
 redef class ToolContext
-       var rta_metrics_phase = new RTAMetricsPhase(self, null)
+
+       # RTA related metrics phase
+       var rta_metrics_phase: Phase = new RTAMetricsPhase(self, null)
 end
 
 private class RTAMetricsPhase
        super Phase
-       redef fun process_mainmodule(mainmodule)
+       redef fun process_mainmodule(mainmodule, given_mmodules)
        do
                if not toolcontext.opt_rta.value and not toolcontext.opt_all.value then return
                var csv = toolcontext.opt_csv.value
                var out = "{toolcontext.opt_dir.value or else "metrics"}/rta"
                out.mkdir
 
+               var model = toolcontext.modelbuilder.model
+               var filter = new ModelFilter(min_visibility = protected_visibility)
+
                print toolcontext.format_h1("\n# RTA metrics")
 
                print toolcontext.format_h2("\n ## Live instances by mainmodules")
                var mmetrics = new MetricSet
-               mmetrics.register(new MNLC(toolcontext.modelbuilder))
-               mmetrics.register(new MNLT(toolcontext.modelbuilder))
-               mmetrics.register(new MNCT(toolcontext.modelbuilder))
-               mmetrics.register(new MNLI(toolcontext.modelbuilder))
-               mmetrics.register(new MNLM(toolcontext.modelbuilder))
-               mmetrics.register(new MNLMD(toolcontext.modelbuilder))
-               mmetrics.register(new MNLDD(toolcontext.modelbuilder))
+               mmetrics.register(new MNLC(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLT(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNCT(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLI(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLM(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLMD(model, mainmodule, filter, toolcontext.modelbuilder))
+               mmetrics.register(new MNLDD(model, mainmodule, filter, toolcontext.modelbuilder))
                mmetrics.collect(new HashSet[MModule].from([mainmodule]))
                mmetrics.to_console(1, not toolcontext.opt_nocolors.value)
-               if csv then mmetrics.to_csv.save("{out}/{mainmodule}.csv")
+               if csv then mmetrics.to_csv.write_to_file("{out}/{mainmodule}.csv")
 
                var mtypes = new HashSet[MType]
-               var analysis = new RapidTypeAnalysis(toolcontext.modelbuilder, mainmodule)
+               var analysis = new MetricsRapidTypeAnalysis(toolcontext.modelbuilder, mainmodule)
                analysis.run_analysis
                mtypes.add_all(analysis.live_types)
                mtypes.add_all(analysis.live_cast_types)
@@ -63,14 +66,14 @@ private class RTAMetricsPhase
                cmetrics.register(analysis.cnli)
                cmetrics.register(analysis.cnlc)
                cmetrics.to_console(1, not toolcontext.opt_nocolors.value)
-               if csv then cmetrics.to_csv.save("{out}/mclasses.csv")
+               if csv then cmetrics.to_csv.write_to_file("{out}/mclasses.csv")
 
                print toolcontext.format_h2("\n ## Total live instances by mtypes")
                var tmetrics = new MetricSet
                tmetrics.register(analysis.tnli)
                tmetrics.register(analysis.tnlc)
                tmetrics.to_console(1, not toolcontext.opt_nocolors.value)
-               if csv then tmetrics.to_csv.save("{out}/mtypes.csv")
+               if csv then tmetrics.to_csv.write_to_file("{out}/mtypes.csv")
 
                print toolcontext.format_h2("\n ## MType complexity")
                var gmetrics = new MetricSet
@@ -78,31 +81,65 @@ private class RTAMetricsPhase
                gmetrics.register(new TDGS)
                gmetrics.collect(mtypes)
                gmetrics.to_console(1, not toolcontext.opt_nocolors.value)
-               if csv then gmetrics.to_csv.save("{out}/complexity.csv")
+               if csv then gmetrics.to_csv.write_to_file("{out}/complexity.csv")
+
+               callsite_info(analysis)
 
                # dump type and method infos
                if csv then
-                       analysis.live_types_to_csv.save("{out}/rta_types.csv")
+                       analysis.live_types_to_csv.write_to_file("{out}/rta_types.csv")
                        analysis.live_methods_to_tree.write_to_file("{out}/rta_methods.dat")
                end
        end
+
+       fun callsite_info(rta: RapidTypeAnalysis)
+       do
+               print toolcontext.format_h2("\n ## Callsites")
+               print "* {rta.live_callsites.length} live callsites"
+
+               var csep = new Counter[MPropDef]
+               var cglo = new Counter[MPropDef]
+               var morphisme = new Counter[Int]
+               for cs in rta.live_callsites do
+                       csep.inc(cs.mpropdef)
+                       var targets = rta.live_targets(cs)
+                       for d in targets do
+                               cglo.inc(d)
+                       end
+                       morphisme.inc(targets.length)
+               end
+
+               print toolcontext.format_h3("MMethodDef locally designated (by number of CallSites)")
+               csep.print_summary
+               csep.print_elements(5)
+
+               print toolcontext.format_h3("MMethodDef possibly invoked at runtime (by number of CallSites)")
+               cglo.print_summary
+               cglo.print_elements(5)
+       end
 end
 
 # Summary metrics
 
+# RTA related metric that needs a `modelbuilder`
+class RTAMetric
+       super MModuleMetric
+
+       # Modelbuilder used to access AST
+       var modelbuilder: ModelBuilder
+end
+
 # MModule Metric: Number of Live Types
 class MNLI
-       super MModuleMetric
+       super RTAMetric
        super IntMetric
        redef fun name do return "mnli"
        redef fun desc do return "number of live instances in a mmodule"
 
-       var modelbuilder: ModelBuilder
-       init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
 
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.tnli.sum
                end
@@ -111,17 +148,14 @@ end
 
 # MModule Metric: Number of Live Types
 class MNLT
-       super MModuleMetric
+       super RTAMetric
        super IntMetric
        redef fun name do return "mnlt"
        redef fun desc do return "number of live mtypes in a mmodule"
 
-       var modelbuilder: ModelBuilder
-       init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
-
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_types.length
                end
@@ -130,17 +164,14 @@ end
 
 # MModule Metric: Number of Live Cast Types
 class MNCT
-       super MModuleMetric
+       super RTAMetric
        super IntMetric
        redef fun name do return "mnct"
        redef fun desc do return "number of live cast mtypes in a mmodule"
 
-       var modelbuilder: ModelBuilder
-       init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
-
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_cast_types.length
                end
@@ -149,18 +180,15 @@ end
 
 # MModule Metric: Number of Live Classes
 class MNLC
-       super MModuleMetric
+       super RTAMetric
        super IntMetric
        redef fun name do return "mnlc"
        redef fun desc do return "number of live mclasses in a mmodule"
 
-       var modelbuilder: ModelBuilder
-       init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
-
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
                        var live = new HashSet[MClass]
-                       var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        for mtype in analysis.live_types do
                                live.add(mtype.mclass)
@@ -172,17 +200,14 @@ end
 
 # MModule Metric: Number of Live Methods
 class MNLM
-       super MModuleMetric
+       super RTAMetric
        super IntMetric
        redef fun name do return "mnlm"
        redef fun desc do return "number of live methods in a mmodule"
 
-       var modelbuilder: ModelBuilder
-       init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
-
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_methods.length
                end
@@ -191,17 +216,14 @@ end
 
 # MModule Metric: Number of Live MethodDefs
 class MNLMD
-       super MModuleMetric
+       super RTAMetric
        super IntMetric
        redef fun name do return "mnlmd"
        redef fun desc do return "number of live method definitions in a mmodule"
 
-       var modelbuilder: ModelBuilder
-       init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
-
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
-                       var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        values[mainmodule] = analysis.live_methoddefs.length
                end
@@ -210,18 +232,15 @@ end
 
 # MModule Metric: Number of Dead MethodDefs
 class MNLDD
-       super MModuleMetric
+       super RTAMetric
        super IntMetric
        redef fun name do return "mnldd"
        redef fun desc do return "number of dead method definitions in a mmodule"
 
-       var modelbuilder: ModelBuilder
-       init(modelbuilder: ModelBuilder) do self.modelbuilder = modelbuilder
-
        redef fun collect(mainmodules) do
                for mainmodule in mainmodules do
                        var dead = 0
-                       var analysis = new RapidTypeAnalysis(modelbuilder, mainmodule)
+                       var analysis = new MetricsRapidTypeAnalysis(modelbuilder, mainmodule)
                        analysis.run_analysis
                        for mmethod in analysis.live_methods do
                                for mdef in mmethod.mpropdefs do
@@ -332,10 +351,20 @@ end
 
 # rta redef
 
-redef class RapidTypeAnalysis
-       var cnli = new CNLI
-       var cnlc = new CNLC
+# Custom RTA analyzer
+class MetricsRapidTypeAnalysis
+       super RapidTypeAnalysis
+
+       # Class Live Instances
+       var cnli: CNLI is lazy do return new CNLI(modelbuilder.model, mainmodule)
+
+       # Class Live Casts
+       var cnlc: CNLC is lazy do return new CNLC(modelbuilder.model, mainmodule)
+
+       # Type Live Instances
        var tnli = new TNLI
+
+       # Rtpe Live Casts
        var tnlc = new TNLC
 
        redef fun add_new(recv, mtype) do
@@ -348,7 +377,7 @@ redef class RapidTypeAnalysis
                super
                tnlc.values.inc(mtype)
 
-               if mtype isa MNullableType then mtype = mtype.mtype
+               mtype = mtype.undecorate
                if mtype isa MClassType then
                        cnlc.values.inc(mtype.mclass)
                end
@@ -359,8 +388,7 @@ end
 
 redef class MType
        private fun signature_depth: Int do
-               var mtype = self
-               if mtype isa MNullableType then mtype = mtype.mtype
+               var mtype = self.undecorate
                if not mtype isa MGenericType then return 0
 
                var depth = 0
@@ -371,4 +399,3 @@ redef class MType
                return depth + 1
        end
 end
-