/usr/local/CPAN/MooseX-MakeImmutable/MooseX/MakeImmutable/Finder.pm
package MooseX::MakeImmutable::Finder;
use Moose;
use Module::Pluggable::Object;
use List::MoreUtils qw/uniq/;
use Devel::InnerPackage qw/list_packages/;
use Carp::Clan qw/^MooseX::MakeImmutable::/;
use Class::Inspector;
has exclude => qw/is ro required 1 lazy 1/, default => sub { [] };
has include_inner => qw/is ro required 1 default 1/;
has _found => qw/is ro required 1 lazy 1 isa ArrayRef/, default => sub {
my $self = shift;
$self->require;
my @manifest;
push @manifest, $self->manifest;
push @manifest, map { list_packages $_ } $self->manifest if $self->include_inner;
push @manifest, $self->recursive_manifest;
push @manifest, map { list_packages $_ } $self->recursive_manifest;
@manifest = uniq @manifest;
@manifest = grep { $self->keep($_) } @manifest;
@manifest = grep { $_->isa("Moose::Object") } @manifest;
return \@manifest;
};
sub BUILD {
my $self = shift;
my $given = shift;
$self->{exclude} = [ $self->{exclude} ] if $self->{exclude} && ref $self->{exclude} ne "ARRAY";
my $manifest = $given->{manifest};
my (@manifest, @recursive_manifest, @search_manifest);
for my $package (split m/\n+/, $manifest) {
chomp $package;
$package =~ s/^\s*//;
$package =~ s/\s*$//;
next unless $package;
next if $package =~ m/^#/;
if ($package =~ s/::\*$//) {
push @search_manifest, $package;
next;
}
elsif ($package =~ s/::\+?$//) {
push @recursive_manifest, $package;
}
push @manifest, $package;
}
if (@search_manifest || @recursive_manifest) {
my $pluggable = Module::Pluggable::Object->new(require => 1, search_path => [ @search_manifest, @recursive_manifest ]);
push @recursive_manifest, $pluggable->plugins;
}
@manifest = grep { $self->keep($_) } uniq @manifest;
@recursive_manifest = grep { $self->keep($_) } uniq @recursive_manifest;
my @total_manifest = sort { $a cmp $b } uniq @manifest, @recursive_manifest;
@$self{qw/manifest recursive_manifest total_manifest/} = (\@manifest, \@recursive_manifest, \@total_manifest);
}
sub keep {
my $self = shift;
my $package = shift;
my @exclude = @{ $self->exclude };
for my $filter (@exclude) {
if (ref $filter eq "") {
return 0 if $package eq $filter;
}
elsif (ref $filter eq "Regexp") {
return 0 if $package =~ $filter;
}
elsif (ref $filter eq "CODE") {
return 0 if $filter->($package);
}
}
return 1;
}
sub manifest {
my $self = shift;
return @{ $self->{manifest} };
}
sub recursive_manifest {
my $self = shift;
return @{ $self->{recursive_manifest} };
}
sub total_manifest {
my $self = shift;
return @{ $self->{total_manifest} };
}
sub require {
my $self = shift;
for my $package ($self->total_manifest) {
next if Class::Inspector->loaded($package); # Don't require already loaded "inner" packages
eval "require $package;" or croak $@;
}
}
sub found {
my $self = shift;
return @{ $self->_found };
}
1;