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
25 redef class ToolContext
26 var inheritance_metrics_phase
= new InheritanceMetricsPhase(self, null)
29 # Extract metrics about module and class hierarchies.
30 private class InheritanceMetricsPhase
32 redef fun process_mainmodule
(mainmodule
)
34 if not toolcontext
.opt_inheritance
.value
and not toolcontext
.opt_all
.value
then return
35 compute_inheritance_metrics
(toolcontext
, toolcontext
.modelbuilder
.model
)
40 # Extract the subset of classes from a set of mclass
41 private fun extract_classes
(mclasses
: Collection[MClass]): Set[MClass] do
42 var lst
= new HashSet[MClass]
43 for mclass
in mclasses
do if mclass
.is_class
then lst
.add
(mclass
)
47 # Extract the subset of interfaces from a set of mclass
48 private fun extract_interfaces
(mclasses
: Collection[MClass]): Set[MClass] do
49 var lst
= new HashSet[MClass]
50 for mclass
in mclasses
do if mclass
.is_interface
then lst
.add
(mclass
)
54 # Extract the subset of generic classes/interfaces from a set of mclass
55 private fun extract_generics
(mclasses
: Collection[MClass]): Set[MClass] do
56 var lst
= new HashSet[MClass]
57 for mclass
in mclasses
do if mclass
.arity
> 0 then lst
.add
(mclass
)
61 # Extract the subset of abstract classes from a set of mclass
62 private fun extract_abstracts
(mclasses
: Collection[MClass]): Set[MClass] do
63 var lst
= new HashSet[MClass]
64 for mclass
in mclasses
do if mclass
.is_abstract
then lst
.add
(mclass
)
68 # Extract the subset of user defined classes/interfaces from a set of mclass
69 private fun extract_user_defined
(mclasses
: Collection[MClass]): Set[MClass] do
70 var lst
= new HashSet[MClass]
71 for mclass
in mclasses
do if mclass
.is_user_defined
then lst
.add
(mclass
)
75 # Extract the subset of user defined modules from a set of mmodules
76 private fun extract_user_defined_modules
(mmodules
: Collection[MModule]): Set[MModule] do
77 var lst
= new HashSet[MModule]
78 for mmodule
in mmodules
do if mmodule
.is_user_defined
then lst
.add
(mmodule
)
82 # Extract the subset of classes/interfaces from sl lib
83 private fun extract_stdlib
(mclasses
: Collection[MClass]): Set[MClass] do
84 var lst
= new HashSet[MClass]
85 for mclass
in mclasses
do if not mclass
.is_user_defined
then lst
.add
(mclass
)
89 # Extract the subset of user defined modules from std lib
90 private fun extract_stdlib_modules
(mmodules
: Collection[MModule]): Set[MModule] do
91 var lst
= new HashSet[MModule]
92 for mmodule
in mmodules
do if not mmodule
.is_user_defined
then lst
.add
(mmodule
)
99 private var nop
: Int = 0 # (NOP) Number of parents (direct superclasses)
100 private var nopc
: Int = 0 # (NOPC) Number of class parents
101 private var nopi
: Int = 0 # (NOPI) Number of interface parents
102 private var noa
: Int = 0 # (NOA) Number of ancestors (direct and indirect)
103 private var noac
: Int = 0 # (NOAC) Number of class ancestors
104 private var noai
: Int = 0 # (NOAI) Number of interface ancestors
105 private var noc
: Int = 0 # (NOC) Number of children (direct subclasses)
106 private var nocc
: Int = 0 # (NOCC) Number of class children
107 private var noci
: Int = 0 # (NOCI) Number of interface children
108 private var nod
: Int = 0 # (NOD) Number of descendants (direct and indirect)
109 private var nodc
: Int = 0 # (NODC) Number of class descendants
110 private var nodi
: Int = 0 # (NODI) Number of interface descendants
111 private var dit
: Int = 0 # (DIT) Depth in Inheritance Tree (maximum distance to root of the hierarchy)
112 private var ditc
: Int = 0 # (DITC) Length of longest path to the root hierarchy and consisting only of extends edges
113 private var diti
: Int = 0 # (DITI) Length of longest path to the root hierarchy and consisting only of extends implements
115 # User Defined inheritance
116 private var nopud
: Int = 0 # (NOPUD) Number of parents (direct superclasses)
117 private var nopcud
: Int = 0 # (NOPCUD) Number of class parents
118 private var nopiud
: Int = 0 # (NOPIUD) Number of interface parents
119 private var noaud
: Int = 0 # (NOAUD) Number of ancestors (direct and indirect)
120 private var noacud
: Int = 0 # (NOACUD) Number of class ancestors
121 private var noaiud
: Int = 0 # (NOAIUD) Number of interface ancestors
122 private var nocud
: Int = 0 # (NOCUD) Number of children (direct subclasses)
123 private var noccud
: Int = 0 # (NOCCUD) Number of class children
124 private var nociud
: Int = 0 # (NOCIUD) Number of interface children
125 private var nodud
: Int = 0 # (NODUD) Number of descendants (direct and indirect)
126 private var nodcud
: Int = 0 # (NODCUD) Number of class descendants
127 private var nodiud
: Int = 0 # (NODIUD) Number of interface descendants
128 private var ditud
: Int = 0 # (DITUD) Depth in Inheritance Tree (maximum distance to root of the hierarchy)
129 private var ditcud
: Int = 0 # (DITCUD) Length of longest path to the root hierarchy and consisting only of extends edges
130 private var ditiud
: Int = 0 # (DITIUD) Length of longest path to the root hierarchy and consisting only of extends implements
132 private fun compute_class_inheritance_metrics
(model
: Model) do
133 # inheritance metrics
134 self.nop
= parents
.length
135 self.nopc
= model
.extract_classes
(parents
).length
136 self.nopi
= model
.extract_interfaces
(parents
).length
137 self.noa
= ancestors
.length
138 self.noac
= model
.extract_classes
(ancestors
).length
139 self.noai
= model
.extract_interfaces
(ancestors
).length
140 self.noc
= children
.length
141 self.nocc
= model
.extract_classes
(children
).length
142 self.noci
= model
.extract_interfaces
(children
).length
143 self.nod
= descendants
.length
144 self.nodc
= model
.extract_classes
(descendants
).length
145 self.nodi
= model
.extract_interfaces
(descendants
).length
146 self.dit
= path_to_object
.length
147 self.ditc
= class_path_to_object
.length
148 self.diti
= interface_path_to_object
.length
150 # used defined metrics
151 self.nopud
= model
.extract_user_defined
(parents
).length
152 self.nopcud
= model
.extract_user_defined
(model
.extract_classes
(parents
)).length
153 self.nopiud
= model
.extract_user_defined
(model
.extract_interfaces
(parents
)).length
154 self.noaud
= model
.extract_user_defined
(ancestors
).length
155 self.noacud
= model
.extract_user_defined
(model
.extract_classes
(ancestors
)).length
156 self.noaiud
= model
.extract_user_defined
(model
.extract_interfaces
(ancestors
)).length
157 self.nocud
= model
.extract_user_defined
(children
).length
158 self.noccud
= model
.extract_user_defined
(model
.extract_classes
(children
)).length
159 self.nociud
= model
.extract_user_defined
(model
.extract_interfaces
(children
)).length
160 self.nodud
= model
.extract_user_defined
(descendants
).length
161 self.nodcud
= model
.extract_user_defined
(model
.extract_classes
(descendants
)).length
162 self.nodiud
= model
.extract_user_defined
(model
.extract_interfaces
(descendants
)).length
163 self.ditud
= ud_path_to_object
.length
164 self.ditcud
= ud_class_path_to_object
.length
165 self.ditiud
= ud_interface_path_to_object
.length
168 # Return the longest path from class to root hierarchy
169 private fun path_to_object
: Array[MClass] do
170 var path
= new Array[MClass]
171 var max_dit
: nullable Int = null
172 var max_parent
: nullable MClass = null
173 var parent_path
: nullable Array[MClass] = null
176 var dit
= p
.path_to_object
.length
177 if max_dit
== null or dit
>= max_dit
then
180 parent_path
= p
.path_to_object
184 if max_parent
!= null and parent_path
!= null then
186 path
.add_all
(parent_path
)
192 # Return the longest path from class to root hierarchy
193 private fun ud_path_to_object
: Array[MClass] do
194 var path
= new Array[MClass]
195 if not self.is_user_defined
then return path
196 var max_dit
: nullable Int = null
197 var max_parent
: nullable MClass = null
198 var parent_path
: nullable Array[MClass] = null
201 var dit
= p
.ud_path_to_object
.length
202 if max_dit
== null or dit
>= max_dit
then
205 parent_path
= p
.ud_path_to_object
209 if max_parent
!= null and parent_path
!= null then
211 path
.add_all
(parent_path
)
217 # Return the longest path from class to root hierarchy following only classes relations
218 private fun class_path_to_object
: Array[MClass] do
219 var path
= new Array[MClass]
220 if not self.is_class
then return path
221 var max_dit
: nullable Int = null
222 var max_parent
: nullable MClass = null
223 var parent_path
: nullable Array[MClass] = null
226 var dit
= p
.class_path_to_object
.length
227 if max_dit
== null or dit
>= max_dit
then
230 parent_path
= p
.class_path_to_object
234 if max_parent
!= null and parent_path
!= null then
236 path
.add_all
(parent_path
)
242 # Return the longest path from class to root hierarchy following only interfaces relations
243 private fun interface_path_to_object
: Array[MClass] do
244 var path
= new Array[MClass]
245 if not self.is_interface
then return path
246 var max_dit
: nullable Int = null
247 var max_parent
: nullable MClass = null
248 var parent_path
: nullable Array[MClass] = null
251 var dit
= p
.interface_path_to_object
.length
252 if max_dit
== null or dit
>= max_dit
then
255 parent_path
= p
.interface_path_to_object
259 if max_parent
!= null and parent_path
!= null then
261 path
.add_all
(parent_path
)
267 # Return the longest path from class to root hierarchy following only ud classes relations
268 private fun ud_class_path_to_object
: Array[MClass] do
269 var path
= new Array[MClass]
270 if not self.is_class
or not self.is_user_defined
then return path
271 var max_dit
: nullable Int = null
272 var max_parent
: nullable MClass = null
273 var parent_path
: nullable Array[MClass] = null
276 var dit
= p
.ud_class_path_to_object
.length
277 if max_dit
== null or dit
>= max_dit
then
280 parent_path
= p
.ud_class_path_to_object
284 if max_parent
!= null and parent_path
!= null then
286 path
.add_all
(parent_path
)
292 # Return the longest path from class to root hierarchy following only ud interfaces relations
293 private fun ud_interface_path_to_object
: Array[MClass] do
294 var path
= new Array[MClass]
295 if not self.is_interface
or not self.is_user_defined
then return path
296 var max_dit
: nullable Int = null
297 var max_parent
: nullable MClass = null
298 var parent_path
: nullable Array[MClass] = null
301 var dit
= p
.ud_interface_path_to_object
.length
302 if max_dit
== null or dit
>= max_dit
then
305 parent_path
= p
.ud_interface_path_to_object
309 if max_parent
!= null and parent_path
!= null then
311 path
.add_all
(parent_path
)
319 private fun is_dui_eligible
: Bool do
320 for parent
in parents
do if parent
.name
!= "Object" then return true
323 private fun is_ccdui_eligible
: Bool do
324 if not is_class
then return false
325 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
then return true
328 private fun is_cidui_eligible
: Bool do
329 if not is_class
then return false
330 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
333 private fun is_iidui_eligible
: Bool do
334 if not is_interface
then return false
335 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
338 private fun is_if_eligible
(model
: Model): Bool do return not children
.is_empty
339 private fun is_ccif_eligible
(model
: Model): Bool do
340 if not is_class
then return false
341 for child
in children
do if child
.is_class
then return true
344 private fun is_icif_eligible
(model
: Model): Bool do
345 if not is_interface
then return false
346 for child
in children
do if child
.is_class
then return true
349 private fun is_iiif_eligible
(model
: Model): Bool do
350 if not is_interface
then return false
351 for child
in children
do if child
.is_interface
then return true
357 private fun is_sldui_eligible
: Bool do
358 if is_user_defined
then return false
359 for parent
in parents
do if parent
.name
!= "Object" then return true
362 private fun is_slccdui_eligible
: Bool do
363 if is_user_defined
then return false
364 if not is_class
then return false
365 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
then return true
368 private fun is_slcidui_eligible
: Bool do
369 if is_user_defined
then return false
370 if not is_class
then return false
371 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
374 private fun is_sliidui_eligible
: Bool do
375 if is_user_defined
then return false
376 if not is_interface
then return false
377 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
380 private fun is_slif_eligible
(model
: Model): Bool do
381 if is_user_defined
then return false
382 return not children
.is_empty
384 private fun is_slccif_eligible
(model
: Model): Bool do
385 if is_user_defined
then return false
386 if not is_class
then return false
387 for child
in children
do if child
.is_class
then return true
390 private fun is_slicif_eligible
(model
: Model): Bool do
391 if is_user_defined
then return false
392 if not is_interface
then return false
393 for child
in children
do if child
.is_class
then return true
396 private fun is_sliiif_eligible
(model
: Model): Bool do
397 if is_user_defined
then return false
398 if not is_interface
then return false
399 for child
in children
do if child
.is_interface
then return true
405 private fun is_slifsl_eligible
(model
: Model): Bool do
406 if is_user_defined
then return false
407 for child
in children
do if not child
.is_user_defined
then return true
410 private fun is_slccifsl_eligible
(model
: Model): Bool do
411 if is_user_defined
then return false
412 if is_class
then return false
413 for child
in children
do if not child
.is_user_defined
and child
.is_class
then return true
416 private fun is_slicifsl_eligible
(model
: Model): Bool do
417 if is_user_defined
then return false
418 if not is_interface
then return false
419 for child
in children
do if not child
.is_user_defined
and child
.is_class
then return true
422 private fun is_sliiifsl_eligible
(model
: Model): Bool do
423 if is_user_defined
then return false
424 if not is_interface
then return false
425 for child
in children
do if not child
.is_user_defined
and child
.is_interface
then return true
431 private fun is_slifud_eligible
(model
: Model): Bool do
432 if is_user_defined
then return false
433 for child
in children
do if child
.is_user_defined
then return true
436 private fun is_slccifud_eligible
(model
: Model): Bool do
437 if is_user_defined
then return false
438 if not is_class
then return false
439 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
442 private fun is_slicifud_eligible
(model
: Model): Bool do
443 if is_user_defined
then return false
444 if not is_interface
then return false
445 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
448 private fun is_sliiifud_eligible
(model
: Model): Bool do
449 if is_user_defined
then return false
450 if not is_interface
then return false
451 for child
in children
do if child
.is_user_defined
and child
.is_interface
then return true
457 private fun is_uddui_eligible
: Bool do
458 if not is_user_defined
then return false
459 for parent
in parents
do if parent
.name
!= "Object" then return true
462 private fun is_udccdui_eligible
: Bool do
463 if not is_user_defined
then return false
464 if not is_class
then return false
465 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
then return true
468 private fun is_udcidui_eligible
: Bool do
469 if not is_user_defined
then return false
470 if not is_class
then return false
471 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
474 private fun is_udiidui_eligible
: Bool do
475 if not is_user_defined
then return false
476 if not is_interface
then return false
477 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
then return true
480 private fun is_udif_eligible
(model
: Model): Bool do
481 if not is_user_defined
then return false
482 return not children
.is_empty
484 private fun is_udccif_eligible
(model
: Model): Bool do
485 if not is_user_defined
then return false
486 if not is_class
then return false
487 for child
in children
do if child
.is_class
then return true
490 private fun is_udicif_eligible
(model
: Model): Bool do
491 if not is_user_defined
then return false
492 if not is_interface
then return false
493 for child
in children
do if child
.is_class
then return true
496 private fun is_udiiif_eligible
(model
: Model): Bool do
497 if not is_user_defined
then return false
498 if not is_interface
then return false
499 for child
in children
do if child
.is_interface
then return true
505 private fun is_udduisl_eligible
: Bool do
506 if not is_user_defined
then return false
507 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" then return true
510 private fun is_udccduisl_eligible
: Bool do
511 if not is_user_defined
then return false
512 if not is_class
then return false
513 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" and parent
.is_class
then return true
516 private fun is_udciduisl_eligible
: Bool do
517 if not is_user_defined
then return false
518 if not is_class
then return false
519 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" and parent
.is_interface
then return true
522 private fun is_udiiduisl_eligible
: Bool do
523 if not is_user_defined
then return false
524 if not is_interface
then return false
525 for parent
in parents
do if not parent
.is_user_defined
and parent
.name
!= "Object" and parent
.is_interface
then return true
531 private fun is_udduiud_eligible
: Bool do
532 if not is_user_defined
then return false
533 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_user_defined
then return true
536 private fun is_udccduiud_eligible
: Bool do
537 if not is_user_defined
then return false
538 if not is_class
then return false
539 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_class
and parent
.is_user_defined
then return true
542 private fun is_udciduiud_eligible
: Bool do
543 if not is_user_defined
then return false
544 if not is_class
then return false
545 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
and parent
.is_user_defined
then return true
548 private fun is_udiiduiud_eligible
: Bool do
549 if not is_user_defined
then return false
550 if not is_interface
then return false
551 for parent
in parents
do if parent
.name
!= "Object" and parent
.is_interface
and parent
.is_user_defined
then return true
554 private fun is_udifud_eligible
(model
: Model): Bool do
555 if not is_user_defined
then return false
556 return not children
.is_empty
558 private fun is_udccifud_eligible
(model
: Model): Bool do
559 if not is_user_defined
then return false
560 if not is_class
then return false
561 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
564 private fun is_udicifud_eligible
(model
: Model): Bool do
565 if not is_user_defined
then return false
566 if not is_interface
then return false
567 for child
in children
do if child
.is_user_defined
and child
.is_class
then return true
570 private fun is_udiiifud_eligible
(model
: Model): Bool do
571 if not is_user_defined
then return false
572 if not is_interface
then return false
573 for child
in children
do if child
.is_user_defined
and child
.is_interface
then return true
580 private var nm
: Int = 0 # (NC) Number of Modules
581 private var nc
: Int = 0 # (NC) Number of Classes
582 private var ni
: Int = 0 # (NI) Number of Interfaces
583 private var nac
: Int = 0 # (NAC) Number of Abstract Classes
584 private var ngc
: Int = 0 # (NGC) Number of Generic Classes
585 private var ngi
: Int = 0 # (NGI) Number of Generic Interfaces
587 private var dit
= "" # (DIT) Global Depth in Inheritance Tree
588 private var dui
= "" # (DUI) Proportion of types that either implement an interface or extend another type other than Object
589 private var ccdui
= "" # (CCDUI) Proportion of classes that extend some other class.
590 private var cidui
= "" # (CIDUI) Proportion of classes that implement some other interface.
591 private var iidui
= "" # (IIDUI) Proportion of interfaces that extend some other interface.
592 private var inhf
= "" # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
593 private var ccif
= "" # (CCIF) Proportion of classes extended by some other class.
594 private var icif
= "" # (ICIF) Proportion of interfaces implemented by some other class.
595 private var iiif
= "" # (IIIF) Proportion of interfaces extended by some other interface.
597 private fun compute_module_inheritance_metrics
(model
: Model) do
608 for mmodule
in self.in_nesting
.greaters
do
609 for mclass
in mmodule
.intro_mclasses
do
611 if mclass
.is_class
then nc
+= 1
612 if mclass
.is_class
and mclass
.arity
> 0 then ngc
+= 1
613 if mclass
.is_class
and mclass
.is_abstract
then nac
+= 1
614 if mclass
.is_interface
then ni
+= 1
615 if mclass
.is_interface
and mclass
.arity
> 0 then ngi
+= 1
616 ditsum
+= mclass
.path_to_object
.length
617 if mclass
.is_dui_eligible
then dui_count
+= 1
618 if mclass
.is_ccdui_eligible
then ccdui_count
+= 1
619 if mclass
.is_cidui_eligible
then cidui_count
+= 1
620 if mclass
.is_iidui_eligible
then iidui_count
+= 1
621 if mclass
.is_if_eligible
(model
) then if_count
+= 1
622 if mclass
.is_ccif_eligible
(model
) then ccif_count
+= 1
623 if mclass
.is_icif_eligible
(model
) then icif_count
+= 1
624 if mclass
.is_iiif_eligible
(model
) then iiif_count
+= 1
628 self.nm
= self.in_nesting
.greaters
.length
629 dit
= div
(ditsum
, count
)
630 dui
= div
(dui_count
* 100, count
)
631 ccdui
= div
(ccdui_count
* 100, nc
)
632 cidui
= div
(cidui_count
* 100, nc
)
633 iidui
= div
(iidui_count
* 100, ni
)
634 inhf
= div
(if_count
* 100, count
)
635 ccif
= div
(ccif_count
* 100, nc
)
636 icif
= div
(icif_count
* 100, ni
)
637 iiif
= div
(iiif_count
* 100, ni
)
641 # Print inheritance usage metrics
642 fun compute_inheritance_metrics
(toolcontext
: ToolContext, model
: Model)
644 # global summary metrics
645 var nmd
: Int = 0 # (NMD) Number of Modules
646 var nc
: Int = 0 # (NC) Number of Classes
647 var ni
: Int = 0 # (NI) Number of Interfaces
648 var nac
: Int = 0 # (NAC) Number of Abstract Classes
649 var ngc
: Int = 0 # (NGC) Number of Generic Classes
650 var ngi
: Int = 0 # (NGI) Number of Generic Interfaces
651 # (SL) Std-Lib summary metrics
652 var nmdsl
: Int = 0 # (NMDSL) Number of Modules in Std-Lib
653 var ncsl
: Int = 0 # (NCSL) Number of Classes in Std-Lib
654 var nisl
: Int = 0 # (NISL) Number of Interfaces in Std-Lib
655 var nacsl
: Int = 0 # (NACSL) Number of Abstract Classes in Std-Lib
656 var ngcsl
: Int = 0 # (NGCSL) Number of Generic Classes in Std-Lib
657 var ngisl
: Int = 0 # (NGISL) Number of Generic Interfaces in Std-Lib
658 # (UD) User-Defined summary metrics
659 var nmdud
: Int = 0 # (NMDUD) Number of Modules User Defined
660 var ncud
: Int = 0 # (NCUD) Number of Classes User Defined
661 var niud
: Int = 0 # (NIUD) Number of Interfaces User Defined
662 var nacud
: Int = 0 # (NACUD) Number of Abstract Classes User Defined
663 var ngcud
: Int = 0 # (NGCUD) Number of Generic Classes User Defined
664 var ngiud
: Int = 0 # (NGIUD) Number of Generic Interfaces User Defined
666 # global summary inheritance metrics
667 var dit
= "" # (DIT) Global Depth in Inheritance Tree
668 var dui
= "" # (DUI) Proportion of types that either implement an interface or extend another type other than Object
669 var ccdui
= "" # (CCDUI) Proportion of classes that extend some other class.
670 var cidui
= "" # (CIDUI) Proportion of classes that implement some other interface.
671 var iidui
= "" # (IIDUI) Proportion of interfaces that extend some other interface.
672 var inhf
= "" # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
673 var ccif
= "" # (CCIF) Proportion of classes extended by some other class.
674 var icif
= "" # (ICIF) Proportion of interfaces implemented by some other class.
675 var iiif
= "" # (IIIF) Proportion of interfaces extended by some other interface.
677 # (SL -> *) Std-Lib summary inheritance metrics
678 var sldui
= "" # (SLDUI) Proportion of std-lib types that either implement an interface or extend another std-lib type other than Object
679 var slccdui
= "" # (SLCCDUI) Proportion of std-lib classes that extend some other std-lib class.
680 var slcidui
= "" # (SLCIDUI) Proportion of std-lib classes that implement some other std-lib interface.
681 var sliidui
= "" # (SLIIDUI) Proportion of std-lib interfaces that extend some other std-lib interface.
682 var slinhf
= "" # (SLIF) Proportion of SL types Inherited From, that is, those types that are either extended or implemented
683 var slccif
= "" # (SLCCIF) Proportion of SL classes extended by some other class.
684 var slicif
= "" # (SLICIF) Proportion of SL interfaces implemented by some other class.
685 var sliiif
= "" # (SLIIIF) Proportion of SL interfaces extended by some other interface.
687 # (SL -> SL) Std-Lib summary inheritance metrics
688 var slinhfsl
= "" # (SLIFSL) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a SL type
689 var slccifsl
= "" # (SLCCIFSL) Proportion of SL classes extended by some other SL class.
690 var slicifsl
= "" # (SLICIFSL) Proportion of SL interfaces implemented by some other SL class.
691 var sliiifsl
= "" # (SLIIIFSL) Proportion of SL interfaces extended by some other SL interface.
693 # (SL -> UD) Std-Lib summary inheritance metrics
694 var slinhfud
= "" # (SLIFUD) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a UD type
695 var slccifud
= "" # (SLCCIFUD) Proportion of SL classes extended by some other UD class.
696 var slicifud
= "" # (SLICIFUD) Proportion of SL interfaces implemented by some other UD class.
697 var sliiifud
= "" # (SLIIIFUD) Proportion of SL interfaces extended by some other UD interface.
699 # (UD -> *) User-defined summary inheritance metrics
700 var uddui
= "" # (UDDUI) Proportion user-defined of types that either implement an interface or extend another type
701 var udccdui
= "" # (UDCCDUI) Proportion of user-defined classes that extend some other class.
702 var udcidui
= "" # (UDCIDUI) Proportion of user-defined classes that implement some other interface.
703 var udiidui
= "" # (UDIIDUI) Proportion of user-defined interfaces that extend some other interface.
704 var udinhf
= "" # (UDIF) Proportion of UD types Inherited From, that is, those types that are either extended or implemented
705 var udccif
= "" # (UDCCIF) Proportion of UD classes extended by some other class.
706 var udicif
= "" # (UDICIF) Proportion of UD interfaces implemented by some other class.
707 var udiiif
= "" # (UDIIIF) Proportion of UD interfaces extended by some other interface.
709 # (UD -> SL) User-defined summary inheritance metrics
710 var udduisl
= "" # (UDDUISL) Proportion user-defined of types that either implement an interface or extend another type SL
711 var udccduisl
= "" # (UDCCDUISL) Proportion of user-defined classes that extend some other SL class.
712 var udciduisl
= "" # (UDCIDUISL) Proportion of user-defined classes that implement some other SL interface.
713 var udiiduisl
= "" # (UDIIDUISL) Proportion of user-defined interfaces that extend some other SL interface.
715 # (UD -> UD) User-defined summary inheritance metrics
717 var udduiud
= "" # (UDDUIUD) Proportion user-defined of types that either implement an interface or extend another type user-defined
718 var udccduiud
= "" # (UDCCDUIUD) Proportion of user-defined classes that extend some other user-defined class.
719 var udciduiud
= "" # (UDCIDUIUD) Proportion of user-defined classes that implement some other user-defined interface.
720 var udiiduiud
= "" # (UDIIDUIUD) Proportion of user-defined interfaces that extend some other user-defined interface.
721 var udinhfud
= "" # (UDIFUD) Proportion of UD types Inherited From, that is, those types that are either extended or implemented by another UD type
722 var udccifud
= "" # (UDCCIFUD) Proportion of UD classes extended by some other UD class.
723 var udicifud
= "" # (UDICIFUD) Proportion of UD interfaces implemented by some other UD class.
724 var udiiifud
= "" # (UDIIIFUD) Proportion of UD interfaces extended by some other UD interface.
726 # compute modules scalar metrics
727 for mmodule
in model
.mmodules
do
728 mmodule
.compute_module_inheritance_metrics
(model
)
731 # compute class scalar metrics
732 for mclass
in model
.mclasses
do
733 mclass
.compute_class_inheritance_metrics
(model
)
736 # compute summary metrics
738 # compute global summary metrics
739 nmd
= model
.mmodules
.length
740 nc
= model
.extract_classes
(model
.mclasses
).length
741 ni
= model
.extract_interfaces
(model
.mclasses
).length
742 nac
= model
.extract_abstracts
(model
.mclasses
).length
743 ngc
= model
.extract_generics
(model
.extract_classes
(model
.mclasses
)).length
744 ngi
= model
.extract_generics
(model
.extract_interfaces
(model
.mclasses
)).length
745 # compute std-lib summary metrics
746 nmdsl
= model
.extract_stdlib_modules
(model
.mmodules
).length
747 ncsl
= model
.extract_stdlib
(model
.extract_classes
(model
.mclasses
)).length
748 nisl
= model
.extract_stdlib
(model
.extract_interfaces
(model
.mclasses
)).length
749 nacsl
= model
.extract_stdlib
(model
.extract_abstracts
(model
.mclasses
)).length
750 ngcsl
= model
.extract_stdlib
(model
.extract_generics
(model
.extract_classes
(model
.mclasses
))).length
751 ngisl
= model
.extract_stdlib
(model
.extract_generics
(model
.extract_interfaces
(model
.mclasses
))).length
752 # compute user-defined summary metrics
753 nmdud
= model
.extract_user_defined_modules
(model
.mmodules
).length
754 ncud
= model
.extract_user_defined
(model
.extract_classes
(model
.mclasses
)).length
755 niud
= model
.extract_user_defined
(model
.extract_interfaces
(model
.mclasses
)).length
756 nacud
= model
.extract_user_defined
(model
.extract_abstracts
(model
.mclasses
)).length
757 ngcud
= model
.extract_user_defined
(model
.extract_generics
(model
.extract_classes
(model
.mclasses
))).length
758 ngiud
= model
.extract_user_defined
(model
.extract_generics
(model
.extract_interfaces
(model
.mclasses
))).length
760 # compute inheritance summary metrics
777 var slccdui_count
= 0
778 var slcidui_count
= 0
779 var sliidui_count
= 0
787 var slccifsl_count
= 0
788 var slicifsl_count
= 0
789 var sliiifsl_count
= 0
793 var slccifud_count
= 0
794 var slicifud_count
= 0
795 var sliiifud_count
= 0
799 var udccdui_count
= 0
800 var udcidui_count
= 0
801 var udiidui_count
= 0
808 var udduisl_count
= 0
809 var udccduisl_count
= 0
810 var udciduisl_count
= 0
811 var udiiduisl_count
= 0
814 var udduiud_count
= 0
815 var udccduiud_count
= 0
816 var udciduiud_count
= 0
817 var udiiduiud_count
= 0
819 var udccifud_count
= 0
820 var udicifud_count
= 0
821 var udiiifud_count
= 0
823 for mclass
in model
.mclasses
do
825 ditudsum
+= mclass
.ditud
828 if mclass
.is_dui_eligible
then dui_count
+= 1
829 if mclass
.is_ccdui_eligible
then ccdui_count
+= 1
830 if mclass
.is_cidui_eligible
then cidui_count
+= 1
831 if mclass
.is_iidui_eligible
then iidui_count
+= 1
832 if mclass
.is_if_eligible
(model
) then if_count
+= 1
833 if mclass
.is_ccif_eligible
(model
) then ccif_count
+= 1
834 if mclass
.is_icif_eligible
(model
) then icif_count
+= 1
835 if mclass
.is_iiif_eligible
(model
) then iiif_count
+= 1
838 if mclass
.is_sldui_eligible
then sldui_count
+= 1
839 if mclass
.is_slccdui_eligible
then slccdui_count
+= 1
840 if mclass
.is_slcidui_eligible
then slcidui_count
+= 1
841 if mclass
.is_sliidui_eligible
then sliidui_count
+= 1
842 if mclass
.is_slif_eligible
(model
) then slif_count
+= 1
843 if mclass
.is_slccif_eligible
(model
) then slccif_count
+= 1
844 if mclass
.is_slicif_eligible
(model
) then slicif_count
+= 1
845 if mclass
.is_sliiif_eligible
(model
) then sliiif_count
+= 1
848 if mclass
.is_slifsl_eligible
(model
) then slifsl_count
+= 1
849 if mclass
.is_slccifsl_eligible
(model
) then slccifsl_count
+= 1
850 if mclass
.is_slicifsl_eligible
(model
) then slicifsl_count
+= 1
851 if mclass
.is_sliiifsl_eligible
(model
) then sliiifsl_count
+= 1
854 if mclass
.is_slifud_eligible
(model
) then slifud_count
+= 1
855 if mclass
.is_slccifud_eligible
(model
) then slccifud_count
+= 1
856 if mclass
.is_slicifud_eligible
(model
) then slicifud_count
+= 1
857 if mclass
.is_sliiifud_eligible
(model
) then sliiifud_count
+= 1
860 if mclass
.is_uddui_eligible
then uddui_count
+= 1
861 if mclass
.is_udccdui_eligible
then udccdui_count
+= 1
862 if mclass
.is_udcidui_eligible
then udcidui_count
+= 1
863 if mclass
.is_udiidui_eligible
then udiidui_count
+= 1
864 if mclass
.is_udif_eligible
(model
) then udif_count
+= 1
865 if mclass
.is_udccif_eligible
(model
) then udccif_count
+= 1
866 if mclass
.is_udicif_eligible
(model
) then udicif_count
+= 1
867 if mclass
.is_udiiif_eligible
(model
) then udiiif_count
+= 1
870 if mclass
.is_udduisl_eligible
then udduisl_count
+= 1
871 if mclass
.is_udccduisl_eligible
then udccduisl_count
+= 1
872 if mclass
.is_udciduisl_eligible
then udciduisl_count
+= 1
873 if mclass
.is_udiiduisl_eligible
then udiiduisl_count
+= 1
876 if mclass
.is_udduiud_eligible
then udduiud_count
+= 1
877 if mclass
.is_udccduiud_eligible
then udccduiud_count
+= 1
878 if mclass
.is_udciduiud_eligible
then udciduiud_count
+= 1
879 if mclass
.is_udiiduiud_eligible
then udiiduiud_count
+= 1
880 if mclass
.is_udifud_eligible
(model
) then udifud_count
+= 1
881 if mclass
.is_udccifud_eligible
(model
) then udccifud_count
+= 1
882 if mclass
.is_udicifud_eligible
(model
) then udicifud_count
+= 1
883 if mclass
.is_udiiifud_eligible
(model
) then udiiifud_count
+= 1
887 dit
= div
(ditsum
, model
.mclasses
.length
)
888 ditud
= div
(ditudsum
, ncud
+ niud
)
889 dui
= div
(dui_count
* 100, model
.mclasses
.length
)
890 ccdui
= div
(ccdui_count
* 100, nc
)
891 cidui
= div
(cidui_count
* 100, nc
)
892 iidui
= div
(iidui_count
* 100, ni
)
893 inhf
= div
(if_count
* 100, nc
+ ni
)
894 ccif
= div
(ccif_count
* 100, nc
)
895 icif
= div
(icif_count
* 100, ni
)
896 iiif
= div
(iiif_count
* 100, ni
)
899 sldui
= div
(sldui_count
* 100, ncsl
+ nisl
)
900 slccdui
= div
(slccdui_count
* 100, ncsl
)
901 slcidui
= div
(slcidui_count
* 100, ncsl
)
902 sliidui
= div
(sliidui_count
* 100, nisl
)
903 slinhf
= div
(slif_count
* 100, ncsl
+ nisl
)
904 slccif
= div
(slccif_count
* 100, ncsl
)
905 slicif
= div
(slicif_count
* 100, nisl
)
906 sliiif
= div
(sliiif_count
* 100, nisl
)
909 slinhfsl
= div
(slifsl_count
* 100, ncsl
+ nisl
)
910 slccifsl
= div
(slccifsl_count
* 100, ncsl
)
911 slicifsl
= div
(slicifsl_count
* 100, nisl
)
912 sliiifsl
= div
(sliiifsl_count
* 100, nisl
)
915 slinhfud
= div
(slifud_count
* 100, ncsl
+ nisl
)
916 slccifud
= div
(slccifud_count
* 100, ncsl
)
917 slicifud
= div
(slicifud_count
* 100, nisl
)
918 sliiifud
= div
(sliiifud_count
* 100, nisl
)
921 uddui
= div
(uddui_count
* 100, ncud
+ niud
)
922 udccdui
= div
(udccdui_count
* 100, ncud
)
923 udcidui
= div
(udcidui_count
* 100, ncud
)
924 udiidui
= div
(udiidui_count
* 100, niud
)
925 udinhf
= div
(if_count
* 100, ncud
+ niud
)
926 udccif
= div
(ccif_count
* 100, ncud
)
927 udicif
= div
(icif_count
* 100, niud
)
928 udiiif
= div
(iiif_count
* 100, niud
)
931 udduisl
= div
(udduisl_count
* 100, ncud
+ niud
)
932 udccduisl
= div
(udccduisl_count
* 100, ncud
)
933 udciduisl
= div
(udciduisl_count
* 100, ncud
)
934 udiiduisl
= div
(udiiduisl_count
* 100, niud
)
937 udduiud
= div
(udduiud_count
* 100, ncud
+ niud
)
938 udccduiud
= div
(udccduiud_count
* 100, ncud
)
939 udciduiud
= div
(udciduiud_count
* 100, ncud
)
940 udiiduiud
= div
(udiiduiud_count
* 100, niud
)
941 udinhfud
= div
(udifud_count
* 100, ncud
+ niud
)
942 udccifud
= div
(udccifud_count
* 100, ncud
)
943 udicifud
= div
(udicifud_count
* 100, niud
)
944 udiiifud
= div
(udiiifud_count
* 100, niud
)
947 if toolcontext
.opt_generate_csv
.value
then
949 var summaryCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("summary_metrics.csv"))
950 summaryCSV
.set_header
("scope", "NMD", "NC", "NI", "NAC", "NGC", "NGI")
951 summaryCSV
.add_line
("global", nmd
, nc
, ni
, nac
, ngc
, ngi
)
952 summaryCSV
.add_line
("std-lib", nmdsl
, ncsl
, nisl
, nacsl
, ngcsl
, ngisl
)
953 summaryCSV
.add_line
("user-defined", nmdud
, ncud
, niud
, nacud
, ngcud
, ngiud
)
954 for m
in model
.mmodules
do
955 summaryCSV
.add_line
(m
.name
, m
.nm
, m
.nc
, m
.ni
, m
.nac
, m
.ngc
, m
.ngi
)
959 # inheritance metrics
960 var inheritanceCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("inheritance_metrics.csv"))
961 inheritanceCSV
.set_header
("scope", "DIT", "DUI", "CCDUI", "CIDUI", "IIDUI", "IF", "CCIF", "ICIF", "IIIF")
962 inheritanceCSV
.add_line
("global", dit
, dui
, ccdui
, cidui
, iidui
, inhf
, ccif
, icif
, iiif
)
963 inheritanceCSV
.add_line
("SL -> *", "", sldui
, slccdui
, slcidui
, sliidui
, slinhf
, slccif
, slicif
, sliiif
)
964 inheritanceCSV
.add_line
("SL -> SL", "", sldui
, slccdui
, slcidui
, sliidui
, slinhfsl
, slccifsl
, slicifsl
, sliiifsl
)
965 inheritanceCSV
.add_line
("SL -> UD", "", 0, 0, 0, 0, slinhfud
, slccifud
, slicifud
, sliiifud
)
966 inheritanceCSV
.add_line
("UD -> *", "", uddui
, udccdui
, udcidui
, udiidui
, udinhf
, udccif
, udicif
, udiiif
)
967 inheritanceCSV
.add_line
("UD -> SL", "", udduisl
, udccduisl
, udciduisl
, udiiduisl
, 0, 0, 0, 0)
968 inheritanceCSV
.add_line
("UD -> UD", ditud
, udduiud
, udccduiud
, udciduiud
, udiiduiud
, udinhfud
, udccifud
, udicifud
, udiiifud
)
969 for m
in model
.mmodules
do
970 if m
.intro_mclasses
.is_empty
and m
.in_nesting
.greaters
.length
== 1 then continue
971 inheritanceCSV
.add_line
(m
.name
, m
.dit
, m
.dui
, m
.ccdui
, m
.cidui
, m
.iidui
, m
.inhf
, m
.ccif
, m
.icif
, m
.iiif
)
976 var scalarCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("global_scalar_metrics.csv"))
977 var udscalarCSV
= new CSVDocument(toolcontext
.output_dir
.join_path
("ud_scalar_metrics.csv"))
978 scalarCSV
.set_header
("mclass", "type", "FT", "DIT", "DITC", "DITI", "NOP", "NOPC", "NOPI", "NOA", "NOAC", "NOAI", "NOC", "NOCC", "NOCI", "NOD", "NODC", "NODI")
979 udscalarCSV
.set_header
("mclass", "type", "FT","DITUD", "DITCUD", "DITIUD", "NOPUD", "NOPCUD", "NOPIUD", "NOAUD", "NOACUD", "NOAIUD", "NOCUD", "NOCCUD", "NOCIUD", "NODUD", "NODCUD", "NODIUD")
980 for mclass
in model
.mclasses
do
981 var name
= mclass
.name
983 if mclass
.is_interface
then typ
= "interface"
984 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
)
985 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
)
991 print
"--- Global Summary metrics ---"
992 print
"(NMD) Number of Modules: {nmd}"
993 print
"(NC) Number of Classes: {nc}"
994 print
"(NI) Number of Interfaces: {ni}"
995 print
"(NAC) Number of Abstract Classes: {nac}"
996 print
"(NGC) Number of Generic Classes: {ngc}"
997 print
"(NGI) Number of Generic Interfaces: {ngi}"
998 print
"--- (SL) Std-Lib Summary metrics ---"
999 print
"(NMDSL) Number of Modules: {nmdsl}"
1000 print
"(NCSL) Number of Classes: {ncsl}"
1001 print
"(NISL) Number of Interfaces: {nisl}"
1002 print
"(NACSL) Number of Abstract Classes: {nacsl}"
1003 print
"(NGCSL) Number of Generic Classes: {ngcsl}"
1004 print
"(NGISL) Number of Generic Interfaces: {ngisl}"
1005 print
"--- (UD) User-Defined Summary metrics ---"
1006 print
"(NMDUD) Number of Modules: {nmdud}"
1007 print
"(NCUD) Number of Classes: {ncud}"
1008 print
"(NIUD) Number of Interfaces: {niud}"
1009 print
"(NACUD) Number of Abstract Classes: {nacud}"
1010 print
"(NGCUD) Number of Generic Classes: {ngcud}"
1011 print
"(NGIUD) Number of Generic Interfaces: {ngiud}"
1013 print
"--- Global Inheritance metrics ---"
1014 print
"(DIT) Global Depth in Inheritance Tree: {dit}"
1015 print
"(DUI) Proportion of types inheriting another type other than Object: {dui}%"
1016 print
"(CCDUI) Proportion of classes that extend some other class: {ccdui}%"
1017 print
"(CIDUI) Proportion of classes that implement some other interface: {cidui}%"
1018 print
"(IIDUI) Proportion of interfaces that extend some other interface: {iidui}%"
1019 print
"(IF) Proportion of types Inherited From: {inhf}%"
1020 print
"(CCIF) Proportion of classes extended by class: {ccif}%"
1021 print
"(ICIF) Proportion of interfaces implemented by class: {icif}%"
1022 print
"(IIIF) Proportion of interfaces extended by interface: {iiif}%"
1024 print
"--- (SL -> *) Std-Lib Inheritance metrics ---"
1025 print
"(SLDUI) Proportion of SL types inheriting another type other than Object: {sldui}%"
1026 print
"(SLCCDUI) Proportion of SL classes that extend some other class: {slccdui}%"
1027 print
"(SLCIDUI) Proportion of SL classes that implement some other interface: {slcidui}%"
1028 print
"(SLIIDUI) Proportion of SL interfaces that extend some other interface: {sliidui}%"
1029 print
"(SLIF) Proportion of SL types Inherited From: {slinhf}%"
1030 print
"(SLCCIF) Proportion of SL classes extended by class: {slccif}%"
1031 print
"(SLICIF) Proportion of SL interfaces implemented by class: {slicif}%"
1032 print
"(SLIIIF) Proportion of SL interfaces extended by interface: {sliiif}%"
1034 print
"--- (SL -> SL) Std-Lib Inheritance metrics ---"
1035 print
"(SLIFSL) Proportion of SL types Inherited From by SL type: {slinhfsl}%"
1036 print
"(SLCCIFSL) Proportion of SL classes extended by SL class: {slccifsl}%"
1037 print
"(SLICIFSL) Proportion of SL interfaces implemented by SL class: {slicifsl}%"
1038 print
"(SLIIIFSL) Proportion of SL interfaces extended by SL interface: {sliiifsl}%"
1040 print
"--- (SL->UD) Std-Lib Inheritance metrics ---"
1041 print
"(SLIFUD) Proportion of SL types Inherited From by UD type: {slinhfud}%"
1042 print
"(SLCCIFUD) Proportion of SL classes extended by UD class: {slccifud}%"
1043 print
"(SLICIFUD) Proportion of SL interfaces implemented by UD class: {slicifud}%"
1044 print
"(SLIIIFUD) Proportion of SL interfaces extended by UD interface: {sliiifud}%"
1046 print
"--- (UD->*) User-Defined Inheritance metrics ---"
1047 print
"(UDDUI) Proportion of UD types inheriting another type other than Object: {uddui}%"
1048 print
"(UDCCDUI) Proportion of UD classes that extend some other class: {udccdui}%"
1049 print
"(UDCIDUI) Proportion of UD classes that implement some other interface: {udcidui}%"
1050 print
"(UDIIDUI) Proportion of UD interfaces that extend some other interface: {udiidui}%"
1051 print
"(UDIF) Proportion of UD types Inherited From: {udinhf}%"
1052 print
"(UDCCIF) Proportion of UD classes extended by class: {udccif}%"
1053 print
"(UDICIF) Proportion of UD interfaces implemented by class: {udicif}%"
1054 print
"(UDIIIF) Proportion of UD interfaces extended by interface: {udiiif}%"
1056 print
"--- (UD -> SL) User-Defined Inheritance metrics ---"
1057 print
"(UDDUISL) Proportion of UD types inheriting another type other SL type: {udduisl}%"
1058 print
"(UDCCDUISL) Proportion of UD classes that extend some other SL class: {udccduisl}%"
1059 print
"(UDCIDUISL) Proportion of UD classes that implement some other SL interface: {udciduisl}%"
1060 print
"(UDIIDUISL) Proportion of UD interfaces that extend some other SL interface: {udiiduisl}%"
1062 print
"--- (UD -> UD) User-Defined Inheritance metrics ---"
1063 print
"(UDDUIUD) Proportion of UD types inheriting another type other UD type: {udduiud}%"
1064 print
"(UDCCDUIUD) Proportion of UD classes that extend some other UD class: {udccduiud}%"
1065 print
"(UDCIDUIUD) Proportion of UD classes that implement some other UD interface: {udciduiud}%"
1066 print
"(UDIIDUIUD) Proportion of UD interfaces that extend some other UD interface: {udiiduiud}%"
1067 print
"(UDIFUD) Proportion of UD types Inherited From: {udinhfud}%"
1068 print
"(UDCCIFUD) Proportion of UD classes extended by UD class: {udccifud}%"
1069 print
"(UDICIFUD) Proportion of UD interfaces implemented by UD class: {udicifud}%"
1070 print
"(UDIIIFUD) Proportion of UD interfaces extended by UD interface: {udiiifud}%"
1073 # TODO Third-Party metrics
1074 # TODO gnu-plot generation