| Moose documentation | Contained in the Moose distribution. |
Moose::Meta::Method::Destructor - Method Meta Object for destructors
version 2.0010
This class is a subclass of Class::MOP::Class::Generated that provides Moose-specific functionality for inlining destructors.
To understand this class, you should read the the Class::MOP::Class::Generated documentation as well.
Moose::Meta::Method::Destructor is a subclass of
Moose::Meta::Method and Class::MOP::Method::Generated.
This constructs a new object. It accepts the following options:
The package for the class in which the destructor is being inlined. This option is required.
The name of the destructor method. This option is required.
The metaclass for the class this destructor belongs to. This is
optional, as it can be set later by calling $metamethod->attach_to_class.
Given a Moose::Meta::Class object, this method returns a boolean
indicating whether the class needs a destructor. If the class or any
of its parents defines a DEMOLISH method, it needs a destructor.
See BUGS in Moose for details on reporting bugs.
Stevan Little <stevan@iinteractive.com>
This software is copyright (c) 2011 by Infinity Interactive, Inc..
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
| Moose documentation | Contained in the Moose distribution. |
package Moose::Meta::Method::Destructor; BEGIN { $Moose::Meta::Method::Destructor::AUTHORITY = 'cpan:STEVAN'; } BEGIN { $Moose::Meta::Method::Destructor::VERSION = '2.0010'; } use strict; use warnings; use Devel::GlobalDestruction (); use Scalar::Util 'blessed', 'weaken'; use Try::Tiny; use base 'Moose::Meta::Method', 'Class::MOP::Method::Inlined'; sub new { my $class = shift; my %options = @_; (ref $options{options} eq 'HASH') || $class->throw_error("You must pass a hash of options", data => $options{options}); ($options{package_name} && $options{name}) || $class->throw_error("You must supply the package_name and name parameters $Class::MOP::Method::UPGRADE_ERROR_TEXT"); my $self = bless { # from our superclass 'body' => undef, 'package_name' => $options{package_name}, 'name' => $options{name}, # ... 'options' => $options{options}, 'definition_context' => $options{definition_context}, 'associated_metaclass' => $options{metaclass}, } => $class; # we don't want this creating # a cycle in the code, if not # needed weaken($self->{'associated_metaclass'}); $self->_initialize_body; return $self; } ## accessors sub options { (shift)->{'options'} } ## method sub is_needed { my $self = shift; my $metaclass = shift; ( blessed $metaclass && $metaclass->isa('Class::MOP::Class') ) || $self->throw_error( "The is_needed method expected a metaclass object as its arugment"); return $metaclass->find_method_by_name("DEMOLISHALL"); } sub initialize_body { Carp::cluck('The initialize_body method has been made private.' . " The public version is deprecated and will be removed in a future release.\n"); shift->_initialize_body; } sub _initialize_body { my $self = shift; # TODO: # the %options should also include a both # a call 'initializer' and call 'SUPER::' # options, which should cover approx 90% # of the possible use cases (even if it # requires some adaption on the part of # the author, after all, nothing is free) my $class = $self->associated_metaclass->name; my @source = ( 'sub {', 'my $self = shift;', 'return ' . $self->_generate_fallback_destructor('$self'), 'if Scalar::Util::blessed($self) ne \'' . $class . '\';', 'local $?;', $self->_generate_DEMOLISHALL('$self'), 'return;', '}', ); warn join("\n", @source) if $self->options->{debug}; my $code = try { $self->_compile_code(source => \@source); } catch { my $source = join("\n", @source); $self->throw_error( "Could not eval the destructor :\n\n$source\n\nbecause :\n\n$_", error => $_, data => $source, ); }; $self->{'body'} = $code; } sub _generate_fallback_destructor { my $self = shift; my ($inv) = @_; return $inv . '->Moose::Object::DESTROY(@_)'; } sub _generate_DEMOLISHALL { my $self = shift; my ($inv) = @_; my @methods = $self->associated_metaclass->find_all_methods_by_name('DEMOLISH'); return unless @methods; return ( 'my $igd = Devel::GlobalDestruction::in_global_destruction;', 'Try::Tiny::try {', (map { $inv . '->' . $_->{class} . '::DEMOLISH($igd);' } @methods), '}', 'Try::Tiny::catch {', 'die $_;', '};', ); } 1; # ABSTRACT: Method Meta Object for destructors
__END__