Squashed commit of the following:
Dave Rolsky [Mon, 26 Jul 2010 17:56:47 +0000 (12:56 -0500)]
commit 8971c228f8023614db46fdb3962872b0cec870c1
Author: Dave Rolsky <autarch@urth.org>
Date:   Mon Jul 26 12:55:53 2010 -0500

    Move changes entry to NEXT

commit f449c3feef8c6529e4285206317f003d890c4d8f
Author: Shawn M Moore <sartak@bestpractical.com>
Date:   Fri Jul 23 23:46:05 2010 -0400

    Changes entry

commit 07bd93af9010bdefce4c97cd01b7144b05356bd9
Author: Shawn M Moore <sartak@bestpractical.com>
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 <sartak@bestpractical.com>
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 <sartak@bestpractical.com>
Date:   Fri Jul 23 22:38:45 2010 -0400

    Remove useless assignment for enums

commit 898f80e945b938916416449c492904b857268798
Author: Shawn M Moore <sartak@bestpractical.com>
Date:   Fri Jul 23 22:33:34 2010 -0400

    Throw errors when enum values include undef or refs

Changes
lib/Moose/Meta/TypeConstraint/Enum.pm
lib/Moose/Util/TypeConstraints.pm
t/040_type_constraints/015_enum.t

diff --git a/Changes b/Changes
index 309d5fa..469977f 100644 (file)
--- 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]
index 64ceb1f..f975196 100644 (file)
@@ -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()
index 7e41723..3c21e45 100644 (file)
@@ -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(
index 4eaa818..92c0062 100644 (file)
@@ -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;