File Coverage

blib/lib/Throwable.pm
Criterion Covered Total %
statement 22 24 91.6
branch 1 4 25.0
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 32 37 86.4


line stmt bran cond sub pod time code
1             package Throwable;
2             # ABSTRACT: a role for classes that can be thrown
3             $Throwable::VERSION = '1.001';
4 1     1   7714 use Moo::Role;
  1         2  
  1         4  
5 1     1   704 use Sub::Quote ();
  1         3921  
  1         18  
6 1     1   29 use Scalar::Util ();
  1         3  
  1         17  
7 1     1   4 use Carp ();
  1         2  
  1         129  
8              
9             #pod =head1 SYNOPSIS
10             #pod
11             #pod package Redirect;
12             #pod # NOTE: Moo can also be used here instead of Moose
13             #pod use Moose;
14             #pod with 'Throwable';
15             #pod
16             #pod has url => (is => 'ro');
17             #pod
18             #pod ...then later...
19             #pod
20             #pod Redirect->throw({ url => $url });
21             #pod
22             #pod =head1 DESCRIPTION
23             #pod
24             #pod Throwable is a role for classes that are meant to be thrown as exceptions to
25             #pod standard program flow. It is very simple and does only two things: saves any
26             #pod previous value for C<$@> and calls C<die $self>.
27             #pod
28             #pod Throwable is implemented with L<Moo>, so you can stick to Moo or use L<Moose>,
29             #pod as you prefer.
30             #pod
31             #pod =attr previous_exception
32             #pod
33             #pod This attribute is created automatically, and stores the value of C<$@> when the
34             #pod Throwable object is created. This is done on a I<best effort basis>. C<$@> is
35             #pod subject to lots of spooky action-at-a-distance. For now, there are clearly
36             #pod ways that the previous exception could be lost.
37             #pod
38             #pod =cut
39              
40             our %_HORRIBLE_HACK;
41              
42             has 'previous_exception' => (
43             is => 'ro',
44             default => Sub::Quote::quote_sub(q<
45             if (defined $Throwable::_HORRIBLE_HACK{ERROR}) {
46             $Throwable::_HORRIBLE_HACK{ERROR}
47             } elsif (defined $@ and (ref $@ or length $@)) {
48             $@;
49             } else {
50             undef;
51             }
52             >),
53             );
54              
55             #pod =method throw
56             #pod
57             #pod Something::Throwable->throw({ attr => $value });
58             #pod
59             #pod This method will call new, passing all arguments along to new, and will then
60             #pod use the created object as the only argument to C<die>.
61             #pod
62             #pod If called on an object that does Throwable, the object will be rethrown.
63             #pod
64             #pod =cut
65              
66             sub throw {
67 20     20 1 12150 my ($inv) = shift;
68              
69 20 50       63 if (Scalar::Util::blessed($inv)) {
70 0 0       0 Carp::confess "throw called on Throwable object with arguments" if @_;
71 0         0 die $inv;
72             }
73              
74 20         43 local $_HORRIBLE_HACK{ERROR} = $@;
75 20         369 my $throwable = $inv->new(@_);
76 20         102 die $throwable;
77             }
78              
79             #pod =method new_with_previous
80             #pod
81             #pod die Something::Throwable->new_with_previous({ attr => $value });
82             #pod
83             #pod Constructs an exception object and return it, while trying to make sure that
84             #pod any values in $@ are safely stored in C<previous_exception> without being
85             #pod stomped by evals in the construction process.
86             #pod
87             #pod This is more reliable than calling C<new> directly, but doesn't include the
88             #pod forced C<die> in C<throw>.
89             #pod
90             #pod =cut
91              
92 4     4 1 12558 sub new_with_previous { local $_HORRIBLE_HACK{ERROR} = $@; shift->new(@_) }
  4         86  
93              
94 1     1   5 no Moo::Role;
  1         2  
  1         6  
