File Coverage

blib/lib/Devel/Leak/Module.pm
Criterion Covered Total %
statement 15 61 24.5
branch 0 16 0.0
condition 0 3 0.0
subroutine 6 18 33.3
pod n/a
total 21 98 21.4


line stmt bran cond sub pod time code
1             package Devel::Leak::Module;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Devel::Leak::Module - Track loaded modules and namespaces
8              
9             =head1 SYNOPSIS
10              
11             TO BE COMPLETED
12              
13             =head1 DESCRIPTION
14              
15             =head1 METHODS
16              
17             =cut
18              
19 2     2   14209 use 5.005;
  2         5  
20 2     2   6 use strict;
  2         2  
  2         37  
21 2     2   11 no strict 'refs';
  2         2  
  2         54  
22              
23 2     2   6 use vars qw{$VERSION};
  2         2  
  2         94  
24             BEGIN {
25 2     2   68 $VERSION = '0.01_04';
26             }
27              
28             BEGIN {
29             # Force sort::hints to be populated early, to avoid a case where
30             # calling all_modules creates a new namespace.
31 2     2   8 my @foo = qw{ b c a };
32 2         10 my @bar = sort @foo;
33              
34             # If Scalar::Util and List::Util are around, load them.
35             # This prevents a problem when tests are run in the debugger.
36             # If they AREN'T available, we don't care
37 2         137 eval "require Scalar::Util; require List::Util;";
38             }
39              
40              
41              
42              
43              
44             #####################################################################
45             # Main Functions
46              
47             my %NAMESPACES = ();
48             my %PACKAGES = ();
49             my %MODULES = ();
50              
51             sub checkpoint {
52 0     0     %NAMESPACES = map { $_ => 1 } all_namespaces();
  0            
53 0           %PACKAGES = map { $_ => 1 } all_packages();
  0            
54 0           %MODULES = %INC;
55 0           return 1;
56             }
57              
58             sub new_namespaces {
59 0     0     grep { ! $NAMESPACES{$_} } all_namespaces();
  0            
60             }
61              
62             sub new_packages {
63 0     0     grep { ! $PACKAGES{$_} } all_packages();
  0            
64             }
65              
66             sub new_modules {
67 0     0     grep { ! $MODULES{$_} } all_modules();
  0            
68             }
69              
70             # Boolean true/false for if there are any new anything
71             sub any_new {
72 0 0   0     return 1 if new_namespaces();
73 0 0         return 1 if new_packages();
74 0 0         return 1 if new_modules();
75 0           return '';
76             }
77              
78             # Print a summary of newly created things
79             sub print_new {
80 0 0   0     my %parts = map { $_ => 1 } (@_ ? @_ : qw{ namespace package module });
  0            
81              
82 0 0         if ( $parts{module} ) {
83 0           foreach my $module ( new_modules() ) {
84 0           print "Module: $module\n";
85             }
86             }
87 0 0         if ( $parts{package} ) {
88 0           foreach my $package ( new_packages() ) {
89 0           print "Package: $package\n";
90             }
91             }
92 0 0         if ( $parts{namespace} ) {
93 0           foreach my $namespace ( new_namespaces() ) {
94 0           print "Namespace: $namespace\n";
95             }
96             }
97              
98             }
99              
100              
101              
102              
103              
104             #####################################################################
105             # Capture Functions
106              
107             sub all_namespaces {
108 0     0     my @names = ();
109 0           my @stack = grep { $_ ne 'main' } _names('main');
  0            
110 0           while ( @stack ) {
111 0           my $c = shift @stack;
112 0           push @names, $c;
113 0           unshift @stack, _namespaces($c);
114             }
115 0           return @names;
116             }
117              
118             # Start with all the namespaces,
119             # limited to the ones that look like classes.
120             # Then check each namespace actually contains something.
121             sub all_packages {
122 0     0     grep { _OCCUPIED($_) } grep { _CLASS($_) } all_namespaces();
  0            
  0            
123             }
124              
125             # Get the list of all modules
126             sub all_modules {
127 0     0     sort grep { $_ ne 'dumpvar.pl' } keys %INC;
  0            
128             }
129              
130              
131              
132              
133              
134             #####################################################################
135             # Support Functions
136              
137             sub _names {
138 0     0     return grep { s/::$// } sort keys %{$_[0] . '::'};
  0            
  0            
139             }
140              
141             sub _namespaces {
142 0     0     return map { $_[0] . '::' . $_ } _names($_[0]);
  0            
143             }
144              
145              
146              
147              
148              
149             #####################################################################
150             # Embedded Functions
151              
152             # Params::Util::_CLASS
153             sub _CLASS ($) {
154 0 0 0 0     (defined $_[0] and ! ref $_[0] and $_[0] =~ m/^[^\W\d]\w*(?:::\w+)*$/s) ? $_[0] : undef;
155             }
156              
157             # Class::Autouse::_namespace_occupied
158             sub _OCCUPIED ($) {
159             # Handle the most likely case
160             my $class = shift or return undef;
161             return 1 if defined @{"${class}::ISA"};
162              
163             # Get the list of glob names, ignoring namespaces
164             foreach ( keys %{"${class}::"} ) {
165             next if substr($_, -2) eq '::';
166              
167             # Only check for methods, since that's all that's reliable
168             return 1 if defined *{"${class}::$_"}{CODE};
169             }
170              
171             '';
172             }
173              
174             1;
175              
176             =pod
177              
178             =head1 SUPPORT
179              
180             Bugs should be always be reported via the CPAN bug tracker at
181              
182             L
183              
184             For other issues, or commercial enhancement or support, contact the author.
185              
186             =head1 AUTHORS
187              
188             Adam Kennedy Eadamk@cpan.orgE
189              
190             =head1 SEE ALSO
191              
192             L, L
193              
194             =head1 COPYRIGHT
195              
196             Copyright 2007 - 2008 Adam Kennedy.
197              
198             This program is free software; you can redistribute
199             it and/or modify it under the same terms as Perl itself.
200              
201             The full text of the license can be found in the
202             LICENSE file included with this module.
203              
204             =cut