File Coverage

blib/lib/Class/MOP/Mixin/HasOverloads.pm
Criterion Covered Total %
statement 85 85 100.0
branch 16 18 88.8
condition 10 12 83.3
subroutine 21 21 100.0
pod 0 9 0.0
total 132 145 91.0


line stmt bran cond sub pod time code
1             package Class::MOP::Mixin::HasOverloads;
2             our $VERSION = '2.2205';
3              
4 450     450   5543 use strict;
  450         1109  
  450         13835  
5 450     450   2551 use warnings;
  450         1001  
  450         12265  
6              
7 450     450   207372 use Class::MOP::Overload;
  450         1415  
  450         20029  
8              
9 450     450   231818 use Devel::OverloadInfo 0.005 'overload_info', 'overload_op_info';
  450         856659  
  450         28139  
10 450     450   3419 use Scalar::Util 'blessed';
  450         1030  
  450         16415  
11              
12 450     450   2785 use overload ();
  450         1055  
  450         7385  
13              
14 450     450   2252 use parent 'Class::MOP::Mixin';
  450         969  
  450         2513  
15              
16             sub is_overloaded {
17 1974     1974 0 8242 my $self = shift;
18 1974         10807 Devel::OverloadInfo::is_overloaded($self->name);
19             }
20              
21             sub get_overload_list {
22 35     35 0 2376 my $self = shift;
23              
24 35         184 my $info = $self->_overload_info;
25 35         153333 return grep { $_ ne 'fallback' } keys %{$info}
  55         335  
  35         160  
26             }
27              
28             sub get_all_overloaded_operators {
29 30     30 0 82 my $self = shift;
30 30         131 return map { $self->_overload_for($_) } $self->get_overload_list;
  32         212  
31             }
32              
33             sub has_overloaded_operator {
34 26     26 0 3482 my $self = shift;
35 26         68 my ($op) = @_;
36 26         118 return defined $self->_overload_info_for($op);
37             }
38              
39             sub _overload_map {
40 63   50 63   285 $_[0]->{_overload_map} ||= {};
41             }
42              
43             sub get_overloaded_operator {
44 8     8 0 522 my $self = shift;
45 8         22 my ($op) = @_;
46 8   100     28 return $self->_overload_map->{$op} ||= $self->_overload_for($op);
47             }
48              
49 450     450   144949 use constant _SET_FALLBACK_EACH_TIME => "$]" < 5.120;
  450         2355  
  450         346637  