95             1;
96              
97             __END__
98              
99             =pod
100              
101             =encoding UTF-8
102              
103             =head1 NAME
104              
105             Throwable - a role for classes that can be thrown
106              
107             =head1 VERSION
108              
109             version 1.001
110              
111             =head1 SYNOPSIS
112              
113             package Redirect;
114             # NOTE: Moo can also be used here instead of Moose
115             use Moose;
116             with 'Throwable';
117              
118             has url => (is => 'ro');
119              
120             ...then later...
121              
122             Redirect->throw({ url => $url });
123              
124             =head1 DESCRIPTION
125              
126             Throwable is a role for classes that are meant to be thrown as exceptions to
127             standard program flow. It is very simple and does only two things: saves any
128             previous value for C<$@> and calls C<die $self>.
129              
130             Throwable is implemented with L<Moo>, so you can stick to Moo or use L<Moose>,
131             as you prefer.
132              
133             =head1 PERL VERSION
134              
135             This library should run on perls released even a long time ago. It should work
136             on any version of perl released in the last five years.
137              
138             Although it may work on older versions of perl, no guarantee is made that the
139             minimum required version will not be increased. The version may be increased
140             for any reason, and there is no promise that patches will be accepted to lower
141             the minimum required perl.
142              
143             =head1 ATTRIBUTES
144              
145             =head2 previous_exception
146              
147             This attribute is created automatically, and stores the value of C<$@> when the
148             Throwable object is created. This is done on a I<best effort basis>. C<$@> is
149             subject to lots of spooky action-at-a-distance. For now, there are clearly
150             ways that the previous exception could be lost.
151              
152             =head1 METHODS
153              
154             =head2 throw
155              
156             Something::Throwable->throw({ attr => $value });
157              
158             This method will call new, passing all arguments along to new, and will then
159             use the created object as the only argument to C<die>.
160              
161             If called on an object that does Throwable, the object will be rethrown.
162              
163             =head2 new_with_previous
164              
165             die Something::Throwable->new_with_previous({ attr => $value });
166              
167             Constructs an exception object and return it, while trying to make sure that
168             any values in $@ are safely stored in C<previous_exception> without being
169             stomped by evals in the construction process.
170              
171             This is more reliable than calling C<new> directly, but doesn't include the
172             forced C<die> in C<throw>.
173              
174             =head1 AUTHORS
175              
176             =over 4
177              
178             =item *
179              
180             Ricardo SIGNES <cpan@semiotic.systems>
181              
182             =item *
183              
184             Florian Ragwitz <rafl@debian.org>
185              
186             =back
187              
188             =head1 CONTRIBUTORS
189              
190             =for stopwords Arthur Axel 'fREW' Schmidt Brian Manning Christian Walde Dagfinn Ilmari Mannsåker Dave Rolsky David E. Wheeler Graham Knop Jeffrey Ryan Thalhammer Justin Hunter Matt S Trout Olaf Alders Ricardo Signes Toby Inkster
191              
192             =over 4
193              
194             =item *
195              
196             Arthur Axel 'fREW' Schmidt <frioux@gmail.com>
197              
198             =item *
199              
200             Brian Manning <brian@xaoc.org>
201              
202             =item *
203              
204             Brian Manning <xaoc@cpan.org>
205              
206             =item *
207              
208             Christian Walde <walde.christian@googlemail.com>
209              
210             =item *
211              
212             Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
213              
214             =item *
215              
216             Dave Rolsky <autarch@urth.org>
217              
218             =item *
219              
220             David E. Wheeler <david@justatheory.com>
221              
222             =item *
223              
224             Graham Knop <haarg@haarg.org>
225              
226             =item *
227              
228             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
229              
230             =item *
231              
232             Justin Hunter <justin.d.hunter@gmail.com>
233              
234             =item *
235              
236             Matt S Trout <mst@shadowcat.co.uk>
237              
238             =item *
239              
240             Olaf Alders <olaf@wundersolutions.com>
241              
242             =item *
243              
244             Ricardo Signes <rjbs@semiotic.systems>
245              
246             =item *
247              
248             Toby Inkster <mail@tobyinkster.co.uk>
249              
250             =back
251              
252             =head1 COPYRIGHT AND LICENSE
253              
254             This software is copyright (c) 2022 by Ricardo SIGNES.
255              
256             This is free software; you can redistribute it and/or modify it under
257             the same terms as the Perl 5 programming language system itself.
258              
259             =cut