From: Dave Rolsky Date: Mon, 26 Jul 2010 17:56:47 +0000 (-0500) Subject: Squashed commit of the following: X-Git-Tag: 1.10~26 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=f6af1028f6d977825235b30a82885ad63b68fbef;p=gitmo%2FMoose.git Squashed commit of the following: commit 8971c228f8023614db46fdb3962872b0cec870c1 Author: Dave Rolsky Date: Mon Jul 26 12:55:53 2010 -0500 Move changes entry to NEXT commit f449c3feef8c6529e4285206317f003d890c4d8f Author: Shawn M Moore Date: Fri Jul 23 23:46:05 2010 -0400 Changes entry commit 07bd93af9010bdefce4c97cd01b7144b05356bd9 Author: Shawn M Moore Date: Fri Jul 23 23:09:11 2010 -0400 Throw an error when enum has a weird argument list This protects users against this kind of construct: has type => ( is => 'rw', isa => enum ['foo', 'bar', 'baz'], required => 1, ); This code will NOT do what you want, being parsed like: enum(['foo', 'bar', 'baz'], 'required', 1); which ends up with an enum named by a stringified array reference where the valid values are "required" and "1". And the required-ness of the attribute is obviously not intact. So this attribute is really FUBAR. commit cebc707b8c48409852974c92a937aa205754c480 Author: Shawn M Moore Date: Fri Jul 23 22:51:56 2010 -0400 Move the <2 values error from the sugar into the class commit c699a721ca06b9a10e3a2dab42a5f3f661e871b7 Author: Shawn M Moore Date: Fri Jul 23 22:38:45 2010 -0400 Remove useless assignment for enums commit 898f80e945b938916416449c492904b857268798 Author: Shawn M Moore Date: Fri Jul 23 22:33:34 2010 -0400 Throw errors when enum values include undef or refs --- diff --git a/Changes b/Changes index 309d5fa..469977f 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,9 @@ NEXT * default => undef now works properly. (doy) + * Enum type constraints now throw errors if their values are nonsensical. + (Sartak) + 1.09 Tue, Jul 25, 2010 [API CHANGES] diff --git a/lib/Moose/Meta/TypeConstraint/Enum.pm b/lib/Moose/Meta/TypeConstraint/Enum.pm index 64ceb1f..f975196 100644 --- a/lib/Moose/Meta/TypeConstraint/Enum.pm +++ b/lib/Moose/Meta/TypeConstraint/Enum.pm @@ -21,6 +21,22 @@ sub new { $args{parent} = Moose::Util::TypeConstraints::find_type_constraint('Str'); + if ( scalar @{ $args{values} } < 2 ) { + require Moose; + Moose->throw_error("You must have at least two values to enumerate through"); + } + + for (@{ $args{values} }) { + if (!defined($_)) { + require Moose; + Moose->throw_error("Enum values must be strings, not undef"); + } + elsif (ref($_)) { + require Moose; + Moose->throw_error("Enum values must be strings, not '$_'"); + } + } + my $self = $class->_new(\%args); $self->compile_type_constraint() diff --git a/lib/Moose/Util/TypeConstraints.pm b/lib/Moose/Util/TypeConstraints.pm index 7e41723..3c21e45 100644 --- a/lib/Moose/Util/TypeConstraints.pm +++ b/lib/Moose/Util/TypeConstraints.pm @@ -435,17 +435,16 @@ sub enum { # if only an array-ref is passed then # you get an anon-enum # - SL - if ( ref $type_name eq 'ARRAY' && !@values ) { + if ( ref $type_name eq 'ARRAY' ) { + @values == 0 + || __PACKAGE__->_throw_error("enum called with an array reference and additional arguments. Did you mean to parenthesize the enum call's parameters?"); + @values = @$type_name; $type_name = undef; } if ( @values == 1 && ref $values[0] eq 'ARRAY' ) { @values = @{ $values[0] }; } - ( scalar @values >= 2 ) - || __PACKAGE__->_throw_error( - "You must have at least two values to enumerate through"); - my %valid = map { $_ => 1 } @values; register_type_constraint( create_enum_type_constraint( diff --git a/t/040_type_constraints/015_enum.t b/t/040_type_constraints/015_enum.t index 4eaa818..92c0062 100644 --- a/t/040_type_constraints/015_enum.t +++ b/t/040_type_constraints/015_enum.t @@ -4,6 +4,7 @@ use strict; use warnings; use Test::More; +use Test::Exception; use Scalar::Util (); @@ -61,4 +62,30 @@ ok( !$anon_enum->is_a_type_of('Object'), 'enum not type of Object'); ok( !$anon_enum->is_subtype_of('ThisTypeDoesNotExist'), 'enum not a subtype of nonexistant type'); ok( !$anon_enum->is_a_type_of('ThisTypeDoesNotExist'), 'enum not type of nonexistant type'); +# validation +throws_ok { Moose::Meta::TypeConstraint::Enum->new(name => 'ZeroValues', values => []) } + qr/You must have at least two values to enumerate through/; + +throws_ok { Moose::Meta::TypeConstraint::Enum->new(name => 'OneValue', values => [ 'a' ]) } + qr/You must have at least two values to enumerate through/; + +throws_ok { Moose::Meta::TypeConstraint::Enum->new(name => 'ReferenceInEnum', values => [ 'a', {} ]) } + qr/Enum values must be strings, not 'HASH\(0x\w+\)'/; + +throws_ok { Moose::Meta::TypeConstraint::Enum->new(name => 'UndefInEnum', values => [ 'a', undef ]) } + qr/Enum values must be strings, not undef/; + +throws_ok { + package Foo; + use Moose; + use Moose::Util::TypeConstraints; + + has error => ( + is => 'ro', + isa => enum ['a', 'aa', 'aaa'], # should be parenthesized! + default => 'aa', + ); +} qr/enum called with an array reference and additional arguments\. Did you mean to parenthesize the enum call's parameters\?/; + + done_testing;