File Coverage

blib/lib/Devel/OverloadInfo.pm
Criterion Covered Total %
statement 58 69 84.0
branch 23 34 67.6
condition 4 12 33.3
subroutine 12 12 100.0
pod 3 4 75.0
total 100 131 76.3


line stmt bran cond sub pod time code
1             package Devel::OverloadInfo;
2             $Devel::OverloadInfo::VERSION = '0.007';
3             # ABSTRACT: introspect overloaded operators
4              
5             #pod =head1 DESCRIPTION
6             #pod
7             #pod Devel::OverloadInfo returns information about L
8             #pod operators for a given class (or object), including where in the
9             #pod inheritance hierarchy the overloads are declared and where the code
10             #pod implementing them is.
11             #pod
12             #pod =cut
13              
14 2     2   154749 use strict;
  2         21  
  2         65  
15 2     2   12 use warnings;
  2         4  
  2         53  
16 2     2   2667 use overload ();
  2         2100  
  2         64  
17 2     2   15 use Scalar::Util qw(blessed);
  2         53  
  2         158  
18 2     2   1098 use Package::Stash 0.14;
  2         15264  
  2         70  
19 2     2   1047 use MRO::Compat;
  2         3692  
  2         422  
20              
21             BEGIN {
22 2 50 33 2   8 if (eval { require Sub::Util } && defined &Sub::Util::subname) {
  2         32  
23 2         62 *subname = \&Sub::Util::subname;
24             }
25             else {
26 0         0 require B;
27             *subname = sub {
28 0         0 my ($coderef) = @_;
29 0 0       0 die 'Not a subroutine reference'
30             unless ref $coderef;
31 0         0 my $cv = B::svref_2object($coderef);
32 0 0       0 die 'Not a subroutine reference'
33             unless $cv->isa('B::CV');
34 0         0 my $gv = $cv->GV;
35             return undef
36 0 0       0 if $gv->isa('B::SPECIAL');
37 0         0 my $stash = $gv->STASH;
38 0 0       0 my $package = $stash->isa('B::SPECIAL') ? '__ANON__' : $stash->NAME;
39 0         0 return $package . '::' . $gv->NAME;
40 0         0 };
41             }
42             }
43              
44              
45 2     2   11 use Exporter 5.57 qw(import);
  2         32  
  2         1285  
