summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2012-01-04 17:52:12 -0600
committerJesse Luehrs <doy@tozt.net>2012-01-04 17:57:37 -0600
commit79b443187ee06d8ee7eedc29012e2b68235e3cd1 (patch)
treecc0d02a87ca053e4ea5a7f3b3a65a7758ed2db13
parent769d407137b20818b5ca38ab8b0904e9c1eb7a5d (diff)
downloadcircular-require-79b443187ee06d8ee7eedc29012e2b68235e3cd1.tar.gz
circular-require-79b443187ee06d8ee7eedc29012e2b68235e3cd1.zip
use filenames in the "from" part too
this also stops using "caller", which can produce incorrect results if there are multiple packages in a file, or if you follow it up too far (saying that the cycle is from 'main' isn't correct)
-rw-r--r--lib/circular/require.pm36
-rw-r--r--t/basic.t6
-rw-r--r--t/hide_middleman.t2
-rw-r--r--t/hide_middleman2.t2
4 files changed, 29 insertions, 17 deletions
diff --git a/lib/circular/require.pm b/lib/circular/require.pm
index c05b935..db1738f 100644
--- a/lib/circular/require.pm
+++ b/lib/circular/require.pm
@@ -48,9 +48,10 @@ or
=cut
-my %being_loaded;
+our %being_loaded;
my $saved;
my @hide;
+our $current;
sub _require {
my ($file) = @_;
@@ -58,20 +59,19 @@ sub _require {
# treat it as a vstring, so be sure we don't use the incoming value in
# string contexts at all
my $string_file = $file;
- if ($being_loaded{$string_file}) {
- my $depth = 0;
- my $caller;
+ if (exists $being_loaded{$string_file}) {
+ my $caller = $current;
- do {
- $caller = caller($depth++)
- } while defined($caller) && grep { m/^$caller$/ } @hide;
+ $caller = $being_loaded{$caller}
+ while defined($caller) && grep { m/^$caller$/ } @hide;
$caller = '<unknown package>'
unless defined $caller;
warn "Circular require detected: $string_file (from $caller)\n";
}
- $being_loaded{$string_file} = 1;
+ local $being_loaded{$string_file} = $current;
+ local $current = $string_file;
my $ret;
# XXX ugh, base.pm checks against the regex
# /^Can't locate .*? at \(eval / to see if it should suppress the error
@@ -79,9 +79,7 @@ sub _require {
# definitely break if some other module that overrides CORE::require tries
# to do the same thing
if (caller eq 'base') {
- my $mod = $file;
- $mod =~ s+[/\\]+::+g;
- $mod =~ s+\.pm$++;
+ my $mod = _pm2mod($file);
$ret = $saved
? $saved->($file)
: (eval "CORE::require $mod" || die $@);
@@ -89,7 +87,6 @@ sub _require {
else {
$ret = $saved ? $saved->($file) : CORE::require($file);
}
- delete $being_loaded{$string_file};
return $ret;
}
@@ -109,6 +106,7 @@ sub unimport {
@hide = ref($params{'-hide'}) ? @{ $params{'-hide'} } : ($params{'-hide'})
if exists $params{'-hide'};
+ @hide = map { /\.pm/ ? $_ : _mod2pm($_) } @hide;
my $stash = Package::Stash->new('CORE::GLOBAL');
my $old_require = $stash->get_package_symbol('&require');
@@ -117,6 +115,20 @@ sub unimport {
$stash->add_package_symbol('&require', \&_require);
}
+sub _mod2pm {
+ my ($mod) = @_;
+ $mod =~ s+::+/+g;
+ $mod .= '.pm';
+ return $mod;
+}
+
+sub _pm2mod {
+ my ($file) = @_;
+ $file =~ s+/+::+g;
+ $file =~ s+\.pm$++;
+ return $file;
+}
+
=head1 CAVEATS
This module works by overriding C<CORE::GLOBAL::require>, and so other modules
diff --git a/t/basic.t b/t/basic.t
index 62d92f5..ea59925 100644
--- a/t/basic.t
+++ b/t/basic.t
@@ -12,7 +12,7 @@ circular::require->unimport;
my $warnings;
local $SIG{__WARN__} = sub { $warnings .= $_[0] };
use_ok('Foo');
- is($warnings, "Circular require detected: Foo.pm (from Baz)\nCircular require detected: Baz.pm (from Bar)\n", "correct warnings");
+ is($warnings, "Circular require detected: Foo.pm (from Baz.pm)\nCircular require detected: Baz.pm (from Bar.pm)\n", "correct warnings");
clear();
}
@@ -20,7 +20,7 @@ circular::require->unimport;
my $warnings;
local $SIG{__WARN__} = sub { $warnings .= $_[0] };
use_ok('Bar');
- is($warnings, "Circular require detected: Baz.pm (from Foo)\nCircular require detected: Bar.pm (from Baz)\n", "correct warnings");
+ is($warnings, "Circular require detected: Baz.pm (from Foo.pm)\nCircular require detected: Bar.pm (from Baz.pm)\n", "correct warnings");
clear();
}
@@ -28,7 +28,7 @@ circular::require->unimport;
my $warnings;
local $SIG{__WARN__} = sub { $warnings .= $_[0] };
use_ok('Baz');
- is($warnings, "Circular require detected: Baz.pm (from Foo)\n", "correct warnings");
+ is($warnings, "Circular require detected: Baz.pm (from Foo.pm)\nCircular require detected: Baz.pm (from Bar.pm)\n", "correct warnings");
clear();
}
diff --git a/t/hide_middleman.t b/t/hide_middleman.t
index 72fa9c6..90950b2 100644
--- a/t/hide_middleman.t
+++ b/t/hide_middleman.t
@@ -16,7 +16,7 @@ my @warnings;
is_deeply(
\@warnings,
- ["Circular require detected: Foo.pm (from Bar)\n"],
+ ["Circular require detected: Foo.pm (from Bar.pm)\n"],
"Show the module that used base, instead of 'base' when a cycle occurs from a use base."
);
diff --git a/t/hide_middleman2.t b/t/hide_middleman2.t
index 917674b..bb3092a 100644
--- a/t/hide_middleman2.t
+++ b/t/hide_middleman2.t
@@ -16,7 +16,7 @@ my @warnings;
is_deeply(
\@warnings,
- ["Circular require detected: Foo.pm (from Bar)\n"],
+ ["Circular require detected: Foo.pm (from Bar.pm)\n"],
"Show the module that used base, instead of 'base' when a cycle occurs from a use base."
);