File Coverage

blib/lib/Linux/Statm/Tiny/Mite.pm
Criterion Covered Total %
statement 64 175 36.5
branch 16 68 23.5
condition 5 25 20.0
subroutine 13 31 41.9
pod 1 12 8.3
total 99 311 31.8


line stmt bran cond sub pod time code
1             # NOTE: Since the intention is to ship this file with a project, this file
2             # cannot have any non-core dependencies.
3             package Linux::Statm::Tiny::Mite;
4 3     3   54 use 5.008001;
  3         15  
5 3     3   28 use strict;
  3         5  
  3         86  
6 3     3   11 use warnings;
  3         6  
  3         221  
7 3     3   19 no strict 'refs';
  3         6  
  3         1324  
8              
9             if ( $] < 5.009005 ) { require MRO::Compat; }
10             else { require mro; }
11              
12             defined ${^GLOBAL_PHASE}
13             or eval { require Devel::GlobalDestruction; 1 }
14             or do {
15             carp( "WARNING: Devel::GlobalDestruction recommended!" );
16             *Devel::GlobalDestruction::in_global_destruction = sub { undef; };
17             };
18              
19             # Constants
20             sub true () { !!1 } sub false () { !!0 }
21             sub ro () { 'ro' } sub rw () { 'rw' } sub rwp () { 'rwp' }
22             sub lazy () { 'lazy' } sub bare () { 'bare' }
23              
24             # More complicated constants
25             BEGIN {
26 3     3   16 my @bool = ( \&false, \&true );
27 3         34 *_HAS_AUTOCLEAN = $bool[ 0+!! eval { require namespace::autoclean } ];
  3         1832  
28 3   0     80761 *STRICT = $bool[ 0+!! ( $ENV{PERL_STRICT} || $ENV{EXTENDED_TESTING} || $ENV{AUTHOR_TESTING} || $ENV{RELEASE_TESTING} ) ];
29             };
30              
31             # Exportable error handlers
32             sub _error_handler {
33 0     0   0 my ( $func, $message, @args ) = @_;
34 0 0       0 if ( @args ) {
35 0         0 require Data::Dumper;
36 0         0 local $Data::Dumper::Terse = 1;
37 0         0 local $Data::Dumper::Indent = 0;
38             $message = sprintf $message, map {
39 0 0       0 ref($_) ? Data::Dumper::Dumper($_) : defined($_) ? $_ : '(undef)'
  0 0       0  
40             } @args;
41             }
42 0         0 my $next = do { require Carp; \&{"Carp::$func"} };
  0         0  
  0         0  
  0         0  
43 0         0 @_ = ( $message );
44 0         0 goto $next;
45             }
46              
47 0     0 0 0 sub carp { unshift @_, 'carp' ; goto \&_error_handler }
  0         0  
48 0     0 0 0 sub croak { unshift @_, 'croak' ; goto \&_error_handler }
  0         0  
49 0     0 0 0 sub confess { unshift @_, 'confess'; goto \&_error_handler }
  0         0  
