File Coverage

blib/lib/Types/Self.pm
Criterion Covered Total %
statement 59 59 100.0
branch 10 16 62.5
condition n/a
subroutine 18 18 100.0
pod n/a
total 87 93 93.5


line stmt bran cond sub pod time code
1 3     3   108781 use 5.008001;
  3         21  
2 3     3   13 use strict;
  3         4  
  3         49  
3 3     3   11 use warnings;
  3         4  
  3         163  
4              
5              
6             our $AUTHORITY = 'cpan:TOBYINK';
7             our $VERSION = '0.002';
8              
9             use Exporter::Tiny qw();
10 3     3   1134 our @ISA = qw( Exporter::Tiny );
  3         7858  
  3         144  
11             our @EXPORT = qw( Self );
12             our @EXPORT_OK = qw( is_Self assert_Self to_Self coercions_for_Self );
13              
14             use Role::Hooks qw();
15 3     3   1082 use Types::Standard qw( InstanceOf ConsumerOf is_ScalarRef );
  3         11265  
  3         66  
16 3     3   1368  
  3         233616  
  3         27  
17             my ( $me, $name, $args, $globals ) = ( shift, @_ );
18              
19 4     4   768 return sub () {
20             $me->_make_type_constraint( $globals ) unless defined $globals->{type};
21             return $globals->{type};
22 2 50   2   1762 };
23 2         6744 }
24 4         23  
25             my ( $me, $name, $args, $globals ) = ( shift, @_ );
26              
27             return sub ($) {
28 1     1   46 my ( $value ) = @_;
29             $me->_make_type_constraint( $globals ) unless defined $globals->{type};
30             return $globals->{type}->check( $value );
31 2     2   25 };
32 2 50       7 }
33 2         5  
34 1         5 my ( $me, $name, $args, $globals ) = ( shift, @_ );
35              
36             return sub {
37             my ( $value ) = @_;
38 1     1   44 $me->_make_type_constraint( $globals ) unless defined $globals->{type};
39             return $globals->{type}->assert_return( $value );
40             };
41 2     2   356 }
42 2 50       6  
43 2         12 my ( $me, $name, $args, $globals ) = ( shift, @_ );
44 1         5  
45             return sub ($) {
46             my ( $value ) = @_;
47             $me->_make_type_constraint( $globals ) unless defined $globals->{type};
48 1     1   40 return $globals->{type}->coerce( $value );
49             };
50             }
51 2     2   9117  
52 2 50       16 my ( $me, $name, $args, $globals ) = ( shift, @_ );
53 2         12  
54 1         5 return sub {
55             my ( @args ) = @_;
56             $me->_make_type_constraint( $globals ) unless defined $globals->{type};
57             my $type = $globals->{type};
58 1     1   40 my $caller = $globals->{into};
59              
60             # expand scalarref args
61 1     1   4846 for my $i ( 0 .. $#args ) {
62 1 50       8 my $arg = $args[$i];
63 1         325 if ( is_ScalarRef $arg ) {
64 1         3 my $method = $$arg;
65             $args[$i] = sub {
66             my $method_ref = $caller->can( $method );
67 1         3 unshift @_, $caller;
68 4         6 goto $method_ref;
69 4 100       8 };
70 1         2 }
71             }
72 1     1   807  
73 1         4 $type->coercion->i_really_want_to_unfreeze;
74 1         3 $type->coercion->add_type_coercions( @args );
75 1         4 $type->coercion->freeze;
76             };
77             }
78              
79 1         3 my ( $me, $globals ) = @_;
80 1         10 return $globals->{type} if defined $globals->{type};
81 1         776  
82 1         6 my $caller = $globals->{into};
83             my $is_role = 'Role::Hooks'->is_role( $caller );
84             my $base = $is_role ? ConsumerOf : InstanceOf;
85              
86 3     3   7 $globals->{type} = $base->parameterize( $caller );
87 3 50       9 }
88              
89 3         6  
90 3         28 =pod
91 3 100       49  
92             =encoding utf-8
93 3         31  
94             =head1 NAME
95              
96             Types::Self - provides a "Self" type constraint, referring to the caller class or role
97              
98             =head1 SYNOPSIS
99              
100             {
101             package Cow;
102             use Moo;
103             }
104            
105             {
106             package Horse;
107             use Moo;
108             use Types::Self;
109             use Types::Standard qw( Str );
110            
111             has name => ( is => 'ro', isa => Str );
112             has mother => ( is => 'ro', isa => Self );
113             has father => ( is => 'ro', isa => Self );
114             }
115            
116             my $alice = Horse->new( name => 'Alice' );
117             my $bob = Horse->new( name => 'Bob' );
118            
119             # Okay
120             my $baby = Horse->new(
121             name => 'Baby',
122             mother => $alice,
123             father => $bob,
124             );
125            
126             # Dies
127             my $baby = Horse->new(
128             name => 'Baby',
129             mother => Cow->new,
130             father => $bob,
131             );
132              
133             =head1 DESCRIPTION
134              
135             =head2 C<< Self >>
136              
137             This module exports a C<Self> type constraint which consrtains values to be
138             blessed objects in the same class as the package it was imported into, or
139             blessed objects which consume the role it was imported into. It should do
140             the right thing with inheritance.
141              
142             Using C<Self> in a class means the same as C<< InstanceOf[__PACKAGE__] >>.
143             (See B<InstanceOf> in L<Types::Standard>.)
144              
145             Using C<Self> in a role means the same as C<< ConsumerOf[__PACKAGE__] >>.
146             (See B<ConsumerOf> in L<Types::Standard>.)
147              
148             =head2 C<< is_Self >>
149              
150             This module also exports C<is_Self>, which returns a boolean.
151              
152             package Marriage;
153             use Moo::Role;
154             use Types::Self qw( is_Self );
155            
156             has spouse => ( is => 'rwp', init_arg => undef );
157            
158             sub marry {
159             my ( $me, $maybe_spouse ) = @_;
160             if ( is_Self( $maybe_spouse ) ) {
161             $me->_set_spouse( $maybe_spouse );
162             $maybe_spouse->_set_spouse( $me );
163             }
164             else {
165             warn "Cannot marry this!";
166             }
167             return $me;
168             }
169              
170             C<< is_Self( $var ) >> can also be written as C<< Self->check( $var ) >>.
171              
172             =head2 C<< assert_Self >>
173              
174             The module also exports C<assert_Self> which acts like C<is_Self> but instead
175             of returning a boolean, either lives or dies. This can be useful is you need
176             to check that the first argument to a function is a blessed object.
177              
178             sub connect {
179             my ( $self ) = ( shift );
180             assert_Self $self; # dies if called as a class method
181             $self->{connected} = 1;
182             return $self;
183             }
184              
185             C<< assert_Self( $var ) >> can also be written as C<< Self->( $var ) >>.
186              
187             =head2 C<< to_Self >>
188              
189             The module also exports C<to_Self> which will attempt to coerce other types
190             to the B<Self> type.
191              
192             C<< to_Self( $var ) >> can also be written as C<< Self->coerce( $var ) >>.
193              
194             =head2 C<< coercions_for_Self >>
195              
196             An easy way of adding coercions to your B<Self> type for the benefit of
197             C<< to_Self >>. Other classes which use C<< InstanceOf[$YourClass] >>
198             will also get these coercions.
199              
200             Accepts a list of type+code pairs. The code can be a scalarref naming a
201             method to call to coerce a value, a coderef to call to coerce the value
202             (operating on C<< $_ >>), or a string of Perl code to call to coerce the
203             value (operating on C<< $_ >>).
204              
205             package MyClass;
206             use Moo;
207             use Types::Self -all;
208             use Types::Standard qw( HashRef ArrayRef ScalarRef );
209              
210             coercions_for_Self(
211             HashRef, \'new',
212             ArrayRef, \'from_array',
213             ScalarRef, sub { ... },
214             );
215              
216             sub from_array {
217             my ( $class, $arrayref ) = ( shift, @_ );
218             ...;
219             }
220              
221             =head2 Exporting
222              
223             Only C<Self> is exported by default.
224              
225             Other functions need to be requested:
226              
227             use Types::Self -all;
228              
229             Functions can be renamed:
230              
231             use Types::Self
232             'Self' => { -as => 'ThisClass' },
233             'is_Self' => { -as => 'is_ThisClass' };
234              
235             =head1 BUGS
236              
237             Please report any bugs to
238             L<http://rt.cpan.org/Dist/Display.html?Queue=Types-Self>.
239              
240             =head1 SEE ALSO
241              
242             L<Types::Standard>, L<Type::Tiny::Manual>.
243              
244             =head1 AUTHOR
245              
246             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
247              
248             =head1 COPYRIGHT AND LICENCE
249              
250             This software is copyright (c) 2022 by Toby Inkster.
251              
252             This is free software; you can redistribute it and/or modify it under
253             the same terms as the Perl 5 programming language system itself.
254              
255             =head1 DISCLAIMER OF WARRANTIES
256              
257             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
258             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
259             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.