File Coverage

blib/lib/Scalar/Does.pm
Criterion Covered Total %
statement 87 94 92.5
branch 24 32 75.0
condition 10 11 90.9
subroutine 25 26 96.1
pod 4 4 100.0
total 150 167 89.8


line stmt bran cond sub pod time code
1             package Scalar::Does;
2              
3 6     6   93009 use 5.008;
  6         15  
4 6     6   34 use strict;
  6         7  
  6         121  
5 6     6   18 use warnings;
  6         9  
  6         201  
6 6     6   3002 use if $] < 5.010, 'UNIVERSAL::DOES';
  6         43  
  6         26  
7              
8             METADATA:
9             {
10             $Scalar::Does::AUTHORITY = 'cpan:TOBYINK';
11             $Scalar::Does::VERSION = '0.203';
12             }
13              
14             UTILITY_CLASS:
15             {
16             package Scalar::Does::RoleChecker;
17             $Scalar::Does::RoleChecker::AUTHORITY = 'cpan:TOBYINK';
18             $Scalar::Does::RoleChecker::VERSION = '0.203';
19 6     6   417 use base "Type::Tiny";
  6         8  
  6         3815  
20             sub new {
21 3     3   4 my $class = shift;
22 3         4 my ($name, $coderef);
23 3         5 for my $p (@_)
24             {
25 3 50       7 if (Scalar::Does::does($p, 'CODE')) { $coderef = $p }
  0         0  
26 3 100       1768 if (Scalar::Does::does($p, 'HASH')) { $coderef = $p->{where} }
  1         7  
27 3 100   2   439 if (Scalar::Does::does($p, 'Regexp')){ $coderef = sub { $_[0] =~ $p } }
  1         10  
  2         47  
28 3 100       395 if (not ref $p) { $name = $p }
  1         2  
29             }
30 3 100       213 Carp::confess("Cannot make role without checker coderef or regexp") unless $coderef;
31 2         15 $class->SUPER::new(display_name => $name, constraint => $coderef);
32             }
33 1     1   701 sub code { shift->constraint };
34             }
35              
36             PRIVATE_STUFF:
37             {
38             sub _lu {
39             require lexical::underscore;
40             goto \&lexical::underscore;
41             }
42            
43 6         494 use constant MISSING_ROLE_MESSAGE => (
44             "Please supply a '-role' argument when exporting custom functions, died"
45 6     6   94071 );
  6         10  
46            
47 6     6   30 use Carp 0 qw( confess );
  6         99  
  6         461  
48 6     6   3391 use Types::Standard 0.004 qw( -types );
  6         207350  
  6         54  
49             }
50              
51 6     6   19213 use namespace::clean 0.19;
  6         66429  
  6         32  
