File Coverage

blib/lib/Export/Lexical.pm
Criterion Covered Total %
statement 92 93 98.9
branch 12 20 60.0
condition 1 3 33.3
subroutine 16 16 100.0
pod n/a
total 121 132 91.6


line stmt bran cond sub pod time code
1             package Export::Lexical;
2              
3 4     4   155287 use 5.010;
  4         18  
  4         192  
4 4     4   27 use strict;
  4         8  
  4         139  
5 4     4   3918 use version; our $VERSION = qv('0.0.4');
  4         12057  
  4         33  
6              
7 4     4   573 use B;
  4         8  
  4         244  
8 4     4   25 use Carp;
  4         9  
  4         2189  
9              
10             my %Exports_for = ();
11             my %Modifier_for = (); # e.g., $Modifier_for{$pkg} = 'silent'
12              
13             sub MODIFY_CODE_ATTRIBUTES {
14 6     6   9042 my ( $package, $coderef, @attrs ) = @_;
15              
16 6         12 my @unused_attrs = ();
17              
18 6         27 while ( my $attr = shift @attrs ) {
19 6 50       87 if ( $attr ~~ /^Export_?Lexical$/i ) {
20 6         11 push @{ $Exports_for{$package} }, $coderef;
  6         46  
21             }
22             else {
23 0         0 push @unused_attrs, $attr;
24             }
25             }
26              
27 6         23 return @unused_attrs;
28             }
29              
30             sub import {
31 4     4   36 my ($class) = @_;
32              
33 4         21 my $caller = caller;
34 4         53 my $key = _get_key($caller);
35 4         8 my @params = ();
36              
37             {
38             # Export our subroutines, if necessary.
39 4     4   33 no strict 'refs'; ## no critic (ProhibitNoStrict)
  4         8  
  4         2746  
  4         9  
40              
41 4 50       9 if ( !exists &{ $caller . '::MODIFY_CODE_ATTRIBUTES' } ) {
  4         33  
42 4         10 *{ $caller . '::MODIFY_CODE_ATTRIBUTES' } = \&MODIFY_CODE_ATTRIBUTES;
  4         28  
43             }
44              
45 4 50       17 if ( !exists &{ $caller . '::import' } ) {
  4         20  
46 4         26 *{ $caller . '::import' } = sub {
47 3     3   476 my ( $class, @args ) = @_;
48              
49 3         16 _export_all_to( $caller, scalar caller );
50              
51 3 50       368 $^H{$key} = @args ? ( join ',', @args ) : 1;
52 4         24 };
53             }
54              
55 4 50       5 if ( !exists &{ $caller . '::unimport' } ) {
  4         27  
56 4         19 *{ $caller . '::unimport' } = sub {
57 6     6   51 my ( $class, @args ) = @_;
58              
59 6 100       22 if ( @args ) {
60             # Leave the '1' on the front of the list from a previous 'use
61             # $module', as well as any subs previously imported.
62 3         13 $^H{$key} = join ',', $^H{$key}, map { "!$_" } @args;
  3         5198  
63             }
64             else {
65 3         557 $^H{$key} = '';
66             }
67 4         20 };
68             }
69             }
70              
71 4         36 while ( my $_ = shift ) {
72 6 100       52 if ( /^:(silent|warn)$/ ) {
73 2 50       8 croak qq('$_' requested when '$Modifier_for{$caller}' already in use)
74             if $Modifier_for{$caller};
75              
76 2         4 $Modifier_for{$caller} = $_;
77 2         94 next;
78             }
79              
80 4         73 push @params, $_;
81             }
82             }
83              
84             sub _export_all_to {
85 3     3   38 my ( $from, $caller ) = @_;
86              
87 3 50       17 return if !exists $Exports_for{$from};
88              
89 3         8 for my $ref ( @{ $Exports_for{$from} } ) {
  3         12  
90 6         58 my $obj = B::svref_2object($ref);
91 6         72 my $pkg = $obj->GV->STASH->NAME;
92 6         156 my $sub = $obj->GV->NAME;
93 6         21 my $key = _get_key($pkg);
94              
95 4     4   29 no strict 'refs'; ## no critic (ProhibitNoStrict)
  4         8  
  4         146  
96 4     4   24 no warnings 'redefine';
  4         9  
  4         3805  
97              
98 6 50       11 next if exists &{ $caller . '::' . $sub };
  6         35  
99              
100 6         81 *{ $caller . '::' . $sub } = sub {
101 24     24   34873 my $hints = (caller(0))[10];
102              
103 24         647 given ( $hints->{$key} ) {
104 24         930 my $re = qr/\b!$sub\b/;
105              
106 24         101 when ( '' ) { return _fail( $pkg, $sub ); } # no $module
  6         23  
107 18         219 when ( /!$sub\b/ ) { return _fail( $pkg, $sub ); } # no $module '$sub'
  3         17  
108              
109 15   33     130 when ( /^1\b/ || /\b$sub\b/ ) { goto $ref; } # use $module
  15         136  
110             # use $module '$sub'
111             }
112 6         33 };
113             }
114             }
115              
116             sub _fail {
117 9     9   24 my ( $pkg, $sub ) = @_;
118              
119 9         23 given ( $Modifier_for{$pkg} ) {
120 9         24 when (':silent') { return }
  3         30  
121 6         13 when (':warn') { carp "$pkg\::$sub not allowed here" }
  3         53  
122              
123 3         56 croak "$pkg\::$sub not allowed here";
124             }
125             }
126              
127             sub _get_key {
128 10     10   22 my ($pkg) = @_;
129              
130 10         34 return __PACKAGE__ . '/' . $pkg;
131             }
132              
133             1;
134              
135             __END__