From: Alexandre Terrasa Date: Mon, 5 Nov 2012 15:40:21 +0000 (-0500) Subject: nitmetrics: add CVS output facilities for inheritance metrics X-Git-Tag: v0.6~81^2~10 X-Git-Url: http://nitlanguage.org nitmetrics: add CVS output facilities for inheritance metrics Signed-off-by: Alexandre Terrasa --- diff --git a/src/metrics/inheritance_metrics.nit b/src/metrics/inheritance_metrics.nit index dab0e83..f9b0b15 100644 --- a/src/metrics/inheritance_metrics.nit +++ b/src/metrics/inheritance_metrics.nit @@ -269,7 +269,8 @@ redef class MClass return path end - # DUI + # * -> * DUI + private fun is_dui_eligible: Bool do for parent in parents do if parent.name != "Object" then return true return false @@ -289,203 +290,249 @@ redef class MClass for parent in parents do if parent.name != "Object" and parent.is_interface then return true return false end - - # SLDUI - private fun is_sldui_eligible: Bool do - if is_user_defined then return false - for parent in parents do if parent.name != "Object" then return true - return false - end - private fun is_slccdui_eligible: Bool do + private fun is_if_eligible(model: Model): Bool do return not children(model).is_empty + private fun is_ccif_eligible(model: Model): Bool do if not is_class then return false - if is_user_defined then return false - for parent in parents do if parent.name != "Object" and parent.is_class then return true + for child in children(model) do if child.is_class then return true return false end - private fun is_slcidui_eligible: Bool do - if not is_class then return false - if is_user_defined then return false - for parent in parents do if parent.name != "Object" and parent.is_interface then return true + private fun is_icif_eligible(model: Model): Bool do + if not is_interface then return false + for child in children(model) do if child.is_class then return true return false end - private fun is_sliidui_eligible: Bool do + private fun is_iiif_eligible(model: Model): Bool do if not is_interface then return false - if is_user_defined then return false - for parent in parents do if parent.name != "Object" and parent.is_interface then return true + for child in children(model) do if child.is_interface then return true return false end - # UDDUI + # SL -> * DUI - private fun is_uddui_eligible: Bool do - if not is_user_defined then return false + private fun is_sldui_eligible: Bool do + if is_user_defined then return false for parent in parents do if parent.name != "Object" then return true return false end - private fun is_udccdui_eligible: Bool do + private fun is_slccdui_eligible: Bool do + if is_user_defined then return false if not is_class then return false - if not is_user_defined then return false for parent in parents do if parent.name != "Object" and parent.is_class then return true return false end - private fun is_udcidui_eligible: Bool do + private fun is_slcidui_eligible: Bool do + if is_user_defined then return false if not is_class then return false - if not is_user_defined then return false for parent in parents do if parent.name != "Object" and parent.is_interface then return true return false end - private fun is_udiidui_eligible: Bool do + private fun is_sliidui_eligible: Bool do + if is_user_defined then return false if not is_interface then return false - if not is_user_defined then return false for parent in parents do if parent.name != "Object" and parent.is_interface then return true return false end - - # UDDUIUD - - private fun is_udduiud_eligible: Bool do - if not is_user_defined then return false - for parent in parents do if parent.name != "Object" and parent.is_user_defined then return true - return false - end - private fun is_udccduiud_eligible: Bool do - if not is_class then return false - if not is_user_defined then return false - for parent in parents do if parent.name != "Object" and parent.is_class and parent.is_user_defined then return true - return false - end - private fun is_udciduiud_eligible: Bool do - if not is_class then return false - if not is_user_defined then return false - for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true - return false - end - private fun is_udiiduiud_eligible: Bool do - if not is_interface then return false - if not is_user_defined then return false - for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true - return false - end - - # IF - private fun is_if_eligible(model: Model): Bool do return not children(model).is_empty - private fun is_ccif_eligible(model: Model): Bool do - if not is_class then return false - for child in children(model) do if child.is_class then return true - return false - end - private fun is_icif_eligible(model: Model): Bool do - if not is_interface then return false - for child in children(model) do if child.is_class then return true - return false - end - private fun is_iiif_eligible(model: Model): Bool do - if not is_interface then return false - for child in children(model) do if child.is_interface then return true - return false - end - - # SLIF private fun is_slif_eligible(model: Model): Bool do if is_user_defined then return false return not children(model).is_empty end private fun is_slccif_eligible(model: Model): Bool do - if not is_class then return false if is_user_defined then return false + if not is_class then return false for child in children(model) do if child.is_class then return true return false end private fun is_slicif_eligible(model: Model): Bool do - if not is_interface then return false if is_user_defined then return false + if not is_interface then return false for child in children(model) do if child.is_class then return true return false end private fun is_sliiif_eligible(model: Model): Bool do - if not is_interface then return false if is_user_defined then return false + if not is_interface then return false for child in children(model) do if child.is_interface then return true return false end - # SLIFSL + # SL -> SL + private fun is_slifsl_eligible(model: Model): Bool do if is_user_defined then return false for child in children(model) do if not child.is_user_defined then return true return false end private fun is_slccifsl_eligible(model: Model): Bool do + if is_user_defined then return false if is_class then return false - if not is_user_defined then return false for child in children(model) do if not child.is_user_defined and child.is_class then return true return false end private fun is_slicifsl_eligible(model: Model): Bool do + if is_user_defined then return false if not is_interface then return false - if not is_user_defined then return false for child in children(model) do if not child.is_user_defined and child.is_class then return true return false end private fun is_sliiifsl_eligible(model: Model): Bool do + if is_user_defined then return false if not is_interface then return false - if not is_user_defined then return false for child in children(model) do if not child.is_user_defined and child.is_interface then return true return false end - #SLIFUD + # SL -> UD + private fun is_slifud_eligible(model: Model): Bool do - if not is_user_defined then return false + if is_user_defined then return false for child in children(model) do if child.is_user_defined then return true return false end private fun is_slccifud_eligible(model: Model): Bool do + if is_user_defined then return false if not is_class then return false - if not is_user_defined then return false for child in children(model) do if child.is_user_defined and child.is_class then return true return false end private fun is_slicifud_eligible(model: Model): Bool do + if is_user_defined then return false if not is_interface then return false - if not is_user_defined then return false for child in children(model) do if child.is_user_defined and child.is_class then return true return false end private fun is_sliiifud_eligible(model: Model): Bool do + if is_user_defined then return false if not is_interface then return false - if not is_user_defined then return false for child in children(model) do if child.is_user_defined and child.is_interface then return true return false end - # UDIF + # UD -> * + + private fun is_uddui_eligible: Bool do + if not is_user_defined then return false + for parent in parents do if parent.name != "Object" then return true + return false + end + private fun is_udccdui_eligible: Bool do + if not is_user_defined then return false + if not is_class then return false + for parent in parents do if parent.name != "Object" and parent.is_class then return true + return false + end + private fun is_udcidui_eligible: Bool do + if not is_user_defined then return false + if not is_class then return false + for parent in parents do if parent.name != "Object" and parent.is_interface then return true + return false + end + private fun is_udiidui_eligible: Bool do + if not is_user_defined then return false + if not is_interface then return false + for parent in parents do if parent.name != "Object" and parent.is_interface then return true + return false + end private fun is_udif_eligible(model: Model): Bool do if not is_user_defined then return false return not children(model).is_empty end private fun is_udccif_eligible(model: Model): Bool do - if not is_class then return false if not is_user_defined then return false + if not is_class then return false for child in children(model) do if child.is_class then return true return false end private fun is_udicif_eligible(model: Model): Bool do - if not is_interface then return false if not is_user_defined then return false + if not is_interface then return false for child in children(model) do if child.is_class then return true return false end private fun is_udiiif_eligible(model: Model): Bool do - if not is_interface then return false if not is_user_defined then return false + if not is_interface then return false for child in children(model) do if child.is_interface then return true return false end + + # UD -> SL + + private fun is_udduisl_eligible: Bool do + if not is_user_defined then return false + for parent in parents do if not parent.is_user_defined and parent.name != "Object" then return true + return false + end + private fun is_udccduisl_eligible: Bool do + if not is_user_defined then return false + if not is_class then return false + for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_class then return true + return false + end + private fun is_udciduisl_eligible: Bool do + if not is_user_defined then return false + if not is_class then return false + for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_interface then return true + return false + end + private fun is_udiiduisl_eligible: Bool do + if not is_user_defined then return false + if not is_interface then return false + for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_interface then return true + return false + end + + # UD -> UD + + private fun is_udduiud_eligible: Bool do + if not is_user_defined then return false + for parent in parents do if parent.name != "Object" and parent.is_user_defined then return true + return false + end + private fun is_udccduiud_eligible: Bool do + if not is_user_defined then return false + if not is_class then return false + for parent in parents do if parent.name != "Object" and parent.is_class and parent.is_user_defined then return true + return false + end + private fun is_udciduiud_eligible: Bool do + if not is_user_defined then return false + if not is_class then return false + for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true + return false + end + private fun is_udiiduiud_eligible: Bool do + if not is_user_defined then return false + if not is_interface then return false + for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true + return false + end + private fun is_udifud_eligible(model: Model): Bool do + if not is_user_defined then return false + return not children(model).is_empty + end + private fun is_udccifud_eligible(model: Model): Bool do + if not is_user_defined then return false + if not is_class then return false + for child in children(model) do if child.is_user_defined and child.is_class then return true + return false + end + private fun is_udicifud_eligible(model: Model): Bool do + if not is_user_defined then return false + if not is_interface then return false + for child in children(model) do if child.is_user_defined and child.is_class then return true + return false + end + private fun is_udiiifud_eligible(model: Model): Bool do + if not is_user_defined then return false + if not is_interface then return false + for child in children(model) do if child.is_user_defined and child.is_interface then return true + return false + end + end # Print inheritance usage metrics -fun compute_inheritance_metrics(model: Model) +fun compute_inheritance_metrics(toolcontext: ToolContext, model: Model) do # global summary metrics var nmd: Int = 0 # (NMD) Number of Modules @@ -511,56 +558,62 @@ do # global summary inheritance metrics var dit = "" # (DIT) Global Depth in Inheritance Tree - # dui - var dui = "" # (DUI) The proportion of types that either implement an interface or extend another type other than Object - var ccdui = "" # (CCDUI) The proportion of classes that extend some other class. - var cidui = "" # (CIDUI) The proportion of classes that implement some other interface. - var iidui = "" # (IIDUI) The proportion of interfaces that extend some other interface. - # if - var inhf = "" # (IF) The proportion of types Inherited From, that is, those types that are either extended or implemented - var ccif = "" # (CCIF) The proportion of classes extended by some other class. - var icif = "" # (ICIF) The proportion of interfaces implemented by some other class. - var iiif = "" # (IIIF) The proportion of interfaces extended by some other interface. - - # (SL) Std-Lib summary inheritance metrics - # sl dui - var sldui = "" # (SLDUI) The proportion of std-lib types that either implement an interface or extend another std-lib type other than Object - var slccdui = "" # (SLCCDUI) The proportion of std-lib classes that extend some other std-lib class. - var slcidui = "" # (SLCIDUI) The proportion of std-lib classes that implement some other std-lib interface. - var sliidui = "" # (SLIIDUI) The proportion of std-lib interfaces that extend some other std-lib interface. - # sl if - var slinhf = "" # (SLIF) The proportion of SL types Inherited From, that is, those types that are either extended or implemented - var slccif = "" # (SLCCIF) The proportion of SL classes extended by some other class. - var slicif = "" # (SLICIF) The proportion of SL interfaces implemented by some other class. - var sliiif = "" # (SLIIIF) The proportion of SL interfaces extended by some other interface. - # sl if sl - var slinhfsl = "" # (SLIFSL) The proportion of SL types Inherited From, that is, those types that are either extended or implemented by a SL type - var slccifsl = "" # (SLCCIFSL) The proportion of SL classes extended by some other SL class. - var slicifsl = "" # (SLICIFSL) The proportion of SL interfaces implemented by some other SL class. - var sliiifsl = "" # (SLIIIFSL) The proportion of SL interfaces extended by some other SL interface. - # sl if ud - var slinhfud = "" # (SLIFUD) The proportion of SL types Inherited From, that is, those types that are either extended or implemented by a UD type - var slccifud = "" # (SLCCIFUD) The proportion of SL classes extended by some other UD class. - var slicifud = "" # (SLICIFUD) The proportion of SL interfaces implemented by some other UD class. - var sliiifud = "" # (SLIIIFUD) The proportion of SL interfaces extended by some other UD interface. - - # (UD) User-defined summary inheritance metrics - #dui - var uddui = "" # (UDDUI) The proportion user-defined of types that either implement an interface or extend another type - var udccdui = "" # (UDCCDUI) The proportion of user-defined classes that extend some other class. - var udcidui = "" # (UDCIDUI) The proportion of user-defined classes that implement some other interface. - var udiidui = "" # (UDIIDUI) The proportion of user-defined interfaces that extend some other interface. - # ud if - var udinhf = "" # (UDIF) The proportion of UD types Inherited From, that is, those types that are either extended or implemented - var udccif = "" # (UDCCIF) The proportion of UD classes extended by some other class. - var udicif = "" # (UDICIF) The proportion of UD interfaces implemented by some other class. - var udiiif = "" # (UDIIIF) The proportion of UD interfaces extended by some other interface. - - # (UD*UD) User-defined summary inheritance metrics - var udduiud = "" # (UDDUIUD) The proportion user-defined of types that either implement an interface or extend another type user-defined - var udccduiud = "" # (UDCCDUIUD) The proportion of user-defined classes that extend some other user-defined class. - var udciduiud = "" # (UDCIDUIUD) The proportion of user-defined classes that implement some other user-defined interface. - var udiiduiud = "" # (UDIIDUIUD) The proportion of user-defined interfaces that extend some other user-defined interface. + var dui = "" # (DUI) Proportion of types that either implement an interface or extend another type other than Object + var ccdui = "" # (CCDUI) Proportion of classes that extend some other class. + var cidui = "" # (CIDUI) Proportion of classes that implement some other interface. + var iidui = "" # (IIDUI) Proportion of interfaces that extend some other interface. + var inhf = "" # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented + var ccif = "" # (CCIF) Proportion of classes extended by some other class. + var icif = "" # (ICIF) Proportion of interfaces implemented by some other class. + var iiif = "" # (IIIF) Proportion of interfaces extended by some other interface. + + # (SL -> *) Std-Lib summary inheritance metrics + var sldui = "" # (SLDUI) Proportion of std-lib types that either implement an interface or extend another std-lib type other than Object + var slccdui = "" # (SLCCDUI) Proportion of std-lib classes that extend some other std-lib class. + var slcidui = "" # (SLCIDUI) Proportion of std-lib classes that implement some other std-lib interface. + var sliidui = "" # (SLIIDUI) Proportion of std-lib interfaces that extend some other std-lib interface. + var slinhf = "" # (SLIF) Proportion of SL types Inherited From, that is, those types that are either extended or implemented + var slccif = "" # (SLCCIF) Proportion of SL classes extended by some other class. + var slicif = "" # (SLICIF) Proportion of SL interfaces implemented by some other class. + var sliiif = "" # (SLIIIF) Proportion of SL interfaces extended by some other interface. + + # (SL -> SL) Std-Lib summary inheritance metrics + var slinhfsl = "" # (SLIFSL) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a SL type + var slccifsl = "" # (SLCCIFSL) Proportion of SL classes extended by some other SL class. + var slicifsl = "" # (SLICIFSL) Proportion of SL interfaces implemented by some other SL class. + var sliiifsl = "" # (SLIIIFSL) Proportion of SL interfaces extended by some other SL interface. + + # (SL -> UD) Std-Lib summary inheritance metrics + var slinhfud = "" # (SLIFUD) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a UD type + var slccifud = "" # (SLCCIFUD) Proportion of SL classes extended by some other UD class. + var slicifud = "" # (SLICIFUD) Proportion of SL interfaces implemented by some other UD class. + var sliiifud = "" # (SLIIIFUD) Proportion of SL interfaces extended by some other UD interface. + + # (UD -> *) User-defined summary inheritance metrics + var uddui = "" # (UDDUI) Proportion user-defined of types that either implement an interface or extend another type + var udccdui = "" # (UDCCDUI) Proportion of user-defined classes that extend some other class. + var udcidui = "" # (UDCIDUI) Proportion of user-defined classes that implement some other interface. + var udiidui = "" # (UDIIDUI) Proportion of user-defined interfaces that extend some other interface. + var udinhf = "" # (UDIF) Proportion of UD types Inherited From, that is, those types that are either extended or implemented + var udccif = "" # (UDCCIF) Proportion of UD classes extended by some other class. + var udicif = "" # (UDICIF) Proportion of UD interfaces implemented by some other class. + var udiiif = "" # (UDIIIF) Proportion of UD interfaces extended by some other interface. + + # (UD -> SL) User-defined summary inheritance metrics + var udduisl = "" # (UDDUISL) Proportion user-defined of types that either implement an interface or extend another type SL + var udccduisl = "" # (UDCCDUISL) Proportion of user-defined classes that extend some other SL class. + var udciduisl = "" # (UDCIDUISL) Proportion of user-defined classes that implement some other SL interface. + var udiiduisl = "" # (UDIIDUISL) Proportion of user-defined interfaces that extend some other SL interface. + + # (UD -> UD) User-defined summary inheritance metrics + var udduiud = "" # (UDDUIUD) Proportion user-defined of types that either implement an interface or extend another type user-defined + var udccduiud = "" # (UDCCDUIUD) Proportion of user-defined classes that extend some other user-defined class. + var udciduiud = "" # (UDCIDUIUD) Proportion of user-defined classes that implement some other user-defined interface. + var udiiduiud = "" # (UDIIDUIUD) Proportion of user-defined interfaces that extend some other user-defined interface. + var udinhfud = "" # (UDIFUD) Proportion of UD types Inherited From, that is, those types that are either extended or implemented by another UD type + var udccifud = "" # (UDCCIFUD) Proportion of UD classes extended by some other UD class. + var udicifud = "" # (UDICIFUD) Proportion of UD interfaces implemented by some other UD class. + var udiiifud = "" # (UDIIIFUD) Proportion of UD interfaces extended by some other UD interface. # compute scalar metrics for mclass in model.mclasses do @@ -593,149 +646,224 @@ do # compute inheritance summary metrics + # * -> * var ditsum = 0 - var dui_count = 0 var ccdui_count = 0 var cidui_count = 0 var iidui_count = 0 - - var sldui_count = 0 - var slccdui_count = 0 - var slcidui_count = 0 - var sliidui_count = 0 - - var uddui_count = 0 - var udccdui_count = 0 - var udcidui_count = 0 - var udiidui_count = 0 - - var udduiud_count = 0 - var udccduiud_count = 0 - var udciduiud_count = 0 - var udiiduiud_count = 0 - var if_count = 0 var ccif_count = 0 var icif_count = 0 var iiif_count = 0 + # SL -> * + var sldui_count = 0 + var slccdui_count = 0 + var slcidui_count = 0 + var sliidui_count = 0 var slif_count = 0 var slccif_count = 0 var slicif_count = 0 var sliiif_count = 0 + # SL -> SL var slifsl_count = 0 var slccifsl_count = 0 var slicifsl_count = 0 var sliiifsl_count = 0 + # SL -> UD var slifud_count = 0 var slccifud_count = 0 var slicifud_count = 0 var sliiifud_count = 0 + # UD -> * + var uddui_count = 0 + var udccdui_count = 0 + var udcidui_count = 0 + var udiidui_count = 0 var udif_count = 0 var udccif_count = 0 var udicif_count = 0 var udiiif_count = 0 + # UD -> SL + var udduisl_count = 0 + var udccduisl_count = 0 + var udciduisl_count = 0 + var udiiduisl_count = 0 + + # UD -> UD + var udduiud_count = 0 + var udccduiud_count = 0 + var udciduiud_count = 0 + var udiiduiud_count = 0 + var udifud_count = 0 + var udccifud_count = 0 + var udicifud_count = 0 + var udiiifud_count = 0 for mclass in model.mclasses do ditsum += mclass.dit + # * -> * if mclass.is_dui_eligible then dui_count += 1 if mclass.is_ccdui_eligible then ccdui_count += 1 if mclass.is_cidui_eligible then cidui_count += 1 if mclass.is_iidui_eligible then iidui_count += 1 - - if mclass.is_sldui_eligible then sldui_count += 1 - if mclass.is_slccdui_eligible then slccdui_count += 1 - if mclass.is_slcidui_eligible then slcidui_count += 1 - if mclass.is_sliidui_eligible then sliidui_count += 1 - - if mclass.is_uddui_eligible then uddui_count += 1 - if mclass.is_udccdui_eligible then udccdui_count += 1 - if mclass.is_udcidui_eligible then udcidui_count += 1 - if mclass.is_udiidui_eligible then udiidui_count += 1 - - if mclass.is_udduiud_eligible then udduiud_count += 1 - if mclass.is_udccduiud_eligible then udccduiud_count += 1 - if mclass.is_udciduiud_eligible then udciduiud_count += 1 - if mclass.is_udiiduiud_eligible then udiiduiud_count += 1 - if mclass.is_if_eligible(model) then if_count += 1 if mclass.is_ccif_eligible(model) then ccif_count += 1 if mclass.is_icif_eligible(model) then icif_count += 1 if mclass.is_iiif_eligible(model) then iiif_count += 1 + # SL -> * + if mclass.is_sldui_eligible then sldui_count += 1 + if mclass.is_slccdui_eligible then slccdui_count += 1 + if mclass.is_slcidui_eligible then slcidui_count += 1 + if mclass.is_sliidui_eligible then sliidui_count += 1 if mclass.is_slif_eligible(model) then slif_count += 1 if mclass.is_slccif_eligible(model) then slccif_count += 1 if mclass.is_slicif_eligible(model) then slicif_count += 1 if mclass.is_sliiif_eligible(model) then sliiif_count += 1 + # SL -> SL if mclass.is_slifsl_eligible(model) then slifsl_count += 1 if mclass.is_slccifsl_eligible(model) then slccifsl_count += 1 if mclass.is_slicifsl_eligible(model) then slicifsl_count += 1 if mclass.is_sliiifsl_eligible(model) then sliiifsl_count += 1 + # SL -> UD if mclass.is_slifud_eligible(model) then slifud_count += 1 if mclass.is_slccifud_eligible(model) then slccifud_count += 1 if mclass.is_slicifud_eligible(model) then slicifud_count += 1 if mclass.is_sliiifud_eligible(model) then sliiifud_count += 1 + # UD -> * + if mclass.is_uddui_eligible then uddui_count += 1 + if mclass.is_udccdui_eligible then udccdui_count += 1 + if mclass.is_udcidui_eligible then udcidui_count += 1 + if mclass.is_udiidui_eligible then udiidui_count += 1 if mclass.is_udif_eligible(model) then udif_count += 1 if mclass.is_udccif_eligible(model) then udccif_count += 1 if mclass.is_udicif_eligible(model) then udicif_count += 1 if mclass.is_udiiif_eligible(model) then udiiif_count += 1 + + # UD -> SL + if mclass.is_udduisl_eligible then udduisl_count += 1 + if mclass.is_udccduisl_eligible then udccduisl_count += 1 + if mclass.is_udciduisl_eligible then udciduisl_count += 1 + if mclass.is_udiiduisl_eligible then udiiduisl_count += 1 + + # UD -> UD + if mclass.is_udduiud_eligible then udduiud_count += 1 + if mclass.is_udccduiud_eligible then udccduiud_count += 1 + if mclass.is_udciduiud_eligible then udciduiud_count += 1 + if mclass.is_udiiduiud_eligible then udiiduiud_count += 1 + if mclass.is_udifud_eligible(model) then udifud_count += 1 + if mclass.is_udccifud_eligible(model) then udccifud_count += 1 + if mclass.is_udicifud_eligible(model) then udicifud_count += 1 + if mclass.is_udiiifud_eligible(model) then udiiifud_count += 1 end - dit = div(ditsum, model.mclasses.length) + # * -> * + dit = div(ditsum, model.mclasses.length) dui = div(dui_count * 100, nc + ni) ccdui = div(ccdui_count * 100, nc) cidui = div(cidui_count * 100, nc) iidui = div(iidui_count * 100, ni) - - sldui = div(sldui_count * 100, ncsl + nisl) - slccdui = div(slccdui_count * 100, ncsl) - slcidui = div(slcidui_count * 100, ncsl) - sliidui = div(sliidui_count * 100, nisl) - - uddui = div(uddui_count * 100, ncud + niud) - udccdui = div(udccdui_count * 100, ncud) - udcidui = div(udcidui_count * 100, ncud) - udiidui = div(udiidui_count * 100, niud) - - udduiud = div(udduiud_count * 100, ncud + niud) - udccduiud = div(udccduiud_count * 100, ncud) - udciduiud = div(udciduiud_count * 100, ncud) - udiiduiud = div(udiiduiud_count * 100, niud) - inhf = div(if_count * 100, nc + ni) ccif = div(ccif_count * 100, nc) icif = div(icif_count * 100, ni) iiif = div(iiif_count * 100, ni) + # SL -> * + sldui = div(sldui_count * 100, ncsl + nisl) + slccdui = div(slccdui_count * 100, ncsl) + slcidui = div(slcidui_count * 100, ncsl) + sliidui = div(sliidui_count * 100, nisl) slinhf = div(slif_count * 100, ncsl + nisl) slccif = div(slccif_count * 100, ncsl) slicif = div(slicif_count * 100, nisl) sliiif = div(sliiif_count * 100, nisl) + # SL -> SL slinhfsl = div(slifsl_count * 100, ncsl + nisl) slccifsl = div(slccifsl_count * 100, ncsl) slicifsl = div(slicifsl_count * 100, nisl) sliiifsl = div(sliiifsl_count * 100, nisl) + # SL -> UD slinhfud = div(slifud_count * 100, ncsl + nisl) slccifud = div(slccifud_count * 100, ncsl) slicifud = div(slicifud_count * 100, nisl) sliiifud = div(sliiifud_count * 100, nisl) + # UD -> * + uddui = div(uddui_count * 100, ncud + niud) + udccdui = div(udccdui_count * 100, ncud) + udcidui = div(udcidui_count * 100, ncud) + udiidui = div(udiidui_count * 100, niud) udinhf = div(if_count * 100, ncud + niud) udccif = div(ccif_count * 100, ncud) udicif = div(icif_count * 100, niud) udiiif = div(iiif_count * 100, niud) + # UD -> SL + udduisl = div(udduisl_count * 100, ncud + niud) + udccduisl = div(udccduisl_count * 100, ncud) + udciduisl = div(udciduisl_count * 100, ncud) + udiiduisl = div(udiiduisl_count * 100, niud) + + # UD -> UD + udduiud = div(udduiud_count * 100, ncud + niud) + udccduiud = div(udccduiud_count * 100, ncud) + udciduiud = div(udciduiud_count * 100, ncud) + udiiduiud = div(udiiduiud_count * 100, niud) + udinhfud = div(udifud_count * 100, ncud + niud) + udccifud = div(udccifud_count * 100, ncud) + udicifud = div(udicifud_count * 100, niud) + udiiifud = div(udiiifud_count * 100, niud) + + # CSV generation + if toolcontext.opt_generate_csv.value then + # summary_metrics + var summaryCSV = new CSVDocument(toolcontext.output_dir.join_path("summary_metrics.csv")) + summaryCSV.set_header("scope", "NMD", "NC", "NI", "NAC", "NGC", "NGI") + summaryCSV.add_line("global", nmd, nc, ni, nac, ngc, ngi) + summaryCSV.add_line("std-lib", nmdsl, ncsl, nisl, nacsl, ngcsl, ngisl) + summaryCSV.add_line("user-defined", nmdud, ncud, niud, nacud, ngcud, ngiud) + summaryCSV.save + + # inheritance metrics + var inheritanceCSV = new CSVDocument(toolcontext.output_dir.join_path("inheritance_metrics.csv")) + inheritanceCSV.set_header("scope", "DIT", "DUI", "CCDUI", "CIDUI", "IIDUI", "IF", "CCIF", "ICIF", "IIIF") + inheritanceCSV.add_line("global", dit, dui, ccdui, cidui, iidui, inhf, ccif, icif, iiif) + inheritanceCSV.add_line("SL -> *", "", sldui, slccdui, slcidui, sliidui, slinhf, slccif, slicif, sliiif) + inheritanceCSV.add_line("SL -> SL", "", sldui, slccdui, slcidui, sliidui, slinhfsl, slccifsl, slicifsl, sliiifsl) + inheritanceCSV.add_line("SL -> UD", "", 0, 0, 0, 0, slinhfud, slccifud, slicifud, sliiifud) + inheritanceCSV.add_line("UD -> *", "", uddui, udccdui, udcidui, udiidui, udinhf, udccif, udicif, udiiif) + inheritanceCSV.add_line("UD -> SL", "", udduisl, udccduisl, udciduisl, udiiduisl, 0, 0, 0, 0) + inheritanceCSV.add_line("UD -> UD", "", udduiud, udccduiud, udciduiud, udiiduiud, udinhfud, udccifud, udicifud, udiiifud) + inheritanceCSV.save + + # scalar metrics + var scalarCSV = new CSVDocument(toolcontext.output_dir.join_path("global_scalar_metrics.csv")) + var udscalarCSV = new CSVDocument(toolcontext.output_dir.join_path("ud_scalar_metrics.csv")) + scalarCSV.set_header("mclass", "type", "DIT", "DITC", "DITI", "NOP", "NOPC", "NOPI", "NOA", "NOAC", "NOAI", "NOC", "NOCC", "NOCI", "NOD", "NODC", "NODI") + udscalarCSV.set_header("mclass", "type", "DITUD", "DITCUD", "DITIUD", "NOPUD", "NOPCUD", "NOPIUD", "NOAUD", "NOACUD", "NOAIUD", "NOCUD", "NOCCUD", "NOCIUD", "NODUD", "NODCUD", "NODIUD") + for mclass in model.mclasses do + var name = mclass.name + var typ = "class" + if mclass.is_interface then typ = "interface" + scalarCSV.add_line(name, typ, mclass.dit, mclass.ditc, mclass.diti, mclass.nop, mclass.nopc, mclass.nopi, mclass.noa, mclass.noac, mclass.noai, mclass.noc, mclass.nocc, mclass.noci, mclass.nod, mclass.nodc, mclass.nodi) + udscalarCSV.add_line(name, typ, mclass.ditud, mclass.ditcud, mclass.ditiud, mclass.nopud, mclass.nopcud, mclass.nopiud, mclass.noaud, mclass.noacud, mclass.noaiud, mclass.nocud, mclass.noccud, mclass.nociud, mclass.nodud, mclass.nodcud, mclass.nodiud) + end + scalarCSV.save + udscalarCSV.save + end + print "--- Global Summary metrics ---" print "(NMD) Number of Modules: {nmd}" print "(NC) Number of Classes: {nc}" @@ -768,7 +896,8 @@ do print "(CCIF) Proportion of classes extended by class: {ccif}%" print "(ICIF) Proportion of interfaces implemented by class: {icif}%" print "(IIIF) Proportion of interfaces extended by interface: {iiif}%" - print "--- (SL) Std-Lib Inheritance metrics ---" + print "" + print "--- (SL -> *) Std-Lib Inheritance metrics ---" print "(SLDUI) Proportion of SL types inheriting another type other than Object: {sldui}%" print "(SLCCDUI) Proportion of SL classes that extend some other class: {slccdui}%" print "(SLCIDUI) Proportion of SL classes that implement some other interface: {slcidui}%" @@ -777,30 +906,44 @@ do print "(SLCCIF) Proportion of SL classes extended by class: {slccif}%" print "(SLICIF) Proportion of SL interfaces implemented by class: {slicif}%" print "(SLIIIF) Proportion of SL interfaces extended by interface: {sliiif}%" - print "--- (SL*SL) Std-Lib Inheritance metrics ---" + print "" + print "--- (SL -> SL) Std-Lib Inheritance metrics ---" print "(SLIFSL) Proportion of SL types Inherited From by SL type: {slinhfsl}%" print "(SLCCIFSL) Proportion of SL classes extended by SL class: {slccifsl}%" print "(SLICIFSL) Proportion of SL interfaces implemented by SL class: {slicifsl}%" print "(SLIIIFSL) Proportion of SL interfaces extended by SL interface: {sliiifsl}%" - print "--- (SL*UD) Std-Lib Inheritance metrics ---" + print "" + print "--- (SL->UD) Std-Lib Inheritance metrics ---" print "(SLIFUD) Proportion of SL types Inherited From by UD type: {slinhfud}%" print "(SLCCIFUD) Proportion of SL classes extended by UD class: {slccifud}%" print "(SLICIFUD) Proportion of SL interfaces implemented by UD class: {slicifud}%" print "(SLIIIFUD) Proportion of SL interfaces extended by UD interface: {sliiifud}%" - print "--- (UD) User-Defined Inheritance metrics ---" + print "" + print "--- (UD->*) User-Defined Inheritance metrics ---" print "(UDDUI) Proportion of UD types inheriting another type other than Object: {uddui}%" print "(UDCCDUI) Proportion of UD classes that extend some other class: {udccdui}%" print "(UDCIDUI) Proportion of UD classes that implement some other interface: {udcidui}%" print "(UDIIDUI) Proportion of UD interfaces that extend some other interface: {udiidui}%" print "(UDIF) Proportion of UD types Inherited From: {udinhf}%" - print "(UDCCIF) Proportion of UD classes extended by UD class: {udccif}%" - print "(UDICIF) Proportion of UD interfaces implemented by UD class: {udicif}%" - print "(UDIIIF) Proportion of UD interfaces extended by UD interface: {udiiif}%" - print "--- (UD*UD) User-Defined Inheritance metrics ---" + print "(UDCCIF) Proportion of UD classes extended by class: {udccif}%" + print "(UDICIF) Proportion of UD interfaces implemented by class: {udicif}%" + print "(UDIIIF) Proportion of UD interfaces extended by interface: {udiiif}%" + print "" + print "--- (UD -> SL) User-Defined Inheritance metrics ---" + print "(UDDUISL) Proportion of UD types inheriting another type other SL type: {udduisl}%" + print "(UDCCDUISL) Proportion of UD classes that extend some other SL class: {udccduisl}%" + print "(UDCIDUISL) Proportion of UD classes that implement some other SL interface: {udciduisl}%" + print "(UDIIDUISL) Proportion of UD interfaces that extend some other SL interface: {udiiduisl}%" + print "" + print "--- (UD -> UD) User-Defined Inheritance metrics ---" print "(UDDUIUD) Proportion of UD types inheriting another type other UD type: {udduiud}%" print "(UDCCDUIUD) Proportion of UD classes that extend some other UD class: {udccduiud}%" print "(UDCIDUIUD) Proportion of UD classes that implement some other UD interface: {udciduiud}%" print "(UDIIDUIUD) Proportion of UD interfaces that extend some other UD interface: {udiiduiud}%" + print "(UDIFUD) Proportion of UD types Inherited From: {udinhfud}%" + print "(UDCCIFUD) Proportion of UD classes extended by UD class: {udccifud}%" + print "(UDICIFUD) Proportion of UD interfaces implemented by UD class: {udicifud}%" + print "(UDIIIFUD) Proportion of UD interfaces extended by UD interface: {udiiifud}%" end # TODO Third-Party metrics diff --git a/src/metrics/metrics_base.nit b/src/metrics/metrics_base.nit index 71db364..86d4953 100644 --- a/src/metrics/metrics_base.nit +++ b/src/metrics/metrics_base.nit @@ -38,6 +38,8 @@ redef class ToolContext var opt_tables = new OptionBool("Compute tables metrics", "--tables") # --rta var opt_rta = new OptionBool("Compute RTA metrics", "--rta") + # --generate-csv + var opt_generate_csv = new OptionBool("Generate CVS format metrics", "--generate-csv") # --generate_hyperdoc var opt_generate_hyperdoc = new OptionBool("Generate Hyperdoc", "--generate_hyperdoc") @@ -55,6 +57,7 @@ redef class ToolContext self.option_context.add_option(opt_static_types) self.option_context.add_option(opt_tables) self.option_context.add_option(opt_rta) + self.option_context.add_option(opt_generate_csv) self.option_context.add_option(opt_generate_hyperdoc) self.option_context.add_option(opt_dir) end @@ -111,6 +114,42 @@ private class CounterSorter[E: Object] 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 + + fun set_header(values: Object...) do + header.clear + for value in values do header.add(value.to_s) + 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) + end + + redef fun to_s do + var str = header.join(";") + "\n" + for line in lines do str += line.join(";") + "\n" + return str + end + + fun save do + var out = new OFStream.open(self.file) + out.write(self.to_s) + out.close + end +end + # Helper function to display n/d and handle division by 0 fun div(n: Int, d: Int): String do diff --git a/src/nitmetrics.nit b/src/nitmetrics.nit index c2f65f5..561d84c 100644 --- a/src/nitmetrics.nit +++ b/src/nitmetrics.nit @@ -61,7 +61,7 @@ var all = toolcontext.opt_all.value # Inheritance usage metrics if all or toolcontext.opt_inheritance.value then print "" - compute_inheritance_metrics(model) + compute_inheritance_metrics(toolcontext, model) end # Refinement usage metrics