File Coverage

blib/lib/Mouse/Exporter.pm
Criterion Covered Total %
statement 130 134 97.0
branch 50 54 92.5
condition 10 28 35.7
subroutine 17 19 89.4
pod 2 4 50.0
total 209 239 87.4


line stmt bran cond sub pod time code
1             package Mouse::Exporter;
2 284     284   994 use strict;
  284         341  
  284         6708  
3 284     284   879 use warnings;
  284         357  
  284         5513  
4 284     284   855 use Carp ();
  284         308  
  284         89532  
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   7273 strict->import;
14 974         14508 warnings->import('all', FATAL => 'recursion');
15 974         35786 return;
16             }
17              
18              
19             sub setup_import_methods{
20 975     975 1 8806 my($class, %args) = @_;
21              
22 975   33     8526 my $exporting_package = $args{exporting_package} ||= caller();
23              
24 975         8578 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   205 my($package, $level, undef, @args) = @_; # the third argument is redundant
        1      
        1      
        0      
32 1         3 $package->import({ into_level => $level + 1 }, @args);
33             },
34             export => sub {
35 1     1   915 my($package, $into, @args) = @_;
        1      
        1      
        0      
36 1         6 $package->import({ into => $into }, @args);
37             },
38 975         11386 );
39 975         2701 return;
40             }
41              
42             sub build_import_methods{
43 975     975 1 2752 my($self, %args) = @_;
44              
45 975   33     4294 my $exporting_package = $args{exporting_package} ||= caller();
46              
47 975         4171 $SPEC{$exporting_package} = \%args;
48              
49             # canonicalize args
50 975         2352 my @export_from;
51 975 100       2575 if($args{also}){
52 7         7 my %seen;
53 7         13 my @stack = ($exporting_package);
54              
55 7         21 while(my $current = shift @stack){
56 15         17 push @export_from, $current;
57              
58 15 100       48 my $also = $SPEC{$current}{also} or next;
59 8 100       19 push @stack, grep{ !$seen{$_}++ } ref($also) ? @{ $also } : $also;
  8         38  
  3         3  
60             }
61             }
62             else{
63 968         2114 @export_from = ($exporting_package);
64             }
65              
66 975         1724 my %exports;
67             my @removables;
68 0         0 my @all;
69              
70 0         0 my @init_meta_methods;
71              
72 975         1594 foreach my $package(@export_from){
73 983 50       5145 my $spec = $SPEC{$package} or next;
74              
75 983 100       3541 if(my $as_is = $spec->{as_is}){
76 978         1504 foreach my $thingy (@{$as_is}){
  978         2123  
77 13936         9684 my($code_package, $code_name, $code);
78              
79 13936 100       14165 if(ref($thingy)){
80 763         700 $code = $thingy;
81 763         2385 ($code_package, $code_name) = Mouse::Util::get_code_info($code);
82             }
83             else{
84 13173         9708 $code_package = $package;
85 13173         8602 $code_name = $thingy;
86 284     284   1845 no strict 'refs';
  284         347  
  284         190127  
87 13173         8806 $code = \&{ $code_package . '::' . $code_name };
  13173         37098  
88             }
89              
90 13936         14528 push @all, $code_name;
91 13936         13556 $exports{$code_name} = $code;
92 13936 100       19553 if($code_package eq $package){
93 13174         15818 push @removables, $code_name;
94             }
95             }
96             }
97              
98 983 100       12737 if(my $init_meta = $package->can('init_meta')){
99 384 50       1105 if(!grep{ $_ == $init_meta } @init_meta_methods){
  3         9  
100 384         790 push @init_meta_methods, $init_meta;
101             }
102             }
103             }
104 975         2629 $args{EXPORTS} = \%exports;
105 975         1220 $args{REMOVABLES} = \@removables;
106              
107 975   50     4790 $args{groups}{all} ||= \@all;
108              
109 975 100       2574 if(my $default_list = $args{groups}{default}){
110 284         329 my %default;
111 284         268 foreach my $keyword(@{$default_list}){
  284         520  
112 0   0     0 $default{$keyword} = $exports{$keyword}
113             || Carp::confess(qq{The $exporting_package package does not export "$keyword"});
114             }
115 284         493 $args{DEFAULT} = \%default;
116             }
117             else{
118 691   50     2534 $args{groups}{default} ||= \@all;
119 691         1003 $args{DEFAULT} = $args{EXPORTS};
120             }
121              
122 975 100       3154 if(@init_meta_methods){
123 381         556 $args{INIT_META} = \@init_meta_methods;
124             }
125              
126 975         2769 return (\&do_import, \&do_unimport);
127             }
128              
129             # the entity of general import()
130             sub do_import {
131 4175     4175 0 567734 my($package, @args) = @_;
132              
133 4175   33     10474 my $spec = $SPEC{$package}
134             || Carp::confess("The package $package package does not use Mouse::Exporter");
135              
136 4175 100       9838 my $into = _get_caller_package(ref($args[0]) ? shift @args : undef);
137              
138 4175         14086 my @exports;
139             my @traits;
140              
141 4175         7747 while(@args){
142 3394         3496 my $arg = shift @args;
143 3394 100       13029 if($arg =~ s/^-//){
    100          
144 17 50       31 if($arg eq 'traits'){
145 17 100       50 push @traits, ref($args[0]) ? @{shift(@args)} : shift(@args);
  10         29  
146             }
147             else {
148 0         0 Mouse::Util::not_supported("-$arg");
149             }
150             }
151             elsif($arg =~ s/^://){
152 2470   33     5330 my $group = $spec->{groups}{$arg}
153             || Carp::confess(qq{The $package package does not export the group "$arg"});
154 2470         1985 push @exports, @{$group};
  2470         7477  
155             }
156             else{
157 907         1807 push @exports, $arg;
158             }
159             }
160              
161 4175         16118 strict->import;
162 4175         50433 warnings->import('all', FATAL => 'recursion');
163              
164 4175 100       10589 if($spec->{INIT_META}){
    100          
165 763         804 my $meta;
166 763         722 foreach my $init_meta(@{$spec->{INIT_META}}){
  763         1424  
167 768         2100 $meta = $package->$init_meta(for_class => $into);
168             }
169              
170 763 100       1579 if(@traits){
171 16         53 my $type = (split /::/, ref $meta)[-1]; # e.g. "Class" for "My::Meta::Class"
172             @traits = map{
173 16 100       29 ref($_)
  19         55  
174             ? $_
175             : Mouse::Util::resolve_metaclass_alias($type => $_, trait => 1)
176             } @traits;
177              
178 16         411 require Mouse::Util::MetaRole;
179 16 100       44 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         30 Carp::confess("Cannot provide traits when $package does not have an init_meta() method");
189             }
190              
191 4174 100       5614 if(@exports){
192 2787         2054 my @export_table;
193 2787         2935 foreach my $keyword(@exports){
194             push @export_table,
195 10799   33     19727 $keyword => ($spec->{EXPORTS}{$keyword}
196             || Carp::confess(qq{The $package package does not export "$keyword"})
197             );
198             }
199 2787         27001 Mouse::Util::install_subroutines($into, @export_table);
200             }
201             else{
202 1387         1317 Mouse::Util::install_subroutines($into, %{$spec->{DEFAULT}});
  1387         16366  
203             }
204 4174         757759 return;
205             }
206              
207             # the entity of general unimport()
208             sub do_unimport {
209 64     64 0 10038 my($package, $arg) = @_;
210              
211 64   33     170 my $spec = $SPEC{$package}
212             || Carp::confess("The package $package does not use Mouse::Exporter");
213              
214 64         100 my $from = _get_caller_package($arg);
215              
216 64         262 my $stash = do{
217 284     284   1998 no strict 'refs';
  284         354  
  284         46460  
218 64         62 \%{$from . '::'}
  64         157  
219             };
220              
221 64         65 for my $keyword (@{ $spec->{REMOVABLES} }) {
  64         143  
222 693 100       887 next if !exists $stash->{$keyword};
223 685         526 my $gv = \$stash->{$keyword};
224              
225             # remove what is from us
226 685 100 66     965 if(ref($gv) eq 'GLOB' && *{$gv}{CODE} == $spec->{EXPORTS}{$keyword}){
  685         1618  
227 684         1022 delete $stash->{$keyword};
228             }
229             }
230 64         18787 return;
231             }
232              
233             sub _get_caller_package {
234 4239     4239   3735 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       5653 if(ref $arg){
239             return defined($arg->{into}) ? $arg->{into}
240             : defined($arg->{into_level}) ? scalar caller(1 + $arg->{into_level})
241 852 50       2065 : scalar caller(1);
    100          
242             }
243             else{
244 3387         7163 return scalar caller(1);
245             }
246             }
247              
248             1;
249             __END__