From: Graham Knop Date: Thu, 18 Jul 2013 07:46:00 +0000 (-0400) Subject: better diagnostics when bad parameters given to has X-Git-Tag: v1.003001~34 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=bf0e0d7a6e2b45079a9cbc307ea07cefd8e641b0;p=gitmo%2FMoo.git better diagnostics when bad parameters given to has --- diff --git a/Changes b/Changes index 4a754ef..1d8d87a 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,5 @@ + - better diagnostics when bad parameters given to has + 1.003000 - 2013-07-15 - fix composing roles that require methods provided by the other (RT#82711) - document optional use of Class::XSAccessor with caveats diff --git a/lib/Moo.pm b/lib/Moo.pm index 271a793..675998b 100644 --- a/lib/Moo.pm +++ b/lib/Moo.pm @@ -37,12 +37,18 @@ sub import { $class->_maybe_reset_handlemoose($target); }; _install_tracked $target => has => sub { - my ($name_proto, %spec) = @_; - my $name_isref = ref $name_proto eq 'ARRAY'; - foreach my $name ($name_isref ? @$name_proto : $name_proto) { - # Note that when $name_proto is an arrayref, each attribute + my $name_proto = shift; + my @name_proto = ref $name_proto eq 'ARRAY' ? @$name_proto : $name_proto; + if (@_ % 2 != 0) { + require Carp; + Carp::croak("Invalid options for " . join(', ', map "'$_'", @name_proto) + . " attribute(s): even number of arguments expected, got " . scalar @_) + } + my %spec = @_; + foreach my $name (@name_proto) { + # Note that when multiple attributes specified, each attribute # needs a separate \%specs hashref - my $spec_ref = $name_isref ? +{%spec} : \%spec; + my $spec_ref = @name_proto > 1 ? +{%spec} : \%spec; $class->_constructor_maker_for($target) ->register_attribute_specs($name, $spec_ref); $class->_accessor_maker_for($target) diff --git a/lib/Moo/Role.pm b/lib/Moo/Role.pm index 7b10f05..596f19b 100644 --- a/lib/Moo/Role.pm +++ b/lib/Moo/Role.pm @@ -29,10 +29,16 @@ sub import { # get symbol table reference my $stash = do { no strict 'refs'; \%{"${target}::"} }; _install_tracked $target => has => sub { - my ($name_proto, %spec) = @_; - my $name_isref = ref $name_proto eq 'ARRAY'; - foreach my $name ($name_isref ? @$name_proto : $name_proto) { - my $spec_ref = $name_isref ? +{%spec} : \%spec; + my $name_proto = shift; + my @name_proto = ref $name_proto eq 'ARRAY' ? @$name_proto : $name_proto; + if (@_ % 2 != 0) { + require Carp; + Carp::croak("Invalid options for " . join(', ', map "'$_'", @name_proto) + . " attribute(s): even number of arguments expected, got " . scalar @_) + } + my %spec = @_; + foreach my $name (@name_proto) { + my $spec_ref = @name_proto > 1 ? +{%spec} : \%spec; ($INFO{$target}{accessor_maker} ||= do { require Method::Generate::Accessor; Method::Generate::Accessor->new diff --git a/t/has-array.t b/t/has-array.t index 277c86e..173ca6b 100644 --- a/t/has-array.t +++ b/t/has-array.t @@ -27,4 +27,18 @@ can_ok( qw( attr1 attr2 attr3 attr4 ), ); +like(exception { + package Local::Test::Role2; + use Moo::Role; + has [qw/ attr1 attr2 /] => (is => 'ro', 'isa'); +}, qr/^Invalid options for 'attr1', 'attr2' attribute\(s\): even number of arguments expected, got 3/, + 'correct exception when has given bad parameters in role'); + +like(exception { + package Local::Test::Class2; + use Moo; + has [qw/ attr3 attr4 /] => (is => 'ro', 'isa'); +}, qr/^Invalid options for 'attr3', 'attr4' attribute\(s\): even number of arguments expected, got 3/, + 'correct exception when has given bad parameters in class'); + done_testing;