Improve the error message so that user that try to pass an array as is instead of elements is hinted about the `...` reverse-vararg operator.
~~~
fun foo(xs: Int...) do end
foo(1,2,3) # OK
var a = [1,2,3]
foo(a) # Error, expected `Int`; got `Array[Int]`. Is `...` missing?
foo(a...) # OK
~~~
![](http://i.imgur.com/zmyi8GR.jpg)
close #98 (quite old bug)
Pull-Request: #1294
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
redef fun compare(a, b) do return a <=> b
end
+# This comparator uses the operator `<=>` to compare objects in a reverse order.
+#
+# See `default_reverse_comparator` for an easy-to-use general stateless reverse
+# default comparator.
+class DefaultReverseComparator
+ super Comparator
+
+ redef type COMPARED: Comparable
+
+ # Returns `b <=> a`.
+ redef fun compare(a, b) do return b <=> a
+end
+
# Easy-to-use general stateless default comparator that uses `<=>` to compare things.
fun default_comparator: DefaultComparator do return once new DefaultComparator
+
+# Easy-to-use general stateless default reverse comparator.
+#
+# Does the same as `default_comparator` but in reverse order.
+fun default_reverse_comparator: DefaultReverseComparator do
+ return once new DefaultReverseComparator
+end
import modelize
redef class ToolContext
+ # Compute MENDEL metrics.
+ #
+ # See `mendel_metrics` module documentation.
var mendel_metrics_phase: Phase = new MendelMetricsPhase(self, null)
end
metrics.collect(mclasses)
if csv then metrics.to_csv.save("{out}/mendel.csv")
- print toolcontext.format_h4("\tlarge mclasses (threshold: {cnblp.threshold})")
- for mclass in cnblp.above_threshold do
- print toolcontext.format_p("\t {mclass.name}: {cnblp.values[mclass]}")
+ var threshold = cnblp.threshold
+ print toolcontext.format_h4("\tlarge mclasses (threshold: {threshold})")
+ for mclass in cnblp.sort do
+ var val = cnblp.values[mclass]
+ if val.to_f < threshold then break
+ print toolcontext.format_p("\t {mclass.name}: {val}")
end
- print toolcontext.format_h4("\tbudding mclasses (threshold: {cnvi.threshold})")
- for mclass in cnvi.above_threshold do
- print toolcontext.format_p("\t {mclass.name}: {cnvi.values[mclass]}")
+ threshold = cnvi.threshold
+ print toolcontext.format_h4("\tbudding mclasses (threshold: {threshold})")
+ for mclass in cnvi.sort do
+ var val = cnvi.values[mclass]
+ if val.to_f < threshold then break
+ print toolcontext.format_p("\t {mclass.name}: {val}")
end
- print toolcontext.format_h4("\tblooming mclasses (threshold: {cnvs.threshold})")
- for mclass in cnvs.above_threshold do
- print toolcontext.format_p("\t {mclass.name}: {cnvs.values[mclass]}")
- end
-
- print toolcontext.format_h4("\tblooming mclasses (threshold: {cnvs.threshold})")
- for mclass in cnvs.above_threshold do
- print toolcontext.format_p("\t {mclass.name}: {cnvs.values[mclass]}")
+ threshold = cnvs.threshold
+ print toolcontext.format_h4("\tblooming mclasses (threshold: {threshold})")
+ for mclass in cnvs.sort do
+ var val = cnvs.values[mclass]
+ if val.to_f < threshold then break
+ print toolcontext.format_p("\t {mclass.name}: {val}")
end
if csv then
redef fun name do return "cbms"
redef fun desc do return "branch mean size, mean number of introduction available among ancestors"
+ # Mainmodule used to compute class hierarchy.
var mainmodule: MModule
- init(mainmodule: MModule) do self.mainmodule = mainmodule
redef fun collect(mclasses) do
for mclass in mclasses do
redef fun name do return "cnvi"
redef fun desc do return "class novelty index, contribution of the class to its branch in term of introductions"
+ # Mainmodule used to compute class hierarchy.
var mainmodule: MModule
- init(mainmodule: MModule) do self.mainmodule = mainmodule
redef fun collect(mclasses) do
var cbms = new CBMS(mainmodule)
redef fun name do return "cnvs"
redef fun desc do return "class novelty score, importance of the contribution of the class to its branch"
+ # Mainmodule used to compute class hierarchy.
var mainmodule: MModule
- init(mainmodule: MModule) do self.mainmodule = mainmodule
redef fun collect(mclasses) do
var cnvi = new CNVI(mainmodule)
var opt_generate_hyperdoc = new OptionBool("Generate Hyperdoc", "--generate_hyperdoc")
# --poset
var opt_poset = new OptionBool("Complete metrics on posets", "--poset")
-
# --no-colors
var opt_nocolors = new OptionBool("Disable colors in console outputs", "--no-colors")
-
-
+ # --dir
var opt_dir = new OptionString("Directory where some statistics files are generated", "-d", "--dir")
+
+ # Output directory for metrics files.
var output_dir: String = "."
redef init
end
end
- # colorize heading 1 for console output
+ # Format and colorize a string heading of level 1 for console output.
+ #
+ # Default style is yellow and bold.
fun format_h1(str: String): String do
if opt_nocolors.value then return str
return str.yellow.bold
end
+ # Format and colorize a string heading of level 2 for console output.
+ #
+ # Default style is white and bold.
fun format_h2(str: String): String do
if opt_nocolors.value then return str
return str.bold
end
+ # Format and colorize a string heading of level 3 for console output.
+ #
+ # Default style is white and nobold.
fun format_h3(str: String): String do
if opt_nocolors.value then return str
return str
end
+ # Format and colorize a string heading of level 4 for console output.
+ #
+ # Default style is green.
fun format_h4(str: String): String do
if opt_nocolors.value then return str
return str.green
end
+ # Format and colorize a string heading of level 5 for console output.
+ #
+ # Default style is light gray.
fun format_p(str: String): String do
if opt_nocolors.value then return str
return str.light_gray
#
# The concept is reified here for a better organization and documentation
interface Metric
+
+ # Type of elements measured by this metric.
type ELM: Object
+
+ # Type of values used to measure elements.
type VAL: Object
+
+ # Type of data representation used to associate elements and values.
type RES: Map[ELM, VAL]
+ # The name of this metric (generally an acronym about the metric).
fun name: String is abstract
+
+ # A long and understandable description about what is measured by this metric.
fun desc: String is abstract
# Clear all results for this metric
end
end
+ # The sum of all the values.
+ fun sum: VAL is abstract
+
# The values standard derivation
fun std_dev: Float is abstract
# The set of element above the threshold
fun above_threshold: Set[ELM] is abstract
+
+ # Sort the metric keys by values
+ fun sort: Array[ELM] do
+ return values.keys_sorted_by_values(default_reverse_comparator)
+ end
end
# A Metric that collects integer data
redef type VAL: Int
redef type RES: Counter[ELM]
+ # `IntMetric` uses a Counter to store values in intern.
protected var values_cache = new Counter[ELM]
+
redef fun values do return values_cache
redef fun clear do values_cache.clear
- fun sum: Int do return values_cache.sum
+ redef fun sum do return values_cache.sum
redef fun max do
assert not values_cache.is_empty
end
# Values average
- redef fun avg: Float do return values_cache.avg
+ redef fun avg do return values_cache.avg
- redef fun std_dev: Float do return values_cache.std_dev
+ redef fun std_dev do return values_cache.std_dev
redef fun above_threshold do
var above = new HashSet[ELM]
redef type VAL: Float
+ # `FloatMetric` uses a Map to store values in intern.
protected var values_cache = new HashMap[ELM, VAL]
+
redef fun values do return values_cache
redef fun clear do values_cache.clear
- fun sum: Float do
+
+ redef fun sum do
var sum = 0.0
for v in values.values do sum += v
return sum
return sum / values.length.to_f
end
- redef fun std_dev: Float do
+ redef fun std_dev do
var sum = 0.0
for value in values.values do
sum += (value - avg).pow(2.to_f)
print "{"\t" * indent} sum: {sum}"
end
end
-
end
# A MetricSet is a metric holder
#
# It purpose is to be extended with a metric collect service
class MetricSet
+
+ # Type of element measured by this `MetricSet`.
type ELM: Object
# Metrics to compute
model.mmodule_importation_hierarchy.sort(mmodules)
var nmodules = new Array[AModule]
for mm in mmodules do
+ if mm.is_fictive then continue
nmodules.add(mmodule2node(mm).as(not null))
end
toolcontext.run_phases(nmodules)
# Registration of the nclassdef associated to each mclassdef
private var mclassdef2nclassdef = new HashMap[MClassDef, AClassdef]
+
+ # Retrieve the associated AST node of a mclassdef.
+ #
+ # This method is used to associate model entity with syntactic entities.
+ # If the class definition is not associated with a node, returns `null`.
+ fun mclassdef2node(mclassdef: MClassDef): nullable AClassdef do
+ return mclassdef2nclassdef.get_or_null(mclassdef)
+ end
end
redef class AModule
Sys: 4.0
blooming mclasses (threshold: 12.0)
Sys: 16.0
- blooming mclasses (threshold: 12.0)
- Sys: 16.0
--- Detection of the usage of covariance static type conformance ---
-- Total --
- Kinds of the subtype -