Import Throwable
[gitmo/Moose.git] / lib / StackTrace / Auto.pm
CommitLineData
7f92fabb 1package StackTrace::Auto;
2use Moose::Role 0.87;
3# ABSTRACT: a role for generating stack traces during instantiation
4
5=head1 SYNOPSIS
6
7First, include StackTrace::Auto in a Moose class...
8
9 package Some::Class;
10 use Moose;
11 with 'StackTrace::Auto';
12
13...then create an object of that class...
14
15 my $obj = Some::Class->new;
16
17...and now you have a stack trace for the object's creation.
18
19 print $obj->stack_trace->as_string;
20
21=attr stack_trace
22
23This attribute will contain an object representing the stack at the point when
24the error was generated and thrown. It must be an object performing the
25C<as_string> method.
26
27=attr stack_trace_class
28
29This attribute may be provided to use an alternate class for stack traces. The
30default is L<Devel::StackTrace|Devel::StackTrace>.
31
32In general, you will not need to think about this attribute.
33
34=cut
35
36{
37 use Moose::Util::TypeConstraints;
38
39 has stack_trace => (
40 is => 'ro',
41 isa => duck_type([ qw(as_string) ]),
42 builder => '_build_stack_trace',
43 init_arg => undef,
44 );
45
46 my $tc = subtype as 'ClassName';
47 coerce $tc, from 'Str', via { Class::MOP::load_class($_); $_ };
48
49 has stack_trace_class => (
50 is => 'ro',
51 isa => $tc,
52 coerce => 1,
53 lazy => 1,
54 builder => '_build_stack_trace_class',
55 );
56
57 no Moose::Util::TypeConstraints;
58}
59
60=attr stack_trace_args
61
62This attribute is an arrayref of arguments to pass when building the stack
63trace. In general, you will not need to think about it.
64
65=cut
66
67has stack_trace_args => (
68 is => 'ro',
69 isa => 'ArrayRef',
70 lazy => 1,
71 builder => '_build_stack_trace_args',
72);
73
74sub _build_stack_trace_class {
75 return 'Devel::StackTrace';
76}
77
78sub _build_stack_trace_args {
79 my ($self) = @_;
80 my $found_mark = 0;
81 my $uplevel = 3; # number of *raw* frames to go up after we found the marker
82 return [
83 frame_filter => sub {
84 my ($raw) = @_;
85 if ($found_mark) {
86 return 1 unless $uplevel;
87 return !$uplevel--;
88 }
89 else {
90 $found_mark = scalar $raw->{caller}->[3] =~ /__stack_marker$/;
91 return 0;
92 }
93 },
94 ];
95}
96
97sub _build_stack_trace {
98 my ($self) = @_;
99 return $self->stack_trace_class->new(
100 @{ $self->stack_trace_args },
101 );
102}
103
104around new => sub {
105 my $next = shift;
106 my $self = shift;
107 return $self->__stack_marker($next, @_);
108};
109
110sub __stack_marker {
111 my $self = shift;
112 my $next = shift;
113 return $self->$next(@_);
114}
115
116no Moose::Role;
1171;