File Coverage

blib/lib/Devel/InnerPackage.pm
Criterion Covered Total %
statement 40 40 100.0
branch 13 14 92.8
condition 2 3 66.6
subroutine 7 7 100.0
pod 1 1 100.0
total 63 65 96.9


line stmt bran cond sub pod time code
1             package Devel::InnerPackage;
2              
3 43     43   401007 use strict;
  43         116  
  43         1672  
4 43     43   198 use Exporter 5.57 'import';
  43         1064  
  43         1892  
5              
6 43     43   207 use if $] > 5.017, 'deprecate';
  43         87  
  43         16555  
7              
8             our $VERSION = '0.4';
9             our @EXPORT_OK = qw(list_packages);
10              
11             =pod
12              
13             =head1 NAME
14              
15             Devel::InnerPackage - find all the inner packages of a package
16              
17             =head1 SYNOPSIS
18              
19             use Foo::Bar;
20             use Devel::InnerPackage qw(list_packages);
21              
22             my @inner_packages = list_packages('Foo::Bar');
23              
24              
25             =head1 DESCRIPTION
26              
27              
28             Given a file like this
29              
30              
31             package Foo::Bar;
32              
33             sub foo {}
34              
35              
36             package Foo::Bar::Quux;
37              
38             sub quux {}
39              
40             package Foo::Bar::Quirka;
41              
42             sub quirka {}
43              
44             1;
45              
46             then
47              
48             list_packages('Foo::Bar');
49              
50             will return
51              
52             Foo::Bar::Quux
53             Foo::Bar::Quirka
54              
55             =head1 METHODS
56              
57             =head2 list_packages <package name>
58              
59             Return a list of all inner packages of that package.
60              
61             =cut
62              
63             sub list_packages {
64 287 50   287 1 286852 my $pack = shift; $pack .= "::" unless $pack =~ m!::$!;
  287         702  
65              
66 43     43   29710 no strict 'refs';
  43         64  
  43         11040  
67 287         314 my @packs;
68 287         333 my @stuff = grep !/^(main|)::$/, keys %{$pack};
  287         1457  
69 287         809 for my $cand (grep /::$/, @stuff)
70             {
71 132         309 $cand =~ s!::$!!;
72 132         293 my @children = list_packages($pack.$cand);
73              
74 132 100 66     444 push @packs, "$pack$cand" unless $cand =~ /^::/ ||
75             !__PACKAGE__->_loaded($pack.$cand); # or @children;
76 132         212 push @packs, @children;
77             }
78 287         567 return grep {$_ !~ /::(::ISA::CACHE|SUPER)/} @packs;
  176         461  
79             }
80              
81             ### XXX this is an inlining of the Class-Inspector->loaded()
82             ### method, but inlined to remove the dependency.
83             sub _loaded {
84 132     132   196 my ($class, $name) = @_;
85              
86 43     43   284 no strict 'refs';
  43         59  
  43         8936  
87              
88             # Handle by far the two most common cases
89             # This is very fast and handles 99% of cases.
90 132 100       133 return 1 if defined ${"${name}::VERSION"};
  132         483  
91 90 100       85 return 1 if @{"${name}::ISA"};
  90         328  
92              
93             # Are there any symbol table entries other than other namespaces
94 66         72 foreach ( keys %{"${name}::"} ) {
  66         153  
95 138 100       245 next if substr($_, -2, 2) eq '::';
96 133 100       152 return 1 if defined &{"${name}::$_"};
  133         442  
97             }
98              
99             # No functions, and it doesn't have a version, and isn't anything.
100             # As an absolute last resort, check for an entry in %INC
101 17         100 my $filename = join( '/', split /(?:'|::)/, $name ) . '.pm';
102 17 100       60 return 1 if defined $INC{$filename};
103              
104 5         13 '';
105             }
106              
107              
108             =head1 AUTHOR
109              
110             Simon Wistow <simon@thegestalt.org>
111              
112             =head1 COPYING
113              
114             Copyright, 2005 Simon Wistow
115              
116             Distributed under the same terms as Perl itself.
117              
118             =head1 BUGS
119              
120             None known.
121              
122             =cut
123              
124              
125              
126              
127              
128             1;