File Coverage

blib/lib/circular/require.pm
Criterion Covered Total %
statement 31 31 100.0
branch 8 10 80.0
condition n/a
subroutine 9 9 100.0
pod n/a
total 48 50 96.0


line stmt bran cond sub pod time code
1             package circular::require;
2             BEGIN {
3 14     14   321250 $circular::require::AUTHORITY = 'cpan:DOY';
4             }
5             {
6             $circular::require::VERSION = '0.11';
7             }
8 14     14   129 use strict;
  14         29  
  14         456  
9 14     14   69 use warnings;
  14         25  
  14         400  
10             # ABSTRACT: detect circularity in use/require statements
11              
12 14     14   334 use 5.010;
  14         45  
  14         608  
13 14     14   13867 use Devel::OverrideGlobalRequire;
  14         15121  
  14         552  
14 14     14   20108 use Module::Runtime 'module_notional_filename';
  14         26685  
  14         85  
15              
16              
17             our %loaded_from;
18             our $previous_file;
19             my @hide;
20              
21             Devel::OverrideGlobalRequire::override_global_require {
22             my ($require, $file) = @_;
23              
24             if (exists $loaded_from{$file}) {
25             my @cycle = ($file);
26              
27             my $caller = $previous_file;
28              
29             while (defined($caller)) {
30             unshift @cycle, $caller
31             unless grep { /^$caller$/ } @hide;
32             last if $caller eq $file;
33             $caller = $loaded_from{$caller};
34             }
35              
36             if (_find_enable_state()) {
37             if (@cycle > 1) {
38             warn "Circular require detected:\n " . join("\n ", @cycle) . "\n";
39             }
40             else {
41             warn "Circular require detected in $file (from unknown file)\n";
42             }
43             }
44             }
45              
46             local $loaded_from{$file} = $previous_file;
47             local $previous_file = $file;
48              
49             $require->();
50             };
51              
52             sub import {
53             # not delete, because we want to see it being explicitly disabled
54 5     5   3707 $^H{'circular::require'} = 0;
55             }
56              
57             sub unimport {
58 17     17   1074 my $class = shift;
59 17         44 my %params = @_;
60              
61 17 100       99 @hide = ref($params{'-hide'}) ? @{ $params{'-hide'} } : ($params{'-hide'})
  3 100       11  
62             if exists $params{'-hide'};
63 17 50       65 @hide = map { /\.pm$/ ? $_ : module_notional_filename($_) } @hide;
  10         268  
64              
65 17         16461 $^H{'circular::require'} = 1;
66             }
67              
68             sub _find_enable_state {
69 28     28   35 my $depth = 0;
70 28         86 while (defined(scalar(caller(++$depth)))) {
71 759         2082 my $hh = (caller($depth))[10];
72 759 100       2428 next unless defined $hh;
73 27 50       70 next unless exists $hh->{'circular::require'};
74 27         114 return $hh->{'circular::require'};
75             }
76 1         4 return 0;
77             }
78              
79              
80             1;
81              
82             __END__