50              
51             # Exportable guard function
52             {
53             my $GUARD_PACKAGE = __PACKAGE__ . '::Guard';
54 0 0   0   0 *{"$GUARD_PACKAGE\::DESTROY"} = sub { $_[0][0] or $_[0][1]->() };
55 0     0   0 *{"$GUARD_PACKAGE\::restore"} = sub { $_[0]->DESTROY; $_[0][0] = true };
  0         0  
56 0     0   0 *{"$GUARD_PACKAGE\::dismiss"} = sub { $_[0][0] = true };
57 0     0   0 *{"$GUARD_PACKAGE\::peek"} = sub { $_[0][2] };
58 0     0   0 *guard = sub (&) { bless [ 0, @_ ] => $GUARD_PACKAGE };
59             }
60              
61             # Exportable lock and unlock
62             sub _lul {
63 0     0   0 my ( $lul, $ref ) = @_;
64 0 0       0 if ( ref $ref eq 'ARRAY' ) {
65 0         0 &Internals::SvREADONLY( $ref, $lul );
66 0         0 &Internals::SvREADONLY( \$_, $lul ) for @$ref;
67 0         0 return;
68             }
69 0 0       0 if ( ref $ref eq 'HASH' ) {
70 0         0 &Internals::hv_clear_placeholders( $ref );
71 0         0 &Internals::SvREADONLY( $ref, $lul );
72 0         0 &Internals::SvREADONLY( \$_, $lul ) for values %$ref;
73 0         0 return;
74             }
75 0         0 return;
76             }
77              
78             sub lock {
79 0     0 0 0 unshift @_, true;
80 0         0 goto \&_lul;
81             }
82              
83             sub unlock {
84 0     0 0 0 my $ref = shift;
85 0         0 _lul( 0 , $ref );
86 0     0   0 &guard( sub { _lul( 1, $ref ) } );
  0         0  
87             }
88              
89             sub _is_compiling {
90 3 50   3   19 defined $Mite::COMPILING and $Mite::COMPILING eq __PACKAGE__;
91             }
92              
93             sub import {
94 3     3   9 my $me = shift;
95 3         16 my %arg = map +( lc($_) => true ), @_;
96 3         17 my ( $caller, $file ) = caller;
97              
98 3 50       11 if( _is_compiling() ) {
99 0         0 require Mite::Project;
100 0         0 'Mite::Project'->default->inject_mite_functions(
101             'package' => $caller,
102             'file' => $file,
103             'arg' => \%arg,
104             'shim' => $me,
105             );
106             }
107             else {
108             # Try to determine original filename for caller, minus libdir.
109             # This would normally be in %INC but caller hasn't finished loading yet.
110 3         18 require File::Spec;
111 3         19 my $orig = $file;
112 3         8 for my $base ( @INC ) {
113 6 50 66     706 $base eq substr $file, 0, length $base
      66        
114             and -f File::Spec->catfile( $base, substr $file, 1 + length $base )
115             and $orig = File::Spec->abs2rel( $file, $base )
116             and last;
117             }
118              
119             # Changes to this filename must be coordinated with Mite::Compiled
120 3         26 my $mite_file = $orig . '.mite.pm';
121 3         5 local $@;
122 3 50       34 if ( not eval { require $mite_file; 1 } ) {
  3         2148  
  3         22  
123 0         0 my $e = $@;
124 0         0 croak "Compiled Mite file ($mite_file) for $file is missing or an error occurred loading it: $e";
125             }
126             }
127              
128 3         85 'warnings'->import;
129 3         88 'strict'->import;
130             'namespace::autoclean'->import( -cleanee => $caller )
131 3 50       109 if _HAS_AUTOCLEAN && !$arg{'-unclean'};
132             }
133              
134             {
135             my ( $cb_before, $cb_after );
136             sub _finalize_application_roletiny {
137 0     0   0 my ( $me, $role, $caller, $args ) = @_;
138 0 0       0 if ( $INC{'Role/Hooks.pm'} ) {
139 0   0     0 $cb_before ||= \%Role::Hooks::CALLBACKS_BEFORE_APPLY;
140 0   0     0 $cb_after ||= \%Role::Hooks::CALLBACKS_AFTER_APPLY;
141             }
142 0 0       0 if ( $cb_before ) {
143 0 0       0 $_->( $role, $caller ) for @{ $cb_before->{$role} || [] };
  0         0  
144             }
145 0         0 'Role::Tiny'->_check_requires( $caller, $role );
146 0         0 my $info = $Role::Tiny::INFO{$role};
147 0 0       0 for ( @{ $info->{modifiers} || [] } ) {
  0         0  
148 0         0 my @args = @$_;
149 0         0 my $modification = shift @args;
150 0         0 my $handler = "HANDLE_$modification";
151 0         0 $me->$handler( $caller, undef, @args );
152             }
153 0 0       0 if ( $cb_after ) {
154 0 0       0 $_->( $role, $caller ) for @{ $cb_after->{$role} || [] };
  0         0  
155             }
156 0         0 return;
157             }
158              
159             # Usage: $me, $caller, @with_args
160             sub HANDLE_with {
161 0     0 0 0 my ( $me, $caller ) = ( shift, shift );
162 0         0 while ( @_ ) {
163 0         0 my $role = shift;
164 0 0       0 my $args = ref($_[0]) ? shift : undef;
165 0 0 0     0 if ( $INC{'Role/Tiny.pm'} and 'Role::Tiny'->is_role( $role ) ) {
166 0         0 $me->_finalize_application_roletiny( $role, $caller, $args );
167             }
168             else {
169 0         0 $role->__FINALIZE_APPLICATION__( $caller, $args );
170             }
171             }
172 0         0 return;
173             }
174             }
175              
176             # Usage: $me, $caller, $keyword, @has_args
177             sub HANDLE_has {
178 90     90 0 197 my ( $me, $caller, $keyword, $names ) = ( shift, shift, shift, shift );
179 90 50       211 if ( @_ % 2 ) {
180 0         0 my $default = shift;
181 0 0       0 unshift @_, ( 'CODE' eq ref( $default ) )
182             ? ( is => lazy, builder => $default )
183             : ( is => ro, default => $default );
184             }
185 90         296 my %spec = @_;
186 90         129 my $code;
187 90 50       197 for my $name ( ref($names) ? @$names : $names ) {
188 90         154 $name =~ s/^\+//;
189             'CODE' eq ref( $code = $spec{default} )
190 90 100       203 and ${"$caller\::__$name\_DEFAULT__"} = $code;
  87         361  
191             'CODE' eq ref( $code = $spec{builder} )
192 90 50       223 and *{"$caller\::_build_$name"} = $code;
  0         0  
193             'CODE' eq ref( $code = $spec{trigger} )
194 90 50       183 and *{"$caller\::_trigger_$name"} = $code;
  0         0  
195             'CODE' eq ref( $code = $spec{clone} )
196 90 50       206 and *{"$caller\::_clone_$name"} = $code;
  0         0  
197             }
198 90         272 return;
199             }
200              
201             {
202             my $_kind = sub { ${ shift() . '::USES_MITE' } =~ /Role/ ? 'role' : 'class' };
203              
204             sub _get_orig_method {
205 3     3   7 my ( $caller, $name ) = @_;
206 3         21 my $orig = $caller->can( $name );
207 3 50       15 return $orig if $orig;
208 0         0 croak "Cannot modify method $name in $caller: no such method";
209             }
210              
211             sub _parse_mm_args {
212 3     3   25 my $coderef = pop;
213 3 50       11 my $names = [ map { ref($_) ? @$_ : $_ } @_ ];
  3         17  
214 3         11 ( $names, $coderef );
215             }
216              
217             # Usage: $me, $caller, $caller_kind, @before_args
218             sub HANDLE_before {
219 0     0 0 0 my ( $me, $caller, $kind ) = ( shift, shift, shift );
220 0         0 my ( $names, $coderef ) = &_parse_mm_args;
221 0   0     0 $kind ||= $caller->$_kind;
222 0 0       0 if ( $kind eq 'role' ) {
223 0         0 push @{"$caller\::METHOD_MODIFIERS"},
  0         0  
224             [ before => $names, $coderef ];
225 0         0 return;
226             }
227 0         0 for my $name ( @$names ) {
228 0         0 my $orig = _get_orig_method( $caller, $name );
229 0         0 local $@;
230 0 0       0 eval <<"BEFORE" or die $@;
231             package $caller;
232             no warnings 'redefine';
233             sub $name {
234             \$coderef->( \@_ );
235             \$orig->( \@_ );
236             }
237             1;
238             BEFORE
239             }
240 0         0 return;
241             }
242              
243             # Usage: $me, $caller, $caller_kind, @after_args
244             sub HANDLE_after {
245 0     0 0 0 my ( $me, $caller, $kind ) = ( shift, shift, shift );
246 0         0 my ( $names, $coderef ) = &_parse_mm_args;
247 0   0     0 $kind ||= $caller->$_kind;
248 0 0       0 if ( $kind eq 'role' ) {
249 0         0 push @{"$caller\::METHOD_MODIFIERS"},
  0         0  
250             [ after => $names, $coderef ];
251 0         0 return;
252             }
253 0         0 for my $name ( @$names ) {
254 0         0 my $orig = _get_orig_method( $caller, $name );
255 0         0 local $@;
256 0 0       0 eval <<"AFTER" or die $@;
257             package $caller;
258             no warnings 'redefine';
259             sub $name {
260             my \@r;
261             if ( wantarray ) {
262             \@r = \$orig->( \@_ );
263             }
264             elsif ( defined wantarray ) {
265             \@r = scalar \$orig->( \@_ );
266             }
267             else {
268             \$orig->( \@_ );
269             1;
270             }
271             \$coderef->( \@_ );
272             wantarray ? \@r : \$r[0];
273             }
274             1;
275             AFTER
276             }
277 0         0 return;
278             }
279              
280             # Usage: $me, $caller, $caller_kind, @around_args
281             sub HANDLE_around {
282 3     3 0 74 my ( $me, $caller, $kind ) = ( shift, shift, shift );
283 3         13 my ( $names, $coderef ) = &_parse_mm_args;
284 3   33     14 $kind ||= $caller->$_kind;
285 3 50       9 if ( $kind eq 'role' ) {
286 0         0 push @{"$caller\::METHOD_MODIFIERS"},
  0         0  
287             [ around => $names, $coderef ];
288 0         0 return;
289             }
290 3         9 for my $name ( @$names ) {
291 3         13 my $orig = _get_orig_method( $caller, $name );
292 3         25 local $@;
293 3 50   3 1 23 eval <<"AROUND" or die $@;
  3     1   5  
  3         350  
  3         377  
  1         15  
294             package $caller;
295             no warnings 'redefine';
296             sub $name {
297             \$coderef->( \$orig, \@_ );
298             }
299             1;
300             AROUND
301             }
302 3         13 return;
303             }
304             }
305              
306             # Usage: $me, $caller, $caller_kind, @signature_for_args
307             sub HANDLE_signature_for {
308 0     0 0   my ( $me, $caller, $kind, $name ) = @_;
309 0           $name =~ s/^\+//;
310 0           $me->HANDLE_around( $caller, $kind, $name, ${"$caller\::SIGNATURE_FOR"}{$name} );
  0            
311 0           return;
312             }
313              
314             1;
315              
316             __END__