52              
53             DEFINE_CONSTANTS:
54             {
55             our %_CONSTANTS = (
56             BOOLEAN => q[bool],
57             STRING => q[""],
58             NUMBER => q[0+],
59             REGEXP => q[qr],
60             SMARTMATCH => q[~~],
61             map {; $_ => $_ } qw(
62             SCALAR ARRAY HASH CODE REF GLOB
63             LVALUE FORMAT IO VSTRING
64             )
65             );
66             require constant;
67             constant->import(\%_CONSTANTS);
68             }
69              
70             EXPORTER:
71             {
72 6     6   2332 use base "Exporter::Tiny";
  6         8  
  6         1273  
73            
74             our %_CONSTANTS;
75             our @EXPORT = ( "does" );
76             our @EXPORT_OK = (
77             qw( does overloads blessed reftype looks_like_number make_role where custom ),
78             keys(%_CONSTANTS),
79             );
80             our %EXPORT_TAGS = (
81             constants => [ "does", keys(%_CONSTANTS) ],
82             only_constants => [ keys(%_CONSTANTS) ],
83             make => [ qw( make_role where ) ],
84             );
85            
86             sub _exporter_validate_opts
87             {
88 7     7   2367 require B;
89 7         15 my $class = shift;
90             $_[0]{exporter} ||= sub {
91 24     24   1044 my $into = $_[0]{into};
92 24         20 my ($name, $sym) = @{ $_[1] };
  24         39  
93 24         137 for (grep ref, $into->can($name))
94             {
95 0 0       0 B::svref_2object($_)->STASH->NAME eq $into
96             and _croak("Refusing to overwrite local sub '$name' with export from $class");
97             }
98 24         96 "namespace::clean"->import(-cleanee => $_[0]{into}, $name);
99 6     6   35 no strict qw(refs);
  6         5  
  6         165  
100 6     6   18 no warnings qw(redefine prototype);
  6         14  
  6         525  
101 24         566 *{"$into\::$name"} = $sym;
  24         93  
102             }
103 7   50     86 }
104             }
105              
106             ROLES:
107             {
108 6     6   21 no warnings;
  6         6  
  6         1953  
109            
110             my $io = "Type::Tiny"->new(
111             display_name => "IO",
112             constraint => sub { require IO::Detect; IO::Detect::is_filehandle($_) },
113             );
114            
115             our %_ROLES = (
116             SCALAR => ( ScalarRef() | Ref->parameterize('SCALAR') | Overload->parameterize('${}') ),
117             ARRAY => ( ArrayRef() | Ref->parameterize('ARRAY') | Overload->parameterize('@{}') ),
118             HASH => ( HashRef() | Ref->parameterize('HASH') | Overload->parameterize('%{}') ),
119             CODE => ( CodeRef() | Ref->parameterize('CODE') | Overload->parameterize('&{}') ),
120             REF => ( Ref->parameterize('REF') ),
121             GLOB => ( GlobRef() | Ref->parameterize('GLOB') | Overload->parameterize('*{}') ),
122             LVALUE => ( Ref->parameterize('LVALUE') ),
123             FORMAT => ( Ref->parameterize('FORMAT') ),
124             IO => $io,
125             VSTRING => ( Ref->parameterize('VSTRING') ),
126             Regexp => ( RegexpRef() | Ref->parameterize('Regexp') | Overload->parameterize('qr') ),
127             bool => ( Value() | Overload->complementary_type | Overload->parameterize('bool') ),
128             q[""] => ( Value() | Overload->complementary_type | Overload->parameterize('""') ),
129             q[0+] => ( Value() | Overload->complementary_type | Overload->parameterize('0+') ),
130             q[<>] => ( Overload->parameterize('<>') | $io ),
131             q[~~] => ( Overload->parameterize('~~') | Object->complementary_type ),
132             q[${}] => 'SCALAR',
133             q[@{}] => 'ARRAY',
134             q[%{}] => 'HASH',
135             q[&{}] => 'CODE',
136             q[*{}] => 'GLOB',
137             q[qr] => 'Regexp',
138             );
139            
140             while (my ($k, $v) = each %_ROLES) { $_ROLES{$k} = $_ROLES{$v} unless ref $v }
141             }
142              
143             PUBLIC_FUNCTIONS:
144             {
145 6     6   37 use Scalar::Util 1.24 qw( blessed reftype looks_like_number );
  6         110  
  6         906  
146            
147             sub overloads ($;$)
148             {
149 0 0   0 1 0 unshift @_, ${+_lu} if @_ == 1;
  0         0  
150 0 0       0 return unless blessed $_[0];
151 0         0 goto \&overload::Method;
152             }
153            
154             sub does ($;$)
155             {
156 171 50   171 1 60081 unshift @_, ${+_lu} if @_ == 1;
  0         0  
157 171         224 my ($thing, $role) = @_;
158            
159 6     6   26 no warnings;
  6         5  
  6         1649  
160 171         131 our %_ROLES;
161 171 100       913 if (my $test = $_ROLES{$role})
162             {
163 96         476 return !! $test->check($thing);
164             }
165            
166 75 100 100     371 if (blessed $role and $role->can('check'))
167             {
168 18         89 return !! $role->check($thing);
169             }
170            
171 57 100 100     432 if (blessed $thing && $thing->can('DOES'))
    100 100        
172             {
173 12 100       72 return !! 1 if $thing->DOES($role);
174             }
175             elsif (UNIVERSAL::can($thing, 'can') && $thing->can('DOES'))
176             {
177 12         14 my $class = $thing;
178 12 100       41 return '0E0' if $class->DOES($role);
179             }
180            
181 49         370 return;
182             }
183            
184             sub _generate_custom
185             {
186 3     3   72 my ($class, $name, $arg) = @_;
187 3 100       202 my $role = $arg->{ -role } or confess MISSING_ROLE_MESSAGE;
188            
189             return sub (;$) {
190 4     4   2185 push @_, $role;
191 4         11 goto \&does;
192             }
193 2         12 }
194            
195             sub make_role
196             {
197 3     3 1 333 return "Scalar::Does::RoleChecker"->new(@_);
198             }
199            
200             sub where (&)
201             {
202 1     1 1 14 return +{ where => $_[0] };
203             }
204             }
205              
206             "it does"
207             __END__