X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=lib%2FMouse%2FMeta%2FClass.pm;h=3113b83514791a0f3139b022f2d69a3ccb14036d;hp=7d4cdcd1f28d005b44b6075c19fe068039caa985;hb=ff6870694bb440c13826e0f0fa25e760247fd24e;hpb=4f9945f5a128e120049ce8a7a30cf469d1568b9b diff --git a/lib/Mouse/Meta/Class.pm b/lib/Mouse/Meta/Class.pm index 7d4cdcd..3113b83 100644 --- a/lib/Mouse/Meta/Class.pm +++ b/lib/Mouse/Meta/Class.pm @@ -9,6 +9,7 @@ use Mouse::Util qw/get_linear_isa not_supported/; use base qw(Mouse::Meta::Module); +sub method_metaclass(){ 'Mouse::Meta::Method' } # required for get_method() sub _new { my($class, %args) = @_; @@ -209,7 +210,8 @@ sub make_immutable { sub make_mutable { not_supported } -sub is_immutable { $_[0]->{is_immutable} } +sub is_immutable { $_[0]->{is_immutable} } +sub is_mutable { !$_[0]->{is_immutable} } sub _install_modifier { my ( $self, $into, $type, $name, $code ) = @_; @@ -237,6 +239,8 @@ sub _install_modifier { $name, $code ); + $self->{methods}{$name}++; # register it to the method map + return; }; } @@ -262,16 +266,12 @@ sub add_after_method_modifier { sub add_override_method_modifier { my ($self, $name, $code) = @_; - my $pkg = $self->name; - my $method = "${pkg}::${name}"; + my $package = $self->name; - # Class::Method::Modifiers won't do this for us, so do it ourselves + my $body = $package->can($name) + or $self->throw_error("You cannot override '$name' because it has no super method"); - my $body = $pkg->can($name) - or $self->throw_error("You cannot override '$method' because it has no super method"); - - no strict 'refs'; - *$method = sub { $code->($pkg, $body, @_) }; + $self->add_method($name => sub { $code->($package, $body, @_) }); } sub does_role { @@ -285,6 +285,7 @@ sub does_role { next unless $meta && $meta->can('roles'); for my $role (@{ $meta->roles }) { + return 1 if $role->does_role($role_name); } } @@ -307,19 +308,18 @@ sub create { || $class->throw_error("You must pass a HASH ref of methods") if exists $options{methods}; - do { + (ref $options{roles} eq 'ARRAY') + || $class->throw_error("You must pass an ARRAY ref of roles") + if exists $options{roles}; + + { ( defined $package_name && $package_name ) || $class->throw_error("You must pass a package name"); - my $code = "package $package_name;"; - $code .= "\$$package_name\:\:VERSION = '" . $options{version} . "';" - if exists $options{version}; - $code .= "\$$package_name\:\:AUTHORITY = '" . $options{authority} . "';" - if exists $options{authority}; - - eval $code; - $class->throw_error("creation of $package_name failed : $@") if $@; - }; + no strict 'refs'; + ${ $package_name . '::VERSION' } = $options{version} if exists $options{version}; + ${ $package_name . '::AUTHORITY' } = $options{authority} if exists $options{authority}; + } my %initialize_options = %options; delete @initialize_options{qw( @@ -327,6 +327,7 @@ sub create { superclasses attributes methods + roles version authority )}; @@ -354,17 +355,67 @@ sub create { $meta->add_method($method_name, $options{methods}->{$method_name}); } } + if (exists $options{roles}){ + Mouse::Util::apply_all_roles($package_name, @{$options{roles}}); + } return $meta; } { my $ANON_CLASS_SERIAL = 0; my $ANON_CLASS_PREFIX = 'Mouse::Meta::Class::__ANON__::SERIAL::'; + + my %IMMORTAL_ANON_CLASSES; sub create_anon_class { my ( $class, %options ) = @_; + + my $cache = $options{cache}; + my $cache_key; + + if($cache){ # anonymous but not mortal + # something like Super::Class|Super::Class::2=Role|Role::1 + $cache_key = join '=' => ( + join('|', @{$options{superclasses} || []}), + join('|', sort @{$options{roles} || []}), + ); + return $IMMORTAL_ANON_CLASSES{$cache_key} if exists $IMMORTAL_ANON_CLASSES{$cache_key}; + } my $package_name = $ANON_CLASS_PREFIX . ++$ANON_CLASS_SERIAL; - return $class->create( $package_name, %options ); + my $meta = $class->create( $package_name, anon_class_id => $ANON_CLASS_SERIAL, %options ); + + if($cache){ + $IMMORTAL_ANON_CLASSES{$cache_key} = $meta; + } + else{ + Mouse::Meta::Module::weaken_metaclass($package_name); + } + return $meta; + } + + sub is_anon_class{ + return exists $_[0]->{anon_class_id}; + } + + + sub DESTROY{ + my($self) = @_; + + my $serial_id = $self->{anon_class_id}; + + return if !$serial_id; + + my $stash = $self->namespace; + + @{$self->{sperclasses}} = (); + %{$stash} = (); + Mouse::Meta::Module::remove_metaclass_by_name($self->name); + + no strict 'refs'; + delete ${$ANON_CLASS_PREFIX}{ $serial_id . '::' }; + + return; } + } 1;