File Coverage

blib/lib/Hades/Realm/Compiled/Params.pm
Criterion Covered Total %
statement 94 97 96.9
branch 54 68 79.4
condition 18 25 72.0
subroutine 10 10 100.0
pod 7 7 100.0
total 183 207 88.4


line stmt bran cond sub pod time code
1             package Hades::Realm::Compiled::Params;
2 4     4   285526 use strict;
  4         33  
  4         121  
3 4     4   23 use warnings;
  4         8  
  4         116  
4 4     4   35 use base qw/Hades/;
  4         9  
  4         2980  
5             our $VERSION = 0.02;
6              
7             sub new {
8 15 100   15 1 22983 my ( $cls, %args ) = ( shift(), scalar @_ == 1 ? %{ $_[0] } : @_ );
  13         61  
9 15         73 my $self = $cls->SUPER::new(%args);
10 15         141 my %accessors = ( cpo => { required => 1, default => [], }, );
11 15         42 for my $accessor ( keys %accessors ) {
12             my $value
13             = $self->$accessor(
14             defined $args{$accessor}
15             ? $args{$accessor}
16 15 100       71 : $accessors{$accessor}->{default} );
17 13 50 33     79 unless ( !$accessors{$accessor}->{required} || defined $value ) {
18 0         0 die "$accessor accessor is required";
19             }
20             }
21 13         87 return $self;
22             }
23              
24             sub cpo {
25 22     22 1 1309 my ( $self, $value ) = @_;
26 22 100       61 if ( defined $value ) {
27 18 100 100     72 if ( ( ref($value) || "" ) ne "ARRAY" ) {
28 4         41 die qq{ArrayRef: invalid value $value for accessor cpo};
29             }
30 14         57 $self->{cpo} = $value;
31             }
32 18         55 return $self->{cpo};
33             }
34              
35             sub push_cpo {
36 17     17 1 2035 my ( $self, $key, $value ) = @_;
37 17 100 66     86 if ( !defined($key) || ref $key ) {
38 2 50       8 $key = defined $key ? $key : 'undef';
39 2         20 die qq{Str: invalid value $key for variable \$key in method push_cpo};
40             }
41 15 100 66     64 if ( !defined($value) || ref $value ) {
42 2 50       9 $value = defined $value ? $value : 'undef';
43 2         20 die
44             qq{Str: invalid value $value for variable \$value in method push_cpo};
45             }
46 13         21 push @{ $self->{cpo} }, qq|$key => $value|;
  13         48  
47             }
48              
49             sub build_accessor {
50 11     11 1 24678 my ( $orig, $self, @params ) = ( 'SUPER::build_accessor', @_ );
51             $params[2]->{ $params[1] }->{type}->[0] =~ s/\s*\[/[/g
52 11 100       106 if $params[2]->{ $params[1] }->{type}->[0];
53             $self->push_cpo( $params[1],
54             '[' . ( $params[2]->{ $params[1] }->{type}->[0] || 'Any' )
55             . ($params[2]->{ $params[1] }->{default}
56 11 100 100     84 ? ', { default => ' . $params[2]->{ $params[1] }->{default} . '} ]'
57             : ']'
58             )
59             );
60 11         51 my @res = $self->$orig(@params);
61 11 50       8201 return wantarray ? @res : $res[0];
62             }
63              
64             sub build_sub {
65 8     8 1 4420 my ( $self, $mg, $name, $meta ) = @_;
66 8 100       33 if ( !ref $mg ) {
67 2 50       7 $mg = defined $mg ? $mg : 'undef';
68 2         20 die qq{Ref: invalid value $mg for variable \$mg in method build_};
69             }
70 6 100 66     38 if ( !defined($name) || ref $name ) {
71 2 50       8 $name = defined $name ? $name : 'undef';
72 2         20 die
73             qq{Str: invalid value $name for variable \$name in method build_sub};
74             }
75 4 100 100     25 if ( ( ref($meta) || "" ) ne "HASH" ) {
76 2 50       7 $meta = defined $meta ? $meta : 'undef';
77 2         19 die
78             qq{HashRef: invalid value $meta for variable \$meta in method build_sub};
79             }
80 2         4 my $code = $meta->{$name}->{code};
81 2         5 my ( $params, $types, $params_explanation, $private );
82 2 50       6 $private = $self->build_private($name) if $meta->{$name}->{private};
83 2 50       6 if ( $meta->{$name}->{param} ) {
84 2         4 for my $param ( @{ $meta->{$name}->{param} } ) {
  2         5  
85 2 50       9 $params_explanation .= ', ' if $params_explanation;
86 2         5 $params .= ', ' . $param;
87 2         4 my $pm = $meta->{$name}->{params_map}->{$param};
88 2   50     11 $pm->{type} ||= q|Any|;
89 2 100       10 my $t = $pm->{type} . ($pm->{default} ? ', { default => ' . $pm->{default} . ' }' : '');
90 2 50       9 $types .= $types ? ', ' . $t : $t;
91 2         9 $params_explanation .= qq|param $param to be a $pm-> { type } |;
92             }
93 2         8 my $type = $self->build_type( $name, $types, $types );
94 2         9 $self->push_cpo( $name, '[' . $types . ']' );
95 2         8 $code = qq| { my (\$self $params) = (shift$type); $code; } |;
96 2         10 $params =~ s/^\,\s*//;
97 2         26 my $example = qq|\$obj->$name($params)|;
98             $mg->sub($name)->code($code)
99             ->pod(qq|call $name method. Expects $params_explanation.|)
100             ->example($example)
101 2         8 ->test( $self->build_tests( $name, $meta->{$name} ) );
102             }
103             }
104              
105             sub build_type {
106 19     19 1 3539 my ( $self, $name, $type, $value ) = @_;
107 19 100 66     110 if ( !defined($name) || ref $name ) {
108 2 50       7 $name = defined $name ? $name : 'undef';
109 2         21 die
110             qq{Str: invalid value $name for variable \$name in method build_type};
111             }
112 17 100       44 if ( defined $type ) {
113 14 100       35 if ( ref $type ) {
114 2         19 die
115             qq{Optional[Str]: invalid value $type for variable \$type in method build_type};
116             }
117             }
118 15 100       56 if ( defined $value ) {
119 4 100       12 if ( ref $value ) {
120 2         22 die
121             qq{Optional[Str]: invalid value $value for variable \$value in method build_type};
122             }
123             }
124 13         23 my $code = '';
125 13 100       25 if ($type) {
126 12 100       41 $code
127             .= $value
128             ? qq|, \$VALIDATE->$name->(\@_)|
129             : qq|(\$value) = \$VALIDATE->$name->(\$value);|;
130             }
131 13         37 return $code;
132             }
133              
134             sub after_class {
135 4     4 1 8130 my ( $self, $mg ) = @_;
136 4 100 100     47 if ( ( ref($mg) || "" ) =~ m/^(|HASH|ARRAY|SCALAR|CODE|GLOB)$/ ) {
137 2 50       7 $mg = defined $mg ? $mg : 'undef';
138 2         20 die
139             qq{Object: invalid value $mg for variable \$mg in method after_class};
140             }
141 2         6 my $cpo = join ', ', @{ $self->cpo };
  2         7  
142 2         13 $mg->use(q|Types::Standard qw/Any Item Bool Str Num Int Ref ScalarRef ArrayRef HashRef CodeRef RegexpRef GlobRef Object Map Tuple Dict Optional/|);
143 2         29 $mg->use(q|Compiled::Params::OO|);
144 2         23 $mg->our(q|$VALIDATE|);
145 2         24 my $code = qq|\$VALIDATE = Compiled::Params::OO::cpo( $cpo );|;
146 2         9 my %class = %Module::Generate::CLASS;
147 2 50       9 if ( $class{CURRENT}{BEGIN} ) {
148 0         0 ( my $begin = $class{CURRENT}{BEGIN} ) =~ s/\s*\}\s*$//;
149 0         0 $code = $begin . $code . "\}";
150             }
151 2         19 else { $code = qq|{ $code }|; }
152 2         25 $class{CURRENT}{BEGIN} = $code;
153             }
154              
155             1;
156              
157             __END__
158              
159             =head1 NAME
160              
161             Hades::Realm::Compiled::Params - The great new Hades::Realm::Compiled::Params!
162              
163             =head1 VERSION
164              
165             Version 0.02
166              
167             =cut
168              
169             =head1 SYNOPSIS
170              
171             use Hades::Realm::Compiled::Params;
172              
173             Hades::Realm::Compiled::Params->run({
174             eval => 'Kosmos { penthos :d(2) :p :pr :c :t(Int) curae :r :t(Any) geras $nosoi :t(Int) { if ($self->penthos == $nosoi) { return $self->curae; } } }',
175             lib => 't/lib'
176             });
177              
178             ... generates ...
179              
180             package Kosmos;
181             use strict;
182             use warnings;
183             use Types::Standard qw/Str Optional HashRef Tuple Map Dict ArrayRef Int Any/;
184             use Compiled::Params::OO;
185             our $VERSION = 0.01;
186             our $VALIDATE;
187              
188             BEGIN {
189             $VALIDATE = Compiled::Params::OO::cpo(
190             penthos => [ Int, { default => 2 } ],
191             curae => [Any],
192             geras => [ Int, { default => 2 } ]
193             );
194             }
195              
196             sub new {
197             my ( $cls, %args ) = ( shift(), scalar @_ == 1 ? %{ $_[0] } : @_ );
198             my $self = bless {}, $cls;
199             my %accessors
200             = ( curae => { required => 1, }, penthos => { default => 2, }, );
201             for my $accessor ( keys %accessors ) {
202             my $value
203             = $self->$accessor(
204             defined $args{$accessor}
205             ? $args{$accessor}
206             : $accessors{$accessor}->{default} );
207             unless ( !$accessors{$accessor}->{required} || defined $value ) {
208             die "$accessor accessor is required";
209             }
210             }
211             return $self;
212             }
213              
214             sub penthos {
215             my ( $self, $value ) = @_;
216             my $private_caller = caller();
217             if ( $private_caller ne __PACKAGE__ ) {
218             die "cannot call private method penthos from $private_caller";
219             }
220             if ( defined $value ) {
221             ($value) = $VALIDATE->penthos->($value);
222             $self->{penthos} = $value;
223             }
224             return $self->{penthos};
225             }
226              
227             sub clear_penthos {
228             my ($self) = @_;
229             delete $self->{penthos};
230             return $self;
231             }
232              
233             sub has_penthos {
234             my ($self) = @_;
235             return exists $self->{penthos};
236             }
237              
238             sub curae {
239             my ( $self, $value ) = @_;
240             if ( defined $value ) {
241             ($value) = $VALIDATE->curae->($value);
242             $self->{curae} = $value;
243             }
244             return $self->{curae};
245             }
246              
247             sub geras {
248             my ( $self, $nosoi ) = ( shift, $VALIDATE->geras->(@_) );
249             if ( $self->penthos == $nosoi ) { return $self->curae; }
250             }
251              
252             =head1 SUBROUTINES/METHODS
253              
254             =head2 new
255              
256             Instantiate a new Hades::Realm::Compiled::Params object.
257              
258             Hades::Realm::Compiled::Params->new
259              
260             =head2 push_cpo
261              
262             call push_cpo method. Expects param $key to be a Str, param $value to be a Str.
263              
264             $obj->push_cpo($key, $value)
265              
266             =head2 build_accessor
267              
268             call build_accessor method.
269              
270             =head2 build_sub
271              
272             call build_sub method. Expects param $mg to be a Ref, param $name to be a Str, param $meta to be a HashRef.
273              
274             $obj->build_sub($mg, $name, $meta)
275              
276             =head2 build_type
277              
278             call build_type method. Expects param $name to be a Str, param $type to be a Optional[Str], param $value to be a Optional[Str].
279              
280             $obj->build_type($name, $type, $value)
281              
282             =head2 after_class
283              
284             call after_class method. Expects param $mg to be a Object.
285              
286             $obj->after_class($mg)
287              
288             =head1 ACCESSORS
289              
290             =head2 cpo
291              
292             get or set cpo.
293              
294             $obj->cpo;
295              
296             $obj->cpo($value);
297              
298             =head1 AUTHOR
299              
300             LNATION, C<< <email at lnation.org> >>
301              
302             =head1 BUGS
303              
304             Please report any bugs or feature requests to C<bug-hadesrealmcompiledparams at rt.cpan.org>, or through
305             the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Hades-Realm-Compiled-Params>. I will be notified, and then you'll
306             automatically be notified of progress on your bug as I make changes.
307              
308             =head1 SUPPORT
309              
310             You can find documentation for this module with the perldoc command.
311              
312             perldoc Hades::Realm::Compiled::Params
313              
314             You can also look for information at:
315              
316             =over 4
317              
318             =item * RT: CPAN's request tracker (report bugs here)
319              
320             L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Hades-Realm-Compiled-Params>
321              
322             =item * AnnoCPAN: Annotated CPAN documentation
323              
324             L<http://annocpan.org/dist/Hades-Realm-Compiled-Params>
325              
326             =item * CPAN Ratings
327              
328             L<https://cpanratings.perl.org/d/Hades-Realm-Compiled-Params>
329              
330             =item * Search CPAN
331              
332             L<https://metacpan.org/release/Hades-Realm-Compiled-Params>
333              
334             =back
335              
336             =head1 ACKNOWLEDGEMENTS
337              
338             =head1 LICENSE AND COPYRIGHT
339              
340             This software is Copyright (c) 2020 by LNATION.
341              
342             This is free software, licensed under:
343              
344             The Artistic License 2.0 (GPL Compatible)
345              
346             =cut
347              
348