X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMooseX%2FTypes%2FTypeDecorator.pm;h=2d1098d2322fb5e329974e8d725e160904c0b5f4;hb=28696c2e1c3e499b4613645f4d6ec02026c025aa;hp=a509a895fe0b6d9f9ab7fc5294b8c586488767ec;hpb=48ec5fb346ff80ab545fcf91af26175e4caf66ef;p=gitmo%2FMooseX-Types.git diff --git a/lib/MooseX/Types/TypeDecorator.pm b/lib/MooseX/Types/TypeDecorator.pm index a509a89..2d1098d 100644 --- a/lib/MooseX/Types/TypeDecorator.pm +++ b/lib/MooseX/Types/TypeDecorator.pm @@ -16,6 +16,8 @@ use overload( my $tc = $self->{__type_constraint}; return 0+$tc; }, + # workaround for perl 5.8.5 bug + '==' => sub { 0+$_[0] == 0+$_[1] }, '""' => sub { my $self = shift @_; if(blessed $self) { @@ -112,13 +114,18 @@ sub __type_constraint { =head2 isa -handle $self->isa since AUTOLOAD can't. +handle $self->isa since AUTOLOAD can't - this tries both the type constraint, +and for a class type, the class. =cut sub isa { - return 1 if $_[1]->isa('Moose::Meta::TypeConstraint'); - shift->_try_delegate('isa', @_) + my $self = shift; + return + blessed $self + ? $self->__type_constraint->isa(@_) + || $self->_try_delegate( 'isa', @_ ) + : $self->SUPER::isa(@_); } =head2 can @@ -127,7 +134,13 @@ handle $self->can since AUTOLOAD can't. =cut -sub can { shift->_try_delegate('can', @_) } +sub can { + my $self = shift; + + return blessed $self + ? $self->_try_delegate( 'can', @_ ) + : $self->SUPER::can(@_); +} =head2 _throw_error @@ -154,7 +167,11 @@ sub DESTROY { =head2 AUTOLOAD -Delegate to the decorator target. +Delegate to the decorator target, unless this is a class type, in which +case it will try to delegate to the type object, then if that fails try +the class. The method 'new' is special cased to only be permitted on +the class; if there is no class, or it does not provide a new method, +an exception will be thrown. =cut @@ -172,15 +189,35 @@ sub AUTOLOAD { sub _try_delegate { my ($self, $method, @args) = @_; my $tc = $self->__type_constraint; - my $inv = ( - $tc->isa('Moose::Meta::TypeConstraint::Class') - ? ( - $method eq 'new' || $tc->class->can($method) - ? $tc->class - : $tc - ) - : $tc - ); + my $class; + if ($tc->can('is_subtype_of')) { # Union can't + my $search_tc = $tc; + while (1) { + if ($search_tc->isa('Moose::Meta::TypeConstraint::Class')) { + $class = $search_tc->class; + last; + } + $search_tc = $search_tc->parent; + last unless $search_tc && $search_tc->is_subtype_of('Object'); + } + } + + my $inv = do { + if ($method eq 'new') { + die "new called on type decorator for non-class-type ".$tc->name + unless $class; + die "new called on class type decorator ".$tc->name."\n" + ." for class ${class}\n" + ." which does not provide a new method - did you forget to load it?" + unless $class->can('new'); + $class + } elsif ($class && !$tc->can($method)) { + $class + } else { + $tc + } + }; + $inv->$method(@args); }