5251216f79543f4dc7369097e0596b87f74e3fe3
[nit.git] / src / metrics / inheritance_metrics.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 # Collect metrics about inheritance usage
18 module inheritance_metrics
19
20 import model
21 private import metrics_base
22
23 redef class Model
24 # Extract the subset of classes from a set of mclass
25 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)
28 return lst
29 end
30
31 # Extract the subset of interfaces from a set of mclass
32 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)
35 return lst
36 end
37
38 # Extract the subset of generic classes/interfaces from a set of mclass
39 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)
42 return lst
43 end
44
45 # Extract the subset of abstract classes from a set of mclass
46 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)
49 return lst
50 end
51
52 # Extract the subset of user defined classes/interfaces from a set of mclass
53 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)
56 return lst
57 end
58
59 # Extract the subset of user defined modules from a set of mmodules
60 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)
63 return lst
64 end
65
66 # Extract the subset of classes/interfaces from sl lib
67 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)
70 return lst
71 end
72
73 # Extract the subset of user defined modules from std lib
74 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)
77 return lst
78 end
79 end
80
81 redef class MClass
82 # Inheritance
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
98
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
115
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(model).length
125 self.nocc = model.extract_classes(children(model)).length
126 self.noci = model.extract_interfaces(children(model)).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
133
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(model)).length
142 self.noccud = model.extract_user_defined(model.extract_classes(children(model))).length
143 self.nociud = model.extract_user_defined(model.extract_interfaces(children(model))).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
150 end
151
152 # Get parents of the class (direct super classes only)
153 fun parents: Set[MClass] do
154 var lst = new HashSet[MClass]
155 # explore all definitions of the class (refinement)
156 for mclassdef in self.mclassdefs do
157 for parent in mclassdef.supertypes do
158 lst.add(parent.mclass)
159 end
160 end
161 return lst
162 end
163
164 # Get ancestors of the class (all super classes)
165 fun ancestors: Set[MClass] do
166 var lst = new HashSet[MClass]
167 for mclassdef in self.mclassdefs do
168 for super_mclassdef in mclassdef.in_hierarchy.greaters do
169 if super_mclassdef == mclassdef then continue # skip self
170 lst.add(super_mclassdef.mclass)
171 end
172 end
173 return lst
174 end
175
176 # Get children of the class (direct subclasses only)
177 fun children(model: Model): Set[MClass] do
178 var lst = new HashSet[MClass]
179 for other in model.mclasses do
180 if other == self then continue # skip self
181 if other.parents.has(self) then
182 lst.add(other)
183 end
184 end
185 return lst
186 end
187
188 # Get children of the class (direct subclasses only)
189 fun descendants: Set[MClass] do
190 var lst = new HashSet[MClass]
191 for mclassdef in self.mclassdefs do
192 for sub_mclassdef in mclassdef.in_hierarchy.smallers do
193 if sub_mclassdef == mclassdef then continue # skip self
194 lst.add(sub_mclassdef.mclass)
195 end
196 end
197 return lst
198 end
199
200 # Return the longest path from class to root hierarchy
201 fun path_to_object: Array[MClass] do
202 var path = new Array[MClass]
203 var max_dit: nullable Int = null
204 var max_parent: nullable MClass = null
205 var parent_path: nullable Array[MClass] = null
206
207 for p in parents do
208 var dit = p.path_to_object.length
209 if max_dit == null or dit >= max_dit then
210 max_dit = dit
211 max_parent = p
212 parent_path = p.path_to_object
213 end
214 end
215
216 if max_parent != null and parent_path != null then
217 path.add(max_parent)
218 path.add_all(parent_path)
219 end
220
221 return path
222 end
223
224 # Return the longest path from class to root hierarchy
225 fun ud_path_to_object: Array[MClass] do
226 var path = new Array[MClass]
227 if not self.is_user_defined then return path
228 var max_dit: nullable Int = null
229 var max_parent: nullable MClass = null
230 var parent_path: nullable Array[MClass] = null
231
232 for p in parents do
233 var dit = p.ud_path_to_object.length
234 if max_dit == null or dit >= max_dit then
235 max_dit = dit
236 max_parent = p
237 parent_path = p.ud_path_to_object
238 end
239 end
240
241 if max_parent != null and parent_path != null then
242 path.add(max_parent)
243 path.add_all(parent_path)
244 end
245
246 return path
247 end
248
249 # Return the longest path from class to root hierarchy following only classes relations
250 fun class_path_to_object: Array[MClass] do
251 var path = new Array[MClass]
252 if not self.is_class then return path
253 var max_dit: nullable Int = null
254 var max_parent: nullable MClass = null
255 var parent_path: nullable Array[MClass] = null
256
257 for p in parents do
258 var dit = p.class_path_to_object.length
259 if max_dit == null or dit >= max_dit then
260 max_dit = dit
261 max_parent = p
262 parent_path = p.class_path_to_object
263 end
264 end
265
266 if max_parent != null and parent_path != null then
267 path.add(max_parent)
268 path.add_all(parent_path)
269 end
270
271 return path
272 end
273
274 # Return the longest path from class to root hierarchy following only interfaces relations
275 fun interface_path_to_object: Array[MClass] do
276 var path = new Array[MClass]
277 if not self.is_interface then return path
278 var max_dit: nullable Int = null
279 var max_parent: nullable MClass = null
280 var parent_path: nullable Array[MClass] = null
281
282 for p in parents do
283 var dit = p.interface_path_to_object.length
284 if max_dit == null or dit >= max_dit then
285 max_dit = dit
286 max_parent = p
287 parent_path = p.interface_path_to_object
288 end
289 end
290
291 if max_parent != null and parent_path != null then
292 path.add(max_parent)
293 path.add_all(parent_path)
294 end
295
296 return path
297 end
298
299 # Return the longest path from class to root hierarchy following only ud classes relations
300 fun ud_class_path_to_object: Array[MClass] do
301 var path = new Array[MClass]
302 if not self.is_class or not self.is_user_defined then return path
303 var max_dit: nullable Int = null
304 var max_parent: nullable MClass = null
305 var parent_path: nullable Array[MClass] = null
306
307 for p in parents do
308 var dit = p.ud_class_path_to_object.length
309 if max_dit == null or dit >= max_dit then
310 max_dit = dit
311 max_parent = p
312 parent_path = p.ud_class_path_to_object
313 end
314 end
315
316 if max_parent != null and parent_path != null then
317 path.add(max_parent)
318 path.add_all(parent_path)
319 end
320
321 return path
322 end
323
324 # Return the longest path from class to root hierarchy following only ud interfaces relations
325 fun ud_interface_path_to_object: Array[MClass] do
326 var path = new Array[MClass]
327 if not self.is_interface or not self.is_user_defined then return path
328 var max_dit: nullable Int = null
329 var max_parent: nullable MClass = null
330 var parent_path: nullable Array[MClass] = null
331
332 for p in parents do
333 var dit = p.ud_interface_path_to_object.length
334 if max_dit == null or dit >= max_dit then
335 max_dit = dit
336 max_parent = p
337 parent_path = p.ud_interface_path_to_object
338 end
339 end
340
341 if max_parent != null and parent_path != null then
342 path.add(max_parent)
343 path.add_all(parent_path)
344 end
345
346 return path
347 end
348
349 # * -> * DUI
350
351 fun is_dui_eligible: Bool do
352 for parent in parents do if parent.name != "Object" then return true
353 return false
354 end
355 fun is_ccdui_eligible: Bool do
356 if not is_class then return false
357 for parent in parents do if parent.name != "Object" and parent.is_class then return true
358 return false
359 end
360 fun is_cidui_eligible: Bool do
361 if not is_class then return false
362 for parent in parents do if parent.name != "Object" and parent.is_interface then return true
363 return false
364 end
365 fun is_iidui_eligible: Bool do
366 if not is_interface then return false
367 for parent in parents do if parent.name != "Object" and parent.is_interface then return true
368 return false
369 end
370 fun is_if_eligible(model: Model): Bool do return not children(model).is_empty
371 fun is_ccif_eligible(model: Model): Bool do
372 if not is_class then return false
373 for child in children(model) do if child.is_class then return true
374 return false
375 end
376 fun is_icif_eligible(model: Model): Bool do
377 if not is_interface then return false
378 for child in children(model) do if child.is_class then return true
379 return false
380 end
381 fun is_iiif_eligible(model: Model): Bool do
382 if not is_interface then return false
383 for child in children(model) do if child.is_interface then return true
384 return false
385 end
386
387 # SL -> * DUI
388
389 fun is_sldui_eligible: Bool do
390 if is_user_defined then return false
391 for parent in parents do if parent.name != "Object" then return true
392 return false
393 end
394 fun is_slccdui_eligible: Bool do
395 if is_user_defined then return false
396 if not is_class then return false
397 for parent in parents do if parent.name != "Object" and parent.is_class then return true
398 return false
399 end
400 fun is_slcidui_eligible: Bool do
401 if is_user_defined then return false
402 if not is_class then return false
403 for parent in parents do if parent.name != "Object" and parent.is_interface then return true
404 return false
405 end
406 fun is_sliidui_eligible: Bool do
407 if is_user_defined then return false
408 if not is_interface then return false
409 for parent in parents do if parent.name != "Object" and parent.is_interface then return true
410 return false
411 end
412 fun is_slif_eligible(model: Model): Bool do
413 if is_user_defined then return false
414 return not children(model).is_empty
415 end
416 fun is_slccif_eligible(model: Model): Bool do
417 if is_user_defined then return false
418 if not is_class then return false
419 for child in children(model) do if child.is_class then return true
420 return false
421 end
422 fun is_slicif_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(model) do if child.is_class then return true
426 return false
427 end
428 fun is_sliiif_eligible(model: Model): Bool do
429 if is_user_defined then return false
430 if not is_interface then return false
431 for child in children(model) do if child.is_interface then return true
432 return false
433 end
434
435 # SL -> SL
436
437 fun is_slifsl_eligible(model: Model): Bool do
438 if is_user_defined then return false
439 for child in children(model) do if not child.is_user_defined then return true
440 return false
441 end
442 fun is_slccifsl_eligible(model: Model): Bool do
443 if is_user_defined then return false
444 if is_class then return false
445 for child in children(model) do if not child.is_user_defined and child.is_class then return true
446 return false
447 end
448 fun is_slicifsl_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(model) do if not child.is_user_defined and child.is_class then return true
452 return false
453 end
454 fun is_sliiifsl_eligible(model: Model): Bool do
455 if is_user_defined then return false
456 if not is_interface then return false
457 for child in children(model) do if not child.is_user_defined and child.is_interface then return true
458 return false
459 end
460
461 # SL -> UD
462
463 fun is_slifud_eligible(model: Model): Bool do
464 if is_user_defined then return false
465 for child in children(model) do if child.is_user_defined then return true
466 return false
467 end
468 fun is_slccifud_eligible(model: Model): Bool do
469 if is_user_defined then return false
470 if not is_class then return false
471 for child in children(model) do if child.is_user_defined and child.is_class then return true
472 return false
473 end
474 fun is_slicifud_eligible(model: Model): Bool do
475 if is_user_defined then return false
476 if not is_interface then return false
477 for child in children(model) do if child.is_user_defined and child.is_class then return true
478 return false
479 end
480 fun is_sliiifud_eligible(model: Model): Bool do
481 if is_user_defined then return false
482 if not is_interface then return false
483 for child in children(model) do if child.is_user_defined and child.is_interface then return true
484 return false
485 end
486
487 # UD -> *
488
489 fun is_uddui_eligible: Bool do
490 if not is_user_defined then return false
491 for parent in parents do if parent.name != "Object" then return true
492 return false
493 end
494 fun is_udccdui_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 parent.name != "Object" and parent.is_class then return true
498 return false
499 end
500 fun is_udcidui_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 parent.name != "Object" and parent.is_interface then return true
504 return false
505 end
506 fun is_udiidui_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 parent.name != "Object" and parent.is_interface then return true
510 return false
511 end
512 fun is_udif_eligible(model: Model): Bool do
513 if not is_user_defined then return false
514 return not children(model).is_empty
515 end
516 fun is_udccif_eligible(model: Model): Bool do
517 if not is_user_defined then return false
518 if not is_class then return false
519 for child in children(model) do if child.is_class then return true
520 return false
521 end
522 fun is_udicif_eligible(model: Model): Bool do
523 if not is_user_defined then return false
524 if not is_interface then return false
525 for child in children(model) do if child.is_class then return true
526 return false
527 end
528 fun is_udiiif_eligible(model: Model): Bool do
529 if not is_user_defined then return false
530 if not is_interface then return false
531 for child in children(model) do if child.is_interface then return true
532 return false
533 end
534
535 # UD -> SL
536
537 fun is_udduisl_eligible: Bool do
538 if not is_user_defined then return false
539 for parent in parents do if not parent.is_user_defined and parent.name != "Object" then return true
540 return false
541 end
542 fun is_udccduisl_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 not parent.is_user_defined and parent.name != "Object" and parent.is_class then return true
546 return false
547 end
548 fun is_udciduisl_eligible: Bool do
549 if not is_user_defined then return false
550 if not is_class then return false
551 for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_interface then return true
552 return false
553 end
554 fun is_udiiduisl_eligible: Bool do
555 if not is_user_defined then return false
556 if not is_interface then return false
557 for parent in parents do if not parent.is_user_defined and parent.name != "Object" and parent.is_interface then return true
558 return false
559 end
560
561 # UD -> UD
562
563 fun is_udduiud_eligible: Bool do
564 if not is_user_defined then return false
565 for parent in parents do if parent.name != "Object" and parent.is_user_defined then return true
566 return false
567 end
568 fun is_udccduiud_eligible: Bool do
569 if not is_user_defined then return false
570 if not is_class then return false
571 for parent in parents do if parent.name != "Object" and parent.is_class and parent.is_user_defined then return true
572 return false
573 end
574 fun is_udciduiud_eligible: Bool do
575 if not is_user_defined then return false
576 if not is_class then return false
577 for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true
578 return false
579 end
580 fun is_udiiduiud_eligible: Bool do
581 if not is_user_defined then return false
582 if not is_interface then return false
583 for parent in parents do if parent.name != "Object" and parent.is_interface and parent.is_user_defined then return true
584 return false
585 end
586 fun is_udifud_eligible(model: Model): Bool do
587 if not is_user_defined then return false
588 return not children(model).is_empty
589 end
590 fun is_udccifud_eligible(model: Model): Bool do
591 if not is_user_defined then return false
592 if not is_class then return false
593 for child in children(model) do if child.is_user_defined and child.is_class then return true
594 return false
595 end
596 fun is_udicifud_eligible(model: Model): Bool do
597 if not is_user_defined then return false
598 if not is_interface then return false
599 for child in children(model) do if child.is_user_defined and child.is_class then return true
600 return false
601 end
602 fun is_udiiifud_eligible(model: Model): Bool do
603 if not is_user_defined then return false
604 if not is_interface then return false
605 for child in children(model) do if child.is_user_defined and child.is_interface then return true
606 return false
607 end
608
609 end
610
611 redef class MModule
612
613 private var nm: Int = 0 # (NC) Number of Modules
614 private var nc: Int = 0 # (NC) Number of Classes
615 private var ni: Int = 0 # (NI) Number of Interfaces
616 private var nac : Int = 0 # (NAC) Number of Abstract Classes
617 protected var ngc : Int = 0 # (NGC) Number of Generic Classes
618 protected var ngi : Int = 0 # (NGI) Number of Generic Interfaces
619
620 private var dit = "" # (DIT) Global Depth in Inheritance Tree
621 private var dui = "" # (DUI) Proportion of types that either implement an interface or extend another type other than Object
622 private var ccdui = "" # (CCDUI) Proportion of classes that extend some other class.
623 private var cidui = "" # (CIDUI) Proportion of classes that implement some other interface.
624 private var iidui = "" # (IIDUI) Proportion of interfaces that extend some other interface.
625 private var inhf = "" # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
626 private var ccif = "" # (CCIF) Proportion of classes extended by some other class.
627 private var icif = "" # (ICIF) Proportion of interfaces implemented by some other class.
628 private var iiif = "" # (IIIF) Proportion of interfaces extended by some other interface.
629
630 fun compute_module_inheritance_metrics(model: Model) do
631 var ditsum = 0
632 var dui_count = 0
633 var ccdui_count = 0
634 var cidui_count = 0
635 var iidui_count = 0
636 var if_count = 0
637 var ccif_count = 0
638 var icif_count = 0
639 var iiif_count = 0
640 var count = 0
641 for mmodule in self.in_nesting.greaters do
642 for mclass in mmodule.intro_mclasses do
643 count += 1
644 if mclass.is_class then nc += 1
645 if mclass.is_class and mclass.arity > 0 then ngc += 1
646 if mclass.is_class and mclass.is_abstract then nac += 1
647 if mclass.is_interface then ni += 1
648 if mclass.is_interface and mclass.arity > 0 then ngi += 1
649 ditsum += mclass.path_to_object.length
650 if mclass.is_dui_eligible then dui_count += 1
651 if mclass.is_ccdui_eligible then ccdui_count += 1
652 if mclass.is_cidui_eligible then cidui_count += 1
653 if mclass.is_iidui_eligible then iidui_count += 1
654 if mclass.is_if_eligible(model) then if_count += 1
655 if mclass.is_ccif_eligible(model) then ccif_count += 1
656 if mclass.is_icif_eligible(model) then icif_count += 1
657 if mclass.is_iiif_eligible(model) then iiif_count += 1
658 end
659 end
660
661 self.nm = self.in_nesting.greaters.length
662 dit = div(ditsum, count)
663 dui = div(dui_count * 100, count)
664 ccdui = div(ccdui_count * 100, nc)
665 cidui = div(cidui_count * 100, nc)
666 iidui = div(iidui_count * 100, ni)
667 inhf = div(if_count * 100, count)
668 ccif = div(ccif_count * 100, nc)
669 icif = div(icif_count * 100, ni)
670 iiif = div(iiif_count * 100, ni)
671 end
672 end
673
674 # Print inheritance usage metrics
675 fun compute_inheritance_metrics(toolcontext: ToolContext, model: Model)
676 do
677 # global summary metrics
678 var nmd: Int = 0 # (NMD) Number of Modules
679 var nc: Int = 0 # (NC) Number of Classes
680 var ni: Int = 0 # (NI) Number of Interfaces
681 var nac : Int = 0 # (NAC) Number of Abstract Classes
682 var ngc : Int = 0 # (NGC) Number of Generic Classes
683 var ngi : Int = 0 # (NGI) Number of Generic Interfaces
684 # (SL) Std-Lib summary metrics
685 var nmdsl: Int = 0 # (NMDSL) Number of Modules in Std-Lib
686 var ncsl: Int = 0 # (NCSL) Number of Classes in Std-Lib
687 var nisl: Int = 0 # (NISL) Number of Interfaces in Std-Lib
688 var nacsl : Int = 0 # (NACSL) Number of Abstract Classes in Std-Lib
689 var ngcsl : Int = 0 # (NGCSL) Number of Generic Classes in Std-Lib
690 var ngisl : Int = 0 # (NGISL) Number of Generic Interfaces in Std-Lib
691 # (UD) User-Defined summary metrics
692 var nmdud: Int = 0 # (NMDUD) Number of Modules User Defined
693 var ncud: Int = 0 # (NCUD) Number of Classes User Defined
694 var niud: Int = 0 # (NIUD) Number of Interfaces User Defined
695 var nacud : Int = 0 # (NACUD) Number of Abstract Classes User Defined
696 var ngcud : Int = 0 # (NGCUD) Number of Generic Classes User Defined
697 var ngiud : Int = 0 # (NGIUD) Number of Generic Interfaces User Defined
698
699 # global summary inheritance metrics
700 var dit = "" # (DIT) Global Depth in Inheritance Tree
701 var dui = "" # (DUI) Proportion of types that either implement an interface or extend another type other than Object
702 var ccdui = "" # (CCDUI) Proportion of classes that extend some other class.
703 var cidui = "" # (CIDUI) Proportion of classes that implement some other interface.
704 var iidui = "" # (IIDUI) Proportion of interfaces that extend some other interface.
705 var inhf = "" # (IF) Proportion of types Inherited From, that is, those types that are either extended or implemented
706 var ccif = "" # (CCIF) Proportion of classes extended by some other class.
707 var icif = "" # (ICIF) Proportion of interfaces implemented by some other class.
708 var iiif = "" # (IIIF) Proportion of interfaces extended by some other interface.
709
710 # (SL -> *) Std-Lib summary inheritance metrics
711 var sldui = "" # (SLDUI) Proportion of std-lib types that either implement an interface or extend another std-lib type other than Object
712 var slccdui = "" # (SLCCDUI) Proportion of std-lib classes that extend some other std-lib class.
713 var slcidui = "" # (SLCIDUI) Proportion of std-lib classes that implement some other std-lib interface.
714 var sliidui = "" # (SLIIDUI) Proportion of std-lib interfaces that extend some other std-lib interface.
715 var slinhf = "" # (SLIF) Proportion of SL types Inherited From, that is, those types that are either extended or implemented
716 var slccif = "" # (SLCCIF) Proportion of SL classes extended by some other class.
717 var slicif = "" # (SLICIF) Proportion of SL interfaces implemented by some other class.
718 var sliiif = "" # (SLIIIF) Proportion of SL interfaces extended by some other interface.
719
720 # (SL -> SL) Std-Lib summary inheritance metrics
721 var slinhfsl = "" # (SLIFSL) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a SL type
722 var slccifsl = "" # (SLCCIFSL) Proportion of SL classes extended by some other SL class.
723 var slicifsl = "" # (SLICIFSL) Proportion of SL interfaces implemented by some other SL class.
724 var sliiifsl = "" # (SLIIIFSL) Proportion of SL interfaces extended by some other SL interface.
725
726 # (SL -> UD) Std-Lib summary inheritance metrics
727 var slinhfud = "" # (SLIFUD) Proportion of SL types Inherited From, that is, those types that are either extended or implemented by a UD type
728 var slccifud = "" # (SLCCIFUD) Proportion of SL classes extended by some other UD class.
729 var slicifud = "" # (SLICIFUD) Proportion of SL interfaces implemented by some other UD class.
730 var sliiifud = "" # (SLIIIFUD) Proportion of SL interfaces extended by some other UD interface.
731
732 # (UD -> *) User-defined summary inheritance metrics
733 var uddui = "" # (UDDUI) Proportion user-defined of types that either implement an interface or extend another type
734 var udccdui = "" # (UDCCDUI) Proportion of user-defined classes that extend some other class.
735 var udcidui = "" # (UDCIDUI) Proportion of user-defined classes that implement some other interface.
736 var udiidui = "" # (UDIIDUI) Proportion of user-defined interfaces that extend some other interface.
737 var udinhf = "" # (UDIF) Proportion of UD types Inherited From, that is, those types that are either extended or implemented
738 var udccif = "" # (UDCCIF) Proportion of UD classes extended by some other class.
739 var udicif = "" # (UDICIF) Proportion of UD interfaces implemented by some other class.
740 var udiiif = "" # (UDIIIF) Proportion of UD interfaces extended by some other interface.
741
742 # (UD -> SL) User-defined summary inheritance metrics
743 var udduisl = "" # (UDDUISL) Proportion user-defined of types that either implement an interface or extend another type SL
744 var udccduisl = "" # (UDCCDUISL) Proportion of user-defined classes that extend some other SL class.
745 var udciduisl = "" # (UDCIDUISL) Proportion of user-defined classes that implement some other SL interface.
746 var udiiduisl = "" # (UDIIDUISL) Proportion of user-defined interfaces that extend some other SL interface.
747
748 # (UD -> UD) User-defined summary inheritance metrics
749 var ditud = ""
750 var udduiud = "" # (UDDUIUD) Proportion user-defined of types that either implement an interface or extend another type user-defined
751 var udccduiud = "" # (UDCCDUIUD) Proportion of user-defined classes that extend some other user-defined class.
752 var udciduiud = "" # (UDCIDUIUD) Proportion of user-defined classes that implement some other user-defined interface.
753 var udiiduiud = "" # (UDIIDUIUD) Proportion of user-defined interfaces that extend some other user-defined interface.
754 var udinhfud = "" # (UDIFUD) Proportion of UD types Inherited From, that is, those types that are either extended or implemented by another UD type
755 var udccifud = "" # (UDCCIFUD) Proportion of UD classes extended by some other UD class.
756 var udicifud = "" # (UDICIFUD) Proportion of UD interfaces implemented by some other UD class.
757 var udiiifud = "" # (UDIIIFUD) Proportion of UD interfaces extended by some other UD interface.
758
759 # compute modules scalar metrics
760 for mmodule in model.mmodules do
761 mmodule.compute_module_inheritance_metrics(model)
762 end
763
764 # compute class scalar metrics
765 for mclass in model.mclasses do
766 mclass.compute_class_inheritance_metrics(model)
767 end
768
769 # compute summary metrics
770
771 # compute global summary metrics
772 nmd = model.mmodules.length
773 nc = model.extract_classes(model.mclasses).length
774 ni = model.extract_interfaces(model.mclasses).length
775 nac = model.extract_abstracts(model.mclasses).length
776 ngc = model.extract_generics(model.extract_classes(model.mclasses)).length
777 ngi = model.extract_generics(model.extract_interfaces(model.mclasses)).length
778 # compute std-lib summary metrics
779 nmdsl = model.extract_stdlib_modules(model.mmodules).length
780 ncsl = model.extract_stdlib(model.extract_classes(model.mclasses)).length
781 nisl = model.extract_stdlib(model.extract_interfaces(model.mclasses)).length
782 nacsl = model.extract_stdlib(model.extract_abstracts(model.mclasses)).length
783 ngcsl = model.extract_stdlib(model.extract_generics(model.extract_classes(model.mclasses))).length
784 ngisl = model.extract_stdlib(model.extract_generics(model.extract_interfaces(model.mclasses))).length
785 # compute user-defined summary metrics
786 nmdud = model.extract_user_defined_modules(model.mmodules).length
787 ncud = model.extract_user_defined(model.extract_classes(model.mclasses)).length
788 niud = model.extract_user_defined(model.extract_interfaces(model.mclasses)).length
789 nacud = model.extract_user_defined(model.extract_abstracts(model.mclasses)).length
790 ngcud = model.extract_user_defined(model.extract_generics(model.extract_classes(model.mclasses))).length
791 ngiud = model.extract_user_defined(model.extract_generics(model.extract_interfaces(model.mclasses))).length
792
793 # compute inheritance summary metrics
794
795 # * -> *
796 var ditsum = 0
797 var ditudsum = 0
798
799 var dui_count = 0
800 var ccdui_count = 0
801 var cidui_count = 0
802 var iidui_count = 0
803 var if_count = 0
804 var ccif_count = 0
805 var icif_count = 0
806 var iiif_count = 0
807
808 # SL -> *
809 var sldui_count = 0
810 var slccdui_count = 0
811 var slcidui_count = 0
812 var sliidui_count = 0
813 var slif_count = 0
814 var slccif_count = 0
815 var slicif_count = 0
816 var sliiif_count = 0
817
818 # SL -> SL
819 var slifsl_count = 0
820 var slccifsl_count = 0
821 var slicifsl_count = 0
822 var sliiifsl_count = 0
823
824 # SL -> UD
825 var slifud_count = 0
826 var slccifud_count = 0
827 var slicifud_count = 0
828 var sliiifud_count = 0
829
830 # UD -> *
831 var uddui_count = 0
832 var udccdui_count = 0
833 var udcidui_count = 0
834 var udiidui_count = 0
835 var udif_count = 0
836 var udccif_count = 0
837 var udicif_count = 0
838 var udiiif_count = 0
839
840 # UD -> SL
841 var udduisl_count = 0
842 var udccduisl_count = 0
843 var udciduisl_count = 0
844 var udiiduisl_count = 0
845
846 # UD -> UD
847 var udduiud_count = 0
848 var udccduiud_count = 0
849 var udciduiud_count = 0
850 var udiiduiud_count = 0
851 var udifud_count = 0
852 var udccifud_count = 0
853 var udicifud_count = 0
854 var udiiifud_count = 0
855
856 for mclass in model.mclasses do
857 ditsum += mclass.dit
858 ditudsum += mclass.ditud
859
860 # * -> *
861 if mclass.is_dui_eligible then dui_count += 1
862 if mclass.is_ccdui_eligible then ccdui_count += 1
863 if mclass.is_cidui_eligible then cidui_count += 1
864 if mclass.is_iidui_eligible then iidui_count += 1
865 if mclass.is_if_eligible(model) then if_count += 1
866 if mclass.is_ccif_eligible(model) then ccif_count += 1
867 if mclass.is_icif_eligible(model) then icif_count += 1
868 if mclass.is_iiif_eligible(model) then iiif_count += 1
869
870 # SL -> *
871 if mclass.is_sldui_eligible then sldui_count += 1
872 if mclass.is_slccdui_eligible then slccdui_count += 1
873 if mclass.is_slcidui_eligible then slcidui_count += 1
874 if mclass.is_sliidui_eligible then sliidui_count += 1
875 if mclass.is_slif_eligible(model) then slif_count += 1
876 if mclass.is_slccif_eligible(model) then slccif_count += 1
877 if mclass.is_slicif_eligible(model) then slicif_count += 1
878 if mclass.is_sliiif_eligible(model) then sliiif_count += 1
879
880 # SL -> SL
881 if mclass.is_slifsl_eligible(model) then slifsl_count += 1
882 if mclass.is_slccifsl_eligible(model) then slccifsl_count += 1
883 if mclass.is_slicifsl_eligible(model) then slicifsl_count += 1
884 if mclass.is_sliiifsl_eligible(model) then sliiifsl_count += 1
885
886 # SL -> UD
887 if mclass.is_slifud_eligible(model) then slifud_count += 1
888 if mclass.is_slccifud_eligible(model) then slccifud_count += 1
889 if mclass.is_slicifud_eligible(model) then slicifud_count += 1
890 if mclass.is_sliiifud_eligible(model) then sliiifud_count += 1
891
892 # UD -> *
893 if mclass.is_uddui_eligible then uddui_count += 1
894 if mclass.is_udccdui_eligible then udccdui_count += 1
895 if mclass.is_udcidui_eligible then udcidui_count += 1
896 if mclass.is_udiidui_eligible then udiidui_count += 1
897 if mclass.is_udif_eligible(model) then udif_count += 1
898 if mclass.is_udccif_eligible(model) then udccif_count += 1
899 if mclass.is_udicif_eligible(model) then udicif_count += 1
900 if mclass.is_udiiif_eligible(model) then udiiif_count += 1
901
902 # UD -> SL
903 if mclass.is_udduisl_eligible then udduisl_count += 1
904 if mclass.is_udccduisl_eligible then udccduisl_count += 1
905 if mclass.is_udciduisl_eligible then udciduisl_count += 1
906 if mclass.is_udiiduisl_eligible then udiiduisl_count += 1
907
908 # UD -> UD
909 if mclass.is_udduiud_eligible then udduiud_count += 1
910 if mclass.is_udccduiud_eligible then udccduiud_count += 1
911 if mclass.is_udciduiud_eligible then udciduiud_count += 1
912 if mclass.is_udiiduiud_eligible then udiiduiud_count += 1
913 if mclass.is_udifud_eligible(model) then udifud_count += 1
914 if mclass.is_udccifud_eligible(model) then udccifud_count += 1
915 if mclass.is_udicifud_eligible(model) then udicifud_count += 1
916 if mclass.is_udiiifud_eligible(model) then udiiifud_count += 1
917 end
918
919 # * -> *
920 dit = div(ditsum, model.mclasses.length)
921 ditud = div(ditudsum, ncud + niud)
922 dui = div(dui_count * 100, model.mclasses.length)
923 ccdui = div(ccdui_count * 100, nc)
924 cidui = div(cidui_count * 100, nc)
925 iidui = div(iidui_count * 100, ni)
926 inhf = div(if_count * 100, nc + ni)
927 ccif = div(ccif_count * 100, nc)
928 icif = div(icif_count * 100, ni)
929 iiif = div(iiif_count * 100, ni)
930
931 # SL -> *
932 sldui = div(sldui_count * 100, ncsl + nisl)
933 slccdui = div(slccdui_count * 100, ncsl)
934 slcidui = div(slcidui_count * 100, ncsl)
935 sliidui = div(sliidui_count * 100, nisl)
936 slinhf = div(slif_count * 100, ncsl + nisl)
937 slccif = div(slccif_count * 100, ncsl)
938 slicif = div(slicif_count * 100, nisl)
939 sliiif = div(sliiif_count * 100, nisl)
940
941 # SL -> SL
942 slinhfsl = div(slifsl_count * 100, ncsl + nisl)
943 slccifsl = div(slccifsl_count * 100, ncsl)
944 slicifsl = div(slicifsl_count * 100, nisl)
945 sliiifsl = div(sliiifsl_count * 100, nisl)
946
947 # SL -> UD
948 slinhfud = div(slifud_count * 100, ncsl + nisl)
949 slccifud = div(slccifud_count * 100, ncsl)
950 slicifud = div(slicifud_count * 100, nisl)
951 sliiifud = div(sliiifud_count * 100, nisl)
952
953 # UD -> *
954 uddui = div(uddui_count * 100, ncud + niud)
955 udccdui = div(udccdui_count * 100, ncud)
956 udcidui = div(udcidui_count * 100, ncud)
957 udiidui = div(udiidui_count * 100, niud)
958 udinhf = div(if_count * 100, ncud + niud)
959 udccif = div(ccif_count * 100, ncud)
960 udicif = div(icif_count * 100, niud)
961 udiiif = div(iiif_count * 100, niud)
962
963 # UD -> SL
964 udduisl = div(udduisl_count * 100, ncud + niud)
965 udccduisl = div(udccduisl_count * 100, ncud)
966 udciduisl = div(udciduisl_count * 100, ncud)
967 udiiduisl = div(udiiduisl_count * 100, niud)
968
969 # UD -> UD
970 udduiud = div(udduiud_count * 100, ncud + niud)
971 udccduiud = div(udccduiud_count * 100, ncud)
972 udciduiud = div(udciduiud_count * 100, ncud)
973 udiiduiud = div(udiiduiud_count * 100, niud)
974 udinhfud = div(udifud_count * 100, ncud + niud)
975 udccifud = div(udccifud_count * 100, ncud)
976 udicifud = div(udicifud_count * 100, niud)
977 udiiifud = div(udiiifud_count * 100, niud)
978
979 # CSV generation
980 if toolcontext.opt_generate_csv.value then
981 # summary_metrics
982 var summaryCSV = new CSVDocument(toolcontext.output_dir.join_path("summary_metrics.csv"))
983 summaryCSV.set_header("scope", "NMD", "NC", "NI", "NAC", "NGC", "NGI")
984 summaryCSV.add_line("global", nmd, nc, ni, nac, ngc, ngi)
985 summaryCSV.add_line("std-lib", nmdsl, ncsl, nisl, nacsl, ngcsl, ngisl)
986 summaryCSV.add_line("user-defined", nmdud, ncud, niud, nacud, ngcud, ngiud)
987 for m in model.mmodules do
988 summaryCSV.add_line(m.name, m.nm, m.nc, m.ni, m.nac, m.ngc, m.ngi)
989 end
990 summaryCSV.save
991
992 # inheritance metrics
993 var inheritanceCSV = new CSVDocument(toolcontext.output_dir.join_path("inheritance_metrics.csv"))
994 inheritanceCSV.set_header("scope", "DIT", "DUI", "CCDUI", "CIDUI", "IIDUI", "IF", "CCIF", "ICIF", "IIIF")
995 inheritanceCSV.add_line("global", dit, dui, ccdui, cidui, iidui, inhf, ccif, icif, iiif)
996 inheritanceCSV.add_line("SL -> *", "", sldui, slccdui, slcidui, sliidui, slinhf, slccif, slicif, sliiif)
997 inheritanceCSV.add_line("SL -> SL", "", sldui, slccdui, slcidui, sliidui, slinhfsl, slccifsl, slicifsl, sliiifsl)
998 inheritanceCSV.add_line("SL -> UD", "", 0, 0, 0, 0, slinhfud, slccifud, slicifud, sliiifud)
999 inheritanceCSV.add_line("UD -> *", "", uddui, udccdui, udcidui, udiidui, udinhf, udccif, udicif, udiiif)
1000 inheritanceCSV.add_line("UD -> SL", "", udduisl, udccduisl, udciduisl, udiiduisl, 0, 0, 0, 0)
1001 inheritanceCSV.add_line("UD -> UD", ditud, udduiud, udccduiud, udciduiud, udiiduiud, udinhfud, udccifud, udicifud, udiiifud)
1002 for m in model.mmodules do
1003 if m.intro_mclasses.is_empty and m.in_nesting.greaters.length == 1 then continue
1004 inheritanceCSV.add_line(m.name, m.dit, m.dui, m.ccdui, m.cidui, m.iidui, m.inhf, m.ccif, m.icif, m.iiif)
1005 end
1006 inheritanceCSV.save
1007
1008 # scalar metrics
1009 var scalarCSV = new CSVDocument(toolcontext.output_dir.join_path("global_scalar_metrics.csv"))
1010 var udscalarCSV = new CSVDocument(toolcontext.output_dir.join_path("ud_scalar_metrics.csv"))
1011 scalarCSV.set_header("mclass", "type", "FT", "DIT", "DITC", "DITI", "NOP", "NOPC", "NOPI", "NOA", "NOAC", "NOAI", "NOC", "NOCC", "NOCI", "NOD", "NODC", "NODI")
1012 udscalarCSV.set_header("mclass", "type", "FT","DITUD", "DITCUD", "DITIUD", "NOPUD", "NOPCUD", "NOPIUD", "NOAUD", "NOACUD", "NOAIUD", "NOCUD", "NOCCUD", "NOCIUD", "NODUD", "NODCUD", "NODIUD")
1013 for mclass in model.mclasses do
1014 var name = mclass.name
1015 var typ = "class"
1016 if mclass.is_interface then typ = "interface"
1017 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)
1018 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)
1019 end
1020 scalarCSV.save
1021 udscalarCSV.save
1022 end
1023
1024 print "--- Global Summary metrics ---"
1025 print "(NMD) Number of Modules: {nmd}"
1026 print "(NC) Number of Classes: {nc}"
1027 print "(NI) Number of Interfaces: {ni}"
1028 print "(NAC) Number of Abstract Classes: {nac}"
1029 print "(NGC) Number of Generic Classes: {ngc}"
1030 print "(NGI) Number of Generic Interfaces: {ngi}"
1031 print "--- (SL) Std-Lib Summary metrics ---"
1032 print "(NMDSL) Number of Modules: {nmdsl}"
1033 print "(NCSL) Number of Classes: {ncsl}"
1034 print "(NISL) Number of Interfaces: {nisl}"
1035 print "(NACSL) Number of Abstract Classes: {nacsl}"
1036 print "(NGCSL) Number of Generic Classes: {ngcsl}"
1037 print "(NGISL) Number of Generic Interfaces: {ngisl}"
1038 print "--- (UD) User-Defined Summary metrics ---"
1039 print "(NMDUD) Number of Modules: {nmdud}"
1040 print "(NCUD) Number of Classes: {ncud}"
1041 print "(NIUD) Number of Interfaces: {niud}"
1042 print "(NACUD) Number of Abstract Classes: {nacud}"
1043 print "(NGCUD) Number of Generic Classes: {ngcud}"
1044 print "(NGIUD) Number of Generic Interfaces: {ngiud}"
1045 print ""
1046 print "--- Global Inheritance metrics ---"
1047 print "(DIT) Global Depth in Inheritance Tree: {dit}"
1048 print "(DUI) Proportion of types inheriting another type other than Object: {dui}%"
1049 print "(CCDUI) Proportion of classes that extend some other class: {ccdui}%"
1050 print "(CIDUI) Proportion of classes that implement some other interface: {cidui}%"
1051 print "(IIDUI) Proportion of interfaces that extend some other interface: {iidui}%"
1052 print "(IF) Proportion of types Inherited From: {inhf}%"
1053 print "(CCIF) Proportion of classes extended by class: {ccif}%"
1054 print "(ICIF) Proportion of interfaces implemented by class: {icif}%"
1055 print "(IIIF) Proportion of interfaces extended by interface: {iiif}%"
1056 print ""
1057 print "--- (SL -> *) Std-Lib Inheritance metrics ---"
1058 print "(SLDUI) Proportion of SL types inheriting another type other than Object: {sldui}%"
1059 print "(SLCCDUI) Proportion of SL classes that extend some other class: {slccdui}%"
1060 print "(SLCIDUI) Proportion of SL classes that implement some other interface: {slcidui}%"
1061 print "(SLIIDUI) Proportion of SL interfaces that extend some other interface: {sliidui}%"
1062 print "(SLIF) Proportion of SL types Inherited From: {slinhf}%"
1063 print "(SLCCIF) Proportion of SL classes extended by class: {slccif}%"
1064 print "(SLICIF) Proportion of SL interfaces implemented by class: {slicif}%"
1065 print "(SLIIIF) Proportion of SL interfaces extended by interface: {sliiif}%"
1066 print ""
1067 print "--- (SL -> SL) Std-Lib Inheritance metrics ---"
1068 print "(SLIFSL) Proportion of SL types Inherited From by SL type: {slinhfsl}%"
1069 print "(SLCCIFSL) Proportion of SL classes extended by SL class: {slccifsl}%"
1070 print "(SLICIFSL) Proportion of SL interfaces implemented by SL class: {slicifsl}%"
1071 print "(SLIIIFSL) Proportion of SL interfaces extended by SL interface: {sliiifsl}%"
1072 print ""
1073 print "--- (SL->UD) Std-Lib Inheritance metrics ---"
1074 print "(SLIFUD) Proportion of SL types Inherited From by UD type: {slinhfud}%"
1075 print "(SLCCIFUD) Proportion of SL classes extended by UD class: {slccifud}%"
1076 print "(SLICIFUD) Proportion of SL interfaces implemented by UD class: {slicifud}%"
1077 print "(SLIIIFUD) Proportion of SL interfaces extended by UD interface: {sliiifud}%"
1078 print ""
1079 print "--- (UD->*) User-Defined Inheritance metrics ---"
1080 print "(UDDUI) Proportion of UD types inheriting another type other than Object: {uddui}%"
1081 print "(UDCCDUI) Proportion of UD classes that extend some other class: {udccdui}%"
1082 print "(UDCIDUI) Proportion of UD classes that implement some other interface: {udcidui}%"
1083 print "(UDIIDUI) Proportion of UD interfaces that extend some other interface: {udiidui}%"
1084 print "(UDIF) Proportion of UD types Inherited From: {udinhf}%"
1085 print "(UDCCIF) Proportion of UD classes extended by class: {udccif}%"
1086 print "(UDICIF) Proportion of UD interfaces implemented by class: {udicif}%"
1087 print "(UDIIIF) Proportion of UD interfaces extended by interface: {udiiif}%"
1088 print ""
1089 print "--- (UD -> SL) User-Defined Inheritance metrics ---"
1090 print "(UDDUISL) Proportion of UD types inheriting another type other SL type: {udduisl}%"
1091 print "(UDCCDUISL) Proportion of UD classes that extend some other SL class: {udccduisl}%"
1092 print "(UDCIDUISL) Proportion of UD classes that implement some other SL interface: {udciduisl}%"
1093 print "(UDIIDUISL) Proportion of UD interfaces that extend some other SL interface: {udiiduisl}%"
1094 print ""
1095 print "--- (UD -> UD) User-Defined Inheritance metrics ---"
1096 print "(UDDUIUD) Proportion of UD types inheriting another type other UD type: {udduiud}%"
1097 print "(UDCCDUIUD) Proportion of UD classes that extend some other UD class: {udccduiud}%"
1098 print "(UDCIDUIUD) Proportion of UD classes that implement some other UD interface: {udciduiud}%"
1099 print "(UDIIDUIUD) Proportion of UD interfaces that extend some other UD interface: {udiiduiud}%"
1100 print "(UDIFUD) Proportion of UD types Inherited From: {udinhfud}%"
1101 print "(UDCCIFUD) Proportion of UD classes extended by UD class: {udccifud}%"
1102 print "(UDICIFUD) Proportion of UD interfaces implemented by UD class: {udicifud}%"
1103 print "(UDIIIFUD) Proportion of UD interfaces extended by UD interface: {udiiifud}%"
1104 end
1105
1106 # TODO Third-Party metrics
1107 # TODO gnu-plot generation