/
Error.pm
158 lines (117 loc) · 3.27 KB
/
Error.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package Throwable::Error;
use Moose;
with 'Throwable';
# ABSTRACT: an easy-to-use class for error objects
=head1 SYNOPSIS
package MyApp::Error;
use Moose;
extends 'Throwable::Error';
has execution_phase => (is => 'ro', isa => 'MyApp::Phase');
...and in your app...
MyApp::Error->throw({ phase => $self->phase });
=head1 DESCRIPTION
Throwable::Error is a base class for exceptions that will be thrown to signal
errors and abort normal program flow. Throwable::Error is an alternative to
L<Exception::Class|Exception::Class>, the features of which are largely
provided by the Moose object system atop which Throwable::Error is built.
Throwable::Error performs the L<Throwable|Throwable> role.
=cut
use overload
q{""} => 'as_string',
fallback => 1;
=attr message
This attribute must be defined and must contain a string describing the error
condition. This string will be printed at the top of the stack trace when the
error is stringified.
=cut
has message => (
is => 'ro',
isa => 'Str',
required => 1,
);
=method as_string
This method will provide a string representing the error, containing the
error's message followed by the its stack trace.
=cut
sub as_string {
my ($self) = @_;
my $str = $self->message;
$str .= "\n\n" . $self->stack_trace->as_string;
return $str;
}
=attr stack_trace
This attribute will contain an object representing the stack at the point when
the error was generated and thrown. It must be an object performing the
C<as_string> method.
=attr stack_trace_class
This attribute may be provided to use an alternate class for stack traces. The
default is L<Devel::StackTrace|Devel::StackTrace>.
In general, you will not need to think about this attribute.
=cut
{
use Moose::Util::TypeConstraints;
has stack_trace => (
is => 'ro',
isa => duck_type([ qw(as_string) ]),
builder => '_build_stack_trace',
);
my $tc = subtype as 'ClassName';
coerce $tc, from 'Str', via { Class::MOP::load_class($_); $_ };
has stack_trace_class => (
is => 'ro',
isa => $tc,
coerce => 1,
lazy => 1,
builder => '_build_stack_trace_class',
);
no Moose::Util::TypeConstraints;
}
=attr stack_trace_args
This attribute is an arrayref of arguments to pass when building the stack
trace. In general, you will not need to think about it.
=cut
has stack_trace_args => (
is => 'ro',
isa => 'ArrayRef',
lazy => 1,
builder => '_build_stack_trace_args',
);
sub _build_stack_trace_class {
return 'Devel::StackTrace';
}
sub _build_stack_trace_args {
my ($self) = @_;
my $found_mark = 0;
my $uplevel = 3; # number of *raw* frames to go up after we found the marker
return [
frame_filter => sub {
my ($raw) = @_;
if ($found_mark) {
return 1 unless $uplevel;
return !$uplevel--;
}
else {
$found_mark = scalar $raw->{caller}->[3] =~ /__stack_marker$/;
return 0;
}
},
];
}
sub _build_stack_trace {
my ($self) = @_;
return $self->stack_trace_class->new(
@{ $self->stack_trace_args },
);
}
around new => sub {
my $next = shift;
my $self = shift;
return $self->__stack_marker($next, @_);
};
sub __stack_marker {
my $self = shift;
my $next = shift;
return $self->$next(@_);
}
no Moose;
1;