line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Throw; |
2
|
3
|
|
|
3
|
|
16352
|
use strict; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
89
|
|
3
|
3
|
|
|
3
|
|
11
|
use warnings; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
115
|
|
4
|
|
|
|
|
|
|
require 5.8.8; |
5
|
3
|
|
|
3
|
|
2026
|
use overload '""' => \&_str, fallback => 1; |
|
3
|
|
|
|
|
1777
|
|
|
3
|
|
|
|
|
17
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 NAME |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Throw - Simple exceptions that do the right things in multiple contexts |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=cut |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our (@EXPORT, $trace, $level, $pretty, $js, $jp) = ('throw'); |
14
|
|
|
|
|
|
|
our $VERSION = '0.12'; #VERSION |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub import { |
17
|
3
|
|
|
3
|
|
281
|
no strict 'refs'; ## no critic |
|
3
|
|
|
|
|
3
|
|
|
3
|
|
|
|
|
3873
|
|
18
|
3
|
100
|
|
3
|
|
21
|
my ($me, $you, $f, $l) = (shift, caller); @_ = @{"$me\::EXPORT"} if !@_; |
|
3
|
|
|
|
|
12
|
|
|
2
|
|
|
|
|
7
|
|
19
|
3
|
50
|
|
|
|
6
|
defined &{"$me\::$_"} ? *{"$you\::$_"} = \&{"$me\::$_"} : die "Cannot export $_ from $me to $you at $f line $l.\n" for @_; |
|
6
|
|
|
|
|
19
|
|
|
6
|
|
|
|
|
1372
|
|
|
6
|
|
|
|
|
9
|
|
20
|
|
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub throw { |
23
|
6
|
100
|
|
6
|
1
|
4237
|
my $args = ref($_[0]) ? shift() : {%{$_[1]||{}}, error => $_[0]}; |
|
6
|
50
|
|
|
|
33
|
|
24
|
6
|
100
|
50
|
|
|
50
|
$args->{'trace'} = caller_trace($trace || $args->{'trace'} || 1, $_[2]) if $trace || $args->{'trace'} || @_>2; |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
25
|
6
|
|
|
|
|
27
|
die bless $args, __PACKAGE__; |
26
|
|
|
|
|
|
|
} |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub new { |
29
|
0
|
|
|
0
|
1
|
0
|
my $class = shift; |
30
|
0
|
0
|
|
|
|
0
|
my $args = ref($_[0]) ? shift() : {%{$_[1]||{}}, error => $_[0]}; |
|
0
|
0
|
|
|
|
0
|
|
31
|
0
|
0
|
0
|
|
|
0
|
$args->{'trace'} = caller_trace($trace || $args->{'trace'} || 1, $_[2]) if $trace || $args->{'trace'} || @_>2; |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
32
|
0
|
|
|
|
|
0
|
return bless $args, $class; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
1
|
50
|
50
|
1
|
1
|
6
|
sub croak { my $a = {%{$_[1]||{}}, error => $_[0]}; $a->{'trace'} = caller_trace(1, ($_[2]||0)+1); die bless $a, __PACKAGE__ } |
|
1
|
|
|
|
|
10
|
|
|
1
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
6
|
|
36
|
0
|
0
|
0
|
0
|
1
|
0
|
sub carp { my $a = {%{$_[1]||{}}, error => $_[0]}; $a->{'trace'} = caller_trace(1, ($_[2]||0)+1); warn bless $a, __PACKAGE__ } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
37
|
1
|
50
|
|
1
|
1
|
1
|
sub confess { my $a = {%{$_[1]||{}}, error => $_[0]}; $a->{'trace'} = caller_trace(2, $_[2]); die bless $a, __PACKAGE__ } |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
5
|
|
38
|
0
|
0
|
|
0
|
1
|
0
|
sub cluck { my $a = {%{$_[1]||{}}, error => $_[0]}; $a->{'trace'} = caller_trace(2, $_[2]); warn bless $a, __PACKAGE__ } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub _str { |
41
|
4
|
|
|
4
|
|
1209
|
my $self = shift; |
42
|
4
|
|
50
|
|
|
13
|
my $err = $self->{'error'} || "Something happened"; |
43
|
4
|
50
|
|
|
|
11
|
my $p = defined($pretty) ? $pretty : $self->{'_pretty'}; |
44
|
4
|
|
|
|
|
10
|
local @$self{'error','_pretty'}; delete @$self{'error','_pretty'}; |
|
4
|
|
|
|
|
7
|
|
45
|
4
|
100
|
|
|
|
20
|
return "$err\n" if !scalar keys %$self; |
46
|
2
|
|
|
|
|
10
|
require JSON; |
47
|
2
|
50
|
0
|
|
|
34
|
my $j = $p ? $jp ||= JSON->new->allow_unknown->allow_blessed->utf8->convert_blessed->canonical->pretty |
|
|
|
66
|
|
|
|
|
48
|
|
|
|
|
|
|
: $js ||= JSON->new->allow_unknown->allow_blessed->utf8->convert_blessed->canonical; |
49
|
2
|
50
|
|
|
|
84
|
return "$err: ".$j->encode({%$self}).($p ? '' : "\n"); |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub caller_trace { |
53
|
5
|
50
|
33
|
5
|
1
|
47
|
my $args = ref($_[0]) ? $_[0] : (!$_[0] || $_[0] !~ /^[123]$/) ? return $_[0]: {verbose => $_[0], level => $_[1]}; |
|
|
50
|
|
|
|
|
|
54
|
5
|
|
100
|
|
|
38
|
my $i = ($level || $_[1] || $args->{'level'} || 0) + 1; |
55
|
5
|
100
|
100
|
|
|
41
|
return sprintf "Called from %s at %s line %s", (caller $i+1)[3]||'main', map{(my$s=$_)=~s|^(?:.+/)?lib/||;$s} (caller $i)[1,2] if $args->{'verbose'} && $args->{'verbose'} eq '1'; |
|
4
|
|
66
|
|
|
8
|
|
|
4
|
|
|
|
|
17
|
|
56
|
3
|
50
|
50
|
|
|
5
|
my ($m1, $m2, $m3, $nv, @trace) = (0, 0, 0, eval {require 5.014} ? ($args->{'verbose'} || '') ne '3' : 1); |
|
3
|
|
|
|
|
66
|
|
57
|
3
|
|
|
|
|
7
|
while (1) { |
58
|
|
|
|
|
|
|
my ($pkg, $file, $line, $sub, $sargs) = $nv ? ((caller $i++)[0..3], []) |
59
|
9
|
100
|
50
|
|
|
32
|
: do { package DB; local $DB::args[0] = \$nv; ((caller $i++)[0..3], ($DB::args[0]||'') ne \$nv ? [@DB::args] : []) }; |
|
3
|
100
|
|
|
|
5
|
|
|
3
|
|
|
|
|
0
|
|
60
|
9
|
100
|
|
|
|
17
|
last if ! $sargs; |
61
|
6
|
|
|
|
|
17
|
$sub =~ s/.*://; $file =~ s|^(?:.+/)?lib/||; |
|
6
|
|
|
|
|
9
|
|
62
|
6
|
50
|
33
|
|
|
55
|
next if ($file eq __FILE__) || $args->{'skip'}->{$file} || $args->{'skip'}->{$pkg} || $args->{'skip'}->{$sub}; |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
63
|
6
|
50
|
100
|
|
|
23
|
splice @$sargs, $args->{'max_args'}, -1, '...' if @$sargs > ($args->{'max_args'} ||= 5); |
64
|
0
|
|
|
|
|
0
|
my $args = (!@$sargs || $i==2 && $sub eq 'throw') ? '' |
65
|
|
|
|
|
|
|
: ' ('.join(', ',map{ |
66
|
6
|
0
|
66
|
|
|
21
|
my$d=!defined($_)?'undef':ref($_)||!/\D/?$_:do{(my$c=$_)=~s|([\'/])|\\$1|g;"'$c'"}; |
|
0
|
0
|
0
|
|
|
0
|
|
|
0
|
50
|
|
|
|
0
|
|
67
|
0
|
|
0
|
|
|
0
|
substr($d,0,$args->{'max_arg_len'}||20) |
68
|
|
|
|
|
|
|
} @$sargs).')'; |
69
|
6
|
100
|
|
|
|
15
|
$m1 = length $sub if length($sub) > $m1; |
70
|
6
|
100
|
|
|
|
11
|
$m2 = length $file if length($file) > $m2; |
71
|
6
|
100
|
|
|
|
12
|
$m3 = length $line if length($line) > $m3; |
72
|
6
|
|
|
|
|
13
|
push @trace, [$sub, $file, $line, $args]; |
73
|
|
|
|
|
|
|
} |
74
|
3
|
|
|
|
|
17
|
return join "\n", map {sprintf "%-${m1}s at %-${m2}s line %${m3}s%s", @$_} @trace; |
|
6
|
|
|
|
|
38
|
|
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
0
|
|
|
0
|
1
|
|
sub TO_JSON { return {%{$_[0]}} } |
|
0
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub classify { |
80
|
0
|
|
|
0
|
1
|
|
my ($err, $ref) = @_; |
81
|
0
|
0
|
|
|
|
|
$ref = {$ref => 1} if ! ref $ref; |
82
|
0
|
0
|
|
|
|
|
my $type = !ref($err) ? 'undef.flat' : defined($err->{'type'}) ? $err->{'type'} : 'undef.none'; |
|
|
0
|
|
|
|
|
|
83
|
0
|
|
|
|
|
|
my @keys = grep {$_ ne 'default'} keys %$ref; |
|
0
|
|
|
|
|
|
|
84
|
0
|
0
|
|
|
|
|
@keys = sort {length($b) <=> length($a) || $a cmp $b} @keys if @keys > 1; |
|
0
|
0
|
|
|
|
|
|
85
|
0
|
|
|
|
|
|
foreach my $key (@keys) { |
86
|
0
|
0
|
|
|
|
|
next if $type !~ /^\Q$key\E\b(?:$|\.)/; |
87
|
0
|
|
|
|
|
|
my $val = $ref->{$key}; |
88
|
0
|
0
|
|
|
|
|
return ref($val) ? $val->($err, $key) : $val; |
89
|
|
|
|
|
|
|
} |
90
|
0
|
0
|
|
|
|
|
return if ! exists $ref->{'default'}; |
91
|
0
|
|
|
|
|
|
my $val = $ref->{'default'}; |
92
|
0
|
0
|
|
|
|
|
return ref($val) ? $val->($err, 'default') : $val; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
1; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
__END__ |