File Coverage

blib/lib/UNIVERSAL/can.pm
Criterion Covered Total %
statement 49 49 100.0
branch 16 18 88.8
condition 13 17 76.4
subroutine 12 12 100.0
pod 0 1 0.0
total 90 97 92.7


line stmt bran cond sub pod time code
1             package UNIVERSAL::can;
2             # ABSTRACT: work around buggy code calling UNIVERSAL::can() as a function
3             $UNIVERSAL::can::VERSION = '1.20140328';
4 9     9   299613 use strict;
  9         26  
  9         365  
5 9     9   201 use warnings;
  9         18  
  9         268  
6 9     9   349 use 5.008;
  9         39  
  9         425  
7              
8 9     9   47 use vars qw( $recursing $always_warn );
  9         18  
  9         2228  
9              
10 9     9   57 use Scalar::Util 'blessed';
  9         26  
  9         1613  
11 9     9   56 use warnings::register;
  9         17  
  9         2787  
12              
13             my $orig;
14              
15             BEGIN
16             {
17 9     9   24 $orig = \&UNIVERSAL::can;
18              
19 9     9   51 no warnings 'redefine';
  9         14  
  9         690  
20 9         590 *UNIVERSAL::can = \&can;
21             }
22              
23             sub import
24             {
25 10     10   296 my $class = shift;
26 10         3485 for my $import (@_)
27             {
28 3 100       18 $always_warn = 1 if $import eq '-always_warn';
29 9     9   48 no strict 'refs';
  9         104  
  9         9662  
30 3 100       274 *{ caller() . '::can' } = \&can if $import eq 'can';
  2         2866  
31             }
32             }
33              
34             sub can
35             {
36 55669     55669 0 251165 my $caller = caller();
37 55669         73254 local $@;
38              
39             # don't get into a loop here
40             goto &$orig if $recursing
41             || ( defined $caller
42             && defined $_[0]
43 55669 100 66     360158 && eval { local $recursing = 1;
  55660   100     77479  
      66        
44 55660 50       132594 warnings->unimport( 'UNIVERSAL::isa' )
45             if $INC{'UNIVERSAL::isa'};
46 55660   66     689048 $caller->isa(blessed $_[0] || $_[0]) } );
47              
48             # call an overridden can() if it exists
49 55657 100       112460 my $can = eval { $_[0]->$orig('can') || 0 };
  55657         225778  
50              
51             # but only if it's a real class
52 55657 100       110530 goto &$orig unless $can;
53              
54             # but not if it inherited this one
55 55651 100       1665976 goto &$orig if $can == \&UNIVERSAL::can;
56              
57             # redirect to an overridden can, making sure not to recurse and warning
58 7         13 local $recursing = 1;
59 7         11 my $invocant = shift;
60              
61 7         18 _report_warning();
62 7         23 return $invocant->can(@_);
63             }
64              
65             sub _report_warning
66             {
67 7 100 100 7   540 if ( $always_warn || warnings::enabled() )
68             {
69 3   50     25 my $calling_sub = ( caller(2) )[3] || '';
70 3 50       594 warnings::warn("Called UNIVERSAL::can() as a function, not a method")
71             if $calling_sub !~ /::can$/;
72             }
73              
74 7         132 return;
75             }
76              
77             1;
78             __END__