File Coverage

blib/lib/Mojo/Bass.pm
Criterion Covered Total %
statement 56 56 100.0
branch 17 18 94.4
condition 5 7 71.4
subroutine 13 13 100.0
pod n/a
total 91 94 96.8


line stmt bran cond sub pod time code
1              
2             package Mojo::Bass;
3             $Mojo::Bass::VERSION = '0.3.0'; # TRIAL
4             # ABSTRACT: Mojo::Base + lexical "has"
5 5     5   1466 use 5.018;
  5         32  
6 5     5   1297 use Mojo::Base -strict;
  5         52734  
  5         28  
7              
8 5     5   705 use Carp ();
  5         12  
  5         201  
9              
10             BEGIN {
11 5     5   152 our @ISA = qw(Mojo::Base);
12             }
13              
14 5     5   1212 use Sub::Inject 0.2.0 ();
  5         1639  
  5         135  
15              
16 5     5   26 use constant ROLES => Mojo::Base::ROLES;
  5         9  
  5         300  
17              
18 5     5   25 use constant SIGNATURES => ($] >= 5.020);
  5         8  
  5         292  
19              
20 5         1522 use constant EXPORTS_FOR => {
21             -base => [ROLES ? qw(has with) : qw(has)],
22             -role => [qw(has)],
23             -strict => [],
24 5     5   24 };
  5         9  
25              
26             sub import {
27 21     21   186543 my ($class, $caller) = (shift, caller);
28 21 100       1618 return unless my $flag = shift;
29              
30             # Base
31 17         26 my $base;
32 17 100 50     110 if ($flag eq '-base') { $base = $class }
  5 100 66     12  
    100          
    100          
33              
34             # Strict
35             elsif ($flag eq '-strict') { }
36              
37             # Role
38             elsif ($flag eq '-role') {
39 2         3 Carp::croak 'Role::Tiny 2.000001+ is required for roles' unless ROLES;
40 2 50       151 eval "package $caller; use Role::Tiny; 1" or die $@;
  1         4  
  1         9  
  1         3  
  1         5  
41             }
42              
43             # Module
44             elsif (($base = $flag) && ($flag = '-base') && !$base->can('new')) {
45 1         10 (my $file = $base) =~ s!::|'!/!g;
46 1         197 require "$file.pm";
47             }
48              
49             # Mojo modules are strict!
50 17         271 $_->import for qw(strict warnings utf8);
51 17         550 feature->import(':5.10');
52              
53             # Signatures (Perl 5.20+)
54 17 100 100     89 if ((shift || '') eq '-signatures') {
55 1         3 Carp::croak 'Subroutine signatures require Perl 5.20+' unless SIGNATURES;
56 1         466 require experimental;
57 1         2413 experimental->import('signatures');
58             }
59              
60             # ISA
61 17 100       71 if ($base) {
62 5     5   29 no strict 'refs';
  5         8  
  5         1555  
63 9         14 push @{"${caller}::ISA"}, $base;
  9         91  
64             }
65              
66 17         38 my $exports = EXPORTS_FOR->{$flag};
67 17 100       1331 if (@$exports) {
68 11         37 @_ = $class->_generate_subs($caller, @$exports);
69 11         50 goto &Sub::Inject::sub_inject;
70             }
71             }
72              
73             our %EXPORT_GEN = (
74             has => sub {
75             my (undef, $target) = @_;
76 11     11   648 return sub { Mojo::Base::attr($target, @_) }
77             },
78             with => sub {
79             my (undef, $target) = @_;
80 1     1   2 return sub { Role::Tiny->apply_roles_to_package($target, @_) }
81             },
82             );
83              
84             sub _generate_subs {
85 11     11   27 my ($class, $target) = (shift, shift);
86 11         20 return map { my $cb = $EXPORT_GEN{$_}; $_ => $class->$cb($target) } @_;
  20         34  
  20         42  
87             }
88              
89             1;
90              
91             #pod =encoding utf8
92             #pod
93             #pod =head1 SYNOPSIS
94             #pod
95             #pod package Cat {
96             #pod use Mojo::Bass -base;
97             #pod
98             #pod has name => 'Nyan';
99             #pod has ['age', 'weight'] => 4;
100             #pod }
101             #pod
102             #pod package Tiger {
103             #pod use Mojo::Bass 'Cat';
104             #pod
105             #pod has friend => sub { Cat->new };
106             #pod has stripes => 42;
107             #pod }
108             #pod
109             #pod package main;
110             #pod use Mojo::Bass -strict;
111             #pod
112             #pod my $mew = Cat->new(name => 'Longcat');
113             #pod say $mew->age;
114             #pod say $mew->age(3)->weight(5)->age;
115             #pod
116             #pod my $rawr = Tiger->new(stripes => 38, weight => 250);
117             #pod say $rawr->tap(sub { $_->friend->name('Tacgnol') })->weight;
118             #pod
119             #pod =head1 DESCRIPTION
120             #pod
121             #pod L works like L but C is imported
122             #pod as lexical subroutine.
123             #pod
124             #pod =head1 CAVEATS
125             #pod
126             #pod =over 4
127             #pod
128             #pod =item *
129             #pod
130             #pod L requires perl 5.18 or newer
131             #pod
132             #pod =item *
133             #pod
134             #pod Because a lexical sub does not behave like a package import,
135             #pod some code may need to be enclosed in blocks to avoid warnings like
136             #pod
137             #pod "state" subroutine &has masks earlier declaration in same scope at...
138             #pod
139             #pod =back
140             #pod
141             #pod =head1 SEE ALSO
142             #pod
143             #pod L.
144             #pod
145             #pod =cut
146              
147             __END__