File Coverage

blib/lib/Error/TypeTiny.pm
Criterion Covered Total %
statement 47 48 97.9
branch 13 18 72.2
condition 8 14 57.1
subroutine 15 15 100.0
pod 8 8 100.0
total 91 103 88.3


line stmt bran cond sub pod time code
1             package Error::TypeTiny;
2              
3 299     299   8326 use 5.008001;
  299         1151  
4 299     299   2523 use strict;
  299         668  
  299         7226  
5 299     299   1690 use warnings;
  299         679  
  299         13974  
6              
7             BEGIN {
8 299     299   1210 $Error::TypeTiny::AUTHORITY = 'cpan:TOBYINK';
9 299         259337 $Error::TypeTiny::VERSION = '2.003_000';
10             }
11              
12             $Error::TypeTiny::VERSION =~ tr/_//d;
13              
14             require Type::Tiny;
15             __PACKAGE__->Type::Tiny::_install_overloads(
16 750     750   231195 q[""] => sub { $_[0]->to_string },
17 1648     1648   12203 q[bool] => sub { 1 },
18             );
19              
20             require Carp;
21             *CarpInternal = \%Carp::CarpInternal;
22              
23             our %CarpInternal;
24             $CarpInternal{$_}++ for @Type::Tiny::InternalPackages;
25              
26             sub new {
27 873     873 1 1648 my $class = shift;
28 873 50       4587 my %params = ( @_ == 1 ) ? %{ $_[0] } : @_;
  0         0  
29 873         3572 return bless \%params, $class;
30             }
31              
32             sub throw {
33 450     450 1 29859 my $next = $_[0]->can( 'throw_cb' );
34 450         1341 splice( @_, 1, 0, undef );
35 450         1255 goto $next;
36             }
37              
38             sub throw_cb {
39 872     872 1 2069 my $class = shift;
40 872         1427 my $callback = shift;
41            
42 872         1896 my ( $level, @caller, %ctxt ) = 0;
43 872         1444 while (
44             do {
45 2445         4176 my $caller = caller $level;
46 2445 50       9574 defined $caller and $CarpInternal{$caller};
47             }
48             )
49             {
50 1573         2359 $level++;
51             }
52 872 100 100     9210 if ( ( ( caller( $level - 1 ) )[1] || "" ) =~
53             /^(?:parameter validation for|exportable function) '(.+?)'$/ )
54             {
55 640         4046 my ( $pkg, $func ) = ( $1 =~ m{^(.+)::(\w+)$} );
56 640 100 50     2587 $level++ if caller( $level ) eq ( $pkg || "" );
57             }
58            
59             # Moo's Method::Generate::Constructor puts an eval in the stack trace,
60             # that is useless for debugging, so show the stack frame one above.
61 872 50 33     6415 $level++
62             if (
63             ( caller( $level ) )[1] =~ /^\(eval \d+\)$/
64             and ( caller( $level ) )[3] eq '(eval)' # (caller())[3] is $subroutine
65             );
66 872         5209 @ctxt{qw/ package file line /} = caller( $level );
67            
68 872         1925 my $stack = undef;
69 872 100       2034 if ( our $StackTrace ) {
70 1         5 require Devel::StackTrace;
71 1         23 $stack = "Devel::StackTrace"->new(
72             ignore_package => [ keys %CarpInternal ],
73             );
74             }
75            
76 872         3977 our $LastError = $class->new(
77             context => \%ctxt,
78             stack_trace => $stack,
79             @_,
80             );
81            
82 872 100       7903 $callback ? $callback->( $LastError ) : die( $LastError );
83             } #/ sub throw
84              
85 769   66 769 1 7670 sub message { $_[0]{message} ||= $_[0]->_build_message }
86 757     757 1 2905 sub context { $_[0]{context} }
87 3     3 1 2627 sub stack_trace { $_[0]{stack_trace} }
88              
89             sub to_string {
90 403     403 1 976 my $e = shift;
91 403         1265 my $c = $e->context;
92 403         1054 my $m = $e->message;
93            
94             $m =~ /\n\z/s
95             ? $m
96             : $c ? sprintf(
97             "%s at %s line %s.\n", $m, $c->{file} || 'file?',
98 403 50 50     5562 $c->{line} || 'NaN'
    50 50        
99             )
100             : sprintf( "%s\n", $m );
101             } #/ sub to_string
102              
103             sub _build_message {
104 1     1   6 return 'An exception has occurred';
105             }
106              
107             sub croak {
108 148     148 1 483 my ( $fmt, @args ) = @_;
109 148         813 @_ = (
110             __PACKAGE__,
111             message => sprintf( $fmt, @args ),
112             );
113 148         587 goto \&throw;
114             }
115              
116             1;
117              
118             __END__
119              
120             =pod
121              
122             =encoding utf-8
123              
124             =head1 NAME
125              
126             Error::TypeTiny - exceptions for Type::Tiny and friends
127              
128             =head1 SYNOPSIS
129              
130             use Data::Dumper;
131             use Try::Tiny;
132             use Types::Standard qw(Str);
133            
134             try {
135             Str->assert_valid(undef);
136             }
137             catch {
138             my $exception = shift;
139             warn "Encountered Error: $exception";
140             warn Dumper($exception->explain)
141             if $exception->isa("Error::TypeTiny::Assertion");
142             };
143              
144             =head1 STATUS
145              
146             This module is covered by the
147             L<Type-Tiny stability policy|Type::Tiny::Manual::Policies/"STABILITY">.
148              
149             =head1 DESCRIPTION
150              
151             When Type::Tiny and its related modules encounter an error, they throw an
152             exception object. These exception objects inherit from Error::TypeTiny.
153              
154             =head2 Constructors
155              
156             =over
157              
158             =item C<< new(%attributes) >>
159              
160             Moose-style constructor function.
161              
162             =item C<< throw(%attributes) >>
163              
164             Constructs an exception and passes it to C<die>.
165              
166             Automatically populates C<context> and C<stack_trace> if appropriate.
167              
168             =item C<< throw_cb($callback, %attributes) >>
169              
170             Constructs an exception and passes it to C<< $callback >> which should
171             be a coderef; if undef, uses C<die>.
172              
173             Automatically populates C<context> and C<stack_trace> if appropriate.
174              
175             =back
176              
177             =head2 Attributes
178              
179             =over
180              
181             =item C<message>
182              
183             The error message.
184              
185             =item C<context>
186              
187             Hashref containing the package, file and line that generated the error.
188              
189             =item C<stack_trace>
190              
191             A more complete stack trace. This feature requires L<Devel::StackTrace>;
192             use the C<< $StackTrace >> package variable to switch it on.
193              
194             =back
195              
196             =head2 Methods
197              
198             =over
199              
200             =item C<to_string>
201              
202             Returns the message, followed by the context if it is set.
203              
204             =back
205              
206             =head2 Functions
207              
208             =over
209              
210             =item C<< Error::TypeTiny::croak($format, @args) >>
211              
212             Functional-style shortcut to C<throw> method. Takes an C<sprintf>-style
213             format string and optional arguments to construct the C<message>.
214              
215             =back
216              
217             =head2 Overloading
218              
219             =over
220              
221             =item *
222              
223             Stringification is overloaded to call C<to_string>.
224              
225             =back
226              
227             =head2 Package Variables
228              
229             =over
230              
231             =item C<< %Carp::CarpInternal >>
232              
233             Error::TypeTiny honours this package variable from L<Carp>.
234             (C< %Error::TypeTiny::CarpInternal> is an alias for it.)
235              
236             =item C<< $Error::TypeTiny::StackTrace >>
237              
238             Boolean to toggle stack trace generation.
239              
240             =item C<< $Error::TypeTiny::LastError >>
241              
242             A reference to the last exception object thrown.
243              
244             =back
245              
246             =head1 CAVEATS
247              
248             Although Error::TypeTiny objects are thrown for errors produced by
249             Type::Tiny, that doesn't mean every time you use Type::Tiny you'll get
250             Error::TypeTinys whenever you want.
251              
252             For example, if you use a Type::Tiny type constraint in a Moose attribute,
253             Moose will not call the constraint's C<assert_valid> method (which throws
254             an exception). Instead it will call C<check> and C<get_message> (which do
255             not), and will C<confess> an error message of its own. (The C<< $LastError >>
256             package variable may save your bacon.)
257              
258             =head1 BUGS
259              
260             Please report any bugs to
261             L<https://github.com/tobyink/p5-type-tiny/issues>.
262              
263             =head1 SEE ALSO
264              
265             L<Error::TypeTiny::Assertion>,
266             L<Error::TypeTiny::WrongNumberOfParameters>.
267              
268             L<Try::Tiny>, L<Try::Tiny::ByClass>.
269              
270             =head1 AUTHOR
271              
272             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
273              
274             =head1 COPYRIGHT AND LICENCE
275              
276             This software is copyright (c) 2013-2014, 2017-2023 by Toby Inkster.
277              
278             This is free software; you can redistribute it and/or modify it under
279             the same terms as the Perl 5 programming language system itself.
280              
281             =head1 DISCLAIMER OF WARRANTIES
282              
283             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
284             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
285             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.