File Coverage

blib/lib/Sub/HandlesVia/Toolkit/Moose.pm
Criterion Covered Total %
statement 87 95 91.5
branch 25 34 73.5
condition 5 15 33.3
subroutine 20 21 95.2
pod 0 5 0.0
total 137 170 80.5


line stmt bran cond sub pod time code
1 22     22   390 use 5.008;
  22         73  
2 22     22   118 use strict;
  22         47  
  22         485  
3 22     22   111 use warnings;
  22         62  
  22         1434  
4              
5             package Sub::HandlesVia::Toolkit::Moose;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.050000';
9              
10 22     22   10112 use Sub::HandlesVia::Mite;
  22         61  
  22         156  
11             extends 'Sub::HandlesVia::Toolkit';
12              
13             sub setup_for {
14 89     89 0 272 my $me = shift;
15 89         286 my ($target) = @_;
16            
17 89         471 require Moose::Util;
18 89         476 my $meta = Moose::Util::find_meta($target);
19 89         1374 $me->meta_hack( $meta );
20             }
21              
22             sub meta_hack {
23 92     92 0 308 my ( $me, $meta ) = ( shift, @_ );
24            
25 92         452 require Moose::Util::MetaRole;
26            
27 92 100       770 if ( $meta->isa('Moose::Meta::Role') ) {
28            
29 3         13 return Moose::Util::MetaRole::apply_metaroles(
30             for => $meta,
31             role_metaroles => { role => [ $me->package_trait, $me->role_trait ] },
32             );
33             }
34             else {
35            
36 89         440 return Moose::Util::MetaRole::apply_metaroles(
37             for => $meta,
38             class_metaroles => { class => [ $me->package_trait ] },
39             );
40             }
41             }
42              
43             sub package_trait {
44 93     93 0 731 __PACKAGE__ . "::PackageTrait";
45             }
46              
47             sub role_trait {
48 4     4 0 25 __PACKAGE__ . "::RoleTrait";
49             }
50              
51             sub code_generator_for_attribute {
52 104     104 0 441 my ($me, $target, $attrname) = (shift, @_);
53            
54 104 50       480 if (ref $attrname) {
55 104 50       462 @$attrname==1 or die;
56 104         358 ($attrname) = @$attrname;
57             }
58            
59 104         244 my $meta;
60 104 50       417 if (ref $target) {
61 0         0 $meta = $target;
62 0         0 $target = $meta->name;
63             }
64             else {
65 104         744 require Moose::Util;
66 104         495 $meta = Moose::Util::find_meta($target);
67             }
68              
69 104         2281 my $attr = $meta->get_attribute($attrname);
70 104         1989 my $spec = +{%$attr};
71              
72 104         368 my $captures = {};
73            
74             my $slot = sub {
75 1542     1542   2599 my $gen = shift;
76 1542         5316 $meta->get_meta_instance->inline_slot_access($gen->generate_self, $attrname);
77 104         712 };
78            
79 104         376 my ($get, $set, $get_is_lvalue, $set_checks_isa);
80 104 100 33     1240 if (!$spec->{lazy} and !$spec->{traits} and !$spec->{auto_deref}) {
    100          
81 80         219 $get = $slot;
82 80         209 ++$get_is_lvalue;
83             }
84             elsif ($attr->has_read_method) {
85 18         482 my $read_method = $attr->get_read_method;
86 18     294   337 $get = sub { my $self = shift->generate_self; "scalar($self\->$read_method)" };
  294         807  
  294         1993  
87             }
88             else {
89 6         76 my $read_method = $attr->get_read_method_ref;
90 6         698 eval { $read_method = $read_method->{body} }; # Moose docs lie!
  6         36  
91 6         17 $captures->{'$shv_read_method'} = \$read_method;
92 6     12   31 $get = sub { my $self = shift->generate_self; "scalar($self\->\$shv_read_method)" };
  12         34  
  12         82  
93             }
94            
95 104 100       773 if ($attr->has_write_method) {
96 76         1288 my $write_method = $attr->get_write_method;
97             $set = sub {
98 777     777   2857 my ($gen, $val) = @_;
99 777         2167 my $self = $gen->generate_self;
100 777         4307 "$self\->$write_method\($val)"
101 76         1281 };
102 76         241 ++$set_checks_isa;
103             }
104             else {
105             $captures->{'$shv_write_method'} = \(
106             $attr->can('set_value')
107 30     30   253285 ? sub { $attr->set_value(@_) }
108 0     0   0 : sub { my ($instance, $value) = @_; $instance->meta->get_attribute($attrname)->set_value($instance, $value) }
  0         0  
109 28 50       549 );
110             $set = sub {
111 13     13   68 my ($gen, $val) = @_;
112 13         54 my $self = $gen->generate_self;
113 13         82 $self.'->$shv_write_method('.$val.')';
114 28         134 };
115 28         61 ++$set_checks_isa;
116             }
117              
118 104         249 my $default;
119 104 100       489 if (exists $spec->{default}) {
    100          
120 81         328 $default = [ default => $spec->{default} ];
121             }
122             elsif (exists $spec->{builder}) {
123 9         32 $default = [ builder => $spec->{builder} ];
124             }
125              
126 104 100       480 if (ref $default->[1] eq 'CODE') {
127 37         134 $captures->{'$shv_default_for_reset'} = \$default->[1];
128             }
129              
130 104         13235 require Sub::HandlesVia::CodeGenerator;
131             return 'Sub::HandlesVia::CodeGenerator'->new(
132             toolkit => $me,
133             target => $target,
134             attribute => $attrname,
135             attribute_spec => $spec,
136             env => $captures,
137             isa => Types::TypeTiny::to_TypeTiny($attr->type_constraint),
138             coerce => !!$spec->{coerce},
139             generator_for_slot => $slot,
140             generator_for_get => $get,
141             generator_for_set => $set,
142             get_is_lvalue => $get_is_lvalue,
143             set_checks_isa => $set_checks_isa,
144             set_strictly => !!1,
145 1295     1295   5223 method_installer => sub { $meta->add_method(@_) },
146             generator_for_default => sub {
147 15 50   15   75 my ( $gen, $handler ) = @_ or die;
148 15 50 33     233 if ( !$default and $handler ) {
    100 33        
    50 33        
    50 33        
    50          
149 0         0 return $handler->default_for_reset->();
150             }
151             elsif ( $default->[0] eq 'builder' ) {
152 4         15 return sprintf(
153             '(%s)->%s',
154             $gen->generate_self,
155             $default->[1],
156             );
157             }
158             elsif ( $default->[0] eq 'default' and ref $default->[1] eq 'CODE' ) {
159 0         0 return sprintf(
160             '(%s)->$shv_default_for_reset',
161             $gen->generate_self,
162             );
163             }
164             elsif ( $default->[0] eq 'default' and !defined $default->[1] ) {
165 0         0 return 'undef';
166             }
167             elsif ( $default->[0] eq 'default' and !ref $default->[1] ) {
168 11         69 require B;
169 11         92 return B::perlstring( $default->[1] );
170             }
171 0         0 return;
172             },
173 104         4618 );
174             }
175              
176             package Sub::HandlesVia::Toolkit::Moose::PackageTrait;
177              
178             our $AUTHORITY = 'cpan:TOBYINK';
179             our $VERSION = '0.050000';
180              
181 22     22   36012 use Moose::Role;
  22         92425  
  22         161  
