File Coverage

blib/lib/Moove.pm
Criterion Covered Total %
statement 67 77 87.0
branch 18 24 75.0
condition 12 19 63.1
subroutine 13 13 100.0
pod n/a
total 110 133 82.7


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