X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMethod%2FGenerate%2FAccessor.pm;h=bfecf26c8d30f313ba2be576a33cd36de3d0dec8;hb=5a1cfeaac93cc99bb25f45e7f68b400bad1a6bac;hp=fe268ba6f50017998fdb58cd4bde44a24b82bc63;hpb=0689a5ab016832be48d8e1b724f42a31ac8a0947;p=gitmo%2FMoo.git diff --git a/lib/Method/Generate/Accessor.pm b/lib/Method/Generate/Accessor.pm index fe268ba..bfecf26 100644 --- a/lib/Method/Generate/Accessor.pm +++ b/lib/Method/Generate/Accessor.pm @@ -5,6 +5,8 @@ use Moo::_Utils; use base qw(Moo::Object); use Sub::Quote; use B 'perlstring'; +use Scalar::Util 'blessed'; +use overload (); BEGIN { our $CAN_HAZ_XS = !$ENV{MOO_XS_DISABLE} @@ -34,6 +36,9 @@ sub generate_method { die "Unknown is ${is}"; } $spec->{builder} = '_build_'.$name if ($spec->{builder}||0) eq 1; + die "Invalid builder for $into->$name - not a valid method name" + if exists $spec->{builder} and (ref $spec->{builder} + or $spec->{builder} !~ /\A[A-Za-z_][A-Za-z0-9_]*(?:::[A-Za-z_][A-Za-z0-9_]*)*\z/); if (($spec->{predicate}||0) eq 1) { $spec->{predicate} = $name =~ /^_/ ? "_has${name}" : "has_${name}"; } @@ -43,16 +48,16 @@ sub generate_method { if (($spec->{trigger}||0) eq 1) { $spec->{trigger} = quote_sub('shift->_trigger_'.$name.'(@_)'); } - if (exists $spec->{default}) { - my $default = $spec->{default}; - unless (ref $default) { - die "Invalid default $default"; - } - if (ref $default ne 'CODE') { - unless (eval { \&$default }) { - die "Invalid default $default"; - } - } + + for my $setting (qw( default coerce )) { + next if !exists $spec->{$setting}; + my $value = $spec->{$setting}; + my $invalid = "Invalid $setting '" . overload::StrVal($value) + . "' for $into->$name - not a coderef"; + die "$invalid or code-convertible object" + unless ref $value and (ref $value eq 'CODE' or blessed($value)); + die "$invalid and could not be converted to a coderef: $@" + if !eval { \&$value }; } my %methods; @@ -185,7 +190,12 @@ sub _generate_get { 'do { '.$self->_generate_use_default( '$_[0]', $name, $spec, $self->_generate_simple_has('$_[0]', $name, $spec), - ).'; '.$simple.' }'; + ).'; ' + .($spec->{isa} + ?($self->_generate_isa_check($name, $simple, $spec->{isa}).'; ') + :'' + ) + .$simple.' }'; } } @@ -277,7 +287,10 @@ sub generate_coerce { sub _generate_coerce { my ($self, $name, $value, $coerce) = @_; - $self->_generate_call_code($name, 'coerce', "${value}", $coerce); + $self->_generate_die_prefix( + "coercion for ${\perlstring($name)} failed: ", + $self->_generate_call_code($name, 'coerce', "${value}", $coerce) + ); } sub generate_trigger { @@ -299,24 +312,37 @@ sub generate_isa_check { ($code, delete $self->{captures}); } +sub _generate_die_prefix { + my ($self, $prefix, $inside) = @_; + "do {\n" + .' my $sig_die = $SIG{__DIE__} || sub { die $_[0] };'."\n" + .' local $SIG{__DIE__} = sub {'."\n" + .' $sig_die->(ref($_[0]) ? $_[0] : '.perlstring($prefix).'.$_[0]);'."\n" + .' };'."\n" + .$inside + ."}\n" +} + sub _generate_isa_check { my ($self, $name, $value, $check) = @_; - $self->_generate_call_code($name, 'isa_check', $value, $check); + $self->_generate_die_prefix( + "isa check for ${\perlstring($name)} failed: ", + $self->_generate_call_code($name, 'isa_check', $value, $check) + ); } sub _generate_call_code { my ($self, $name, $type, $values, $sub) = @_; if (my $quoted = quoted_from_sub($sub)) { my $code = $quoted->[1]; - my $at_ = '@_ = ('.$values.');'; if (my $captures = $quoted->[2]) { my $cap_name = qq{\$${type}_captures_for_${name}}; $self->{captures}->{$cap_name} = \$captures; Sub::Quote::inlinify( - $code, $values, Sub::Quote::capture_unroll($cap_name, $captures, 6) + $code, $values, Sub::Quote::capture_unroll($cap_name, $captures, 6), 1 ); } else { - Sub::Quote::inlinify($code, $values); + Sub::Quote::inlinify($code, $values, undef, 1); } } else { my $cap_name = qq{\$${type}_for_${name}};