--- /dev/null
+package Method::Generate::DemolishAll;
+
+use strictures 1;
+use base qw(Moo::Object);
+use Sub::Quote;
+use Moo::_Utils;
+use B qw(perlstring);
+
+sub generate_method {
+ my ($self, $into) = @_;
+ quote_sub "${into}::DEMOLISHALL", join '',
+ $self->_handle_subdemolish($into),
+ qq{ my \$self = shift;\n},
+ $self->demolishall_body_for($into, '$self', '@_'),
+ qq{ return \$self\n};
+}
+
+sub demolishall_body_for {
+ my ($self, $into, $me, $args) = @_;
+ my @demolishers =
+ grep *{_getglob($_)}{CODE},
+ map "${_}::DEMOLISH",
+ @{Moo::_Utils::_get_linear_isa($into)};
+ join '', map qq{ ${me}->${_}(${args});\n}, @demolishers;
+}
+
+sub _handle_subdemolish {
+ my ($self, $into) = @_;
+ ' if (ref($_[0]) ne '.perlstring($into).') {'."\n".
+ ' return shift->Moo::Object::DEMOLISHALL(@_)'.";\n".
+ ' }'."\n";
+}
+
+1;
our %NO_BUILD;
our $BUILD_MAKER;
+our $DEMOLISH_MAKER;
sub new {
my $class = shift;
eval {
# DEMOLISHALL
- # We cannot count on being able to retrieve a previously made
- # metaclass, _or_ being able to make a new one during global
- # destruction. However, we should still be able to use mro at
- # that time (at least tests suggest so ;)
-
- foreach my $class (@{ Moo::_Utils::_get_linear_isa(ref $self) }) {
- my $demolish = $class->can('DEMOLISH') || next;
-
- $self->$demolish($Moo::_Utils::_in_global_destruction);
- }
+ $self->DEMOLISHALL($Moo::_Utils::_in_global_destruction);
};
$@;
};
die $e if $e; # rethrow
}
-
+sub DEMOLISHALL {
+ my $self = shift;
+ $self->${\(($DEMOLISH_MAKER ||= do {
+ require Method::Generate::DemolishAll;
+ Method::Generate::DemolishAll->new
+ })->generate_method(ref($self)))}(@_);
+}
sub does {
require Role::Tiny;