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