50              
51             sub add_overloaded_operator {
52 18     18 0 1733 my $self = shift;
53 18         94 my ( $op, $overload ) = @_;
54              
55 18         70 my %p = ( associated_metaclass => $self );
56 18 100       140 if ( !ref $overload ) {
    100          
57 1         8 %p = (
58             %p,
59             operator => $op,
60             method_name => $overload,
61             associated_metaclass => $self,
62             );
63 1 50       8 $p{method} = $self->get_method($overload)
64             if $self->has_method($overload);
65 1         10 $overload = Class::MOP::Overload->new(%p);
66             }
67             elsif ( !blessed $overload) {
68 1         9 my ($coderef_package, $coderef_name) = Class::MOP::get_code_info($overload);
69 1         7 $overload = Class::MOP::Overload->new(
70             operator => $op,
71             coderef => $overload,
72             coderef_name => $coderef_name,
73             coderef_package => $coderef_package,
74             %p,
75             );
76             }
77              
78 18         107 $overload->attach_to_class($self);
79 18         101 $self->_overload_map->{$op} = $overload;
80              
81 18 100       100 my %overload = (
82             $op => $overload->has_coderef
83             ? $overload->coderef
84             : $overload->method_name
85             );
86              
87             # Perl 5.10 and earlier appear to have a bug where setting a new
88             # overloading operator wipes out the fallback value unless we pass it each
89             # time.
90 18         42 if (_SET_FALLBACK_EACH_TIME) {
91 18         683 $overload{fallback} = $self->get_overload_fallback_value;
92             }
93              
94 18         1778 $self->name->overload::OVERLOAD(%overload);
95             }
96              
97             sub remove_overloaded_operator {
98 2     2 0 6 my $self = shift;
99 2         6 my ($op) = @_;
100              
101 2         6 delete $self->_overload_map->{$op};
102              
103             # overload.pm provides no api for this - but the problem that makes this
104             # necessary has been fixed in 5.18
105 2 50       13 $self->get_or_add_package_symbol('%OVERLOAD')->{dummy}++
106             if "$]" < 5.017000;
107              
108 2         16 $self->remove_package_symbol('&(' . $op);
109             }
110              
111             sub get_overload_fallback_value {
112 47     47 0 115 my $self = shift;
113 47   100     200 return ($self->_overload_info_for('fallback') || {})->{value};
114             }
115              
116             sub set_overload_fallback_value {
117 15     15 0 1281 my $self = shift;
118 15         33 my $value = shift;
119              
120 15         112 $self->name->overload::OVERLOAD( fallback => $value );
121             }
122              
123             # We could cache this but we'd need some logic to clear it at all the right
124             # times, which seems more tedious than it's worth.
125             sub _overload_info {
126 35     35   74 my $self = shift;
127 35   50     190 return overload_info( $self->name ) || {};
128             }
129              
130             sub _overload_info_for {
131 94     94   169 my $self = shift;
132 94         167 my $op = shift;
133 94         415 return overload_op_info( $self->name, $op );
134             }
135              
136             sub _overload_for {
137 35     35   84 my $self = shift;
138 35         70 my $op = shift;
139              
140 35         176 my $map = $self->_overload_map;
141 35 100       165 return $map->{$op} if $map->{$op};
142              
143 21         75 my $info = $self->_overload_info_for($op);
144 21 100       2153 return unless $info;
145              
146 19         115 my %p = (
147             operator => $op,
148             associated_metaclass => $self,
149             );
150              
151 19 100 100     157 if ( $info->{code} && !$info->{method_name} ) {
152 3         9 $p{coderef} = $info->{code};
153             @p{ 'coderef_package', 'coderef_name' }
154 3         26 = $info->{code_name} =~ /(.+)::([^:]+)/;
155             }
156             else {
157 16         57 $p{method_name} = $info->{method_name};
158 16 100       161 if ( $self->has_method( $p{method_name} ) ) {
159 14         88 $p{method} = $self->get_method( $p{method_name} );
160             }
161             }
162              
163 19         200 return $map->{$op} = Class::MOP::Overload->new(%p);
164             }
165              
166             1;
167              
168             # ABSTRACT: Methods for metaclasses which have overloads
169              
170             __END__
171              
172             =pod
173              
174             =encoding UTF-8
175              
176             =head1 NAME
177              
178             Class::MOP::Mixin::HasOverloads - Methods for metaclasses which have overloads
179              
180             =head1 VERSION
181              
182             version 2.2205
183              
184             =head1 DESCRIPTION
185              
186             This class implements methods for metaclasses which have overloads
187             (L<Class::MOP::Clas> and L<Moose::Meta::Role>). See L<Class::MOP::Class> for
188             API details.
189              
190             =head1 AUTHORS
191              
192             =over 4
193              
194             =item *
195              
196             Stevan Little <stevan@cpan.org>
197              
198             =item *
199              
200             Dave Rolsky <autarch@urth.org>
201              
202             =item *
203              
204             Jesse Luehrs <doy@cpan.org>
205              
206             =item *
207              
208             Shawn M Moore <sartak@cpan.org>
209              
210             =item *
211              
212             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
213              
214             =item *
215              
216             Karen Etheridge <ether@cpan.org>
217              
218             =item *
219              
220             Florian Ragwitz <rafl@debian.org>
221              
222             =item *
223              
224             Hans Dieter Pearcey <hdp@cpan.org>
225              
226             =item *
227              
228             Chris Prather <chris@prather.org>
229              
230             =item *
231              
232             Matt S Trout <mstrout@cpan.org>
233              
234             =back
235              
236             =head1 COPYRIGHT AND LICENSE
237              
238             This software is copyright (c) 2006 by Infinity Interactive, Inc.
239              
240             This is free software; you can redistribute it and/or modify it under
241             the same terms as the Perl 5 programming language system itself.
242              
243             =cut