Moose
view release on metacpan or search on metacpan
t/immutable/inline_close_over.t view on Meta::CPAN
use strict;
use warnings;
use Test::Needs {
'Data::Visitor' => '0.26',
'PadWalker' => undef,
};
use Test::More;
use Class::Load 'load_class';
use Try::Tiny;
my $can_partialdump = try {
load_class('Devel::PartialDump', { -version => 0.14 }); 1;
};
{
package Test::Visitor;
use Moose;
use Moose::Util::TypeConstraints;
extends 'Data::Visitor';
has closed_over => (
traits => ['Array'],
isa => 'ArrayRef',
default => sub { [] },
handles => {
add_closed_over => 'push',
closed_over => 'elements',
pass => 'is_empty',
},
);
before visit_code => sub {
my $self = shift;
my ($code) = @_;
my $closed_over = PadWalker::closed_over($code);
$self->visit_ref($closed_over);
};
after visit => sub {
my $self = shift;
my ($thing) = @_;
$self->add_closed_over($thing)
unless $self->_is_okay_to_close_over($thing);
};
sub _is_okay_to_close_over {
my $self = shift;
my ($thing) = @_;
match_on_type $thing => (
'RegexpRef' => sub { 1 },
'Object' => sub { 0 },
'GlobRef' => sub { 0 },
'FileHandle' => sub { 0 },
'Any' => sub { 1 },
);
}
}
sub close_over_ok {
local $Test::Builder::Level = $Test::Builder::Level + 1;
my ($package, $method) = @_;
my $visitor = Test::Visitor->new;
my $code = $package->meta->find_method_by_name($method)->body;
$visitor->visit($code);
if ($visitor->pass) {
pass("${package}::${method} didn't close over anything complicated");
}
else {
fail("${package}::${method} closed over some stuff:");
my @closed_over = $visitor->closed_over;
for my $i (1..10) {
last unless @closed_over;
my $closed_over = shift @closed_over;
if ($can_partialdump) {
$closed_over = Devel::PartialDump->new->dump($closed_over);
}
diag($closed_over);
}
diag("... and " . scalar(@closed_over) . " more")
if @closed_over;
}
}
{
package Foo;
use Moose;
use Moose::Util::TypeConstraints;
has foo => (
is => 'ro',
isa => 'Str',
);
( run in 0.658 second using v1.01-cache-2.11-cpan-98e64b0badf )