File Coverage

blib/lib/Class/LazyLoad.pm
Criterion Covered Total %
statement 99 99 100.0
branch 34 34 100.0
condition 3 3 100.0
subroutine 22 22 100.0
pod 6 6 100.0
total 164 164 100.0


line stmt bran cond sub pod time code
1             package Class::LazyLoad;
2              
3 15     15   276577 use strict 'vars';
  15         65  
  15         580  
4              
5 15         8892 use vars qw(
6             $AUTOLOAD
7             $VERSION
8 15     15   951 );
  15         57  
9              
10             $VERSION = 0.04;
11              
12             {
13             my @todo;
14             sub import
15             {
16 16     16   1338 shift;
17 16 100       995 return if (caller)[0] eq 'Class::LazyLoad::Functions';
18            
19 10 100       44 unless ( @_ ) {
20 6         30 push @todo, [ (caller)[0], 'new' ];
21 6         377 return;
22             }
23              
24 4         13 foreach ( @_ ) {
25 6 100       21 if (ref($_) eq 'ARRAY') {
26 2         84 push @todo, $_;
27             } else {
28 4         29 push @todo, [ $_, 'new' ];
29             }
30             }
31             }
32              
33 14     14 1 129 sub init_lazyloads { lazyload( @$_ ) for @todo }
34 14     14   64 INIT { init_lazyloads() }
35             }
36              
37             use overload
38 2     2   2238 '${}' => sub { _build($_[0]); $_[0] },
  2         6  
39 2     2   1968 '%{}' => sub { _build($_[0]); $_[0] },
  2         26  
40 2     2   1760 '&{}' => sub { _build($_[0]); $_[0] },
  2         5  
41             '@{}' => sub {
42             # C::LL does array access, so make sure it's not us before building.
43 105 100   105   2892 return $_[0] if (caller)[0] eq __PACKAGE__;
44 2         8 _build($_[0]); $_[0]
  2         6  
45             },
46             nomethod => sub {
47 11     11   9876 my $realclass = $_[0][1];
48 11 100       1340 if ($_[3] eq '""') {
49 8 100       52 if (my $func = overload::Method($realclass, $_[3])) {
50 1         1574 _build($_[0]);
51 1         4 return $_[0]->$func();
52             }
53             else {
54 7         12200 return overload::StrVal($_[0]);
55             }
56             }
57 3 100       13 die "LazyLoaded object '$realclass' is not overloaded, cannot perform '$_[3]'\n"
58             unless overload::Overloaded($realclass);
59 2         2960 my $func = overload::Method($realclass, $_[3]);
60 2 100       65 die "LazyLoaded object '$realclass' does not overloaded '$_[3]'\n"
61             unless defined $func;
62 1         5 _build($_[0]);
63 1         6 $_[0]->$func($_[1], $_[2]);
64 15     15   31911 };
  14         15307  
  14         369  
65              
66             sub can
67             {
68 8     8 1 8220 _build( $_[0] );
69 8         55 $_[0]->can($_[1]);
70             }
71              
72 48     48 1 9456 sub isa { $_[0][1]->isa($_[1]) }
73              
74             sub AUTOLOAD
75             {
76 13     13   17094 my ($subname) = $AUTOLOAD =~ /([^:]+)$/;
77              
78 13         87 my $realclass = $_[0][1];
79 13         78 _build( $_[0] );
80              
81 11         85 my $func = $_[0]->can( $subname );
82 11 100       662 die "Cannot call '$subname' on an instance of '$realclass'\n"
83             unless ref( $func ) eq 'CODE';
84              
85 10         616 goto &$func;
86             }
87              
88             sub _compile
89             {
90 21     21   39 my $pkg = shift;
91 21         66 (my $filename = $pkg) =~ s!::!/!g;
92             # print "$pkg => " . $INC{"$filename.pm"} . "\n";
93 21 100       125 return if exists $INC{"$filename.pm"};
94              
95 8     5   664 eval "use $pkg;";
  5         2079  
  5         139  
  5         80  
96 8 100       43 die "Could not load '$pkg' because : $@" if $@;
97             }
98              
99             {
100             my %lazyloads;
101              
102             sub lazyload
103             {
104 18     18 1 7703 my $pkg = shift;
105              
106 18         86 _compile( $pkg );
107              
108 17         39 my @functions = @_;
109 17 100       229 @functions = qw( new ) unless @functions;
110              
111 17         43 foreach my $name (@functions)
112             {
113 17         54 my $subname = __PACKAGE__ . '::' . $pkg . '::' . $name;
114              
115             # Don't override a function we've already overridden;
116 17 100       29 next if defined &{$subname};
  17         89  
117              
118 16         31 my $func = \&{ $pkg . '::' . $name };
  16         66  
119 16     34   205 *$subname = sub { unshift @_, $func; bless \@_, __PACKAGE__ };
  34         17652  
  34         148  
120              
121 16         73 local $^W = 0;
122 16         51 *{ $pkg . '::' . $name } = \&$subname;
  16         67  
123              
124 16         96 $lazyloads{ $pkg }{ $name } = $func;
125             }
126              
127 17         92 return ~~1;
128             }
129              
130             sub unlazyload
131             {
132 3     3 1 3036 my $pkg = shift;
133              
134 3         6 foreach my $name ( keys %{ $lazyloads{ $pkg } } )
  3         18  
135             {
136 3         11 my $subname = __PACKAGE__ . '::' . $pkg . '::' . $name;
137              
138 3         13 local $^W = 0;
139 3         10 *{ $pkg . '::' . $name } = delete $lazyloads{ $pkg }{ $name };
  3         25  
140             }
141              
142 3         10 delete $lazyloads{ $pkg };
143              
144 3         13 return ~~1;
145             }
146              
147             sub _build
148             {
149 31     31   61 my @x = @{$_[0]};
  31         685  
150              
151 31         706 my $func = shift @x;
152 31         106 $_[0] = $func->(@x);
153              
154 31 100       289 die "INTERNAL ERROR: Cannot build instance of '$x[0]'\n"
155             unless defined $_[0];
156              
157             # This can occur if the class wasn't loaded correctly.
158 30 100       1166 die "INTERNAL ERROR: _build() failed to build a new object\n"
159             if ref($_[0]) eq __PACKAGE__;
160              
161 29         101 return ~~1;
162             }
163              
164             sub lazyload_one
165             {
166 4     4 1 2803 my ($pkg, $name, @args) = @_;
167              
168 4 100       22 die "Must pass in (CLASS, [ CONSTRUCTOR, [ARGS] ]) to lazyload_one().\n"
169             unless defined $pkg;
170              
171 3 100 100     24 $name = 'new' unless defined $name && length $name;
172              
173 3         12 _compile( $pkg );
174              
175 3         5 my $func = \&{ $pkg . '::' . $name };
  3         10  
176 3         16 bless [ $func, $pkg, @args ];
177             }
178             }
179              
180 38     38   10483 sub DESTROY{ undef }
181              
182             1;
183             __END__