File Coverage

blib/lib/Hades/Realm/Compiled/Params.pm
Criterion Covered Total %
statement 93 96 96.8
branch 50 64 78.1
condition 18 25 72.0
subroutine 10 10 100.0
pod 7 7 100.0
total 178 202 88.1


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