File Coverage

blib/lib/Method/Generate/Accessor.pm
Criterion Covered Total %
statement 306 306 100.0
branch 194 194 100.0
condition 90 104 86.5
subroutine 52 52 100.0
pod 0 16 0.0
total 642 672 95.5


line stmt bran cond sub pod time code
1             package Method::Generate::Accessor;
2 188     188   149056 use strict;
  188         446  
  188         5759  
3 188     188   1036 use warnings;
  188         413  
  188         5764  
4              
5 188     188   1953 use Moo::_Utils qw(_maybe_load_module _install_coderef _module_name_rx);
  188         402  
  188         9531  
6 188     188   10906 use Moo::Object ();
  188         471  
  188         6529  
7 188     188   9209 BEGIN { our @ISA = qw(Moo::Object) }
8 188     188   14171 use Sub::Quote qw(quote_sub quoted_from_sub quotify sanitize_identifier);
  188         191325  
  188         11841  
9 188     188   1350 use Scalar::Util 'blessed';
  188         421  
  188         8014  
10 188     188   1247 use Carp qw(croak);
  188         447  
  188         11420  
11             BEGIN {
12 188     188   30580 our @CARP_NOT = qw(
13             Moo::_Utils
14             Moo::Object
15             Moo::Role
16             );
17             }
18             BEGIN {
19             *_CAN_WEAKEN_READONLY = (
20             "$]" < 5.008_003 or $ENV{MOO_TEST_PRE_583}
21 188 100 66 188   2957 ) ? sub(){0} : sub(){1};
22             our $CAN_HAZ_XS =
23             !$ENV{MOO_XS_DISABLE}
24             &&
25             _maybe_load_module('Class::XSAccessor')
26             &&
27 188   66     1561 (eval { Class::XSAccessor->VERSION('1.07') })
28             ;
29             our $CAN_HAZ_XS_PRED =
30             $CAN_HAZ_XS &&
31 188   66     4868 (eval { Class::XSAccessor->VERSION('1.17') })
32             ;
33             }
34             BEGIN {
35             package
36             Method::Generate::Accessor::_Generated;
37 188     188   928342 $Carp::Internal{+__PACKAGE__} = 1;
38             }
39              
40             sub _die_overwrite {
41 18     18   41 my ($pkg, $method, $type) = @_;
42 18   50     3792 croak "You cannot overwrite a locally defined method ($method) with "
43             . ( $type || 'an accessor' );
44             }
45              
46             sub generate_method {
47 696     696 0 28871 my ($self, $into, $name, $spec, $quote_opts) = @_;
48             $quote_opts = {
49             no_defer => 1,
50             package => 'Method::Generate::Accessor::_Generated',
51 696 100       1232 %{ $quote_opts||{} },
  696         4350  
52             };
53              
54 696 100       2644 $spec->{allow_overwrite}++
55             if $name =~ s/^\+//;
56              
57 696         1515 my $is = $spec->{is};
58 696 100       2928 if (!$is) {
    100          
    100          
    100          
    100          
    100          
59 6         1194 croak "Must have an is";
60             }
61             elsif ($is eq 'ro') {
62 460 100       1501 $spec->{reader} = $name unless exists $spec->{reader};
63             }
64             elsif ($is eq 'rw') {
65             $spec->{accessor} = $name unless exists $spec->{accessor}
66 184 100 100     969 or ( $spec->{reader} and $spec->{writer} );
      100        
67             }
68             elsif ($is eq 'lazy') {
69 28 100       107 $spec->{reader} = $name unless exists $spec->{reader};
70 28         60 $spec->{lazy} = 1;
71 28 100 66     128 $spec->{builder} ||= '_build_'.$name unless exists $spec->{default};
72             }
73             elsif ($is eq 'rwp') {
74 12 100       51 $spec->{reader} = $name unless exists $spec->{reader};
75 12 100       61 $spec->{writer} = "_set_${name}" unless exists $spec->{writer};
76             }
77             elsif ($is ne 'bare') {
78 2         200 croak "Unknown is ${is}";
79             }
80              
81 688 100       1701 if (exists $spec->{builder}) {
82 46 100       126 if(ref $spec->{builder}) {
83             $self->_validate_codulatable('builder', $spec->{builder},
84 10         54 "$into->$name", 'or a method name');
85 10         23 $spec->{builder_sub} = $spec->{builder};
86 10         21 $spec->{builder} = 1;
87             }
88 46 100 50     189 $spec->{builder} = '_build_'.$name if ($spec->{builder}||0) eq 1;
89             croak "Invalid builder for $into->$name - not a valid method name"
90 46 100       659 if $spec->{builder} !~ _module_name_rx;
91             }
92              
93 686 100 100     3243 if (($spec->{predicate}||0) eq 1) {
94 8 100       49 $spec->{predicate} = $name =~ /^_/ ? "_has${name}" : "has_${name}";
95             }
96              
97 686 100 100     2803 if (($spec->{clearer}||0) eq 1) {
98 4 100       14 $spec->{clearer} = $name =~ /^_/ ? "_clear${name}" : "clear_${name}";
99             }
100              
101 686 100 100     2845 if (($spec->{trigger}||0) eq 1) {
102 2         12 $spec->{trigger} = quote_sub('shift->_trigger_'.$name.'(@_)');
103             }
104              
105 686 100 100     3009 if (($spec->{coerce}||0) eq 1) {
106 10         18 my $isa = $spec->{isa};
107 10 100 100     120 if (blessed $isa and $isa->can('coercion')) {
    100 100        
108 4         112 $spec->{coerce} = $isa->coercion;
109             }
110             elsif (blessed $isa and $isa->can('coerce')) {
111 2     2   10 $spec->{coerce} = sub { $isa->coerce(@_) };
  2         298  
112             }
113             else {
114 4         888 croak "Invalid coercion for $into->$name - no appropriate type constraint";
115             }
116             }
117              
118 682         1623 foreach my $setting (qw( isa coerce )) {
119             next
120 1364 100       3761 if !exists $spec->{$setting};
121 182         823 $self->_validate_codulatable($setting, $spec->{$setting}, "$into->$name");
122             }
123              
124 672 100       1754 if (exists $spec->{default}) {
125 188 100       750 if (ref $spec->{default}) {
126 152         596 $self->_validate_codulatable('default', $spec->{default}, "$into->$name",
127             'or a non-ref');
128             }
129             }
130              
131 664 100       2485 if (exists $spec->{moosify}) {
132 8 100       24 if (ref $spec->{moosify} ne 'ARRAY') {
133 2         7 $spec->{moosify} = [$spec->{moosify}];
134             }
135              
136 8         14 foreach my $spec (@{$spec->{moosify}}) {
  8         19  
137 12         51 $self->_validate_codulatable('moosify', $spec, "$into->$name");
138             }
139             }
140              
141 664         1126 my %methods;
142 664 100       1807 if (my $reader = $spec->{reader}) {
143             _die_overwrite($into, $reader, 'a reader')
144 488 100 100     1543 if !$spec->{allow_overwrite} && defined &{"${into}::${reader}"};
  452         3603  
145 482 100 100     2105 if (our $CAN_HAZ_XS && $self->is_simple_get($name, $spec)) {
146 218         663 $methods{$reader} = $self->_generate_xs(
147             getters => $into, $reader, $name, $spec
148             );
149             }
150             else {
151 264         703 $self->{captures} = {};
152             $methods{$reader} =
153             quote_sub "${into}::${reader}"
154             => ' Carp::croak("'.$reader.' is a read-only accessor") if @_ > 1;'."\n"
155             .$self->_generate_get($name, $spec)
156             => delete $self->{captures}
157 264         1270 => $quote_opts
158             ;
159             }
160             }
161              
162 658 100       152183 if (my $accessor = $spec->{accessor}) {
163             _die_overwrite($into, $accessor, 'an accessor')
164 186 100 100     549 if !$spec->{allow_overwrite} && defined &{"${into}::${accessor}"};
  176         1236  
165 184 100 100     813 if (
      100        
166             our $CAN_HAZ_XS
167             && $self->is_simple_get($name, $spec)
168             && $self->is_simple_set($name, $spec)
169             ) {
170 31         84 $methods{$accessor} = $self->_generate_xs(
171             accessors => $into, $accessor, $name, $spec
172             );
173             }
174             else {
175 153         391 $self->{captures} = {};
176             $methods{$accessor} =
177             quote_sub "${into}::${accessor}"
178             => $self->_generate_getset($name, $spec)
179             => delete $self->{captures}
180 153         504 => $quote_opts
181             ;
182             }
183             }
184              
185 656 100       104193 if (my $writer = $spec->{writer}) {
186             _die_overwrite($into, $writer, 'a writer')
187 22 100 66     110 if !$spec->{allow_overwrite} && defined &{"${into}::${writer}"};
  22         201  
188 20 100 100     119 if (
189             our $CAN_HAZ_XS
190             && $self->is_simple_set($name, $spec)
191             ) {
192 5         18 $methods{$writer} = $self->_generate_xs(
193             setters => $into, $writer, $name, $spec
194             );
195             }
196             else {
197 15         49 $self->{captures} = {};
198             $methods{$writer} =
199             quote_sub "${into}::${writer}"
200             => $self->_generate_set($name, $spec)
201             => delete $self->{captures}
202 15         62 => $quote_opts
203             ;
204             }
205             }
206 654 100       10362 if (my $pred = $spec->{predicate}) {
207             _die_overwrite($into, $pred, 'a predicate')
208 14 100 66     53 if !$spec->{allow_overwrite} && defined &{"${into}::${pred}"};
  14         110  
209 12 100 66     50 if (our $CAN_HAZ_XS && our $CAN_HAZ_XS_PRED) {
210 6         20 $methods{$pred} = $self->_generate_xs(
211             exists_predicates => $into, $pred, $name, $spec
212             );
213             }
214             else {
215 6         17 $self->{captures} = {};
216             $methods{$pred} =
217             quote_sub "${into}::${pred}"
218             => $self->_generate_simple_has('$_[0]', $name, $spec)."\n"
219             => delete $self->{captures}
220 6         21 => $quote_opts
221             ;
222             }
223             }
224              
225 652 100       4800 if (my $builder = delete $spec->{builder_sub}) {
226 10         53 _install_coderef( "${into}::$spec->{builder}" => $builder );
227             }
228              
229 652 100       1538 if (my $cl = $spec->{clearer}) {
230             _die_overwrite($into, $cl, 'a clearer')
231 16 100 66     56 if !$spec->{allow_overwrite} && defined &{"${into}::${cl}"};
  16         128  
232 14         36 $self->{captures} = {};
233             $methods{$cl} =
234             quote_sub "${into}::${cl}"
235             => $self->_generate_simple_clear('$_[0]', $name, $spec)."\n"
236             => delete $self->{captures}
237 14         59 => $quote_opts
238             ;
239             }
240              
241 650 100       8979 if (my $hspec = $spec->{handles}) {
242 42   66     222 my $asserter = $spec->{asserter} ||= '_assert_'.$name;
243             my @specs =
244             ref $hspec eq 'ARRAY' ? (
245             map [ $_ => $_ ], @$hspec
246             )
247             : ref $hspec eq 'HASH' ? (
248 2         10 map [ $_ => ref($hspec->{$_}) ? @{$hspec->{$_}} : $hspec->{$_} ],
249             keys %$hspec
250             )
251 42 100       690 : !ref $hspec ? do {
    100          
    100          
    100          
252 14         1066 require Moo::Role;
253 14         83 map [ $_ => $_ ], Moo::Role->methods_provided_by($hspec)
254             }
255             : croak "You gave me a handles of ${hspec} and I have no idea why";
256              
257 36         431 foreach my $delegation_spec (@specs) {
258 38         1120 my ($proxy, $target, @args) = @$delegation_spec;
259             _die_overwrite($into, $proxy, 'a delegation')
260 38 100 100     121 if !$spec->{allow_overwrite} && defined &{"${into}::${proxy}"};
  34         233  
261 36         116 $self->{captures} = {};
262             $methods{$proxy} =
263             quote_sub "${into}::${proxy}"
264             => $self->_generate_delegation($asserter, $target, \@args)
265             => delete $self->{captures}
266 36         160 => $quote_opts
267             ;
268             }
269             }
270              
271 642 100       18992 if (my $asserter = $spec->{asserter}) {
272             _die_overwrite($into, $asserter, 'an asserter')
273 44 100 100     168 if !$spec->{allow_overwrite} && defined &{"${into}::${asserter}"};
  36         277  
274 42         127 local $self->{captures} = {};
275             $methods{$asserter} =
276             quote_sub "${into}::${asserter}"
277             => $self->_generate_asserter($name, $spec)
278             => delete $self->{captures}
279 42         163 => $quote_opts
280             ;
281             }
282              
283 640         25898 \%methods;
284             }
285              
286             sub merge_specs {
287 26     26 0 76 my ($self, @specs) = @_;
288 26         64 my $spec = shift @specs;
289 26         60 for my $old_spec (@specs) {
290 26         94 foreach my $key (keys %$old_spec) {
291 122 100 100     556 if ($key eq 'handles') {
    100          
    100          
    100          
292             }
293             elsif ($key eq 'moosify') {
294             $spec->{$key} = [
295 4 100       18 map { ref $_ eq 'ARRAY' ? @$_ : $_ }
296             grep defined,
297 2         10 ($old_spec->{$key}, $spec->{$key})
298             ];
299             }
300             elsif ($key eq 'builder' || $key eq 'default') {
301             $spec->{$key} = $old_spec->{$key}
302 24 100 100     134 if !(exists $spec->{builder} || exists $spec->{default});
303             }
304             elsif (!exists $spec->{$key}) {
305 74         182 $spec->{$key} = $old_spec->{$key};
306             }
307             }
308             }
309 26         73 $spec;
310             }
311              
312             sub is_simple_attribute {
313 4     4 0 789 my ($self, $name, $spec) = @_;
314             # clearer doesn't have to be listed because it doesn't
315             # affect whether defined/exists makes a difference
316 4         36 !grep $spec->{$_},
317             qw(lazy default builder coerce isa trigger predicate weak_ref);
318             }
319              
320             sub is_simple_get {
321 792     792 0 1740 my ($self, $name, $spec) = @_;
322 792   100     3832 !($spec->{lazy} and (exists $spec->{default} or $spec->{builder}));
323             }
324              
325             sub is_simple_set {
326 259     259 0 497 my ($self, $name, $spec) = @_;
327 259         1455 !grep $spec->{$_}, qw(coerce isa trigger weak_ref);
328             }
329              
330             sub has_default {
331 56     56 0 325 my ($self, $name, $spec) = @_;
332 56 100 50     796 $spec->{builder} or exists $spec->{default} or (($spec->{is}||'') eq 'lazy');
      100        
333             }
334              
335             sub has_eager_default {
336 1596     1596 0 2770 my ($self, $name, $spec) = @_;
337 1596 100 66     7189 (!$spec->{lazy} and (exists $spec->{default} or $spec->{builder}));
338             }
339              
340             sub _generate_get {
341 459     459   1077 my ($self, $name, $spec) = @_;
342 459         1261 my $simple = $self->_generate_simple_get('$_[0]', $name, $spec);
343 459 100       1311 if ($self->is_simple_get($name, $spec)) {
344 389         2029 $simple;
345             } else {
346 70         250 $self->_generate_use_default(
347             '$_[0]', $name, $spec,
348             $self->_generate_simple_has('$_[0]', $name, $spec),
349             );
350             }
351             }
352              
353             sub generate_simple_has {
354 14     14 0 26 my $self = shift;
355 14         51 $self->{captures} = {};
356 14         54 my $code = $self->_generate_simple_has(@_);
357 14         195 ($code, delete $self->{captures});
358             }
359              
360             sub _generate_simple_has {
361 132     132   294 my ($self, $me, $name) = @_;
362 132         317 "exists ${me}->{${\quotify $name}}";
  132         357  
363             }
364              
365             sub _generate_simple_clear {
366 14     14   36 my ($self, $me, $name) = @_;
367 14         31 " delete ${me}->{${\quotify $name}}\n"
  14         52  
368             }
369              
370             sub generate_get_default {
371 2     2 0 5 my $self = shift;
372 2         8 $self->{captures} = {};
373 2         9 my $code = $self->_generate_get_default(@_);
374 2         43 ($code, delete $self->{captures});
375             }
376              
377             sub generate_use_default {
378 14     14 0 25 my $self = shift;
379 14         26 $self->{captures} = {};
380 14         45 my $code = $self->_generate_use_default(@_);
381 14         50 ($code, delete $self->{captures});
382             }
383              
384             sub _generate_use_default {
385 84     84   825 my ($self, $me, $name, $spec, $test) = @_;
386 84         233 my $get_value = $self->_generate_get_default($me, $name, $spec);
387 84 100       677 if ($spec->{coerce}) {
388             $get_value = $self->_generate_coerce(
389             $name, $get_value,
390             $spec->{coerce}
391             )
392 6         17 }
393             $test." ? \n"
394             .$self->_generate_simple_get($me, $name, $spec)."\n:"
395             .($spec->{isa} ?
396             " do {\n my \$value = ".$get_value.";\n"
397 84 100       373 ." ".$self->_generate_isa_check($name, '$value', $spec->{isa}).";\n"
398             ." ".$self->_generate_simple_set($me, $name, $spec, '$value')."\n"
399             ." }\n"
400             : ' ('.$self->_generate_simple_set($me, $name, $spec, $get_value).")\n"
401             );
402             }
403              
404             sub _generate_get_default {
405 210     210   458 my ($self, $me, $name, $spec) = @_;
406 210 100       571 if (exists $spec->{default}) {
407             ref $spec->{default}
408             ? $self->_generate_call_code($name, 'default', $me, $spec->{default})
409 172 100       653 : quotify $spec->{default};
410             }
411             else {
412 38         91 "${me}->${\$spec->{builder}}"
  38         129  
413             }
414             }
415              
416             sub generate_simple_get {
417 2     2 0 2760 my ($self, @args) = @_;
418 2         8 $self->{captures} = {};
419 2         8 my $code = $self->_generate_simple_get(@args);
420 2         19 ($code, delete $self->{captures});
421             }
422              
423             sub _generate_simple_get {
424 676     676   1707 my ($self, $me, $name) = @_;
425 676         1662 my $name_str = quotify $name;
426 676         6914 "${me}->{${name_str}}";
427             }
428              
429             sub _generate_set {
430 168     168   326 my ($self, $name, $spec) = @_;
431 168         376 my ($me, $source) = ('$_[0]', '$_[1]');
432 168 100       411 if ($self->is_simple_set($name, $spec)) {
433 42         148 return $self->_generate_simple_set($me, $name, $spec, $source);
434             }
435              
436 126         256 my ($coerce, $trigger, $isa_check) = @{$spec}{qw(coerce trigger isa)};
  126         327  
437 126 100       300 if ($coerce) {
438 46         111 $source = $self->_generate_coerce($name, $source, $coerce);
439             }
440 126 100       1329 if ($isa_check) {
    100          
441 48 100       176 'scalar do { my $value = '.$source.";\n"
442             .' ('.$self->_generate_isa_check($name, '$value', $isa_check)."),\n"
443             .' ('.$self->_generate_simple_set($me, $name, $spec, '$value')."),\n"
444             .($trigger
445             ? '('.$self->_generate_trigger($name, $me, '$value', $trigger)."),\n"
446             : '')
447             .' ('.$self->_generate_simple_get($me, $name, $spec)."),\n"
448             ."}";
449             }
450             elsif ($trigger) {
451 20         53 my $set = $self->_generate_simple_set($me, $name, $spec, $source);
452 20         67 "scalar (\n"
453             . ' ('.$self->_generate_trigger($name, $me, "($set)", $trigger)."),\n"
454             . ' ('.$self->_generate_simple_get($me, $name, $spec)."),\n"
455             . ")";
456             }
457             else {
458 58         139 '('.$self->_generate_simple_set($me, $name, $spec, $source).')';
459             }
460             }
461              
462             sub generate_coerce {
463 2     2 0 2607 my $self = shift;
464 2         7 $self->{captures} = {};
465 2         9 my $code = $self->_generate_coerce(@_);
466 2         96 ($code, delete $self->{captures});
467             }
468              
469             sub _attr_desc {
470 268     268   575 my ($name, $init_arg) = @_;
471 268 100 100     1449 return quotify($name) if !defined($init_arg) or $init_arg eq $name;
472 10         27 return quotify($name).' (constructor argument: '.quotify($init_arg).')';
473             }
474              
475             sub _generate_coerce {
476 122     122   310 my ($self, $name, $value, $coerce, $init_arg) = @_;
477 122         401 $self->_wrap_attr_exception(
478             $name,
479             "coercion",
480             $init_arg,
481             $self->_generate_call_code($name, 'coerce', "${value}", $coerce),
482             1,
483             );
484             }
485              
486             sub generate_trigger {
487 2     2 0 3136 my $self = shift;
488 2         7 $self->{captures} = {};
489 2         10 my $code = $self->_generate_trigger(@_);
490 2         48 ($code, delete $self->{captures});
491             }
492              
493             sub _generate_trigger {
494 62     62   128 my ($self, $name, $obj, $value, $trigger) = @_;
495 62         174 $self->_generate_call_code($name, 'trigger', "${obj}, ${value}", $trigger);
496             }
497              
498             sub generate_isa_check {
499 2     2 0 2785 my ($self, @args) = @_;
500 2         5 $self->{captures} = {};
501 2         8 my $code = $self->_generate_isa_check(@args);
502 2         48 ($code, delete $self->{captures});
503             }
504              
505             sub _wrap_attr_exception {
506 268     268   3264 my ($self, $name, $step, $arg, $code, $want_return) = @_;
507 268         691 my $prefix = quotify("${step} for "._attr_desc($name, $arg).' failed: ');
508 268 100       4340 "do {\n"
    100          
    100          
509             .' local $Method::Generate::Accessor::CurrentAttribute = {'."\n"
510             .' init_arg => '.quotify($arg).",\n"
511             .' name => '.quotify($name).",\n"
512             .' step => '.quotify($step).",\n"
513             ." };\n"
514             .($want_return ? ' (my $_return),'."\n" : '')
515             .' (my $_error), (my $_old_error = $@);'."\n"
516             ." (eval {\n"
517             .' ($@ = $_old_error),'."\n"
518             .' ('
519             .($want_return ? '$_return ='."\n" : '')
520             .$code."),\n"
521             ." 1\n"
522             ." } or\n"
523             .' $_error = CORE::ref $@ ? $@ : '.$prefix.'.$@);'."\n"
524             .' ($@ = $_old_error),'."\n"
525             .' (defined $_error and CORE::die $_error);'."\n"
526             .($want_return ? ' $_return;'."\n" : '')
527             ."}\n"
528             }
529              
530             sub _generate_isa_check {
531 146     146   417 my ($self, $name, $value, $check, $init_arg) = @_;
532 146         425 $self->_wrap_attr_exception(
533             $name,
534             "isa check",
535             $init_arg,
536             $self->_generate_call_code($name, 'isa_check', $value, $check)
537             );
538             }
539              
540             sub _generate_call_code {
541 458     458   941 my ($self, $name, $type, $values, $sub) = @_;
542 458 100       1404 $sub = \&{$sub} if blessed($sub); # coderef if blessed
  22         87  
543 458 100       3326 if (my $quoted = quoted_from_sub($sub)) {
544 104         5412 my $local = 1;
545 104 100 66     548 if ($values eq '@_' || $values eq '$_[0]') {
546 4         14 $local = 0;
547 4         7 $values = '@_';
548             }
549 104         219 my $code = $quoted->[1];
550 104 100       273 if (my $captures = $quoted->[2]) {
551 38         127 my $cap_name = qq{\$${type}_captures_for_}.sanitize_identifier($name);
552 38         474 $self->{captures}->{$cap_name} = \$captures;
553 38         123 Sub::Quote::inlinify($code, $values,
554             Sub::Quote::capture_unroll($cap_name, $captures, 6), $local);
555             } else {
556 66         237 Sub::Quote::inlinify($code, $values, undef, $local);
557             }
558             } else {
559 354         3277 my $cap_name = qq{\$${type}_for_}.sanitize_identifier($name);
560 354         4257 $self->{captures}->{$cap_name} = \$sub;
561 354         1394 "${cap_name}->(${values})";
562             }
563             }
564              
565 2     2   9979 sub _sanitize_name { sanitize_identifier($_[1]) }
566              
567             sub generate_populate_set {
568 1560     1560 0 5428 my $self = shift;
569 1560         3015 $self->{captures} = {};
570 1560         3509 my $code = $self->_generate_populate_set(@_);
571 1560         5646 ($code, delete $self->{captures});
572             }
573              
574             sub _generate_populate_set {
575 1560     1560   3639 my ($self, $me, $name, $spec, $source, $test, $init_arg) = @_;
576              
577 1560         3496 my $has_default = $self->has_eager_default($name, $spec);
578 1560 100 100     5752 if (!($has_default || $test)) {
579 2         8 return '';
580             }
581 1558 100       3549 if ($has_default) {
582 124         351 my $get_default = $self->_generate_get_default($me, $name, $spec);
583 124 100       892 $source =
584             $test
585             ? "(\n ${test}\n"
586             ." ? ${source}\n : "
587             .$get_default
588             .")"
589             : $get_default;
590             }
591 1558 100       3341 if ($spec->{coerce}) {
592             $source = $self->_generate_coerce(
593             $name, $source,
594 68         247 $spec->{coerce}, $init_arg
595             )
596             }
597 1558 100       4576 if ($spec->{isa}) {
598             $source = 'scalar do { my $value = '.$source.";\n"
599             .' ('.$self->_generate_isa_check(
600 84         348 $name, '$value', $spec->{isa}, $init_arg
601             )."),\n"
602             ." \$value\n"
603             ."}\n";
604             }
605 1558         5746 my $set = $self->_generate_simple_set($me, $name, $spec, $source);
606             my $trigger = $spec->{trigger} ? $self->_generate_trigger(
607             $name, $me, $self->_generate_simple_get($me, $name, $spec),
608             $spec->{trigger}
609 1558 100       3437 ) : undef;
610 1558 100       3110 if ($has_default) {
611 124 100 100     835 "($set)," . ($trigger && $test ? "($test and $trigger)," : '') . "\n";
612             }
613             else {
614 1434 100       6565 "($test and ($set)" . ($trigger ? ", ($trigger)" : '') . "),\n";
615             }
616             }
617              
618             sub _generate_core_set {
619 1772     1772   3600 my ($self, $me, $name, $spec, $value) = @_;
620 1772         4656 my $name_str = quotify $name;
621 1772         14021 "${me}->{${name_str}} = ${value}";
622             }
623              
624             sub _generate_simple_set {
625 1810     1810   5245 my ($self, $me, $name, $spec, $value) = @_;
626 1810         3864 my $name_str = quotify $name;
627 1810         15271 my $simple = $self->_generate_core_set($me, $name, $spec, $value);
628              
629 1810 100       4269 if ($spec->{weak_ref}) {
630 44         220 require Scalar::Util;
631 44         107 my $get = $self->_generate_simple_get($me, $name, $spec);
632              
633             # Perl < 5.8.3 can't weaken refs to readonly vars
634             # (e.g. string constants). This *can* be solved by:
635             #
636             # &Internals::SvREADONLY($foo, 0);
637             # Scalar::Util::weaken($foo);
638             # &Internals::SvREADONLY($foo, 1);
639             #
640             # but requires Internal functions and is just too damn crazy
641             # so simply throw a better exception
642 44         272 my $weak_simple = _CAN_WEAKEN_READONLY
643             ? "do { Scalar::Util::weaken(${simple}); no warnings 'void'; $get }"
644             : <<"EOC"
645             ( eval { Scalar::Util::weaken($simple); 1 }
646             ? do { no warnings 'void'; $get }
647             : do {
648             if( \$@ =~ /Modification of a read-only value attempted/) {
649             require Carp;
650             Carp::croak( sprintf (
651             'Reference to readonly value in "%s" can not be weakened on Perl < 5.8.3',
652             $name_str,
653             ) );
654             } else {
655             die \$@;
656             }
657             }
658             )
659             EOC
660             } else {
661 1766         4518 $simple;
662             }
663             }
664              
665             sub _generate_getset {
666 153     153   397 my ($self, $name, $spec) = @_;
667 153         420 q{(@_ > 1}."\n ? ".$self->_generate_set($name, $spec)
668             ."\n : ".$self->_generate_get($name, $spec)."\n )";
669             }
670              
671             sub _generate_asserter {
672 42     42   106 my ($self, $name, $spec) = @_;
673 42         106 my $name_str = quotify($name);
674 42         455 "do {\n"
675             ." my \$val = ".$self->_generate_get($name, $spec).";\n"
676             ." ".$self->_generate_simple_has('$_[0]', $name, $spec)."\n"
677             ." or Carp::croak(q{Attempted to access '}.${name_str}.q{' but it is not set});\n"
678             ." \$val;\n"
679             ."}\n";
680             }
681             sub _generate_delegation {
682 36     36   101 my ($self, $asserter, $target, $args) = @_;
683 36         50 my $arg_string = do {
684 36 100       86 if (@$args) {
685             # I could, I reckon, linearise out non-refs here using quotify
686             # plus something to check for numbers but I'm unsure if it's worth it
687 2         5 $self->{captures}{'@curries'} = $args;
688 2         4 '@curries, @_';
689             } else {
690 34         65 '@_';
691             }
692             };
693 36         217 "shift->${asserter}->${target}(${arg_string});";
694             }
695              
696             sub _generate_xs {
697 249     249   609 my ($self, $type, $into, $name, $slot) = @_;
698 249         1496 Class::XSAccessor->import(
699             class => $into,
700             $type => { $name => $slot },
701             replace => 1,
702             );
703 249         37091 $into->can($name);
704             }
705              
706 426     426 0 2747 sub default_construction_string { '{}' }
707              
708             sub _validate_codulatable {
709 356     356   1520 my ($self, $setting, $value, $into, $appended) = @_;
710              
711 356         520 my $error;
712              
713 356 100       1518 if (blessed $value) {
    100          
714 34         54 local $@;
715 188     188   1860 no warnings 'void';
  188         570  
  188         35674  
716 34 100       64 eval { \&$value; 1 }
  34         319  
  24         2322  
717             and return 1;
718 10         27 $error = "could not be converted to a coderef: $@";
719             }
720             elsif (ref $value eq 'CODE') {
721 314         806 return 1;
722             }
723             else {
724 8         20 $error = 'is not a coderef or code-convertible object';
725             }
726              
727             croak "Invalid $setting '"
728 18 100       783 . ($INC{'overload.pm'} ? overload::StrVal($value) : $value)
    100          
729             . "' for $into " . $error
730             . ($appended ? " $appended" : '');
731             }
732              
733             1;