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;