File Coverage

blib/lib/Mouse/Exporter.pm
Criterion Covered Total %
statement 132 134 98.5
branch 50 54 92.5
condition 10 28 35.7
subroutine 17 19 89.4
pod 2 4 50.0
total 211 239 88.2


line stmt bran cond sub pod time code
1             package Mouse::Exporter;
2 284     284   2309 use strict;
  284         1370  
  284         9607  
3 284     284   2317 use warnings;
  284         670  
  284         9405  
4 284     284   1709 use Carp ();
  284         699  
  284         125351  
5              
6             my %SPEC;
7              
8             # it must be "require", because Mouse::Util depends on Mouse::Exporter,
9             # which depends on Mouse::Util::import()
10             require Mouse::Util;
11              
12             sub import{
13 974     974   13202 strict->import;
14 974         19791 warnings->import('all', FATAL => 'recursion');
15 974         45226 return;
16             }
17              
18              
19             sub setup_import_methods{
20 975     975 1 19469 my($class, %args) = @_;
21              
22 975   33     11517 my $exporting_package = $args{exporting_package} ||= caller();
23              
24 975         11104 my($import, $unimport) = $class->build_import_methods(%args);
25              
26             Mouse::Util::install_subroutines($exporting_package,
27             import => $import,
28             unimport => $unimport,
29              
30             export_to_level => sub {
31 1     1   621 my($package, $level, undef, @args) = @_; # the third argument is redundant
        1      
        1      
        0      
32 1         8 $package->import({ into_level => $level + 1 }, @args);
33             },
34             export => sub {
35 1     1   737 my($package, $into, @args) = @_;
        1      
        1      
        0      
36 1         6 $package->import({ into => $into }, @args);
37             },
38 975         17935 );
39 975         4349 return;
40             }
41              
42             sub build_import_methods{
43 975     975 1 4181 my($self, %args) = @_;
44              
45 975   33     6929 my $exporting_package = $args{exporting_package} ||= caller();
46              
47 975         2796 $SPEC{$exporting_package} = \%args;
48              
49             # canonicalize args
50 975         2190 my @export_from;
51 975 100       4739 if($args{also}){
52 7         15 my %seen;
53 7         19 my @stack = ($exporting_package);
54              
55 7         34 while(my $current = shift @stack){
56 15         32 push @export_from, $current;
57              
58 15 100       64 my $also = $SPEC{$current}{also} or next;
59 8 100       29 push @stack, grep{ !$seen{$_}++ } ref($also) ? @{ $also } : $also;
  8         59  
  3         11  
60             }
61             }
62             else{
63 968         3324 @export_from = ($exporting_package);
64             }
65              
66 975         7005 my %exports;
67             my @removables;
68 975         0 my @all;
69              
70 975         0 my @init_meta_methods;
71              
72 975         3714 foreach my $package(@export_from){
73 983 50       5859 my $spec = $SPEC{$package} or next;
74              
75 983 100       5075 if(my $as_is = $spec->{as_is}){
76 978         4063 foreach my $thingy (@{$as_is}){
  978         3520  
77 13936         24888 my($code_package, $code_name, $code);
78              
79 13936 100       29926 if(ref($thingy)){
80 763         1465 $code = $thingy;
81 763         5196 ($code_package, $code_name) = Mouse::Util::get_code_info($code);
82             }
83             else{
84 13173         21754 $code_package = $package;
85 13173         22745 $code_name = $thingy;
86 284     284   2297 no strict 'refs';
  284         2639  
  284         268418  
87 13173         22399 $code = \&{ $code_package . '::' . $code_name };
  13173         59939  
88             }
89              
90 13936         33691 push @all, $code_name;
91 13936         31156 $exports{$code_name} = $code;
92 13936 100       36032 if($code_package eq $package){
93 13174         31901 push @removables, $code_name;
94             }
95             }
96             }
97              
98 983 100       14749 if(my $init_meta = $package->can('init_meta')){
99 384 50       1933 if(!grep{ $_ == $init_meta } @init_meta_methods){
  3         13  
100 384         1517 push @init_meta_methods, $init_meta;
101             }
102             }
103             }
104 975         3556 $args{EXPORTS} = \%exports;
105 975         3280 $args{REMOVABLES} = \@removables;
106              
107 975   50     8584 $args{groups}{all} ||= \@all;
108              
109 975 100       4454 if(my $default_list = $args{groups}{default}){
110 284         2292 my %default;
111 284         1418 foreach my $keyword(@{$default_list}){
  284         1481  
112 0   0     0 $default{$keyword} = $exports{$keyword}
113             || Carp::confess(qq{The $exporting_package package does not export "$keyword"});
114             }
115 284         855 $args{DEFAULT} = \%default;
116             }
117             else{
118 691   50     4535 $args{groups}{default} ||= \@all;
119 691         1961 $args{DEFAULT} = $args{EXPORTS};
120             }
121              
122 975 100       5707 if(@init_meta_methods){
123 381         1077 $args{INIT_META} = \@init_meta_methods;
124             }
125              
126 975         7250 return (\&do_import, \&do_unimport);
127             }
128              
129             # the entity of general import()
130             sub do_import {
131 4175     4175 0 799603 my($package, @args) = @_;
132              
133 4175   33     15903 my $spec = $SPEC{$package}
134             || Carp::confess("The package $package package does not use Mouse::Exporter");
135              
136 4175 100       16585 my $into = _get_caller_package(ref($args[0]) ? shift @args : undef);
137              
138 4175         26911 my @exports;
139             my @traits;
140              
141 4175         13412 while(@args){
142 3394         7645 my $arg = shift @args;
143 3394 100       20505 if($arg =~ s/^-//){
    100          
144 17 50       56 if($arg eq 'traits'){
145 17 100       62 push @traits, ref($args[0]) ? @{shift(@args)} : shift(@args);
  10         43  
146             }
147             else {
148 0         0 Mouse::Util::not_supported("-$arg");
149             }
150             }
151             elsif($arg =~ s/^://){
152 2470   33     9315 my $group = $spec->{groups}{$arg}
153             || Carp::confess(qq{The $package package does not export the group "$arg"});
154 2470         4980 push @exports, @{$group};
  2470         11153  
155             }
156             else{
157 907         3009 push @exports, $arg;
158             }
159             }
160              
161 4175         27540 strict->import;
162 4175         74387 warnings->import('all', FATAL => 'recursion');
163              
164 4175 100       17952 if($spec->{INIT_META}){
    100          
165 763         1628 my $meta;
166 763         1493 foreach my $init_meta(@{$spec->{INIT_META}}){
  763         2250  
167 768         2920 $meta = $package->$init_meta(for_class => $into);
168             }
169              
170 763 100       2792 if(@traits){
171 16         85 my $type = (split /::/, ref $meta)[-1]; # e.g. "Class" for "My::Meta::Class"
172             @traits = map{
173 16 100       47 ref($_)
  19         86  
174             ? $_
175             : Mouse::Util::resolve_metaclass_alias($type => $_, trait => 1)
176             } @traits;
177              
178 16         427 require Mouse::Util::MetaRole;
179 16 100       67 Mouse::Util::MetaRole::apply_metaroles(
180             for => $into,
181             Mouse::Util::is_a_metarole($into->meta)
182             ? (role_metaroles => { role => \@traits })
183             : (class_metaroles => { class => \@traits }),
184             );
185             }
186             }
187             elsif(@traits){
188 1         26 Carp::confess("Cannot provide traits when $package does not have an init_meta() method");
189             }
190              
191 4174 100       11208 if(@exports){
192 2787         5062 my @export_table;
193 2787         5575 foreach my $keyword(@exports){
194             push @export_table,
195 10799   33     37225 $keyword => ($spec->{EXPORTS}{$keyword}
196             || Carp::confess(qq{The $package package does not export "$keyword"})
197             );
198             }
199 2787         37890 Mouse::Util::install_subroutines($into, @export_table);
200             }
201             else{
202 1387         2795 Mouse::Util::install_subroutines($into, %{$spec->{DEFAULT}});
  1387         23773  
203             }
204 4174         950814 return;
205             }
206              
207             # the entity of general unimport()
208             sub do_unimport {
209 64     64 0 15065 my($package, $arg) = @_;
210              
211 64   33     343 my $spec = $SPEC{$package}
212             || Carp::confess("The package $package does not use Mouse::Exporter");
213              
214 64         194 my $from = _get_caller_package($arg);
215              
216 64         542 my $stash = do{
217 284     284   7074 no strict 'refs';
  284         754  
  284         62419  
218 64         129 \%{$from . '::'}
  64         327  
219             };
220              
221 64         179 for my $keyword (@{ $spec->{REMOVABLES} }) {
  64         226  
222 693 100       1754 next if !exists $stash->{$keyword};
223 685         1339 my $gv = \$stash->{$keyword};
224              
225             # remove what is from us
226 685 100 66     1898 if(ref($gv) eq 'GLOB' && *{$gv}{CODE} == $spec->{EXPORTS}{$keyword}){
  685         2625  
227 684         2013 delete $stash->{$keyword};
228             }
229             }
230 64         23841 return;
231             }
232              
233             sub _get_caller_package {
234 4239     4239   9612 my($arg) = @_;
235              
236             # We need one extra level because it's called by import so there's a layer
237             # of indirection
238 4239 100       11034 if(ref $arg){
239             return defined($arg->{into}) ? $arg->{into}
240             : defined($arg->{into_level}) ? scalar caller(1 + $arg->{into_level})
241 852 50       3553 : scalar caller(1);
    100          
242             }
243             else{
244 3387         12171 return scalar caller(1);
245             }
246             }
247              
248             1;
249             __END__