182              
183             sub _shv_toolkit {
184 213     213   1457 'Sub::HandlesVia::Toolkit::Moose',
185             }
186              
187             around add_attribute => sub {
188             my ($next, $self, @args) = (shift, shift, @_);
189             my ($spec, $attrobj, $attrname);
190             if (@args == 1) {
191             $spec = $attrobj = $_[0];
192             $attrname = $attrobj->name;
193             }
194             elsif (@args == 2) {
195             ($attrname, $spec) = @args;
196             }
197             else {
198             my %spec;
199             ($attrname, %spec) = @args;
200             $spec = \%spec;
201             }
202             ( my $real_attrname = $attrname ) =~ s/^[+]//;
203             $spec->{definition_context}{shv} = $self->_shv_toolkit->clean_spec($self->name, $real_attrname, $spec)
204             unless $spec->{definition_context}{shv};
205             my $attr = $self->$next($attrobj ? $attrobj : ($attrname, %$spec));
206             if ($spec->{definition_context}{shv} and $self->isa('Moose::Meta::Class')) {
207             $self->_shv_toolkit->install_delegations(+{
208             %{ $spec->{definition_context}{shv} },
209             target => $self->name,
210             });
211             }
212             return $attr;
213             };
214              
215             package Sub::HandlesVia::Toolkit::Moose::RoleTrait;
216              
217             our $AUTHORITY = 'cpan:TOBYINK';
218             our $VERSION = '0.050000';
219              
220 22     22   140877 use Moose::Role;
  22         67  
  22         402  
221             requires '_shv_toolkit';
222              
223             around apply => sub {
224             my ($next, $self, $other, %args) = (shift, shift, @_);
225             $other = $self->_shv_toolkit->meta_hack( $other );
226             $self->$next( $other, %args );
227             };
228              
229             around composition_class_roles => sub {
230             my ( $next, $self ) = ( shift, shift );
231             my @return = $self->$next( @_ );
232             return (
233             @return,
234             $self->_shv_toolkit->package_trait,
235             $self->_shv_toolkit->role_trait,
236             );
237             };
238              
239             1;