46             our @EXPORT_OK = qw(overload_info overload_op_info is_overloaded);
47              
48             sub stash_with_symbol {
49 467     467 0 817 my ($class, $symbol) = @_;
50              
51 467         656 for my $package (@{mro::get_linear_isa($class)}) {
  467         1128  
52 697         3370 my $stash = Package::Stash->new($package);
53 697         3466 my $value_ref = $stash->get_symbol($symbol);
54 697 100       2286 return ($stash, $value_ref) if $value_ref;
55             }
56 439         1669 return;
57             }
58              
59             #pod =func is_overloaded
60             #pod
61             #pod if (is_overloaded($class_or_object)) { ... }
62             #pod
63             #pod Returns a boolean indicating whether the given class or object has any
64             #pod overloading declared. Note that a bare C with no
65             #pod actual operators counts as being overloaded.
66             #pod
67             #pod Equivalent to
68             #pod L, but
69             #pod doesn't trigger various bugs associated with it in versions of perl
70             #pod before 5.16.
71             #pod
72             #pod =cut
73              
74             sub is_overloaded {
75 470   33 470 1 3162 my $class = blessed($_[0]) || $_[0];
76              
77             # Perl before 5.16 seems to corrupt inherited overload info if
78             # there's a lone dereference overload and overload::Overloaded()
79             # is called before any object has been blessed into the class.
80 470 50       1516 return !!("$]" >= 5.016
81             ? overload::Overloaded($class)
82             : stash_with_symbol($class, '&()')
83             );
84             }
85              
86             #pod =func overload_op_info
87             #pod
88             #pod my $info = overload_op_info($class_or_object, $op);
89             #pod
90             #pod Returns a hash reference with information about the specified
91             #pod overloaded operator of the named class or blessed object.
92             #pod
93             #pod Returns C if the operator is not overloaded.
94             #pod
95             #pod See L for the available operators.
96             #pod
97             #pod The keys in the returned hash are as follows:
98             #pod
99             #pod =over
100             #pod
101             #pod =item class
102             #pod
103             #pod The name of the class in which the operator overloading was declared.
104             #pod
105             #pod =item code
106             #pod
107             #pod A reference to the function implementing the overloaded operator.
108             #pod
109             #pod =item code_name
110             #pod
111             #pod The fully qualified name of the function implementing the overloaded operator.
112             #pod
113             #pod =item method_name (optional)
114             #pod
115             #pod The name of the method implementing the overloaded operator, if the
116             #pod overloading was specified as a named method, e.g. C<< use overload $op
117             #pod => 'method'; >>.
118             #pod
119             #pod =item code_class (optional)
120             #pod
121             #pod The name of the class in which the method specified by C
122             #pod was found.
123             #pod
124             #pod =item value (optional)
125             #pod
126             #pod For the special C key, the value it was given in C.
127             #pod
128             #pod =back
129             #pod
130             #pod =cut
131              
132             sub overload_op_info {
133 458     458 1 6452 my ($class, $op) = @_;
134 458   33     1406 $class = blessed($class) || $class;
135              
136 458 100       732 return undef unless is_overloaded($class);
137 457 100       16136 my $op_method = $op eq 'fallback' ? "()" : "($op";
138 457 100       1193 my ($stash, $func) = stash_with_symbol($class, "&$op_method")
139             or return undef;
140 21         91 my $info = {
141             class => $stash->name,
142             };
143 21 100       86 if ($func == \&overload::nil) {
144             # Named method or fallback, stored in the scalar slot
145 13 50       89 if (my $value_ref = $stash->get_symbol("\$$op_method")) {
146 13         32 my $value = $$value_ref;
147 13 100       31 if ($op eq 'fallback') {
148 3         21 $info->{value} = $value;
149             } else {
150 10         24 $info->{method_name} = $value;
151 10 100       33 if (my ($impl_stash, $impl_func) = stash_with_symbol($class, "&$value")) {
152 7         22 $info->{code_class} = $impl_stash->name;
153 7         20 $info->{code} = $impl_func;
154             }
155             }
156             }
157             } else {
158 8         22 $info->{code} = $func;
159             }
160             $info->{code_name} = subname($info->{code})
161 21 100       164 if exists $info->{code};
162              
163 21         82 return $info;
164             }
165              
166             #pod =func overload_info
167             #pod
168             #pod my $info = overload_info($class_or_object);
169             #pod
170             #pod Returns a hash reference with information about all the overloaded
171             #pod operators of specified class name or blessed object. The keys are the
172             #pod overloaded operators, as specified in C<%overload::ops> (see
173             #pod L), and the values are the hashes
174             #pod returned by L.
175             #pod
176             #pod =cut
177              
178             sub overload_info {
179 7   33 7 1 2799 my $class = blessed($_[0]) || $_[0];
180              
181 7 100       25 return {} unless is_overloaded($class);
182              
183 6         348 my (%overloaded);
184 6         316 for my $op (map split(/\s+/), values %overload::ops) {
185 450 100       810 my $info = overload_op_info($class, $op)
186             or next;
187 16         47 $overloaded{$op} = $info
188             }
189 6         86 return \%overloaded;
190             }
191              
192             #pod =head1 CAVEATS
193             #pod
194             #pod Whether the C key exists when it has its default value of
195             #pod C varies between perl versions: Before 5.18 it's there, in
196             #pod later versions it's not.
197             #pod
198             #pod =cut
199              
200             1;
201              
202             __END__