File Coverage

blib/lib/Moove.pm
Criterion Covered Total %
statement 67 76 88.1
branch 18 24 75.0
condition 12 19 63.1
subroutine 13 13 100.0
pod n/a
total 110 132 83.3


line stmt bran cond sub pod time code
1 5     5   147444 use strictures 2;
  5         6365  
  5         218  
2              
3             package Moove;
4              
5             # ABSTRACT: functions and methods with parameter lists and type constraints
6              
7 5     5   3355 use Type::Tiny 1.000005 ();
  5         54356  
  5         144  
8 5     5   2383 use Type::Registry ();
  5         109072  
  5         153  
9 5     5   2789 use Type::Utils qw(class_type);
  5         33430  
  5         51  
10              
11 5     5   5450 use Function::Parameters 1.0703 qw(:lax);
  5         14649  
  5         32  
12 5     5   4450 use Import::Into 1.002004 ();
  5         10667  
  5         127  
13 5     5   2027 use Syntax::Feature::Try 1.003 ();
  5         5113  
  5         132  
14 5     5   1907 use Data::OptList 0.109 ();
  5         25404  
  5         162  
15              
16 5     5   42 use Carp qw(croak confess);
  5         20  
  5         635  
17              
18             our @EXPORT;
19              
20             our $VERSION = '0.005'; # VERSION
21              
22             my %OPTIONS;
23              
24 5     5   39 use constant PKGRE => qr{^\w+(::\w+)+$};
  5         10  
  5         4351  
