use warnings;
require Mouse::TypeRegistry;
+use MouseX::Types::TypeDecorator;
sub import {
my $class = shift;
if (defined $args{'-declare'} && ref($args{'-declare'}) eq 'ARRAY') {
my $storage = $caller->type_storage($caller);
for my $name (@{ $args{'-declare'} }) {
- $storage->{$name} = "$caller\::$name";
- *{"$caller\::$name"} = sub () { $caller->type_storage->{$name} };
+ my $obj = $storage->{$name} = "$caller\::$name";
+ *{"$caller\::$name"} = sub () { $obj };
}
}
my($type_class, $pkg, @types) = @_;
no strict 'refs';
for my $name (@types) {
- *{"$pkg\::$name"} = sub () { $type_class->type_storage->{$name} }
+ my $obj = $type_class->type_storage->{$name};
+ $obj = $type_class->type_storage->{$name} = MouseX::Types::TypeDecorator->new($obj)
+ unless ref($obj);
+ *{"$pkg\::$name"} = sub () { $obj };
}
}
--- /dev/null
+package MouseX::Types::TypeDecorator;
+
+use strict;
+use warnings;
+
+use Mouse::Util 'blessed';
+
+use overload(
+ '""' => sub { ${ $_[0] } },
+ '|' => sub {
+
+ ## It's kind of ugly that we need to know about Union Types, but this
+ ## is needed for syntax compatibility. Maybe someday we'll all just do
+ ## Or[Str,Str,Int]
+
+ my @tc = grep {blessed $_} @_;
+ use Data::Dumper;
+ my $ret;
+ if (ref($_[0])) {
+ $ret = ${ $_[0] };
+ } else {
+ $ret = $_[0];
+ }
+ $ret .= '|';
+ if (ref($_[1])) {
+ $ret .= ${ $_[1] };
+ } else {
+ $ret .= $_[1];
+ }
+ $ret;
+ },
+ fallback => 1,
+
+);
+
+sub new {
+ my $type = $_[1];
+ bless \$type, $_[0];
+}
+
+1;
--- /dev/null
+use strict;
+use warnings;
+use Test::More tests => 13;
+
+{
+ package Types;
+ use strict;
+ use warnings;
+ use MouseX::Types -declare => [qw/ Baz Type1 Type2 /];
+ use MouseX::Types::Mouse qw( ArrayRef );
+
+ subtype Baz, where { defined($_) && $_ eq 'Baz' };
+ coerce Baz, from ArrayRef, via { 'Baz' };
+
+ subtype Type1, where { defined($_) && $_ eq 'Name' };
+ coerce Type1, from 'Str', via { 'Names' };
+
+ subtype Type2, where { defined($_) && $_ eq 'Group' };
+ coerce Type2, from 'Str', via { 'Name' };
+
+}
+
+{
+ package Foo;
+ use Mouse;
+ use MouseX::Types::Mouse qw( Str Undef );
+ BEGIN { Types->import(qw( Baz Type1 )) }
+ has 'bar' => ( is => 'rw', isa => Str | Baz | Undef, coerce => 1 );
+}
+
+eval {
+ Foo->new( bar => +{} );
+};
+ok $@, 'not got an object';
+
+eval {
+ isa_ok(Foo->new( bar => undef ), 'Foo');
+};
+ok !$@, 'got an object 1';
+
+eval {
+ isa_ok(Foo->new( bar => 'foo' ), 'Foo');
+
+};
+ok !$@, 'got an object 2';
+
+
+my $f = Foo->new;
+eval {
+ $f->bar([]);
+};
+ok !$@;
+is $f->bar, 'Baz', 'bar is baz (coerce from ArrayRef)';
+
+eval {
+ $f->bar('hoge');
+};
+ok !$@;
+is $f->bar, 'hoge', 'bar is hoge';
+
+eval {
+ $f->bar(undef);
+};
+ok !$@;
+is $f->bar, undef, 'bar is undef';
+
+
+{
+ package Bar;
+ use Mouse;
+ BEGIN { Types->import(qw( Type1 Type2 )) }
+ has 'foo' => ( is => 'rw', isa => Type1 | Type2 , coerce => 1 );
+}
+
+my $foo = Bar->new( foo => 'aaa' );
+ok $foo, 'got an object 3';
+is $foo->foo, 'Name', 'foo is Name';