File Coverage

blib/lib/MooseX/Enumeration/Meta/Method/Accessor/Native/Enumeration/assign.pm
Criterion Covered Total %
statement 32 35 91.4
branch 2 4 50.0
condition n/a
subroutine 8 8 100.0
pod n/a
total 42 47 89.3


line stmt bran cond sub pod time code
1 3     3   1689 use 5.008001;
  3         11  
2 3     3   17 use strict;
  3         6  
  3         62  
3 3     3   13 use warnings;
  3         6  
  3         190  
4              
5             package MooseX::Enumeration::Meta::Method::Accessor::Native::Enumeration::assign;
6             our $AUTHORITY = 'cpan:TOBYINK';
7             our $VERSION = '0.010';
8              
9 3     3   17 use Moose::Role;
  3         6  
  3         22  
10             with 'Moose::Meta::Method::Accessor::Native::Writer';
11              
12             around _minimum_arguments => sub { 1 };
13             around _maximum_arguments => sub { 2 };
14              
15             sub _potential_value
16             {
17 3     3   377 my $self = shift;
18 3         12 my $type = $self->associated_attribute->type_constraint;
19            
20 3 50       114 if ($self->associated_attribute->should_coerce)
21             {
22 0         0 my $type = $self->associated_attribute->type_constraint;
23 0         0 $self->_eval_environment->{'$type'} = $type;
24 0         0 return '$type->coerce($_[0])';
25             }
26            
27 3         138 '$_[0]';
28             }
29              
30             around _inline_return_value => sub
31             {
32             # Technically speaking, we can't rely on the invocant
33             # being called '$self'
34             '$self';
35             };
36              
37             around _inline_process_arguments => sub
38             {
39             my $next = shift;
40             my $self = shift;
41             my ($inv, $slot_access) = @_;
42            
43             my $orig = $self->$next(@_);
44             $orig = "" unless defined $orig;
45            
46             $self->_inline_check_allowed_transition($slot_access, 1) . $orig;
47             };
48              
49             sub _inline_force_build {
50 6     6   27 my $self = shift;
51 6         17 my ($inv, $slot_access) = @_;
52            
53 6         19 my $method = $self->associated_attribute->get_read_method;
54            
55 6 50       111 sprintf(
56             'if (!exists %s) { %s }',
57             $slot_access,
58             $method
59             ? "${inv}->${method}"
60             : sprintf("%s = Moose::Util::find_meta(%s)->find_attribute_by_name(%s)->get_value(%s)", $slot_access, $inv, B::perlstring($self->associate_attribute->name, $inv))
61             );
62             }
63              
64             sub _inline_check_allowed_transition
65             {
66 6     6   29 require B;
67 6         1304 require match::simple;
68            
69 6         14755 my $self = shift;
70 6         17 my ($slot_access, $allow) = @_;
71            
72 6         19 my $die = $self->_inline_allowed_transition_exception($slot_access);
73 6         24 my $force_build = $self->_inline_force_build('$self', $slot_access);
74 6         51 return "$force_build; \$#_ < $allow or match::simple::match($slot_access, \$_[$allow]) or $die;";
75             }
76              
77             sub _inline_allowed_transition_exception
78             {
79 9     9   17 my $self = shift;
80 9         22 my ($slot_access) = @_;
81            
82 9         63 my $name = B::perlstring($self->name);
83 9         28 my $attr = B::perlstring($self->associated_attribute->name);
84 9         50 my $tmpl = '"Method %s cannot be called when attribute %s has value %s, stopped"';
85            
86 9         43 return "Carp::confess(sprintf($tmpl, $name, $attr, $slot_access))";
87             }
88              
89             around _generate_method => sub
90             {
91             my $next = shift;
92             my $self = shift;
93             ### $self->$next(@_); # can't remember why we do this???
94            
95             my $inv = '$self';
96             my @curried = @{ $self->curried_arguments };
97             my $type = $self->associated_attribute->type_constraint;
98             my $coerce = $self->associated_attribute->should_coerce;
99            
100             # Optimized accessor for one curried argument
101             if ( @curried==1
102             and !$coerce
103             and not $self->associated_attribute->is_lazy
104             and $self->_maximum_arguments==2
105             and $self->_minimum_arguments==1 )
106             {
107             $type->assert_valid($curried[0]);
108            
109             my $slot_access = $self->_get_value($inv);
110            
111             require B;
112             require Moose::Util;
113             return sprintf(
114             'sub { my %s = shift; %s if @_ > 1; %s; %s; %s }',
115             $inv,
116             "Moose::Util::throw_exception('MethodExpectsFewerArgs', 'method_name', 'assign', 'maximum_args', 2)",
117             $self->_inline_check_allowed_transition($slot_access, 0),
118             $self->_inline_set_new_value($inv, B::perlstring($curried[0]), $slot_access),
119             $self->_inline_return_value($slot_access, 'for writer'),
120             );
121             }
122            
123             # Optimized accessor for two curried arguments
124             if ( @curried==2
125             and !$coerce
126             and not $self->associated_attribute->is_lazy
127             and $self->_maximum_arguments==2
128             and $self->_minimum_arguments==1 )
129             {
130             $type->assert_valid($curried[0]);
131            
132             my $slot_access = $self->_get_value($inv);
133            
134             if ($type->check($curried[1]))
135             {
136             return sprintf(
137             'sub { my %s = shift; %s if @_; return %s if %s eq %s; %s eq %s or %s; %s; %s }',
138             $inv,
139             "Moose::Util::throw_exception('MethodExpectsFewerArgs', 'method_name', 'assign', 'maximum_args', 2)",
140             $inv,
141             $slot_access,
142             B::perlstring($curried[0]),
143             $slot_access,
144             B::perlstring($curried[1]),
145             $self->_inline_allowed_transition_exception($slot_access),
146             $self->_inline_set_new_value($inv, B::perlstring($curried[0]), $slot_access),
147             $self->_inline_return_value($slot_access, 'for writer'),
148             );
149             }
150            
151             else
152             {
153             require match::simple;
154            
155             return sprintf(
156             'sub { my %s = shift; %s if @_; return %s if %s eq %s; match::simple::match(%s, $curried[1]) or %s; %s; %s }',
157             $inv,
158             "Moose::Util::throw_exception('MethodExpectsFewerArgs', 'method_name', 'assign', 'maximum_args', 2)",
159             $inv,
160             $slot_access,
161             B::perlstring($curried[0]),
162             $slot_access,
163             $self->_inline_allowed_transition_exception($slot_access),
164             $self->_inline_set_new_value($inv, B::perlstring($curried[0]), $slot_access),
165             $self->_inline_return_value($slot_access, 'for writer'),
166             );
167             }
168             }
169              
170             # Otherwise we should trust the default implementation
171             # from Moose::Meta::Method::Accessor::Native::Reader.
172             $self->$next(@_);
173             };
174              
175             1;