File Coverage

blib/lib/Test/Run/Class/Hierarchy.pm
Criterion Covered Total %
statement 33 33 100.0
branch 8 8 100.0
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 50 50 100.0


line stmt bran cond sub pod time code
1             package Test::Run::Class::Hierarchy;
2              
3 24     24   21070 use strict;
  24         51  
  24         654  
4 24     24   126 use warnings;
  24         41  
  24         746  
5              
6             =head1 NAME
7              
8             Test::Run::Class::Hierarchy - returns a list of super-classes in topological
9             order.
10              
11             =head1 SYNPOSIS
12              
13             use Test::Run::Class::Hierarchy;
14              
15             my $base_classes = hierarchy_of("MyClass::Sub::Sub::Sub");
16              
17             my $base_classes_rev = rev_hierarchy_of("MyClass::Sub::Sub::Sub");
18              
19             =head1 DESCRIPTION
20              
21             Returns a list of classes in the current namespace. Note that it caches
22             the results.
23              
24             =head1 EXPORTS
25              
26             =cut
27              
28 24     24   954 use Moose;
  24         471832  
  24         147  
29              
30             extends('Exporter');
31              
32 24     24   151121 use List::MoreUtils (qw(uniq));
  24         55  
  24         358  
33              
34             our @EXPORT_OK = (qw(hierarchy_of rev_hierarchy_of));
35              
36             our %_hierarchy_of = ();
37              
38             =head2 my [@list] = hierarchy_of($class)
39              
40             Returns a list of the classes in the hierarchy of the class, from bottom to
41             top.
42              
43             =cut
44              
45             sub hierarchy_of
46             {
47 4     4 1 66 my $class = shift;
48              
49 4 100       14 if (exists($_hierarchy_of{$class}))
50             {
51 2         16 return $_hierarchy_of{$class};
52             }
53              
54 24     24   13151 no strict 'refs';
  24         49  
  24         7524  
55              
56 2         5 my @hierarchy = $class;
57 2         4 my @parents = @{$class. '::ISA'};
  2         8  
58              
59 2         8 while (my $p = shift(@parents))
60             {
61 8         13 push @hierarchy, $p;
62 8         10 push @parents, @{$p. '::ISA'};
  8         36  
63             }
64              
65 2         16 my @unique = uniq(@hierarchy);
66              
67             return $_hierarchy_of{$class} =
68             [
69             sort
70             {
71 2 100       10 $a->isa($b) ? -1
  11 100       85  
72             : $b->isa($a) ? +1
73             : 0
74             }
75             @unique
76             ];
77             }
78              
79             our %_rev_hierarchy_of = ();
80              
81             =head2 my [@list] = rev_hierarchy_of($class)
82              
83             Returns the classes from top to bottom.
84              
85             =cut
86              
87             sub rev_hierarchy_of
88             {
89 4     4 1 8 my $class = shift;
90              
91 4 100       16 if (exists($_rev_hierarchy_of{$class}))
92             {
93 2         14 return $_rev_hierarchy_of{$class};
94             }
95              
96 2         3 return $_rev_hierarchy_of{$class} = [reverse @{hierarchy_of($class)}];
  2         6  
97             }
98              
99             1;
100              
101             =head1 LICENSE
102              
103             This file is licensed under the MIT X11 License:
104              
105             http://www.opensource.org/licenses/mit-license.php
106              
107             =head1 CREDITS
108              
109             The code was inspired by the code from Damian Conway's L<Class::Std>, but
110             is not inclusive of it.
111              
112             Written by Shlomi Fish: L<http://www.shlomifish.org/>.
113              
114             =head1 SEE ALSO
115              
116             L<Class::Std>, L<Test::Run>
117              
118             =cut
119