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 8     8   228886 use 5.008;
  8         29  
  8         302  
2 8     8   41 use strict;
  8         14  
  8         257  
3 8     8   122 use warnings;
  8         22  
  8         251  
4              
5 8     8   7748 use Moo 1.000006 ();
  8         148041  
  8         208  
6 8     8   7273 use MooX::Struct 0.009 ();
  8         1862854  
  8         290  
7 8     8   9986 use Throwable::Error 0.200000 ();
  8         187376  
  8         906  
8              
9             {
10             package Throwable::Factory;
11             our $AUTHORITY = 'cpan:TOBYINK';
12             our $VERSION = '0.007';
13            
14             our @SHORTCUTS;
15            
16 8         159 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 8     8   72 ;
  8         20  
24            
25             sub import
26             {
27 15     15   5639 my $class = shift() . '::Struct';
28 15         47 unshift @_, $class;
29 15         83 goto \&MooX::Struct::import;
30             }
31            
32             {
33             package Throwable::Taxonomy::Caller;
34 8     8   32651 use Moo::Role;
  8         17  
  8         73  
35             push @SHORTCUTS, __PACKAGE__;
36             }
37            
38             {
39             package Throwable::Taxonomy::Environment;
40 8     8   4332 use Moo::Role;
  8         99  
  8         41  
41             push @SHORTCUTS, __PACKAGE__;
42             }
43            
44             {
45             package Throwable::Taxonomy::NotImplemented;
46 8     8   2701 use Moo::Role;
  8         15  
  8         34  
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.007';
57            
58 8     8   14099 use Data::Dumper ();
  8         77737  
  8         239  
59 8     8   83 use Moo;
  8         15  
  8         75  
60 8     8   2951 use namespace::clean;
  8         19  
  8         175  
61             extends 'MooX::Struct';
62            
63 3     3 0 9886 sub description { 'Generic exception' }
64 6     6 0 26534 sub error { shift->message }
65 2     2 0 25 sub package { shift->stack_trace->frame(0)->package }
66 2     2 0 3186 sub file { shift->stack_trace->frame(0)->filename }
67 2     2 0 3958 sub line { shift->stack_trace->frame(0)->line }
68            
69             sub BUILDARGS
70             {
71 26     26 1 140786 my $class = shift;
72 26 100       283 return +{} unless @_;
73 18 100 100     145 unshift @_, 'message' if @_ % 2 and not ref $_[0];
74 18         168 $class->SUPER::BUILDARGS(@_);
75             }
76            
77             sub TO_STRING
78             {
79 1     1 1 10112 local $Data::Dumper::Terse = 1;
80 1         2 local $Data::Dumper::Indent = 0;
81 1         2 local $Data::Dumper::Useqq = 1;
82 1         3 local $Data::Dumper::Deparse = 0;
83 1         2 local $Data::Dumper::Quotekeys = 0;
84 1         2 local $Data::Dumper::Sortkeys = 1;
85            
86 1         2 my $self = shift;
87 1         10 my $str = $self->message . "\n\n";
88            
89 1         6 for my $f ($self->FIELDS) {
90 4 100       127 next if $f eq 'message';
91 3         8 my $v = $self->$f;
92 3 100       18 $str .= sprintf(
93             "%-8s = %s\n",
94             $f,
95             ref($v) ? Data::Dumper::Dumper($v) : $v,
96             );
97             }
98 1         102 $str .= "\n";
99 1         11 $str .= $self->stack_trace->as_string;
100 1         1320 return $str;
101             }
102             }
103              
104             {
105             package Throwable::Factory::Struct::Processor;
106             our $AUTHORITY = 'cpan:TOBYINK';
107             our $VERSION = '0.007';
108            
109 8     8   7299 use Moo;
  8         35  
  8         37  
110 8     8   2609 use Carp;
  8         25  
  8         647  
111 8     8   59 use namespace::clean;
  8         16  
  8         50  
112             extends 'MooX::Struct::Processor';
113            
114             has '+base' => (
115             default => sub { Throwable::Factory::Base },
116             );
117            
118             sub process_meta
119             {
120 15     15 0 35171 my ($self, $klass, $name, $value) = @_;
121            
122 15 100       100 if ($name !~ /^-(isa|extends|with|class)$/) {
123 9         26 my $k = substr $name, 1;
124 9         186 my @matches = grep /::$k$/i, @Throwable::Factory::SHORTCUTS;
125 9 100       194 croak "Shortcut '$name' has too many matches: @matches" if @matches > 1;
126 8 100       208 croak "Shortcut '$name' has no matches" if @matches < 1;
127 7         15 $name = '-with';
128 7         15 $value = \@matches;
129             }
130            
131 13         112 $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 28     28 0 4735 my ($self, $name, $proto) = @_;
138 28 100       96 if (ref $proto eq 'HASH')
139             {
140 9         39 my %proto = %$proto;
141 9         20 $proto = [];
142            
143 9 100       29 if (defined $proto{isa}) {
144 7         15 my $isa = delete $proto{isa};
145 7         27 push @$proto, -extends => [$isa];
146             }
147 9 100       74 if (defined $proto{description}) {
148 3         8 my $desc = delete $proto{description};
149 3     2   15 push @$proto, description => sub { $desc };
  2         2167  
150             }
151 9 100       53 if (defined $proto{fields}) {
152 5         10 my $fields = delete $proto{fields};
153 5 100       22 push @$proto, ref $fields ? @$fields : $fields;
154             }
155            
156 9 100       29 if (keys %proto) {
157 1         286 croak sprintf(
158             "Exception::Class-style %s option not supported",
159             join('/', sort keys %proto),
160             );
161             }
162             }
163 27         173 return $self->SUPER::make_sub($name, $proto);
164             }
165             }
166              
167             1;
168              
169             __END__