| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Module::UseFrom; | 
| 2 |  |  |  |  |  |  | { | 
| 3 |  |  |  |  |  |  | $Module::UseFrom::VERSION = '0.03_001'; | 
| 4 |  |  |  |  |  |  | } | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 6 |  |  | 6 |  | 327109 | use strict; | 
|  | 6 |  |  |  |  | 16 |  | 
|  | 6 |  |  |  |  | 259 |  | 
| 7 | 6 |  |  | 6 |  | 47 | use warnings; | 
|  | 6 |  |  |  |  | 14 |  | 
|  | 6 |  |  |  |  | 182 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 6 |  |  | 6 |  | 99 | use v5.8.1; | 
|  | 6 |  |  |  |  | 20 |  | 
|  | 6 |  |  |  |  | 290 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 6 |  |  | 6 |  | 31 | use Carp; | 
|  | 6 |  |  |  |  | 8 |  | 
|  | 6 |  |  |  |  | 636 |  | 
| 12 | 6 |  |  | 6 |  | 30395 | use Module::CoreList; | 
|  | 6 |  |  |  |  | 3142197 |  | 
|  | 6 |  |  |  |  | 99 |  | 
| 13 | 6 |  |  | 6 |  | 4816 | use Scalar::Util qw/dualvar/; | 
|  | 6 |  |  |  |  | 16 |  | 
|  | 6 |  |  |  |  | 1125 |  | 
| 14 | 6 |  |  | 6 |  | 6489 | use ExtUtils::Installed; | 
|  | 6 |  |  |  |  | 3477703 |  | 
|  | 6 |  |  |  |  | 382 |  | 
| 15 | 6 |  |  | 6 |  | 53 | use version 0.77; | 
|  | 6 |  |  |  |  | 204 |  | 
|  | 6 |  |  |  |  | 63 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 6 |  |  | 6 |  | 9876 | use Devel::Declare (); | 
|  | 6 |  |  |  |  | 56830 |  | 
|  | 6 |  |  |  |  | 2818 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | my $inst = ExtUtils::Installed->new(); | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | our $verbose; | 
| 22 |  |  |  |  |  |  | my %export_ok = ( | 
| 23 |  |  |  |  |  |  | 'use_from' => { const => \&rewrite_use_from }, | 
| 24 |  |  |  |  |  |  | 'use_if_available' => { const => \&rewrite_use_if_available }, | 
| 25 |  |  |  |  |  |  | ); | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | ###################### | 
| 28 |  |  |  |  |  |  | ## utility functions | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | sub _my_warn { | 
| 31 | 47 |  |  | 47 |  | 62 | my $string = shift; | 
| 32 | 47 | 100 |  |  |  | 108 | if ($verbose) { | 
| 33 | 41 | 50 | 50 |  |  | 115 | if ((ref $verbose || '') eq 'SCALAR') { | 
| 34 | 41 |  |  |  |  | 111 | $$verbose .= "$string\n"; | 
| 35 |  |  |  |  |  |  | } else { | 
| 36 | 0 |  |  |  |  | 0 | warn $string; | 
| 37 |  |  |  |  |  |  | } | 
| 38 |  |  |  |  |  |  | } | 
| 39 |  |  |  |  |  |  | } | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | sub find_module_version { | 
| 42 | 7 |  |  | 7 | 0 | 9 | my $module = shift; | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | my $version = | 
| 45 | 7 | 100 | 100 |  |  | 14 | eval { $inst->version($module) } || | 
|  |  |  | 100 |  |  |  |  | 
| 46 |  |  |  |  |  |  | exists $Module::CoreList::version{$]}{$module} | 
| 47 |  |  |  |  |  |  | ? ( $Module::CoreList::version{$]}{$module} || 1e-7 ) | 
| 48 |  |  |  |  |  |  | : 0; | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | # some core module do not have version numbers, they are returned as 1e-7 | 
| 51 |  |  |  |  |  |  |  | 
| 52 | 7 |  |  |  |  | 3338 | $version = version->parse($version); | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 7 | 100 |  |  |  | 178 | _my_warn $version ? "\tFound version $version" : "\tCouldn't find version info for $module!"; | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 7 |  |  |  |  | 33 | return $version; | 
| 57 |  |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | sub get_varref_by_name { | 
| 60 | 9 |  |  | 9 | 0 | 18 | my ($caller, $var) = @_; | 
| 61 | 9 |  |  |  |  | 23 | my $varname = $caller . '::' . $var; | 
| 62 |  |  |  |  |  |  |  | 
| 63 | 9 |  |  |  |  | 33 | _my_warn "\tInvestigating package $caller for variable $caller, resolved as $varname"; | 
| 64 |  |  |  |  |  |  |  | 
| 65 | 6 |  |  | 6 |  | 136 | no strict 'refs'; | 
|  | 6 |  |  |  |  | 13 |  | 
|  | 6 |  |  |  |  | 1713 |  | 
| 66 | 9 |  |  |  |  | 38 | my $varref = | 
| 67 | 9 |  |  |  |  | 21 | (defined ${$varname}) | 
| 68 | 9 | 50 |  |  |  | 15 | ? \${$varname} | 
| 69 |  |  |  |  |  |  | : croak "Cannot access variable \$$varname"; | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 9 |  |  |  |  | 20 | return $varref; | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | ########### | 
| 75 |  |  |  |  |  |  | ## import | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | sub import { | 
| 78 | 6 |  |  | 6 |  | 88 | my $class = shift; | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | # setup from explicit imports | 
| 81 | 6 |  |  |  |  | 18 | my $export = {}; | 
| 82 | 6 |  |  |  |  | 20 | foreach my $keyword (@_) { | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | # :all tag | 
| 85 | 3 | 100 |  |  |  | 21 | if ($keyword eq ':all') { | 
| 86 | 1 |  |  |  |  | 2 | $export = \%export_ok; | 
| 87 | 1 |  |  |  |  | 3 | last; | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | # check import is available | 
| 91 | 2 | 50 |  |  |  | 10 | unless ( exists $export_ok{$keyword} ) { | 
| 92 | 0 |  |  |  |  | 0 | carp "Keyword $keyword is not exported by Module::UseFrom"; | 
| 93 | 0 |  |  |  |  | 0 | next; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | # setup specific keyword | 
| 97 | 2 |  |  |  |  | 7 | $export->{$keyword} = $export_ok{$keyword}; | 
| 98 |  |  |  |  |  |  | } | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | # if called without explicit imports | 
| 101 | 6 | 100 |  |  |  | 42 | unless (keys %$export) { | 
| 102 | 3 |  |  |  |  | 8 | $export->{'use_from'} = $export_ok{'use_from'}; | 
| 103 |  |  |  |  |  |  | } | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 6 |  |  |  |  | 25 | my $caller = caller; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 6 |  |  |  |  | 83 | Devel::Declare->setup_for( $caller, $export ); | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 6 |  |  |  |  | 167 | foreach my $keyword (keys %$export) { | 
| 110 | 6 |  |  | 6 |  | 42 | no strict 'refs'; | 
|  | 6 |  |  |  |  | 11 |  | 
|  | 6 |  |  |  |  | 5166 |  | 
| 111 | 7 |  |  | 9 |  | 77 | *{$caller.'::'.$keyword} = sub (@) {}; | 
|  | 7 |  |  |  |  | 6107 |  | 
|  | 9 |  |  |  |  | 37 |  | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | } | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | ################## | 
| 117 |  |  |  |  |  |  | ## rewrite rules | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | sub rewrite_use_from { | 
| 120 | 2 |  |  | 2 | 0 | 53616 | my $linestr = Devel::Declare::get_linestr; | 
| 121 |  |  |  |  |  |  |  | 
| 122 | 2 |  |  |  |  | 11 | _my_warn "use_from got: $linestr"; | 
| 123 |  |  |  |  |  |  |  | 
| 124 | 2 |  |  |  |  | 7 | my $caller = Devel::Declare::get_curstash_name; | 
| 125 |  |  |  |  |  |  |  | 
| 126 | 2 |  |  |  |  | 23 | $linestr =~ s/use_from\s+\$(\w+)/ | 
| 127 | 2 |  |  |  |  | 9 | my $varref = get_varref_by_name($caller, $1); | 
| 128 | 2 |  |  |  |  | 4 | my $module = $$varref; | 
| 129 | 2 |  |  |  |  | 6 | "use_from; use $module"; | 
| 130 |  |  |  |  |  |  | /e; | 
| 131 |  |  |  |  |  |  |  | 
| 132 | 2 |  |  |  |  | 9 | _my_warn "use_from returned: $linestr"; | 
| 133 |  |  |  |  |  |  |  | 
| 134 | 2 |  |  |  |  | 14 | Devel::Declare::set_linestr($linestr); | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | sub rewrite_use_if_available { | 
| 138 | 7 |  |  | 7 | 0 | 3320749 | my $linestr = Devel::Declare::get_linestr; | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 7 |  |  |  |  | 26 | _my_warn "use_if_available got: $linestr"; | 
| 141 |  |  |  |  |  |  |  | 
| 142 | 7 |  |  |  |  | 18 | my $caller = Devel::Declare::get_curstash_name; | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 7 |  |  |  |  | 67 | $linestr =~ s/use_if_available\s+\$(\w+)(\s+[^\s;]+)?/ | 
| 145 | 7 |  |  |  |  | 23 | my $name = $1; | 
| 146 | 7 |  |  |  |  | 12 | my $version = $2; | 
| 147 | 7 |  |  |  |  | 18 | do_use_if_available($caller, $name, $version); | 
| 148 |  |  |  |  |  |  | /e; | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 7 |  |  |  |  | 24 | _my_warn "use_if_available returned: $linestr"; | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 7 |  |  |  |  | 75 | Devel::Declare::set_linestr($linestr); | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | sub do_use_if_available { | 
| 156 | 7 |  |  | 7 | 0 | 16 | my ($caller, $name, $version) = @_; | 
| 157 | 7 |  |  |  |  | 11 | my $return = 'use_if_available '; | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 7 |  |  |  |  | 17 | my $varref = get_varref_by_name($caller, $name); | 
| 160 | 7 |  |  |  |  | 14 | my $module = $$varref; | 
| 161 |  |  |  |  |  |  |  | 
| 162 | 7 |  |  |  |  | 18 | _my_warn "\tFound request for module $module"; | 
| 163 |  |  |  |  |  |  |  | 
| 164 | 7 |  |  |  |  | 15 | my $found_version = find_module_version($module); | 
| 165 |  |  |  |  |  |  |  | 
| 166 | 7 | 100 |  |  |  | 81 | unless ($found_version) { | 
| 167 | 1 |  |  |  |  | 7 | my $dualvar = dualvar 0, $module; | 
| 168 | 1 |  |  |  |  | 2 | $$varref = $dualvar; | 
| 169 | 1 |  |  |  |  | 7 | return $return; | 
| 170 |  |  |  |  |  |  | } | 
| 171 |  |  |  |  |  |  |  | 
| 172 | 6 |  |  |  |  | 19 | my $requested_version; | 
| 173 | 6 | 100 |  |  |  | 15 | if ($version) { | 
| 174 | 4 |  |  |  |  | 6 | $requested_version = eval { version->parse($version) }; | 
|  | 4 |  |  |  |  | 22 |  | 
| 175 | 4 |  |  |  |  | 16 | _my_warn "\tRequested version $requested_version"; | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  |  | 
| 178 | 6 | 100 | 100 |  |  | 61 | if (defined $requested_version and $requested_version > $found_version) { | 
| 179 | 2 |  |  |  |  | 5 | _my_warn "\tInsufficient version found, skipping import!"; | 
| 180 | 2 |  |  |  |  | 6 | my $dualvar = dualvar 0, $module; | 
| 181 | 2 |  |  |  |  | 2 | $$varref = $dualvar; | 
| 182 | 2 |  |  |  |  | 12 | return $return; | 
| 183 |  |  |  |  |  |  | } | 
| 184 |  |  |  |  |  |  |  | 
| 185 | 4 |  |  |  |  | 54 | my $dualvar = dualvar $found_version->numify, $module; | 
| 186 | 4 |  |  |  |  | 7 | $$varref = $dualvar; | 
| 187 |  |  |  |  |  |  |  | 
| 188 | 4 |  |  |  |  | 11 | $return .= "; use $module"; | 
| 189 | 4 | 100 |  |  |  | 8 | $return .= $version if $version; | 
| 190 |  |  |  |  |  |  |  | 
| 191 | 4 |  |  |  |  | 25 | return $return; | 
| 192 |  |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  | 1; | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | __END__ |