File Coverage

lib/Unexpected/TraitFor/Throwing.pm
Criterion Covered Total %
statement 40 40 100.0
branch 14 14 100.0
condition 5 5 100.0
subroutine 12 12 100.0
pod 4 4 100.0
total 75 75 100.0


line stmt bran cond sub pod time code
1             package Unexpected::TraitFor::Throwing;
2              
3 4     4   1551 use namespace::autoclean;
  4         6  
  4         26  
4              
5 4     4   224 use Carp ( );
  4         7  
  4         57  
6 4     4   13 use English qw( -no_match_vars );
  4         4  
  4         28  
7 4     4   1260 use Scalar::Util qw( blessed );
  4         5  
  4         150  
8 4     4   15 use Unexpected::Functions qw( is_one_of_us parse_arg_list );
  4         5  
  4         24  
9 4     4   19 use Unexpected::Types qw( Maybe Object );
  4         5  
  4         18  
10 4     4   1658 use Moo::Role;
  4         3  
  4         22  
11              
12             requires qw( BUILD );
13              
14             # Private functions
15             my $_cache_key = sub {
16             # uncoverable branch true
17             return $PID.'-'.(exists $INC{ 'threads.pm' } ? threads->tid() : 0);
18             };
19              
20             my $_exception_cache = {};
21              
22             # Public attributes. Lifted from Throwable
23             has 'previous_exception' => is => 'ro', isa => Maybe[Object],
24 30     30   1818 builder => sub { $_exception_cache->{ $_cache_key->() } };
25              
26             # Construction
27             after 'BUILD' => sub {
28             my $self = shift; my $e = $self->clone; delete $e->{previous_exception};
29              
30             $_exception_cache->{ $_cache_key->() } = $e;
31              
32             return;
33             };
34              
35             # Private methods
36             my $_is_object_ref = sub {
37             my ($self, @args) = @_; blessed $self or return 0;
38              
39             scalar @args and Carp::confess
40             'Trying to throw an Exception object with arguments';
41             return 1;
42             };
43              
44             # Public methods
45             sub caught {
46 10     10 1 831 my ($self, @args) = @_;
47              
48 10 100       26 $self->$_is_object_ref( @args ) and return $self;
49              
50 9         27 my $attr = parse_arg_list @args;
51 9 100 100     55 my $error = $attr->{error} ||= $EVAL_ERROR; $error or return;
  9         25  
52              
53 8 100       28 return (is_one_of_us $error) ? $error : $self->new( $attr );
54             }
55              
56             sub clone {
57 33     33 1 641 my ($self, $args) = @_;
58              
59 33 100       97 my $class = blessed $self or $self->throw( 'Clone is an object method' );
60              
61 32   100     36 return bless { %{ $self }, %{ $args // {} } }, $class;
  32         77  
  32         222  
62             }
63              
64             sub throw {
65 30     30 1 6322 my ($self, @args) = @_;
66              
67 30 100       47 $self->$_is_object_ref( @args ) and die $self;
68 28 100       99 is_one_of_us $args[ 0 ] and die $args[ 0 ];
69 27         499 die $self->new( @args );
70             }
71              
72             sub throw_on_error {
73 4 100   4 1 186 my $e; $e = shift->caught( @_ ) and die $e; return;
  4         16  
  1         2  
74             }
75              
76             1;
77              
78             __END__