module metrics_base
import modelbuilder
+import csv
+import counter
redef class ToolContext
# --inheritance
var opt_inheritance = new OptionBool("Compute metrics about inheritance usage", "--inheritance")
# --genericity
- var opt_genericity = new OptionBool("Compute metrics about genericity usage", "--genericity")
- # --refinement
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")
super
self.option_context.add_option(opt_all)
self.option_context.add_option(opt_inheritance)
- self.option_context.add_option(opt_genericity)
self.option_context.add_option(opt_refinement)
self.option_context.add_option(opt_self)
self.option_context.add_option(opt_nullables)
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