File Coverage

blib/lib/Package/MoreUtil.pm
Criterion Covered Total %
statement 76 78 97.4
branch 25 34 73.5
condition 9 16 56.2
subroutine 11 11 100.0
pod 4 4 100.0
total 125 143 87.4


line stmt bran cond sub pod time code
1             package Package::MoreUtil;
2              
3             our $DATE = '2019-01-06'; # DATE
4             our $VERSION = '0.591'; # VERSION
5              
6 1     1   59052 use 5.010001;
  1         13  
7 1     1   12 use strict;
  1         2  
  1         24  
8 1     1   5 use warnings;
  1         1  
  1         78  
9              
10             require Exporter;
11             our @ISA = qw(Exporter);
12             our @EXPORT_OK = qw(
13             package_exists
14             list_package_contents
15             list_package_subs
16             list_subpackages
17             );
18              
19             sub package_exists {
20 1     1   6 no strict 'refs';
  1         2  
  1         163  
21              
22 11     11 1 166 my $pkg = shift;
23              
24             # opt
25             #return unless $pkg =~ /\A\w+(::\w+)*\z/;
26              
27 11 100       41 if ($pkg =~ s/::(\w+)\z//) {
28 3         5 return !!${$pkg . "::"}{$1 . "::"};
  3         17  
29             } else {
30 8         44 return !!$::{$pkg . "::"};
31             }
32             }
33              
34             # XXX incomplete/improper
35             sub list_package_contents {
36 1     1   6 no strict 'refs';
  1         2  
  1         307  
37              
38 1     1 1 4 my $pkg = shift;
39              
40 1 50 33     5 return () unless !length($pkg) || package_exists($pkg);
41 1         23 my $symtbl = \%{$pkg . "::"};
  1         5  
42              
43 1         2 my %res;
44 1         6 while (my ($k, $v) = each %$symtbl) {
45 2 50       5 next if $k =~ /::$/; # subpackage
46 2         3 my $n;
47 2 50       11 if ("$v" !~ /^\*/) {
48             # constant
49 0         0 $res{$k} = $v;
50 0         0 next;
51             }
52 2 100       7 if (defined *$v{CODE}) {
53 1         4 $res{$k} = *$v{CODE}; # subroutine
54 1         15 $n++;
55             }
56 2 100       16 if (defined *$v{HASH}) {
57 1         2 $res{"\%$k"} = \%{*$v}; # hash
  1         4  
58 1         2 $n++;
59             }
60 2 100       6 if (defined *$v{ARRAY}) {
61 1         1 $res{"\@$k"} = \@{*$v}; # array
  1         3  
62 1         2 $n++;
63             }
64 2 100 66     6 if (defined(*$v{SCALAR}) # XXX always defined?
65 2         6 && defined(${*$v})) { # currently we filter undef values
66 1         1 $res{"\$$k"} = \${*$v}; # scalar
  1         4  
67 1         2 $n++;
68             }
69              
70 2 100       20 if (!$n) {
71 1         5 $res{"\*$k"} = $v; # glob
72             }
73             }
74              
75 1         6 %res;
76             }
77              
78             # XXX incomplete/improper too?
79             sub list_package_subs {
80 1     1   7 no strict 'refs';
  1         2  
  1         133  
81              
82 1     1 1 558 my $pkg = shift;
83              
84 1 50 33     7 return () unless !length($pkg) || package_exists($pkg);
85 1         2 my $symtbl = \%{$pkg . "::"};
  1         4  
86              
87 1         2 my @res;
88 1         7 while (my ($k, $v) = each %$symtbl) {
89 2 50       4 next if $k =~ /::$/; # subpackage
90 2 100       9 if (defined *$v{CODE}) {
91 1         5 push @res, $k;
92             }
93             }
94              
95 1         3 @res;
96             }
97              
98             sub list_subpackages {
99 1     1   6 no strict 'refs';
  1         2  
  1         171  
100              
101 5     5 1 444 my ($pkg, $recursive, $cur_res, $ref_mem) = @_;
102              
103 5 50 33     16 return () unless !length($pkg) || package_exists($pkg);
104              
105             # this is used to avoid deep recursion. for example (the only one?) %:: and
106             # %main:: point to the same thing.
107 5   100     17 $ref_mem //= {};
108              
109 5         5 my $symtbl = \%{$pkg . "::"};
  5         12  
110 5 50       16 return () if $ref_mem->{"$symtbl"}++;
111              
112 5   100     14 my $res = $cur_res // [];
113 5         15 for (sort keys %$symtbl) {
114 4 50       17 next unless s/::$//;
115 4 50       11 my $name = (length($pkg) ? "$pkg\::" : "" ) . $_;
116 4         7 push @$res, $name;
117 4 100       15 list_subpackages($name, 1, $res, $ref_mem) if $recursive;
118             }
119              
120 5         20 @$res;
121             }
122              
123             1;
124             # ABSTRACT: Package-related utilities
125              
126             __END__