X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FMeta%2FAttribute.pm;h=e347197cfbc199c5f0827dfedf7671871eb597e3;hb=064a13a3104c7c38981bdc571b130da00b59945a;hp=b0160bc3a44853d8953a715fd6822f56abb23edc;hpb=dc2b7cc8f128cbc6c677b209553f6fe0c45af8be;p=gitmo%2FMoose.git diff --git a/lib/Moose/Meta/Attribute.pm b/lib/Moose/Meta/Attribute.pm index b0160bc..e347197 100644 --- a/lib/Moose/Meta/Attribute.pm +++ b/lib/Moose/Meta/Attribute.pm @@ -4,8 +4,8 @@ package Moose::Meta::Attribute; use strict; use warnings; -use Class::MOP (); use B (); +use Class::Load qw(is_class_loaded load_class); use Scalar::Util 'blessed', 'weaken'; use List::MoreUtils 'any'; use Try::Tiny; @@ -80,7 +80,7 @@ sub _inline_throw_error { sub new { my ($class, $name, %options) = @_; $class->_process_options($name, \%options) unless $options{__hack_no_process_options}; # used from clone()... YECHKKK FIXME ICKY YUCK GROSS - + delete $options{__hack_no_process_options}; my %attrs = @@ -129,6 +129,8 @@ sub interpolate_class { if (my $traits = $options->{traits}) { my $i = 0; + my $has_foreign_options = 0; + while ($i < @$traits) { my $trait = $traits->[$i++]; next if ref($trait); # options to a trait we discarded @@ -141,17 +143,28 @@ sub interpolate_class { push @traits, $trait; # are there options? - push @traits, $traits->[$i++] - if $traits->[$i] && ref($traits->[$i]); + if ($traits->[$i] && ref($traits->[$i])) { + $has_foreign_options = 1 + if any { $_ ne '-alias' && $_ ne '-excludes' } keys %{ $traits->[$i] }; + + push @traits, $traits->[$i++]; + } } if (@traits) { - my $anon_class = Moose::Meta::Class->create_anon_class( + my %options = ( superclasses => [ $class ], roles => [ @traits ], - cache => 1, ); + if ($has_foreign_options) { + $options{weaken} = 0; + } + else { + $options{cache} = 1; + } + + my $anon_class = Moose::Meta::Class->create_anon_class(%options); $class = $anon_class->name; } } @@ -746,6 +759,44 @@ sub _inline_trigger { return '$trigger->(' . $instance . ', ' . $value . ', ' . $old . ');'; } +sub _eval_environment { + my $self = shift; + + my $env = { }; + + $env->{'$trigger'} = \($self->trigger) + if $self->has_trigger; + $env->{'$attr_default'} = \($self->default) + if $self->has_default; + + if ($self->has_type_constraint) { + my $tc_obj = $self->type_constraint; + + $env->{'$type_constraint'} = \( + $tc_obj->_compiled_type_constraint + ) unless $tc_obj->can_be_inlined; + # these two could probably get inlined versions too + $env->{'$type_coercion'} = \( + $tc_obj->coercion->_compiled_type_coercion + ) if $tc_obj->has_coercion; + $env->{'$type_message'} = \( + $tc_obj->has_message ? $tc_obj->message : $tc_obj->_default_message + ); + + $env = { %$env, %{ $tc_obj->inline_environment } }; + } + + # XXX ugh, fix these + $env->{'$attr'} = \$self + if $self->has_initializer && $self->is_lazy; + # pretty sure this is only going to be closed over if you use a custom + # error class at this point, but we should still get rid of this + # at some point + $env->{'$meta'} = \($self->associated_class); + + return $env; +} + sub _weaken_value { my ( $self, $instance ) = @_; @@ -859,7 +910,7 @@ sub _inline_generate_default { my ($instance, $default) = @_; if ($self->has_default) { - my $source = 'my ' . $default . ' = $default'; + my $source = 'my ' . $default . ' = $attr_default'; $source .= '->(' . $instance . ')' if $self->is_default_a_coderef; return $source . ';'; @@ -1027,7 +1078,7 @@ sub install_delegation { # install the delegation ... my $associated_class = $self->associated_class; - foreach my $handle (keys %handles) { + foreach my $handle (sort keys %handles) { my $method_to_call = $handles{$handle}; my $class_name = $associated_class->name; my $name = "${class_name}::${handle}"; @@ -1096,7 +1147,7 @@ sub _canonicalize_handles { } } - Class::MOP::load_class($handles); + load_class($handles); my $role_meta = Class::MOP::class_of($handles); (blessed $role_meta && $role_meta->isa('Moose::Meta::Role')) @@ -1129,7 +1180,7 @@ sub _get_delegate_method_list { sub _find_delegate_metaclass { my $self = shift; if (my $class = $self->_isa_metadata) { - unless ( Class::MOP::is_class_loaded($class) ) { + unless ( is_class_loaded($class) ) { $self->throw_error( sprintf( 'The %s attribute is trying to delegate to a class which has not been loaded - %s', @@ -1143,7 +1194,7 @@ sub _find_delegate_metaclass { return Class::MOP::Class->initialize($class); } elsif (my $role = $self->_does_metadata) { - unless ( Class::MOP::is_class_loaded($class) ) { + unless ( is_class_loaded($class) ) { $self->throw_error( sprintf( 'The %s attribute is trying to delegate to a role which has not been loaded - %s',