25              
26             sub import {
27 8     8   2528 my $caller = scalar caller;
28 8         73 my $class = shift;
29 8         42 my $opts = Data::OptList::mkopt_hash(\@_);
30              
31 8         447 my $registry = Type::Registry->for_class($caller);
32              
33 8   50     173 my $options = $OPTIONS{$caller} ||= {};
34              
35 8 100       35 if (my $types = delete $opts->{types}) {
36 1 50       5 if (ref $types eq 'ARRAY') {
    50          
37 0         0 $registry->add_types(@$types);
38             } elsif (ref $types eq 'SCALAR') {
39 1         6 $registry->add_types($$types);
40             } else {
41 0         0 croak "unknown value for argument 'types': $types";
42             }
43             }
44 8 50       108867 if (my $classes = delete $opts->{classes}) {
45 0         0 foreach my $class (@$classes) {
46 0         0 $registry->add_type(class_type($class) => $class);
47             }
48             }
49 8 50       29 if (my $types = delete $opts->{type}) {
50 0         0 foreach my $type (@$types) {
51 0         0 $registry->add_type($type);
52             }
53             }
54              
55 8 50       33 unless (exists $opts->{-nostdtypes}) {
56 8         40 $registry->add_types(-Standard);
57             }
58              
59 8 100       201385 if (exists $opts->{-autoclass}) {
60 2         9 $options->{autoclass} = 1;
61             }
62              
63 8         154 Function::Parameters->import::into($caller, {
64             method => {
65             defaults => 'method',
66             runtime => 0,
67             strict => 1,
68             reify_type => \&_reify_type,
69             },
70             func => {
71             defaults => 'function',
72             runtime => 0,
73             strict => 1,
74             reify_type => \&_reify_type,
75             }
76             });
77              
78 8 100       6298 if (exists $opts->{-trycatch}) {
79             Syntax::Feature::Try::register_exception_matcher(sub {
80 9     9   18586 my ($exception, $typedef) = @_;
81 9 100 66     94 if ($options->{autoclass} and $typedef =~ PKGRE) {
82 6 100       50 if ($typedef->can('caught')) {
83 4   100     19 return $typedef->caught($exception) || undef;
84             } else {
85 2   50     15 return class_type($typedef)->check($exception) || undef;
86             }
87             } else {
88 3   100     12 return $registry->lookup($typedef)->check($exception) || undef;
89             }
90 2         25 });
91              
92 2         1115 require syntax;
93 2         24851 syntax->import_into($caller, 'try');
94             }
95             }
96              
97             sub _reify_type {
98 5     5   64 my ($typedef, $package) = @_;
99 5         24 my ($caller, $file, $line) = caller;
100 5   33     54 $package //= $caller;
101 5   50     16 my $options = $OPTIONS{$package} || {};
102 5         11 my $type;
103 5         13 eval {
104 5 100 66     23 if ($options->{autoclass} and $typedef =~ PKGRE) {
105 1         6 $type = class_type($typedef);
106             } else {
107 4         16 my $registry = Type::Registry->for_class($package);
108 4         32 $type = $registry->lookup($typedef);
109             }
110             };
111 5 50       2373 if (my $e = $@) {
112 0         0 $e =~ s{\s+ at \s+ \S+ \s+ line \s+ \S+ \s*$}{}xs;
113 0         0 warn "$e at $file line $line\n";
114 0         0 exit 255;
115             } else {
116 5         261 return $type;
117             }
118             }
119              
120             1;
121              
122             __END__
123              
124             =pod
125              
126             =head1 NAME
127              
128             Moove - functions and methods with parameter lists and type constraints
129              
130             =head1 VERSION
131              
132             version 0.005
133              
134             =head1 SYNOPSIS
135              
136             use Moove;
137              
138             func foo (Int $number, Str $text)
139             {
140             ...
141             }
142              
143              
144             use Moove classes => [qw[ Some::Class ]];
145              
146             method bar (Some::Class $obj)
147             {
148             ...
149             }
150              
151              
152             use Moove -trycatch;
153              
154             func foobar () {
155             try {
156             die "meh";
157             } catch {
158             return "caught meh.";
159             }
160             }
161              
162              
163             use Moove -autoclass;
164              
165             method bar (Some::Class $obj)
166             {
167             ...
168             }
169              
170             =head1 DESCRIPTION
171              
172             This module inherits L<Function::Parameters> with some defaults and type constraints with L<Type::Tiny>.
173              
174             Some reasons to use Moove:
175              
176             =over 4
177              
178             =item * No L<Moose> dependency
179              
180             =item * No L<Devel::Declare> dependency
181              
182             =item * A nearly replacement for L<Method::Signatures>
183              
184             But with some differences...
185              
186             =back
187              
188             This is also a very early release.
189              
190             =head1 IMPORT OPTIONS
191              
192             The I<import> method supports these keywords:
193              
194             =over 4
195              
196             =item * types
197              
198             As an ArrayRef, calls C<<< Types::Registry->for_class($caller)->add_types(@$types) >>>.
199              
200             As a ScalarRef, calls C<<< Types::Registry->for_class($caller)->add_types($$types) >>>.
201              
202             =item * classes
203              
204             For each class in this ArrayRef, calls C<<< Types::Registry->for_class($caller)->add_types(Type::Utils::class_type($class)) >>>.
205              
206             =item * -nostdtypes
207              
208             Do not import L<Types::Standard>.
209              
210             =item * -trycatch
211              
212             Import L<Syntax::Feature::Try> with type constraints.
213              
214             =item * -autoclass
215              
216             Enable auto-generation of class contraints (L<Type::Tiny::Class>) if the constraint looks like a package name (C</^\w+(::\w+)+$/>). This always takes precedence over the general type registry.
217              
218             This also works with I<-trycatch>.
219              
220             =back
221              
222             =head1 BUGS
223              
224             Please report any bugs or feature requests on the bugtracker website
225             https://github.com/zurborg/libmoove-perl/issues
226              
227             When submitting a bug or request, please include a test-file or a
228             patch to an existing test-file that illustrates the bug or desired
229             feature.
230              
231             =head1 AUTHOR
232              
233             David Zurborg <zurborg@cpan.org>
234              
235             =head1 COPYRIGHT AND LICENSE
236              
237             This software is Copyright (c) 2016 by David Zurborg.
238              
239             This is free software, licensed under:
240              
241             The ISC License
242              
243             =cut