1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2012 Jean Privat <jean@pryen.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Collect metrics about inheritance usage
18 module inheritance_metrics
21 private import metrics_base
24 # Extract the subset of classes from a set of mclass
25 private fun extract_classes
(mclasses
: Collection[MClass]): Set[MClass] do
26 var lst
= new HashSet[MClass]
27 for mclass
in mclasses
do if mclass
.is_class
then lst
.add
(mclass
)
31 # Extract the subset of interfaces from a set of mclass
32 private fun extract_interfaces
(mclasses
: Collection[MClass]): Set[MClass] do
33 var lst
= new HashSet[MClass]
34 for mclass
in mclasses
do if mclass
.is_interface
then lst
.add
(mclass
)
38 # Extract the subset of generic classes/interfaces from a set of mclass
39 private fun extract_generics
(mclasses
: Collection[MClass]): Set[MClass] do
40 var lst
= new HashSet[MClass]
41 for mclass
in mclasses
do if mclass
.arity
> 0 then lst
.add
(mclass
)
45 # Extract the subset of abstract classes from a set of mclass
46 private fun extract_abstracts
(mclasses
: Collection[MClass]): Set[MClass] do
47 var lst
= new HashSet[MClass]
48 for mclass
in mclasses
do if mclass
.is_abstract
then lst
.add
(mclass
)
52 # Extract the subset of user defined classes/interfaces from a set of mclass
53 private fun extract_user_defined
(mclasses
: Collection[MClass]): Set[MClass] do
54 var lst
= new HashSet[MClass]
55 for mclass
in mclasses
do if mclass
.is_user_defined
then lst
.add
(mclass
)
59 # Extract the subset of user defined modules from a set of mmodules
60 private fun extract_user_defined_modules
(mmodules
: Collection[MModule]): Set[MModule] do
61 var lst
= new HashSet[MModule]
62 for mmodule
in mmodules
do if mmodule
.is_user_defined
then lst
.add
(mmodule
)
66 # Extract the subset of classes/interfaces from sl lib
67 private fun extract_stdlib
(mclasses
: Collection[MClass]): Set[MClass] do
68 var lst
= new HashSet[MClass]
69 for mclass
in mclasses
do if not mclass
.is_user_defined
then lst
.add
(mclass
)
73 # Extract the subset of user defined modules from std lib
74 private fun extract_stdlib_modules
(mmodules
: Collection[MModule]): Set[MModule] do
75 var lst
= new HashSet[MModule]
76 for mmodule
in mmodules
do if not mmodule
.is_user_defined
then lst
.add
(mmodule
)
83 private var nop
: Int = 0 # (NOP) Number of parents (direct superclasses)
84 private var nopc
: Int = 0 # (NOPC) Number of class parents
85 private var nopi
: Int = 0 # (NOPI) Number of interface parents
86 private var noa
: Int = 0 # (NOA) Number of ancestors (direct and indirect)
87 private var noac
: Int = 0 # (NOAC) Number of class ancestors
88 private var noai
: Int = 0 # (NOAI) Number of interface ancestors
89 private var noc
: Int = 0 # (NOC) Number of children (direct subclasses)
90 private var nocc
: Int = 0 # (NOCC) Number of class children
91 private var noci
: Int = 0 # (NOCI) Number of interface children
92 private var nod
: Int = 0 # (NOD) Number of descendants (direct and indirect)
93 private var nodc
: Int = 0 # (NODC) Number of class descendants
94 private var nodi
: Int = 0 # (NODI) Number of interface descendants
95 private var dit
: Int = 0 # (DIT) Depth in Inheritance Tree (maximum distance to root of the hierarchy)
96 private var ditc
: Int = 0 # (DITC) Length of longest path to the root hierarchy and consisting only of extends edges
97 private var diti
: Int = 0 # (DITI) Length of longest path to the root hierarchy and consisting only of extends implements
99 # User Defined inheritance
100 private var nopud
: Int = 0 # (NOPUD) Number of parents (direct superclasses)
101 private var nopcud
: Int = 0 # (NOPCUD) Number of class parents
102 private var nopiud
: Int = 0 # (NOPIUD) Number of interface parents
103 private var noaud
: Int = 0 # (NOAUD) Number of ancestors (direct and indirect)
104 private var noacud
: Int = 0 # (NOACUD) Number of class ancestors
105 private var noaiud
: Int = 0 # (NOAIUD) Number of interface ancestors
106 private var nocud
: Int = 0 # (NOCUD) Number of children (direct subclasses)
107 private var noccud
: Int = 0 # (NOCCUD) Number of class children
108 private var nociud
: Int = 0 # (NOCIUD) Number of interface children
109 private var nodud
: Int = 0 # (NODUD) Number of descendants (direct and indirect)
110 private var nodcud
: Int = 0 # (NODCUD) Number of class descendants
111 private var nodiud
: Int = 0 # (NODIUD) Number of interface descendants
112 private var ditud
: Int = 0 # (DITUD) Depth in Inheritance Tree (maximum distance to root of the hierarchy)
113 private var ditcud
: Int = 0 # (DITCUD) Length of longest path to the root hierarchy and consisting only of extends edges
114 private var ditiud
: Int = 0 # (DITIUD) Length of longest path to the root hierarchy and consisting only of extends implements
116 private fun compute_class_inheritance_metrics
(model
: Model) do
117 # inheritance metrics
118 self.nop
= parents
.length
119 self.nopc
= model
.extract_classes
(parents
).length
120 self.nopi
= model
.extract_interfaces
(parents
).length
121 self.noa
= ancestors
.length
122 self.noac
= model
.extract_classes
(ancestors
).length
123 self.noai
= model
.extract_interfaces
(ancestors
).length
124 self.noc
= children
.length
125 self.nocc
= model
.extract_classes
(children
).length
126 self.noci
= model
.extract_interfaces
(children
).length
127 self.nod
= descendants
.length
128 self.nodc
= model
.extract_classes
(descendants
).length
129 self.nodi
= model
.extract_interfaces
(descendants
).length
130 self.dit
= path_to_object
.length
131 self.ditc
= class_path_to_object
.length
132 self.diti
= interface_path_to_object
.length
134 # used defined metrics
135 self.nopud
= model
.extract_user_defined
(parents
).length
136 self.nopcud
= model
.extract_user_defined
(model
.extract_classes
(parents
)).length
137 self.nopiud
= model
.extract_user_defined
(model
.extract_interfaces
(parents
)).length
138 self.noaud
= model
.extract_user_defined
(ancestors
).length
139 self.noacud
= model
.extract_user_defined
(model
.extract_classes
(ancestors
)).length
140 self.noaiud
= model
.extract_user_defined
(model
.extract_interfaces
(ancestors
)).length
141 self.nocud
= model
.extract_user_defined
(children
).length
142 self.noccud
= model
.extract_user_defined
(model
.extract_classes
(children
)).length
143 self.nociud
= model
.extract_user_defined
(model
.extract_interfaces
(children
)).length
144 self.nodud
= model
.extract_user_defined
(descendants
).length
145 self.nodcud
= model
.extract_user_defined
(model
.extract_classes
(descendants
)).length
146 self.nodiud
= model
.extract_user_defined
(model
.extract_interfaces
(descendants
)).length
147 self.ditud
= ud_path_to_object
.length
148 self.ditcud
= ud_class_path_to_object
.length
149 self.ditiud
= ud_interface_path_to_object
.length
152 # Return the longest path from class to root hierarchy
153 private fun path_to_object
: Array[MClass] do
154 var path
= new Array[MClass]
155 var max_dit
: nullable Int = null
156 var max_parent
: nullable MClass = null
157 var parent_path
: nullable Array[MClass] = null
160 var dit
= p
.path_to_object
.length
161 if max_dit
== null or dit
>= max_dit
then
164 parent_path
= p
.path_to_object
168 if max_parent
!= null and parent_path
!= null then
170 path
.add_all
(parent_path
)
176 # Return the longest path from class to root hierarchy
177 private fun ud_path_to_object
: Array[MClass] do
178 var path
= new Array[MClass]
179 if not self.is_user_defined
then return path
180 var max_dit
: nullable Int = null
181 var max_parent
: nullable MClass = null
182 var parent_path
: nullable Array[MClass] = null
185 var dit
= p
.ud_path_to_object
.length
186 if max_dit
== null or dit
>= max_dit
then
189 parent_path
= p
.ud_path_to_object
193 if max_parent
!= null and parent_path
!= null then
195 path
.add_all
(parent_path
)
201 # Return the longest path from class to root hierarchy following only classes relations
202 private fun class_path_to_object
: Array[MClass] do
203 var path
= new Array[MClass]
204 if not self.is_class
then return path
205 var max_dit
: nullable Int = null
206 var max_parent
: nullable MClass = null
207 var parent_path
: nullable Array[MClass] = null
210 var dit
= p
.class_path_to_object
.length
211 if max_dit
== null or dit
>= max_dit
then
214 parent_path
= p
.class_path_to_object
218 if max_parent
!= null and parent_path
!= null then
220 path
.add_all
(parent_path
)
226 # Return the longest path from class to root hierarchy following only interfaces relations
227 private fun interface_path_to_object
: Array[MClass] do
228 var path
= new Array[MClass]
229 if not self.is_interface
then return path
230 var max_dit
: nullable Int = null
231 var max_parent
: nullable MClass = null
232 var parent_path
: nullable Array[MClass] = null
235 var dit
= p
.interface_path_to_object
.length
236 if max_dit
== null or dit
>= max_dit
then
239 parent_path
= p
.interface_path_to_object
243 if max_parent
!= null and parent_path
!= null then
245 path
.add_all
(parent_path
)
251 # Return the longest path from class to root hierarchy following only ud classes relations
252 private fun ud_class_path_to_object
: Array[MClass] do
253 var path
= new Array[MClass]
254 if not self.is_class
or not self.is_user_defined
then return path
255 var max_dit
: nullable Int = null
256 var max_parent
: nullable MClass = null
257 var parent_path
: nullable Array[MClass] = null
260 var dit
= p
.ud_class_path_to_object
.length
261 if max_dit
== null or dit
>= max_dit
then
264 parent_path
= p
.ud_class_path_to_object
268 if max_parent
!= null and parent_path
!= null then
270 path
.add_all
(parent_path
)
276 # Return the longest path from class to root hierarchy following only ud interfaces relations
277 private fun ud_interface_path_to_object
: Array[MClass] do
278 var path
= new Array[MClass]
279 if not self.is_interface
or not self.is_user_defined
then return path
280 var max_dit
: nullable Int = null
281 var max_parent
: nullable MClass = null
282 var parent_path
: nullable Array[MClass] = null
285 var dit
= p
.ud_interface_path_to_object
.length
286 if max_dit
== null or dit
>= max_dit
then
289 parent_path
= p
.ud_interface_path_to_object
293 if max_parent
!= null and parent_path
!= null then
295 path
.add_all
(parent_path
)
303 private fun is_dui_eligible
: Bool do
304 for parent
in parents
do if parent
.name
!= "Object" then return true
307 private fun is_ccdui_eligible
: Bool do
308 if not is_class
then return false
309 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
then return true
312 private fun is_cidui_eligible
: Bool do
313 if not is_class
then return false
314 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
317 private fun is_iidui_eligible
: Bool do
318 if not is_interface
then return false
319 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
322 private fun is_if_eligible
(model
: Model): Bool do return not children
.is_empty
323 private fun is_ccif_eligible
(model
: Model): Bool do
324 if not is_class
then return false
325 for child
in children
do if child
.is_class
then return true
328 private fun is_icif_eligible
(model
: Model): Bool do
329 if not is_interface
then return false
330 for child
in children
do if child
.is_class
then return true
333 private fun is_iiif_eligible
(model
: Model): Bool do
334 if not is_interface
then return false
335 for child
in children
do if child
.is_interface
then return true
341 private fun is_sldui_eligible
: Bool do
342 if is_user_defined
then return false
343 for parent
in parents
do if parent
.name
!= "Object" then return true
346 private fun is_slccdui_eligible
: Bool do
347 if is_user_defined
then return false
348 if not is_class
then return false
349 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
then return true
352 private fun is_slcidui_eligible
: Bool do
353 if is_user_defined
then return false
354 if not is_class
then return false
355 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
358 private fun is_sliidui_eligible
: Bool do
359 if is_user_defined
then return false
360 if not is_interface
then return false
361 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
364 private fun is_slif_eligible
(model
: Model): Bool do
365 if is_user_defined
then return false
366 return not children
.is_empty
368 private fun is_slccif_eligible
(model
: Model): Bool do
369 if is_user_defined
then return false
370 if not is_class
then return false
371 for child
in children
do if child
.is_class
then return true
374 private fun is_slicif_eligible
(model
: Model): Bool do
375 if is_user_defined
then return false
376 if not is_interface
then return false
377 for child
in children
do if child
.is_class
then return true
380 private fun is_sliiif_eligible
(model
: Model): Bool do
381 if is_user_defined
then return false
382 if not is_interface
then return false
383 for child
in children
do if child
.is_interface
then return true
389 private fun is_slifsl_eligible
(model
: Model): Bool do
390 if is_user_defined
then return false
391 for child
in children
do if not child
.is_user_defined
then return true
394 private fun is_slccifsl_eligible
(model
: Model): Bool do
395 if is_user_defined
then return false
396 if is_class
then return false
397 for child
in children
do if not child
.is_user_defined
and child
.is_class
then return true
400 private fun is_slicifsl_eligible
(model
: Model): Bool do
401 if is_user_defined
then return false
402 if not is_interface
then return false
403 for child
in children
do if not child
.is_user_defined
and child
.is_class
then return true
406 private fun is_sliiifsl_eligible
(model
: Model): Bool do
407 if is_user_defined
then return false
408 if not is_interface
then return false
409 for child
in children
do if not child
.is_user_defined
and child
.is_interface
then return true
415 private fun is_slifud_eligible
(model
: Model): Bool do
416 if is_user_defined
then return false
417 for child
in children
do if child
.is_user_defined
then return true
420 private fun is_slccifud_eligible
(model
: Model): Bool do
421 if is_user_defined
then return false
422 if not is_class
then return false
423 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
426 private fun is_slicifud_eligible
(model
: Model): Bool do
427 if is_user_defined
then return false
428 if not is_interface
then return false
429 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
432 private fun is_sliiifud_eligible
(model
: Model): Bool do
433 if is_user_defined
then return false
434 if not is_interface
then return false
435 for child
in children
do if child
.is_user_defined
and child
.is_interface
then return true
441 private fun is_uddui_eligible
: Bool do
442 if not is_user_defined
then return false
443 for parent
in parents
do if parent
.name
!= "Object" then return true
446 private fun is_udccdui_eligible
: Bool do
447 if not is_user_defined
then return false
448 if not is_class
then return false
449 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
then return true
452 private fun is_udcidui_eligible
: Bool do
453 if not is_user_defined
then return false
454 if not is_class
then return false
455 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
458 private fun is_udiidui_eligible
: Bool do
459 if not is_user_defined
then return false
460 if not is_interface
then return false
461 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
464 private fun is_udif_eligible
(model
: Model): Bool do
465 if not is_user_defined
then return false
466 return not children
.is_empty
468 private fun is_udccif_eligible
(model
: Model): Bool do
469 if not is_user_defined
then return false
470 if not is_class
then return false
471 for child
in children
do if child
.is_class
then return true
474 private fun is_udicif_eligible
(model
: Model): Bool do
475 if not is_user_defined
then return false
476 if not is_interface
then return false
477 for child
in children
do if child
.is_class
then return true
480 private fun is_udiiif_eligible
(model
: Model): Bool do
481 if not is_user_defined
then return false
482 if not is_interface
then return false
483 for child
in children
do if child
.is_interface
then return true
489 private fun is_udduisl_eligible
: Bool do
490 if not is_user_defined
then return false
491 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" then return true
494 private fun is_udccduisl_eligible
: Bool do
495 if not is_user_defined
then return false
496 if not is_class
then return false
497 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" and parent
.is_class
then return true
500 private fun is_udciduisl_eligible
: Bool do
501 if not is_user_defined
then return false
502 if not is_class
then return false
503 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" and parent
.is_interface
then return true
506 private fun is_udiiduisl_eligible
: Bool do
507 if not is_user_defined
then return false
508 if not is_interface
then return false
509 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" and parent
.is_interface
then return true
515 private fun is_udduiud_eligible
: Bool do
516 if not is_user_defined
then return false
517 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_user_defined
then return true
520 private fun is_udccduiud_eligible
: Bool do
521 if not is_user_defined
then return false
522 if not is_class
then return false
523 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
and parent
.is_user_defined
then return true
526 private fun is_udciduiud_eligible
: Bool do
527 if not is_user_defined
then return false
528 if not is_class
then return false
529 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
and parent
.is_user_defined
then return true
532 private fun is_udiiduiud_eligible
: Bool do
533 if not is_user_defined
then return false
534 if not is_interface
then return false
535 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
and parent
.is_user_defined
then return true
538 private fun is_udifud_eligible
(model
: Model): Bool do
539 if not is_user_defined
then return false
540 return not children
.is_empty
542 private fun is_udccifud_eligible
(model
: Model): Bool do
543 if not is_user_defined
then return false
544 if not is_class
then return false
545 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
548 private fun is_udicifud_eligible
(model
: Model): Bool do
549 if not is_user_defined
then return false
550 if not is_interface
then return false
551 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
554 private fun is_udiiifud_eligible
(model
: Model): Bool do
555 if not is_user_defined
then return false
556 if not is_interface
then return false
557 for child
in children
do if child
.is_user_defined
and child
.is_interface
then return true
564 private var nm
: Int = 0 # (NC) Number of Modules
565 private var nc
: Int = 0 # (NC) Number of Classes
566 private var ni
: Int = 0 # (NI) Number of Interfaces
567 private var nac
: Int = 0 # (NAC) Number of Abstract Classes
568 private var ngc
: Int = 0 # (NGC) Number of Generic Classes
569 private var ngi
: Int = 0 # (NGI) Number of Generic Interfaces
571 private var dit
= "" # (DIT) Global Depth in Inheritance Tree
572 private var dui
= "" # (DUI) Proportion of types that either implement an interface or extend another type other than Object
573 private var ccdui
= "" # (CCDUI) Proportion of classes that extend some other class.
574 private var cidui
= "" # (CIDUI) Proportion of classes that implement some other interface.
575 private var iidui
= "" # (IIDUI) Proportion of interfaces that extend some other interface.
576 private var inhf
= "" # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
577 private var ccif
= "" # (CCIF) Proportion of classes extended by some other class.
578 private var icif
= "" # (ICIF) Proportion of interfaces implemented by some other class.
579 private var iiif
= "" # (IIIF) Proportion of interfaces extended by some other interface.
581 private fun compute_module_inheritance_metrics
(model
: Model) do
592 for mmodule
in self.in_nesting
.greaters
do
593 for mclass
in mmodule
.intro_mclasses
do
595 if mclass
.is_class
then nc
+= 1
596 if mclass
.is_class
and mclass
.arity
> 0 then ngc
+= 1
597 if mclass
.is_class
and mclass
.is_abstract
then nac
+= 1
598 if mclass
.is_interface
then ni
+= 1
599 if mclass
.is_interface
and mclass
.arity
> 0 then ngi
+= 1
600 ditsum
+= mclass
.path_to_object
.length
601 if mclass
.is_dui_eligible
then dui_count
+= 1
602 if mclass
.is_ccdui_eligible
then ccdui_count
+= 1
603 if mclass
.is_cidui_eligible
then cidui_count
+= 1
604 if mclass
.is_iidui_eligible
then iidui_count
+= 1
605 if mclass
.is_if_eligible
(model
) then if_count
+= 1
606 if mclass
.is_ccif_eligible
(model
) then ccif_count
+= 1
607 if mclass
.is_icif_eligible
(model
) then icif_count
+= 1
608 if mclass
.is_iiif_eligible
(model
) then iiif_count
+= 1
612 self.nm
= self.in_nesting
.greaters
.length
613 dit
= div
(ditsum
, count
)
614 dui
= div
(dui_count
* 100, count
)
615 ccdui
= div
(ccdui_count
* 100, nc
)
616 cidui
= div
(cidui_count
* 100, nc
)
617 iidui
= div
(iidui_count
* 100, ni
)
618 inhf
= div
(if_count
* 100, count
)
619 ccif
= div
(ccif_count
* 100, nc
)
620 icif
= div
(icif_count
* 100, ni
)
621 iiif
= div
(iiif_count
* 100, ni
)
625 # Print inheritance usage metrics
626 fun compute_inheritance_metrics
(toolcontext
: ToolContext, model
: Model)
628 # global summary metrics
629 var nmd
: Int = 0 # (NMD) Number of Modules
630 var nc
: Int = 0 # (NC) Number of Classes
631 var ni
: Int = 0 # (NI) Number of Interfaces
632 var nac
: Int = 0 # (NAC) Number of Abstract Classes
633 var ngc
: Int = 0 # (NGC) Number of Generic Classes
634 var ngi
: Int = 0 # (NGI) Number of Generic Interfaces
635 # (SL) Std-Lib summary metrics
636 var nmdsl
: Int = 0 # (NMDSL) Number of Modules in Std-Lib
637 var ncsl
: Int = 0 # (NCSL) Number of Classes in Std-Lib
638 var nisl
: Int = 0 # (NISL) Number of Interfaces in Std-Lib
639 var nacsl
: Int = 0 # (NACSL) Number of Abstract Classes in Std-Lib
640 var ngcsl
: Int = 0 # (NGCSL) Number of Generic Classes in Std-Lib
641 var ngisl
: Int = 0 # (NGISL) Number of Generic Interfaces in Std-Lib
642 # (UD) User-Defined summary metrics
643 var nmdud
: Int = 0 # (NMDUD) Number of Modules User Defined
644 var ncud
: Int = 0 # (NCUD) Number of Classes User Defined
645 var niud
: Int = 0 # (NIUD) Number of Interfaces User Defined
646 var nacud
: Int = 0 # (NACUD) Number of Abstract Classes User Defined
647 var ngcud
: Int = 0 # (NGCUD) Number of Generic Classes User Defined
648 var ngiud
: Int = 0 # (NGIUD) Number of Generic Interfaces User Defined
650 # global summary inheritance metrics
651 var dit
= "" # (DIT) Global Depth in Inheritance Tree
652 var dui
= "" # (DUI) Proportion of types that either implement an interface or extend another type other than Object
653 var ccdui
= "" # (CCDUI) Proportion of classes that extend some other class.
654 var cidui
= "" # (CIDUI) Proportion of classes that implement some other interface.
655 var iidui
= "" # (IIDUI) Proportion of interfaces that extend some other interface.
656 var inhf
= "" # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
657 var ccif
= "" # (CCIF) Proportion of classes extended by some other class.
658 var icif
= "" # (ICIF) Proportion of interfaces implemented by some other class.
659 var iiif
= "" # (IIIF) Proportion of interfaces extended by some other interface.
661 # (SL -> *) Std-Lib summary inheritance metrics
662 var sldui
= "" # (SLDUI) Proportion of std-lib types that either implement an interface or extend another std-lib type other than Object
663 var slccdui
= "" # (SLCCDUI) Proportion of std-lib classes that extend some other std-lib class.
664 var slcidui
= "" # (SLCIDUI) Proportion of std-lib classes that implement some other std-lib interface.
665 var sliidui
= "" # (SLIIDUI) Proportion of std-lib interfaces that extend some other std-lib interface.
666 var slinhf
= "" # (SLIF) Proportion of SL types Inherited From, that is, those types that are either extended or implemented
667 var slccif
= "" # (SLCCIF) Proportion of SL classes extended by some other class.
668 var slicif
= "" # (SLICIF) Proportion of SL interfaces implemented by some other class.
669 var sliiif
= "" # (SLIIIF) Proportion of SL interfaces extended by some other interface.
671 # (SL -> SL) Std-Lib summary inheritance metrics
672 var slinhfsl
= "" # (SLIFSL) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a SL type
673 var slccifsl
= "" # (SLCCIFSL) Proportion of SL classes extended by some other SL class.
674 var slicifsl
= "" # (SLICIFSL) Proportion of SL interfaces implemented by some other SL class.
675 var sliiifsl
= "" # (SLIIIFSL) Proportion of SL interfaces extended by some other SL interface.
677 # (SL -> UD) Std-Lib summary inheritance metrics
678 var slinhfud
= "" # (SLIFUD) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a UD type
679 var slccifud
= "" # (SLCCIFUD) Proportion of SL classes extended by some other UD class.
680 var slicifud
= "" # (SLICIFUD) Proportion of SL interfaces implemented by some other UD class.
681 var sliiifud
= "" # (SLIIIFUD) Proportion of SL interfaces extended by some other UD interface.
683 # (UD -> *) User-defined summary inheritance metrics
684 var uddui
= "" # (UDDUI) Proportion user-defined of types that either implement an interface or extend another type
685 var udccdui
= "" # (UDCCDUI) Proportion of user-defined classes that extend some other class.
686 var udcidui
= "" # (UDCIDUI) Proportion of user-defined classes that implement some other interface.
687 var udiidui
= "" # (UDIIDUI) Proportion of user-defined interfaces that extend some other interface.
688 var udinhf
= "" # (UDIF) Proportion of UD types Inherited From, that is, those types that are either extended or implemented
689 var udccif
= "" # (UDCCIF) Proportion of UD classes extended by some other class.
690 var udicif
= "" # (UDICIF) Proportion of UD interfaces implemented by some other class.
691 var udiiif
= "" # (UDIIIF) Proportion of UD interfaces extended by some other interface.
693 # (UD -> SL) User-defined summary inheritance metrics
694 var udduisl
= "" # (UDDUISL) Proportion user-defined of types that either implement an interface or extend another type SL
695 var udccduisl
= "" # (UDCCDUISL) Proportion of user-defined classes that extend some other SL class.
696 var udciduisl
= "" # (UDCIDUISL) Proportion of user-defined classes that implement some other SL interface.
697 var udiiduisl
= "" # (UDIIDUISL) Proportion of user-defined interfaces that extend some other SL interface.
699 # (UD -> UD) User-defined summary inheritance metrics
701 var udduiud
= "" # (UDDUIUD) Proportion user-defined of types that either implement an interface or extend another type user-defined
702 var udccduiud
= "" # (UDCCDUIUD) Proportion of user-defined classes that extend some other user-defined class.
703 var udciduiud
= "" # (UDCIDUIUD) Proportion of user-defined classes that implement some other user-defined interface.
704 var udiiduiud
= "" # (UDIIDUIUD) Proportion of user-defined interfaces that extend some other user-defined interface.
705 var udinhfud
= "" # (UDIFUD) Proportion of UD types Inherited From, that is, those types that are either extended or implemented by another UD type
706 var udccifud
= "" # (UDCCIFUD) Proportion of UD classes extended by some other UD class.
707 var udicifud
= "" # (UDICIFUD) Proportion of UD interfaces implemented by some other UD class.
708 var udiiifud
= "" # (UDIIIFUD) Proportion of UD interfaces extended by some other UD interface.
710 # compute modules scalar metrics
711 for mmodule
in model
.mmodules
do
712 mmodule
.compute_module_inheritance_metrics
(model
)
715 # compute class scalar metrics
716 for mclass
in model
.mclasses
do
717 mclass
.compute_class_inheritance_metrics
(model
)
720 # compute summary metrics
722 # compute global summary metrics
723 nmd
= model
.mmodules
.length
724 nc
= model
.extract_classes
(model
.mclasses
).length
725 ni
= model
.extract_interfaces
(model
.mclasses
).length
726 nac
= model
.extract_abstracts
(model
.mclasses
).length
727 ngc
= model
.extract_generics
(model
.extract_classes
(model
.mclasses
)).length
728 ngi
= model
.extract_generics
(model
.extract_interfaces
(model
.mclasses
)).length
729 # compute std-lib summary metrics
730 nmdsl
= model
.extract_stdlib_modules
(model
.mmodules
).length
731 ncsl
= model
.extract_stdlib
(model
.extract_classes
(model
.mclasses
)).length
732 nisl
= model
.extract_stdlib
(model
.extract_interfaces
(model
.mclasses
)).length
733 nacsl
= model
.extract_stdlib
(model
.extract_abstracts
(model
.mclasses
)).length
734 ngcsl
= model
.extract_stdlib
(model
.extract_generics
(model
.extract_classes
(model
.mclasses
))).length
735 ngisl
= model
.extract_stdlib
(model
.extract_generics
(model
.extract_interfaces
(model
.mclasses
))).length
736 # compute user-defined summary metrics
737 nmdud
= model
.extract_user_defined_modules
(model
.mmodules
).length
738 ncud
= model
.extract_user_defined
(model
.extract_classes
(model
.mclasses
)).length
739 niud
= model
.extract_user_defined
(model
.extract_interfaces
(model
.mclasses
)).length
740 nacud
= model
.extract_user_defined
(model
.extract_abstracts
(model
.mclasses
)).length
741 ngcud
= model
.extract_user_defined
(model
.extract_generics
(model
.extract_classes
(model
.mclasses
))).length
742 ngiud
= model
.extract_user_defined
(model
.extract_generics
(model
.extract_interfaces
(model
.mclasses
))).length
744 # compute inheritance summary metrics
761 var slccdui_count
= 0
762 var slcidui_count
= 0
763 var sliidui_count
= 0
771 var slccifsl_count
= 0
772 var slicifsl_count
= 0
773 var sliiifsl_count
= 0
777 var slccifud_count
= 0
778 var slicifud_count
= 0
779 var sliiifud_count
= 0
783 var udccdui_count
= 0
784 var udcidui_count
= 0
785 var udiidui_count
= 0
792 var udduisl_count
= 0
793 var udccduisl_count
= 0
794 var udciduisl_count
= 0
795 var udiiduisl_count
= 0
798 var udduiud_count
= 0
799 var udccduiud_count
= 0
800 var udciduiud_count
= 0
801 var udiiduiud_count
= 0
803 var udccifud_count
= 0
804 var udicifud_count
= 0
805 var udiiifud_count
= 0
807 for mclass
in model
.mclasses
do
809 ditudsum
+= mclass
.ditud
812 if mclass
.is_dui_eligible
then dui_count
+= 1
813 if mclass
.is_ccdui_eligible
then ccdui_count
+= 1
814 if mclass
.is_cidui_eligible
then cidui_count
+= 1
815 if mclass
.is_iidui_eligible
then iidui_count
+= 1
816 if mclass
.is_if_eligible
(model
) then if_count
+= 1
817 if mclass
.is_ccif_eligible
(model
) then ccif_count
+= 1
818 if mclass
.is_icif_eligible
(model
) then icif_count
+= 1
819 if mclass
.is_iiif_eligible
(model
) then iiif_count
+= 1
822 if mclass
.is_sldui_eligible
then sldui_count
+= 1
823 if mclass
.is_slccdui_eligible
then slccdui_count
+= 1
824 if mclass
.is_slcidui_eligible
then slcidui_count
+= 1
825 if mclass
.is_sliidui_eligible
then sliidui_count
+= 1
826 if mclass
.is_slif_eligible
(model
) then slif_count
+= 1
827 if mclass
.is_slccif_eligible
(model
) then slccif_count
+= 1
828 if mclass
.is_slicif_eligible
(model
) then slicif_count
+= 1
829 if mclass
.is_sliiif_eligible
(model
) then sliiif_count
+= 1
832 if mclass
.is_slifsl_eligible
(model
) then slifsl_count
+= 1
833 if mclass
.is_slccifsl_eligible
(model
) then slccifsl_count
+= 1
834 if mclass
.is_slicifsl_eligible
(model
) then slicifsl_count
+= 1
835 if mclass
.is_sliiifsl_eligible
(model
) then sliiifsl_count
+= 1
838 if mclass
.is_slifud_eligible
(model
) then slifud_count
+= 1
839 if mclass
.is_slccifud_eligible
(model
) then slccifud_count
+= 1
840 if mclass
.is_slicifud_eligible
(model
) then slicifud_count
+= 1
841 if mclass
.is_sliiifud_eligible
(model
) then sliiifud_count
+= 1
844 if mclass
.is_uddui_eligible
then uddui_count
+= 1
845 if mclass
.is_udccdui_eligible
then udccdui_count
+= 1
846 if mclass
.is_udcidui_eligible
then udcidui_count
+= 1
847 if mclass
.is_udiidui_eligible
then udiidui_count
+= 1
848 if mclass
.is_udif_eligible
(model
) then udif_count
+= 1
849 if mclass
.is_udccif_eligible
(model
) then udccif_count
+= 1
850 if mclass
.is_udicif_eligible
(model
) then udicif_count
+= 1
851 if mclass
.is_udiiif_eligible
(model
) then udiiif_count
+= 1
854 if mclass
.is_udduisl_eligible
then udduisl_count
+= 1
855 if mclass
.is_udccduisl_eligible
then udccduisl_count
+= 1
856 if mclass
.is_udciduisl_eligible
then udciduisl_count
+= 1
857 if mclass
.is_udiiduisl_eligible
then udiiduisl_count
+= 1
860 if mclass
.is_udduiud_eligible
then udduiud_count
+= 1
861 if mclass
.is_udccduiud_eligible
then udccduiud_count
+= 1
862 if mclass
.is_udciduiud_eligible
then udciduiud_count
+= 1
863 if mclass
.is_udiiduiud_eligible
then udiiduiud_count
+= 1
864 if mclass
.is_udifud_eligible
(model
) then udifud_count
+= 1
865 if mclass
.is_udccifud_eligible
(model
) then udccifud_count
+= 1
866 if mclass
.is_udicifud_eligible
(model
) then udicifud_count
+= 1
867 if mclass
.is_udiiifud_eligible
(model
) then udiiifud_count
+= 1
871 dit
= div
(ditsum
, model
.mclasses
.length
)
872 ditud
= div
(ditudsum
, ncud
+ niud
)
873 dui
= div
(dui_count
* 100, model
.mclasses
.length
)
874 ccdui
= div
(ccdui_count
* 100, nc
)
875 cidui
= div
(cidui_count
* 100, nc
)
876 iidui
= div
(iidui_count
* 100, ni
)
877 inhf
= div
(if_count
* 100, nc
+ ni
)
878 ccif
= div
(ccif_count
* 100, nc
)
879 icif
= div
(icif_count
* 100, ni
)
880 iiif
= div
(iiif_count
* 100, ni
)
883 sldui
= div
(sldui_count
* 100, ncsl
+ nisl
)
884 slccdui
= div
(slccdui_count
* 100, ncsl
)
885 slcidui
= div
(slcidui_count
* 100, ncsl
)
886 sliidui
= div
(sliidui_count
* 100, nisl
)
887 slinhf
= div
(slif_count
* 100, ncsl
+ nisl
)
888 slccif
= div
(slccif_count
* 100, ncsl
)
889 slicif
= div
(slicif_count
* 100, nisl
)
890 sliiif
= div
(sliiif_count
* 100, nisl
)
893 slinhfsl
= div
(slifsl_count
* 100, ncsl
+ nisl
)
894 slccifsl
= div
(slccifsl_count
* 100, ncsl
)
895 slicifsl
= div
(slicifsl_count
* 100, nisl
)
896 sliiifsl
= div
(sliiifsl_count
* 100, nisl
)
899 slinhfud
= div
(slifud_count
* 100, ncsl
+ nisl
)
900 slccifud
= div
(slccifud_count
* 100, ncsl
)
901 slicifud
= div
(slicifud_count
* 100, nisl
)
902 sliiifud
= div
(sliiifud_count
* 100, nisl
)
905 uddui
= div
(uddui_count
* 100, ncud
+ niud
)
906 udccdui
= div
(udccdui_count
* 100, ncud
)
907 udcidui
= div
(udcidui_count
* 100, ncud
)
908 udiidui
= div
(udiidui_count
* 100, niud
)
909 udinhf
= div
(if_count
* 100, ncud
+ niud
)
910 udccif
= div
(ccif_count
* 100, ncud
)
911 udicif
= div
(icif_count
* 100, niud
)
912 udiiif
= div
(iiif_count
* 100, niud
)
915 udduisl
= div
(udduisl_count
* 100, ncud
+ niud
)
916 udccduisl
= div
(udccduisl_count
* 100, ncud
)
917 udciduisl
= div
(udciduisl_count
* 100, ncud
)
918 udiiduisl
= div
(udiiduisl_count
* 100, niud
)
921 udduiud
= div
(udduiud_count
* 100, ncud
+ niud
)
922 udccduiud
= div
(udccduiud_count
* 100, ncud
)
923 udciduiud
= div
(udciduiud_count
* 100, ncud
)
924 udiiduiud
= div
(udiiduiud_count
* 100, niud
)
925 udinhfud
= div
(udifud_count
* 100, ncud
+ niud
)
926 udccifud
= div
(udccifud_count
* 100, ncud
)
927 udicifud
= div
(udicifud_count
* 100, niud
)
928 udiiifud
= div
(udiiifud_count
* 100, niud
)
931 if toolcontext
.opt_generate_csv
.value
then
933 var summaryCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("summary_metrics.csv"))
934 summaryCSV
.set_header
("scope", "NMD", "NC", "NI", "NAC", "NGC", "NGI")
935 summaryCSV
.add_line
("global", nmd
, nc
, ni
, nac
, ngc
, ngi
)
936 summaryCSV
.add_line
("std-lib", nmdsl
, ncsl
, nisl
, nacsl
, ngcsl
, ngisl
)
937 summaryCSV
.add_line
("user-defined", nmdud
, ncud
, niud
, nacud
, ngcud
, ngiud
)
938 for m
in model
.mmodules
do
939 summaryCSV
.add_line
(m
.name
, m
.nm
, m
.nc
, m
.ni
, m
.nac
, m
.ngc
, m
.ngi
)
943 # inheritance metrics
944 var inheritanceCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("inheritance_metrics.csv"))
945 inheritanceCSV
.set_header
("scope", "DIT", "DUI", "CCDUI", "CIDUI", "IIDUI", "IF", "CCIF", "ICIF", "IIIF")
946 inheritanceCSV
.add_line
("global", dit
, dui
, ccdui
, cidui
, iidui
, inhf
, ccif
, icif
, iiif
)
947 inheritanceCSV
.add_line
("SL -> *", "", sldui
, slccdui
, slcidui
, sliidui
, slinhf
, slccif
, slicif
, sliiif
)
948 inheritanceCSV
.add_line
("SL -> SL", "", sldui
, slccdui
, slcidui
, sliidui
, slinhfsl
, slccifsl
, slicifsl
, sliiifsl
)
949 inheritanceCSV
.add_line
("SL -> UD", "", 0, 0, 0, 0, slinhfud
, slccifud
, slicifud
, sliiifud
)
950 inheritanceCSV
.add_line
("UD -> *", "", uddui
, udccdui
, udcidui
, udiidui
, udinhf
, udccif
, udicif
, udiiif
)
951 inheritanceCSV
.add_line
("UD -> SL", "", udduisl
, udccduisl
, udciduisl
, udiiduisl
, 0, 0, 0, 0)
952 inheritanceCSV
.add_line
("UD -> UD", ditud
, udduiud
, udccduiud
, udciduiud
, udiiduiud
, udinhfud
, udccifud
, udicifud
, udiiifud
)
953 for m
in model
.mmodules
do
954 if m
.intro_mclasses
.is_empty
and m
.in_nesting
.greaters
.length
== 1 then continue
955 inheritanceCSV
.add_line
(m
.name
, m
.dit
, m
.dui
, m
.ccdui
, m
.cidui
, m
.iidui
, m
.inhf
, m
.ccif
, m
.icif
, m
.iiif
)
960 var scalarCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("global_scalar_metrics.csv"))
961 var udscalarCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("ud_scalar_metrics.csv"))
962 scalarCSV
.set_header
("mclass", "type", "FT", "DIT", "DITC", "DITI", "NOP", "NOPC", "NOPI", "NOA", "NOAC", "NOAI", "NOC", "NOCC", "NOCI", "NOD", "NODC", "NODI")
963 udscalarCSV
.set_header
("mclass", "type", "FT","DITUD", "DITCUD", "DITIUD", "NOPUD", "NOPCUD", "NOPIUD", "NOAUD", "NOACUD", "NOAIUD", "NOCUD", "NOCCUD", "NOCIUD", "NODUD", "NODCUD", "NODIUD")
964 for mclass
in model
.mclasses
do
965 var name
= mclass
.name
967 if mclass
.is_interface
then typ
= "interface"
968 scalarCSV
.add_line
(name
, typ
, mclass
.arity
, 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
)
969 udscalarCSV
.add_line
(name
, typ
, mclass
.arity
, 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
)
975 print
"--- Global Summary metrics ---"
976 print
"(NMD) Number of Modules: {nmd}"
977 print
"(NC) Number of Classes: {nc}"
978 print
"(NI) Number of Interfaces: {ni}"
979 print
"(NAC) Number of Abstract Classes: {nac}"
980 print
"(NGC) Number of Generic Classes: {ngc}"
981 print
"(NGI) Number of Generic Interfaces: {ngi}"
982 print
"--- (SL) Std-Lib Summary metrics ---"
983 print
"(NMDSL) Number of Modules: {nmdsl}"
984 print
"(NCSL) Number of Classes: {ncsl}"
985 print
"(NISL) Number of Interfaces: {nisl}"
986 print
"(NACSL) Number of Abstract Classes: {nacsl}"
987 print
"(NGCSL) Number of Generic Classes: {ngcsl}"
988 print
"(NGISL) Number of Generic Interfaces: {ngisl}"
989 print
"--- (UD) User-Defined Summary metrics ---"
990 print
"(NMDUD) Number of Modules: {nmdud}"
991 print
"(NCUD) Number of Classes: {ncud}"
992 print
"(NIUD) Number of Interfaces: {niud}"
993 print
"(NACUD) Number of Abstract Classes: {nacud}"
994 print
"(NGCUD) Number of Generic Classes: {ngcud}"
995 print
"(NGIUD) Number of Generic Interfaces: {ngiud}"
997 print
"--- Global Inheritance metrics ---"
998 print
"(DIT) Global Depth in Inheritance Tree: {dit}"
999 print
"(DUI) Proportion of types inheriting another type other than Object: {dui}%"
1000 print
"(CCDUI) Proportion of classes that extend some other class: {ccdui}%"
1001 print
"(CIDUI) Proportion of classes that implement some other interface: {cidui}%"
1002 print
"(IIDUI) Proportion of interfaces that extend some other interface: {iidui}%"
1003 print
"(IF) Proportion of types Inherited From: {inhf}%"
1004 print
"(CCIF) Proportion of classes extended by class: {ccif}%"
1005 print
"(ICIF) Proportion of interfaces implemented by class: {icif}%"
1006 print
"(IIIF) Proportion of interfaces extended by interface: {iiif}%"
1008 print
"--- (SL -> *) Std-Lib Inheritance metrics ---"
1009 print
"(SLDUI) Proportion of SL types inheriting another type other than Object: {sldui}%"
1010 print
"(SLCCDUI) Proportion of SL classes that extend some other class: {slccdui}%"
1011 print
"(SLCIDUI) Proportion of SL classes that implement some other interface: {slcidui}%"
1012 print
"(SLIIDUI) Proportion of SL interfaces that extend some other interface: {sliidui}%"
1013 print
"(SLIF) Proportion of SL types Inherited From: {slinhf}%"
1014 print
"(SLCCIF) Proportion of SL classes extended by class: {slccif}%"
1015 print
"(SLICIF) Proportion of SL interfaces implemented by class: {slicif}%"
1016 print
"(SLIIIF) Proportion of SL interfaces extended by interface: {sliiif}%"
1018 print
"--- (SL -> SL) Std-Lib Inheritance metrics ---"
1019 print
"(SLIFSL) Proportion of SL types Inherited From by SL type: {slinhfsl}%"
1020 print
"(SLCCIFSL) Proportion of SL classes extended by SL class: {slccifsl}%"
1021 print
"(SLICIFSL) Proportion of SL interfaces implemented by SL class: {slicifsl}%"
1022 print
"(SLIIIFSL) Proportion of SL interfaces extended by SL interface: {sliiifsl}%"
1024 print
"--- (SL->UD) Std-Lib Inheritance metrics ---"
1025 print
"(SLIFUD) Proportion of SL types Inherited From by UD type: {slinhfud}%"
1026 print
"(SLCCIFUD) Proportion of SL classes extended by UD class: {slccifud}%"
1027 print
"(SLICIFUD) Proportion of SL interfaces implemented by UD class: {slicifud}%"
1028 print
"(SLIIIFUD) Proportion of SL interfaces extended by UD interface: {sliiifud}%"
1030 print
"--- (UD->*) User-Defined Inheritance metrics ---"
1031 print
"(UDDUI) Proportion of UD types inheriting another type other than Object: {uddui}%"
1032 print
"(UDCCDUI) Proportion of UD classes that extend some other class: {udccdui}%"
1033 print
"(UDCIDUI) Proportion of UD classes that implement some other interface: {udcidui}%"
1034 print
"(UDIIDUI) Proportion of UD interfaces that extend some other interface: {udiidui}%"
1035 print
"(UDIF) Proportion of UD types Inherited From: {udinhf}%"
1036 print
"(UDCCIF) Proportion of UD classes extended by class: {udccif}%"
1037 print
"(UDICIF) Proportion of UD interfaces implemented by class: {udicif}%"
1038 print
"(UDIIIF) Proportion of UD interfaces extended by interface: {udiiif}%"
1040 print
"--- (UD -> SL) User-Defined Inheritance metrics ---"
1041 print
"(UDDUISL) Proportion of UD types inheriting another type other SL type: {udduisl}%"
1042 print
"(UDCCDUISL) Proportion of UD classes that extend some other SL class: {udccduisl}%"
1043 print
"(UDCIDUISL) Proportion of UD classes that implement some other SL interface: {udciduisl}%"
1044 print
"(UDIIDUISL) Proportion of UD interfaces that extend some other SL interface: {udiiduisl}%"
1046 print
"--- (UD -> UD) User-Defined Inheritance metrics ---"
1047 print
"(UDDUIUD) Proportion of UD types inheriting another type other UD type: {udduiud}%"
1048 print
"(UDCCDUIUD) Proportion of UD classes that extend some other UD class: {udccduiud}%"
1049 print
"(UDCIDUIUD) Proportion of UD classes that implement some other UD interface: {udciduiud}%"
1050 print
"(UDIIDUIUD) Proportion of UD interfaces that extend some other UD interface: {udiiduiud}%"
1051 print
"(UDIFUD) Proportion of UD types Inherited From: {udinhfud}%"
1052 print
"(UDCCIFUD) Proportion of UD classes extended by UD class: {udccifud}%"
1053 print
"(UDICIFUD) Proportion of UD interfaces implemented by UD class: {udicifud}%"
1054 print
"(UDIIIFUD) Proportion of UD interfaces extended by UD interface: {udiiifud}%"
1057 # TODO Third-Party metrics
1058 # TODO gnu-plot generation