metrics: add Counter#print_summary
[nit.git] / src / metrics / metrics_base.nit
index 86d4953..c7e381b 100644 (file)
@@ -18,6 +18,8 @@
 module metrics_base
 
 import modelbuilder
+import csv
+import counter
 
 redef class ToolContext
 
@@ -26,7 +28,7 @@ redef class ToolContext
 
        # --inheritance
        var opt_inheritance = new OptionBool("Compute metrics about inheritance usage", "--inheritance")
-       # --refinement
+       # --genericity
        var opt_refinement = new OptionBool("Compute metrics about refinement usage", "--refinement")
        # --self
        var opt_self = new OptionBool("Compute metrics about the usage of explicit and implicit self", "--self")
@@ -74,85 +76,62 @@ redef class ToolContext
        end
 end
 
-# A counter counts occurence of things
-# Use this instead of a HashMap[E, Int]
-class Counter[E: Object]
-       # Total number of counted occurences
-       var total: Int = 0
-
-       private var map = new HashMap[E, Int]
-
-       # The number of counted occurences of `e'
-       fun [](e: E): Int
-       do
-               var map = self.map
-               if map.has_key(e) then return map[e]
-               return 0
-       end
-
-       # Count one more occurence of `e'
-       fun inc(e: E)
-       do
-               self.map[e] = self[e] + 1
-               total += 1
-       end
-
-       # Return an array of elements sorted by occurences
-       fun sort: Array[E]
-       do
-               var res = map.keys.to_a
-               var sorter = new CounterSorter[E](self)
-               sorter.sort(res)
-               #res.sort !cmp a, b = map[a] <=> map[b]
-               return res
+redef class Model
+
+       # List of modules in std lib
+       # FIXME this is quite ugly, find a dynamic way...
+       fun std_modules: Set[String] do
+               if self.std_modules_cache == null then
+                       self.std_modules_cache = new HashSet[String]
+                       self.std_modules_cache.add("collection")
+                       self.std_modules_cache.add("abstract_collection")
+                       self.std_modules_cache.add("array")
+                       self.std_modules_cache.add("hash_collection")
+                       self.std_modules_cache.add("list")
+                       self.std_modules_cache.add("range")
+                       self.std_modules_cache.add("sorter")
+                       self.std_modules_cache.add("environ")
+                       self.std_modules_cache.add("exec")
+                       self.std_modules_cache.add("file")
+                       self.std_modules_cache.add("gc")
+                       self.std_modules_cache.add("hash")
+                       self.std_modules_cache.add("kernel")
+                       self.std_modules_cache.add("math")
+                       self.std_modules_cache.add("standard")
+                       self.std_modules_cache.add("stream")
+                       self.std_modules_cache.add("string")
+                       self.std_modules_cache.add("string_search")
+                       self.std_modules_cache.add("time")
+               end
+               return self.std_modules_cache.as(not null)
        end
+       private var std_modules_cache: nullable Set[String]
 end
 
-private class CounterSorter[E: Object]
-       super AbstractSorter[E]
-       var counter: Counter[E]
-       redef fun compare(a,b) do return self.counter.map[a] <=> self.counter.map[b]
-end
-
-# Helper class to output metrics as CVS formatted files
-class CSVDocument
-       private var file: String
-       private var header: Array[String] = new Array[String]
-       private var lines: Array[Array[String]] = new Array[Array[String]]
-
-       init(file: String) do self.file = file
+redef class MClass
+       fun is_class: Bool do
+               return self.kind == concrete_kind or self.kind == abstract_kind
+       end
 
-       fun set_header(values: Object...) do
-               header.clear
-               for value in values do header.add(value.to_s)
+       fun is_interface: Bool do
+               return self.kind == interface_kind
        end
 
-       fun add_line(values: Object...) do
-               if values.length != header.length then
-                       print "CSV error: header declares {header.length} columns, line contains {values.length} values"
-                       abort
-               end
-               var line = new Array[String]
-               for value in values do line.add(value.to_s)
-               lines.add(line)
+       fun is_enum: Bool do
+               return self.kind == enum_kind
        end
 
-       redef fun to_s do
-               var str = header.join(";") + "\n"
-               for line in lines do str += line.join(";") + "\n"
-               return str
+       fun is_abstract: Bool do
+               return self.kind == abstract_kind
        end
 
-       fun save do
-               var out = new OFStream.open(self.file)
-               out.write(self.to_s)
-               out.close
+       fun is_user_defined: Bool do
+               return self.intro_mmodule.is_user_defined
        end
 end
 
-# Helper function to display n/d and handle division by 0
-fun div(n: Int, d: Int): String
-do
-       if d == 0 then return "na"
-       return ((100*n/d).to_f/100.0).to_precision(2)
+redef class MModule
+       fun is_user_defined: Bool do
+               return not self.model.std_modules.has(self.name)
+       end
 end