File Coverage

blib/lib/Test/NoOverride.pm
Criterion Covered Total %
statement 71 73 97.2
branch 9 12 75.0
condition 2 3 66.6
subroutine 12 12 100.0
pod n/a
total 94 100 94.0


line stmt bran cond sub pod time code
1             package Test::NoOverride;
2 2     2   30724 use strict;
  2         5  
  2         87  
3 2     2   13 use warnings;
  2         2  
  2         61  
4 2     2   912 use Module::Functions;
  2         4640  
  2         100  
5 2     2   11 use Test::More;
  2         2  
  2         9  
6              
7             our $VERSION = '0.03';
8              
9             sub import {
10 2     2   15 my $class = shift;
11              
12 2         3 my $caller = caller;
13 2     2   405 no strict 'refs'; ## no critic
  2         5  
  2         702  
14 2         3 for my $func (qw/ no_override /) {
15 2         2 *{"${caller}::$func"} = \&{ __PACKAGE__. "::_$func" };
  2         1202  
  2         12  
16             }
17             }
18              
19             sub _no_override {
20 3     3   1007 my ($klass, %opt) = @_;
21              
22 3         3 my %exclude;
23 3 100       7 if (exists $opt{exclude}) {
24 1         1 $exclude{$_} = 1 for @{$opt{exclude}};
  1         5  
25             }
26 3 50       4 unless ($opt{new}) {
27 3         5 $exclude{new} = 1; # default ignore 'new' method
28             }
29              
30 3         6 _load_class($klass);
31 3         7 my @functions = _get_functions($klass);
32              
33 3         8 my @methods;
34 3         5 _isa_list(\@methods, $klass);
35              
36 3         3 my $fail = 0;
37 3         4 for my $func (@functions) {
38 4         3 for my $m (@methods) {
39 28         16 my ($class, $method) = %{$m};
  28         33  
40 28 50 66     425 if ($func eq $method && !$exclude{$func}) {
41 0         0 fail("[$klass\::$func] overrides [$class\::$method]");
42 0         0 $fail++;
43             }
44             }
45             }
46              
47 3 50       15 ok(1, "No Override: $klass") unless $fail;
48             }
49              
50             sub _load_class {
51 3     3   3 my $class = shift;
52              
53 3         4 my $class_path = $class;
54 3         10 $class_path =~ s!::!/!g;
55 3         970 require "$class_path\.pm"; ## no critic
56 3         1609 $class->import;
57             }
58              
59             sub _isa_list {
60 9     9   13 my ($methods, @klass_list) = @_;
61              
62 9         5 my @parents;
63 9         10 for my $klass (@klass_list) {
64             {
65 2     2   9 no strict 'refs'; ## no critic
  2         2  
  2         273  
  12         9  
66 12         9 push @parents, @{"$klass\::ISA"};
  12         25  
67             }
68 12         13 for my $parent_klass (@parents) {
69 9         22 my @functions = _get_functions($parent_klass);
70 9         10 for my $func (@functions) {
71 21         14 push @{$methods}, { $parent_klass => $func };
  21         47  
72             }
73             }
74             }
75              
76 9 100       17 if ( scalar @parents ) {
77 6         11 _isa_list($methods, @parents);
78             }
79              
80             }
81              
82             sub _get_functions {
83 12     12   9 my $package = shift;
84              
85 12         22 my @functions = get_public_functions($package);
86              
87             {
88 2     2   11 no strict 'refs'; ## no critic
  2         2  
  2         210  
  12         595  
89 12         11 my %class = %{"${package}::"};
  12         57  
90 12         35 while (my ($k, $v) = each %class) {
91 62 100       234 push @functions, $k if $k =~ /^_.+/;
92             }
93             }
94              
95 12         23 return @functions;
96             }
97              
98             1;
99              
100             __END__