File Coverage

blib/lib/Glitch.pm
Criterion Covered Total %
statement 71 71 100.0
branch 19 28 67.8
condition 9 20 45.0
subroutine 17 20 85.0
pod 1 1 100.0
total 117 140 83.5


line stmt bran cond sub pod time code
1             package Glitch;
2             our $VERSION = '0.04';
3 4     4   260508 use 5.006; use strict; use warnings;
  4     4   36  
  4     4   16  
  4         7  
  4         74  
  4         19  
  4         6  
  4         193  
4 4     4   2840 use Data::Dumper; use feature qw/state/;
  4     4   24459  
  4         323  
  4         31  
  4         6  
  4         479  
5             state %GLITCHES;
6              
7             BEGIN {
8 4     4   339 $Data::Dumper::Deparse = 1;
9             }
10              
11             sub import {
12 5     5   494 my ($pkg, %import) = @_;
13 5 100       22 if (keys %import) {
14             _build_glitch(
15             name => $_,
16 2         8 %{ $import{$_} },
17 10         18 map { $_ => '' } ("file", "filepath", "line", "stacktrace", "module")
18 2         10 ) for sort keys %import;
19             }
20 5         8 do {
21 4     4   25 no strict 'refs';
  4         6  
  4         3380  
22 5         13 my $package = caller();
23 5         8 *{"${package}::glitch"} = \&glitch;
  5         2398  
24             };
25             }
26              
27             sub glitch {
28 3     3 1 207 my %options = (
29             name => shift,
30             _stack(),
31             @_
32             );
33              
34 3 100       13 _build_glitch(%options) if (!$GLITCHES{$options{name}});
35              
36 3         64 die $GLITCHES{$options{name}}->new(%options);
37             }
38              
39             sub _build_glitch {
40 3     3   12 my (%options) = @_;
41 3   50     33 my $class = sprintf q|%s::%s|, $options{object_name} ||= 'Glitch', $options{name};
42 3 100       19 my @methods = map { my $struct = $_ =~ m/(file|filepath|line|stacktrace|module)/ ? "''" : _stringify_struct($options{$_}); "sub $_ { return \$_[0]->{$_} || $struct; }" } sort keys %options;
  24         89  
  24         68  
43 3         8 unshift @methods, 'sub new { my $self = shift; return bless {@_}, $self; }';
44 3         5 push @methods, 'sub stringify { return $_[0]->message . " at " . $_[0]->filepath . " line " . $_[0]->line . "\n"; }';
45 3         28 my $package = sprintf(q|package %s;
46             use overload '""' => \&stringify;
47             %s
48             1;|, $class, join( "\n", @methods) );
49 3   50 5   265 eval $package;
  3   50 2   2349  
  3   0 0   1956  
  3   50 1   22  
      0 3      
      0 0      
        0      
        2      
50 3 50       21 die $@ if ($@);
51 3         11 $GLITCHES{$options{name}} = $class;
52 3         16 return 1;
53             }
54              
55             sub _stringify_struct {
56 9     9   17 my ( $struct ) = @_;
57 11 50       27 return 'undefined' unless defined $struct;
58 11 50       33 $struct = ref $struct ? Dumper $struct : "'$struct'";
59 11         27 $struct =~ s/\$VAR1 = //;
60 9         23 $struct =~ s/\s*\n*\s*package Glitch\;|use warnings\;|use strict\;//g;
61 10         52 $struct =~ s/{\s*\n*/{/;
62 12         20 $struct =~ s/;$//;
63 12         42 return $struct;
64             }
65              
66             sub _stack {
67 3     5   6 my @caller; my $i = 0; my @stack;
  3         4  
  5         1257  
68 3         41 while(@caller = caller($i++)){
69 9 100       35 next if $caller[0] eq 'Glitch';
70 6         18 $stack[$i+1]->{module} = $caller[0];
71 6         11 $stack[$i+1]->{filepath} = $caller[1];
72 6 50       38 $stack[$i+1]->{file} = $1 if $caller[1] =~ /([^\/]+)$/;;
73 6 50       40 $stack[$i+1]->{line} = $1 if $caller[2] =~ /(\d+)/;
74 6 50       40 $stack[$i]->{sub} = $1 if $caller[3] =~ /([^:]+)$/;
75             }
76 3         6 my $msg = $stack[-1];
77             $msg->{stacktrace} = join '->', reverse map {
78 6 50       23 my $module = $_->{module} !~ m/^main$/ ? $_->{module} : $_->{file};
79             $_->{sub}
80             ? $module . '::' . $_->{sub} . ':' . $_->{line}
81             : $module . ':' . $_->{line}
82 6 100       32 } grep {
83 3         6 $_ && $_->{module} && $_->{line} && $_->{file}
84 15 50 100     62 } @stack;
      66        
85 3 50       11 delete $msg->{stacktrace} unless $msg->{stacktrace};
86 3         4 return %{$msg};
  3         25  
87             }
88              
89             =head1 NAME
90              
91             Glitch - Exception Handling.
92              
93             =head1 VERSION
94              
95             Version 0.04
96              
97             =cut
98              
99             =head1 SYNOPSIS
100              
101             package Foo;
102              
103             use Glitch;
104              
105             sub bar {
106             do { ... } or glitch('one', message => 'Create a new glitch error message');
107              
108             ... later in your code you can then reuse glitch 'one'
109              
110             do { ... } or glitch('one');
111             }
112              
113             ...
114              
115             package Foo;
116              
117             use Glitch (
118             one => {
119             message => 'Create a new glitch error message'
120             },
121             two => {
122             message => 'A different glitch error message',
123             fileName => '',
124             }
125             );
126              
127             sub bar {
128             eval {
129             do { ... } or glitch('one');
130             ...
131             do { ... } or glitch('two', fileName => 'abc');
132             };
133             if ($@) {
134             do { ... } if $@->name eq 'one';
135             do { ... } if $@->name eq 'two';
136             }
137             }
138              
139             1;
140              
141             ...
142              
143             package Glitches;
144              
145             use Glitch (
146             one => {
147             message => 'Create a new glitch error message'
148             },
149             two => {
150             message => 'A different glitch error message',
151             fileName => '',
152             }
153             );
154              
155             1;
156              
157             package Foo;
158              
159             use Glitch;
160             use Glitches;
161              
162             sub bar {
163             eval {
164             do { ... } or glitch('one');
165             ...
166             do { ... } or glitch('two', fileName => 'abc');
167             };
168             if ($@) {
169             if ($@->name eq 'one') { ... }
170             elsif ($@->name eq 'two') { ... }
171             }
172             }
173              
174             1;
175              
176             =head1 EXPORT
177              
178             =head2 glitch
179              
180             =cut
181              
182             =head1 AUTHOR
183              
184             LNATION, C<< >>
185              
186             =head1 BUGS
187              
188             Please report any bugs or feature requests to C, or through
189             the web interface at L. I will be notified, and then you'll
190             automatically be notified of progress on your bug as I make changes.
191              
192             =head1 SUPPORT
193              
194             You can find documentation for this module with the perldoc command.
195              
196             perldoc Glitch
197              
198             You can also look for information at:
199              
200             =over 4
201              
202             =item * RT: CPAN's request tracker (report bugs here)
203              
204             L
205              
206             =item * CPAN Ratings
207              
208             L
209              
210             =item * Search CPAN
211              
212             L
213              
214             =back
215              
216             =head1 ACKNOWLEDGEMENTS
217              
218             =head1 LICENSE AND COPYRIGHT
219              
220             This software is Copyright (c) 2022 by LNATION.
221              
222             This is free software, licensed under:
223              
224             The Artistic License 2.0 (GPL Compatible)
225              
226             =cut
227              
228             1; # End of Glitch