Tweaks
[gitmo/Mouse.git] / lib / Mouse / Util / TypeConstraints.pm
index f7b320a..e669f40 100644 (file)
@@ -17,6 +17,7 @@ Mouse::Exporter->setup_import_methods(
         coerce
 
         find_type_constraint
+        register_type_constraint
     )],
 );
 
@@ -82,13 +83,13 @@ $TYPE{HashRef} {constraint_generator} = \&_parameterize_HashRef_for;
 
 # sugars
 
-sub as          ($) { (as          => $_[0]) }
-sub where       (&) { (where       => $_[0]) }
-sub message     (&) { (message     => $_[0]) }
-sub optimize_as (&) { (optimize_as => $_[0]) }
+sub as          ($) { (as          => $_[0]) } ## no critic
+sub where       (&) { (where       => $_[0]) } ## no critic
+sub message     (&) { (message     => $_[0]) } ## no critic
+sub optimize_as (&) { (optimize_as => $_[0]) } ## no critic
 
 sub from    { @_ }
-sub via (&) { $_[0] }
+sub via (&) { $_[0] } ## no critic
 
 # type utilities
 
@@ -149,9 +150,18 @@ sub _create_type{
 
         if($TYPE{$name}){
             my $that = $TYPE{$name}->{package_defined_in} || __PACKAGE__;
-            ($this eq $that) or Carp::croak(
-                "The type constraint '$name' has already been created in $that and cannot be created again in $this"
-            );
+            if($this ne $that) {
+                my $note = '';
+                if($that eq __PACKAGE__) {
+                    $note = sprintf " ('%s' is %s type constraint)",
+                        $name,
+                        scalar(grep { $name eq $_ } list_all_builtin_type_constraints())
+                            ? 'a builtin'
+                            : 'an implicitly created';
+                }
+                Carp::croak("The type constraint '$name' has already been created in $that"
+                          . " and cannot be created again in $this" . $note);
+            }
         }
     }
     else{
@@ -227,7 +237,8 @@ sub duck_type {
     @methods = (@_ == 1 && ref($_[0]) eq 'ARRAY') ? @{$_[0]} : @_;
 
     # DuckType
-    return _create_type 'type', $name => (
+    return _create_type 'subtype', $name => (
+        as           => 'Object',
         optimized_as => Mouse::Util::generate_can_predicate_for(\@methods),
     );
 }
@@ -242,7 +253,8 @@ sub enum {
     %valid = map{ $_ => undef } (@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_);
 
     # EnumType
-    return _create_type 'type', $name => (
+    return _create_type 'subtype', $name => (
+        as            => 'Str',
         optimized_as  => sub{ defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]} },
     );
 }
@@ -358,17 +370,25 @@ sub _parse_type {
 
 sub find_type_constraint {
     my($spec) = @_;
-    return $spec if Mouse::Util::is_a_type_constraint($spec);
-    return undef if !defined $spec;
+    return $spec if Mouse::Util::is_a_type_constraint($spec) or not defined $spec;
 
     $spec =~ s/\s+//g;
     return $TYPE{$spec};
 }
 
+sub register_type_constraint {
+    my($constraint) = @_;
+    Carp::croak("No type supplied / type is not a valid type constraint")
+        unless Mouse::Util::is_a_type_constraint($constraint);
+    my $name = $constraint->name;
+    Carp::croak("can't register an unnamed type constraint")
+        unless defined $name;
+    return $TYPE{$name} = $constraint;
+}
+
 sub find_or_parse_type_constraint {
     my($spec) = @_;
-    return $spec if Mouse::Util::is_a_type_constraint($spec);
-    return undef if !defined $spec;
+    return $spec if Mouse::Util::is_a_type_constraint($spec) or not defined $spec;
 
     $spec =~ s/\s+//g;
     return $TYPE{$spec} || do{
@@ -404,7 +424,7 @@ Mouse::Util::TypeConstraints - Type constraint system for Mouse
 
 =head1 VERSION
 
-This document describes Mouse version 0.50_07
+This document describes Mouse version 0.68
 
 =head2 SYNOPSIS
 
@@ -505,10 +525,6 @@ If Mouse finds a name in brackets that it does not recognize as an
 existing type, it assumes that this is a class name, for example
 C<ArrayRef[DateTime]>.
 
-B<NOTE:> Unless you parameterize a type, then it is invalid to include
-the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
-name, I<not> as a parameterization of C<ArrayRef>.
-
 B<NOTE:> The C<Undef> type constraint for the most part works
 correctly now, but edge cases may still exist, please use it
 sparingly.