Checking in changes prior to tagging of version 0.40_02. Changelog diff is:
[gitmo/Mouse.git] / lib / Mouse / Util / TypeConstraints.pm
index 74afc1d..c6f7b17 100644 (file)
@@ -2,7 +2,7 @@ package Mouse::Util::TypeConstraints;
 use Mouse::Util qw(does_role not_supported); # enables strict and warnings
 
 use Carp qw(confess);
-use Scalar::Util qw/blessed looks_like_number openhandle/;
+use Scalar::Util ();
 
 use Mouse::Meta::TypeConstraint;
 use Mouse::Exporter;
@@ -14,15 +14,13 @@ Mouse::Exporter->setup_import_methods(
         type subtype coerce class_type role_type enum
         find_type_constraint
     )],
-
-    _export_to_main => 1,
 );
 
 my %TYPE;
 
-sub as          ($) { (as => $_[0]) }
-sub where       (&) { (where => $_[0]) }
-sub message     (&) { (message => $_[0]) }
+sub as          ($) { (as          => $_[0]) }
+sub where       (&) { (where       => $_[0]) }
+sub message     (&) { (message     => $_[0]) }
 sub optimize_as (&) { (optimize_as => $_[0]) }
 
 sub from    { @_ }
@@ -34,32 +32,28 @@ BEGIN {
         Item       => undef, # null check
         Maybe      => undef, # null check
 
-        Bool       => sub { $_[0] ? $_[0] eq '1' : 1 },
-        Undef      => sub { !defined($_[0]) },
-        Defined    => sub { defined($_[0]) },
-        Value      => sub { defined($_[0]) && !ref($_[0]) },
-        Num        => sub { !ref($_[0]) && looks_like_number($_[0]) },
-        Int        => sub { defined($_[0]) && !ref($_[0]) && $_[0] =~ /^-?[0-9]+$/ },
-        Str        => sub { defined($_[0]) && !ref($_[0]) },
-        Ref        => sub { ref($_[0]) },
-
-        ScalarRef  => sub { ref($_[0]) eq 'SCALAR' },
-        ArrayRef   => sub { ref($_[0]) eq 'ARRAY'  },
-        HashRef    => sub { ref($_[0]) eq 'HASH'   },
-        CodeRef    => sub { ref($_[0]) eq 'CODE'   },
-        RegexpRef  => sub { ref($_[0]) eq 'Regexp' },
-        GlobRef    => sub { ref($_[0]) eq 'GLOB'   },
-
-        FileHandle => sub {
-            ref($_[0]) eq 'GLOB' && openhandle($_[0])
-            or
-            blessed($_[0]) && $_[0]->isa("IO::Handle")
-        },
-
-        Object     => sub { blessed($_[0]) && blessed($_[0]) ne 'Regexp' },
-
-        ClassName  => sub { Mouse::Util::is_class_loaded($_[0]) },
-        RoleName   => sub { (Mouse::Util::find_meta($_[0]) || return 0)->isa('Mouse::Meta::Role') },
+        Bool       => \&Bool,
+        Undef      => \&Undef,
+        Defined    => \&Defined,
+        Value      => \&Value,
+        Num        => \&Num,
+        Int        => \&Int,
+        Str        => \&Str,
+        Ref        => \&Ref,
+
+        ScalarRef  => \&ScalarRef,
+        ArrayRef   => \&ArrayRef,
+        HashRef    => \&HashRef,
+        CodeRef    => \&CodeRef,
+        RegexpRef  => \&RegexpRef,
+        GlobRef    => \&GlobRef,
+
+        FileHandle => \&FileHandle,
+
+        Object     => \&Object,
+
+        ClassName  => \&ClassName,
+        RoleName   => \&RoleName,
     );
 
     while (my ($name, $code) = each %builtins) {
@@ -80,6 +74,14 @@ BEGIN {
     sub list_all_type_constraints         { keys %TYPE }
 }
 
+# is-a predicates
+BEGIN{
+    _generate_class_type_for('Mouse::Meta::TypeConstraint' => '_is_a_type_constraint');
+    _generate_class_type_for('Mouse::Meta::Class'          => '_is_a_metaclass');
+    _generate_class_type_for('Mouse::Meta::Role'           => '_is_a_metarole');
+}
+
+
 sub _create_type{
     my $mode = shift;
 
@@ -157,30 +159,22 @@ sub coerce {
 }
 
 sub class_type {
-    my($name, $conf) = @_;
-    if ($conf && $conf->{class}) {
-        # No, you're using this wrong
-        warn "class_type() should be class_type(ClassName). Perhaps you're looking for subtype $name => as '$conf->{class}'?";
-        _create_type 'type', $name => (
-            as   => $conf->{class},
-
-            type => 'Class',
-       );
-    }
-    else {
-        _create_type 'type', $name => (
-            optimized_as => sub { blessed($_[0]) && $_[0]->isa($name) },
+    my($name, $options) = @_;
+    my $class = $options->{class} || $name;
+    return _create_type 'subtype', $name => (
+        as           => 'Object',
+        optimized_as => _generate_class_type_for($class),
 
-            type => 'Class',
-        );
-    }
+        type => 'Class',
+    );
 }
 
 sub role_type {
-    my($name, $conf) = @_;
-    my $role = ($conf && $conf->{role}) ? $conf->{role} : $name;
-    _create_type 'type', $name => (
-        optimized_as => sub { blessed($_[0]) && does_role($_[0], $role) },
+    my($name, $options) = @_;
+    my $role = $options->{role} || $name;
+    return _create_type 'subtype', $name => (
+        as           => 'Object',
+        optimized_as => sub { Scalar::Util::blessed($_[0]) && does_role($_[0], $role) },
 
         type => 'Role',
     );
@@ -220,33 +214,15 @@ sub _find_or_create_regular_type{
 
     return $TYPE{$spec} if exists $TYPE{$spec};
 
-    my $meta  = Mouse::Util::get_metaclass_by_name($spec);
+    my $meta = Mouse::Util::get_metaclass_by_name($spec)
+        or return undef;
 
-    if(!$meta){
-        return;
-    }
-
-    my $check;
-    my $type;
-    if($meta->isa('Mouse::Meta::Role')){
-        $check = sub{
-            return blessed($_[0]) && $_[0]->does($spec);
-        };
-        $type = 'Role';
+    if(_is_a_metarole($meta)){
+        return role_type($spec);
     }
     else{
-        $check = sub{
-            return blessed($_[0]) && $_[0]->isa($spec);
-        };
-        $type = 'Class';
+        return class_type($spec);
     }
-
-    return $TYPE{$spec} = Mouse::Meta::TypeConstraint->new(
-        name      => $spec,
-        optimized => $check,
-
-        type      => $type,
-    );
 }
 
 $TYPE{ArrayRef}{constraint_generator} = sub {
@@ -364,7 +340,16 @@ sub _parse_type{
         }
     }
     if($i - $start){
-        push @list, _find_or_create_regular_type(substr $spec, $start, $i - $start);
+        my $type = _find_or_create_regular_type( substr $spec, $start, $i - $start );
+
+        if(defined $type){
+            push @list, $type;
+        }
+        elsif($start != 0) {
+            # RT #50421
+            # create a new class type
+            push @list, class_type( substr $spec, $start, $i - $start );
+        }
     }
 
     if(@list == 0){
@@ -381,7 +366,7 @@ sub _parse_type{
 
 sub find_type_constraint {
     my($spec) = @_;
-    return $spec if blessed($spec) && $spec->isa('Mouse::Meta::TypeConstraint');
+    return $spec if _is_a_type_constraint($spec);
 
     $spec =~ s/\s+//g;
     return $TYPE{$spec};
@@ -389,7 +374,7 @@ sub find_type_constraint {
 
 sub find_or_parse_type_constraint {
     my($spec) = @_;
-    return $spec if blessed($spec) && $spec->isa('Mouse::Meta::TypeConstraint');
+    return $spec if _is_a_type_constraint($spec);
 
     $spec =~ s/\s+//g;
     return $TYPE{$spec} || do{
@@ -399,10 +384,12 @@ sub find_or_parse_type_constraint {
 }
 
 sub find_or_create_does_type_constraint{
+    # XXX: Moose does not register a new role_type, but Mouse does.
     return find_or_parse_type_constraint(@_) || role_type(@_);
 }
 
 sub find_or_create_isa_type_constraint {
+    # XXX: Moose does not register a new class_type, but Mouse does.
     return find_or_parse_type_constraint(@_) || class_type(@_);
 }
 
@@ -416,7 +403,7 @@ Mouse::Util::TypeConstraints - Type constraint system for Mouse
 
 =head1 VERSION
 
-This document describes Mouse version 0.38
+This document describes Mouse version 0.40_02
 
 =head2 SYNOPSIS