File Coverage

blib/lib/Throwable/Factory.pm
Criterion Covered Total %
statement 101 101 100.0
branch 26 26 100.0
condition 3 3 100.0
subroutine 27 27 100.0
pod 2 9 22.2
total 159 166 95.7


line stmt bran cond sub pod time code
1 5     5   146893 use 5.008;
  5         18  
  5         181  
2 5     5   24 use strict;
  5         8  
  5         136  
3 5     5   24 use warnings;
  5         11  
  5         129  
4              
5 5     5   4354 use Moo 1.000006 ();
  5         86794  
  5         132  
6 5     5   4182 use MooX::Struct 0.009 ();
  5         800361  
  5         163  
7 5     5   4551 use Throwable::Error 0.200000 ();
  5         91916  
  5         509  
8              
9             {
10             package Throwable::Factory;
11             our $AUTHORITY = 'cpan:TOBYINK';
12             our $VERSION = '0.006';
13            
14             our @SHORTCUTS;
15            
16 5         68 use MooX::Struct -retain,
17             Base => [
18             -class => \'Throwable::Factory::Struct',
19             -extends => ['Throwable::Factory::Base'],
20             -with => ['Throwable', 'StackTrace::Auto'],
21             '$message',
22             ],
23 5     5   48 ;
  5         9  
24            
25             sub import
26             {
27 9     9   3307 my $class = shift() . '::Struct';
28 9         30 unshift @_, $class;
29 9         51 goto \&MooX::Struct::import;
30             }
31            
32             {
33             package Throwable::Taxonomy::Caller;
34 5     5   16191 use Moo::Role;
  5         12  
  5         44  
35             push @SHORTCUTS, __PACKAGE__;
36             }
37            
38             {
39             package Throwable::Taxonomy::Environment;
40 5     5   1804 use Moo::Role;
  5         46  
  5         20  
41             push @SHORTCUTS, __PACKAGE__;
42             }
43            
44             {
45             package Throwable::Taxonomy::NotImplemented;
46 5     5   1455 use Moo::Role;
  5         9  
  5         17  
47             push @SHORTCUTS, __PACKAGE__;
48             }
49            
50             Base;
51             }
52              
53             {
54             package Throwable::Factory::Base;
55             our $AUTHORITY = 'cpan:TOBYINK';
56             our $VERSION = '0.006';
57            
58 5     5   12740 use Data::Dumper ();
  5         37592  
  5         134  
59 5     5   46 use Moo;
  5         12  
  5         39  
60 5     5   9289 use namespace::clean;
  5         9  
  5         104  
61             extends 'MooX::Struct';
62            
63 1     1 0 7045 sub description { 'Generic exception' }
64 2     2 0 8699 sub error { shift->message }
65 1     1 0 7 sub package { shift->stack_trace->frame(0)->package }
66 1     1 0 353 sub file { shift->stack_trace->frame(0)->filename }
67 1     1 0 332 sub line { shift->stack_trace->frame(0)->line }
68            
69             sub BUILDARGS
70             {
71 14     14 1 58729 my $class = shift;
72 14 100       228 return +{} unless @_;
73 7 100 100     64 unshift @_, 'message' if @_ % 2 and not ref $_[0];
74 7         58 $class->SUPER::BUILDARGS(@_);
75             }
76            
77             sub TO_STRING
78             {
79 1     1 1 9190 local $Data::Dumper::Terse = 1;
80 1         3 local $Data::Dumper::Indent = 0;
81 1         2 local $Data::Dumper::Useqq = 1;
82 1         3 local $Data::Dumper::Deparse = 0;
83 1         3 local $Data::Dumper::Quotekeys = 0;
84 1         2 local $Data::Dumper::Sortkeys = 1;
85            
86 1         2 my $self = shift;
87 1         11 my $str = $self->message . "\n\n";
88            
89 1         4 for my $f ($self->FIELDS) {
90 4 100       119 next if $f eq 'message';
91 3         7 my $v = $self->$f;
92 3 100       17 $str .= sprintf(
93             "%-8s = %s\n",
94             $f,
95             ref($v) ? Data::Dumper::Dumper($v) : $v,
96             );
97             }
98 1         47 $str .= "\n";
99 1         11 $str .= $self->stack_trace->as_string;
100 1         429 return $str;
101             }
102             }
103              
104             {
105             package Throwable::Factory::Struct::Processor;
106             our $AUTHORITY = 'cpan:TOBYINK';
107             our $VERSION = '0.006';
108            
109 5     5   4224 use Moo;
  5         13  
  5         21  
110 5     5   1384 use Carp;
  5         19  
  5         352  
111 5     5   24 use namespace::clean;
  5         9  
  5         21  
112             extends 'MooX::Struct::Processor';
113            
114             has '+base' => (
115             default => sub { Throwable::Factory::Base },
116             );
117            
118             sub process_meta
119             {
120 11     11 0 30761 my ($self, $klass, $name, $value) = @_;
121            
122 11 100       75 if ($name !~ /^-(isa|extends|with|class)$/) {
123 9         71 my $k = substr $name, 1;
124 9         191 my @matches = grep /::$k$/i, @Throwable::Factory::SHORTCUTS;
125 9 100       284 croak "Shortcut '$name' has too many matches: @matches" if @matches > 1;
126 8 100       281 croak "Shortcut '$name' has no matches" if @matches < 1;
127 7         15 $name = '-with';
128 7         18 $value = \@matches;
129             }
130            
131 9         56 $self->SUPER::process_meta($klass, $name, $value);
132             }
133            
134             # Allow make_sub to accept Exception::Class-like hashrefs.
135             sub make_sub
136             {
137 14     14 0 2755 my ($self, $name, $proto) = @_;
138 14 100       57 if (ref $proto eq 'HASH')
139             {
140 3         14 my %proto = %$proto;
141 3         6 $proto = [];
142            
143 3 100       11 if (defined $proto{isa}) {
144 2         4 my $isa = delete $proto{isa};
145 2         8 push @$proto, -extends => [$isa];
146             }
147 3 100       27 if (defined $proto{description}) {
148 2         3 my $desc = delete $proto{description};
149 2     1   7 push @$proto, description => sub { $desc };
  1         5  
150             }
151 3 100       10 if (defined $proto{fields}) {
152 2         4 my $fields = delete $proto{fields};
153 2 100       7 push @$proto, ref $fields ? @$fields : $fields;
154             }
155            
156 3 100       10 if (keys %proto) {
157 1         337 croak sprintf(
158             "Exception::Class-style %s option not supported",
159             join('/', sort keys %proto),
160             );
161             }
162             }
163 13         72 return $self->SUPER::make_sub($name, $proto);
164             }
165             }
166              
167             1;
168              
169             __END__