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