File Coverage

lib/Unexpected/TraitFor/TracingStacks.pm
Criterion Covered Total %
statement 45 45 100.0
branch 16 20 100.0
condition 9 12 83.3
subroutine 10 10 100.0
pod 3 3 100.0
total 83 90 97.7


line stmt bran cond sub pod time code
1             package Unexpected::TraitFor::TracingStacks;
2              
3 4     4   3227 use namespace::autoclean;
  4         9  
  4         33  
4              
5 4     4   357 use Scalar::Util qw( weaken );
  4         10  
  4         287  
6 4     4   27 use Unexpected::Types qw( HashRef LoadableClass Tracer );
  4         10  
  4         32  
7 4     4   4222 use Moo::Role;
  4         10  
  4         30  
8              
9             requires qw( BUILD );
10              
11             # Object attributes (public)
12             has 'trace' => is => 'lazy', isa => Tracer, builder => sub {
13 31     31   572 $_[ 0 ]->trace_class->new( %{ $_[ 0 ]->trace_args } ) },
  31         924  
14             handles => [ qw( frames ) ], init_arg => undef;
15              
16             has 'trace_args' => is => 'lazy', isa => HashRef, builder => sub { {
17 30     30   573 filter_frames_early => 1,
18             no_refs => 1,
19             respect_overload => 0,
20             max_arg_length => 0,
21             frame_filter => $_[ 0 ]->trace_frame_filter, } };
22              
23             has 'trace_class' => is => 'ro', isa => LoadableClass,
24             default => 'Devel::StackTrace';
25              
26             # Construction
27             before 'BUILD' => sub {
28             my $self = shift; $self->trace; return;
29             };
30              
31             # Public methods
32             sub message { # Stringify self and a full stack trace
33 1     1 1 677 my $self = shift; return "${self}\n".$self->trace->as_string."\n";
  1         9  
34             }
35              
36             sub stacktrace {
37 3     3 1 3648 my ($self, $skip) = @_; my (@lines, %seen, $subr);
  3         9  
38              
39 3         95 for my $frame (reverse $self->frames) {
40 12         320 my $package = $frame->package; my $l_no;
  12         83  
41              
42 12 100 100     53 unless ($l_no = $seen{ $package } and $l_no == $frame->line) {
43 9   66     68 my $lead = $subr || $package; # uncoverable condition false
44              
45             # uncoverable branch false
46 9 50       67 $lead !~ m{ (?: \A \(eval\) ) | (?: ::try) | (?: :: __ANON__ \z) }mx
47             and push @lines, join q( ), $lead, 'line', $frame->line;
48 9         101 $seen{ $package } = $frame->line;
49             }
50              
51 12 50       98 $frame->subroutine !~ m{ :: __ANON__ \z }mx # uncoverable branch false
52             and $subr = $frame->subroutine;
53             }
54              
55 3 100       49 defined $skip or $skip = 0; pop @lines while ($skip--);
  3         12  
56              
57 3 100       29 return wantarray ? reverse @lines : (join "\n", reverse @lines)."\n";
58             }
59              
60             sub trace_frame_filter { # Lifted from StackTrace::Auto
61 30     30 1 95 my $self = shift; my $found_mark = 0; weaken( $self );
  30         76  
  30         182  
62              
63             return sub {
64 268     268   17581 my ($raw) = @_;
65 268         710 my $subr = $raw->{caller}->[ 3 ];
66 268         1827 (my $package = $subr) =~ s{ :: \w+ \z }{}mx;
67              
68             # uncoverable branch true
69             # uncoverable condition right
70 268 50       1068 $ENV{UNEXPECTED_SHOW_RAW_TRACE} and warn "${subr}\n";
71              
72 268 100       939 if ($found_mark == 2) { return 1 }
  59 100       240  
73             elsif ($found_mark == 1) {
74             # uncoverable branch true
75             # uncoverable condition right
76 29 50 33     157 $subr =~ m{ :: new \z }mx and $self->isa( $package ) and return 0;
77 29         82 $found_mark++; return 1;
  29         118  
78             }
79              
80             # uncoverable condition right
81 180 100 100     1197 $subr =~ m{ :: new \z }mx and $self->isa( $package ) and $found_mark++;
82 180         718 return 0;
83             }
84 30         1108 }
85              
86             1;
87              
88             __END__