File Coverage

blib/lib/Parse/ErrorString/Perl.pm
Criterion Covered Total %
statement 1181 1213 97.3
branch 1066 2070 51.5
condition 15 21 71.4
subroutine 21 21 100.0
pod 2 3 66.6
total 2285 3328 68.6


line stmt bran cond sub pod time code
1             package Parse::ErrorString::Perl;
2              
3 6     6   138592 use v5.8.7;
  6         34  
4 6     6   96 use strict;
  6         18  
  6         203  
5 6     6   42 use warnings;
  6         21  
  6         418  
6              
7             our $VERSION = '0.26';
8              
9 6     6   48 use Carp qw(carp cluck);
  6         17  
  6         520  
10 6     6   49 use Pod::Find ();
  6         23  
  6         233  
11 6     6   4456 use Pod::POM 0.27 ();
  6         198242  
  6         203  
12 6     6   76 use File::Spec ();
  6         19  
  6         145  
13 6     6   45 use File::Basename ();
  6         18  
  6         124  
14 6     6   3797 use Parse::ErrorString::Perl::ErrorItem ();
  6         28  
  6         170  
15 6     6   3605 use Parse::ErrorString::Perl::StackItem ();
  6         25  
  6         1002  
16              
17             sub new {
18 6     6 1 124 my $class = shift;
19 6         29 my %options = @_;
20 6   33     60 my $self = bless {}, ref $class || $class;
21 6         42 $self->_prepare_diagnostics;
22 6         1163134 $self->_prepare_localized_diagnostics(%options);
23 6         86 my %error_desc_hash = (
24             W => 'warning',
25             D => 'deprecation',
26             S => 'severe warning',
27             F => 'fatal error',
28             P => 'internal error',
29             X => 'very fatal error',
30             A => 'alien error message',
31             );
32 6         31 $self->{error_desc_hash} = \%error_desc_hash;
33 6         55 return $self;
34             }
35              
36             sub parse_string {
37 15     15 1 39698 my $self = shift;
38 15         58 my $string = shift;
39              
40             # installs a sub named 'transmo', which returns the type of the error message
41 15 100       96 if ( $self->{transmo} ) {
42 6     6   55 no warnings 'redefine';
  6         18  
  6         18850  
43 6 50   28 0 132638 eval $self->{transmo};
  28 50       120  
  28 50       135  
  28 50       126  
  28 50       126  
  28 50       116  
  28 50       119  
  28 50       129  
  28 50       126  
  28 50       120  
  28 50       128  
  28 50       115  
  28 50       120  
  28 50       116  
  28 50       117  
  28 50       108  
  28 50       110  
  28 50       114  
  28 50       123  
  28 50       117  
  28 50       113  
  28 50       118  
  28 50       113  
  28 50       113  
  28 50       165  
  28 50       121  
  28 50       122  
  28 50       116  
  28 50       120  
  28 50       113  
  28 50       163  
  28 50       118  
  28 50       112  
  28 50       111  
  28 50       118  
  28 50       134  
  28 50       111  
  28 50       120  
  28 50       110  
  28 50       140  
  28 50       226  
  28 50       127  
  28 50       206  
  28 50       126  
  28 50       116  
  28 50       207  
  28 50       119  
  28 50       140  
  28 50       125  
  28 100       124  
  28 50       119  
  28 50       152  
  27 50       111  
  27 50       120  
  27 50       104  
  27 50       104  
  27 50       107  
  27 50       106  
  27 50       102  
  27 50       124  
  27 50       107  
  27 50       109  
  27 50       103  
  27 50       107  
  27 50       107  
  27 50       106  
  27 50       113  
  27 50       101  
  27 50       95  
  27 50       103  
  27 50       99  
  27 50       103  
  27 50       106  
  27 50       101  
  27 50       98  
  27 50       107  
  27 50       111  
  27 50       111  
  27 50       103  
  27 50       105  
  27 50       109  
  27 50       100  
  27 50       107  
  27 50       106  
  27 50       108  
  27 50       102  
  27 50       103  
  27 50       103  
  27 50       102  
  27 50       103  
  27 50       96  
  27 50       102  
  27 50       101  
  27 50       96  
  27 50       106  
  27 50       105  
  27 50       107  
  27 50       98  
  27 50       106  
  27 50       105  
  27 50       105  
  27 50       108  
  27 50       111  
  27 50       114  
  27 50       104  
  27 50       105  
  27 50       104  
  27 50       104  
  27 50       157  
  27 50       112  
  27 50       101  
  27 50       106  
  27 50       100  
  27 50       106  
  27 50       104  
  27 50       103  
  27 50       103  
  27 50       104  
  27 50       111  
  27 50       100  
  27 50       102  
  27 50       113  
  27 50       98  
  27 50       106  
  27 50       99  
  27 50       105  
  27 50       99  
  27 50       98  
  27 50       97  
  27 50       104  
  27 50       107  
  27 50       98  
  27 50       101  
  27 50       103  
  27 50       104  
  27 50       136  
  27 50       109  
  27 50       104  
  27 50       113  
  27 50       107  
  27 50       108  
  27 50       106  
  27 50       108  
  27 50       109  
  27 50       102  
  27 50       100  
  27 50       106  
  27 50       99  
  27 50       103  
  27 50       104  
  27 50       115  
  27 50       103  
  27 50       112  
  27 50       102  
  27 50       104  
  27 50       102  
  27 50       109  
  27 50       106  
  27 50       111  
  27 50       101  
  27 50       110  
  27 50       105  
  27 50       102  
  27 50       110  
  27 50       107  
  27 50       98  
  27 50       107  
  27 50       108  
  27 50       104  
  27 50       106  
  27 50       101  
  27 50       104  
  27 50       97  
  27 50       103  
  27 50       107  
  27 50       111  
  27 50       108  
  27 50       109  
  27 50       99  
  27 50       107  
  27 50       109  
  27 50       106  
  27 50       104  
  27 50       113  
  27 50       112  
  27 50       100  
  27 50       100  
  27 50       104  
  27 50       105  
  27 50       101  
  27 50       115  
  27 50       103  
  27 50       114  
  27 50       102  
  27 50       111  
  27 50       102  
  27 50       99  
  27 50       104  
  27 50       103  
  27 50       102  
  27 50       161  
  27 50       111  
  27 50       109  
  27 50       109  
  27 50       101  
  27 50       110  
  27 50       104  
  27 50       110  
  27 50       101  
  27 50       106  
  27 50       104  
  27 50       102  
  27 50       108  
  27 50       102  
  27 50       110  
  27 50       114  
  27 50       104  
  27 50       106  
  27 50       108  
  27 50       105  
  27 50       102  
  27 50       108  
  27 50       113  
  27 50       100  
  27 50       104  
  27 50       109  
  27 50       106  
  27 50       104  
  27 50       99  
  27 50       105  
  27 50       95  
  27 50       135  
  27 50       105  
  27 50       122  
  27 50       115  
  27 50       103  
  27 50       109  
  27 50       115  
  27 50       108  
  27 50       110  
  27 50       104  
  27 50       101  
  27 50       105  
  27 50       114  
  27 50       103  
  27 50       112  
  27 50       105  
  27 50       106  
  27 50       106  
  27 50       99  
  27 50       117  
  27 50       105  
  27 50       103  
  27 50       102  
  27 50       109  
  27 50       103  
  27 50       101  
  27 50       142  
  27 50       107  
  27 50       108  
  27 50       105  
  27 50       110  
  27 50       104  
  27 50       109  
  27 50       109  
  27 50       105  
  27 50       101  
  27 50       106  
  27 50       106  
  27 50       104  
  27 50       105  
  27 50       110  
  27 50       105  
  27 50       113  
  27 50       106  
  27 50       112  
  27 50       111  
  27 50       112  
  27 50       108  
  27 50       114  
  27 50       108  
  27 50       111  
  27 50       118  
  27 50       110  
  27 50       113  
  27 50       104  
  27 50       105  
  27 50       116  
  27 50       111  
  27 50       107  
  27 50       107  
  27 50       118  
  27 50       110  
  27 50       121  
  27 50       122  
  27 50       134  
  27 50       107  
  27 50       128  
  27 50       111  
  27 50       128  
  27 50       108  
  27 50       136  
  27 50       115  
  27 50       104  
  27 50       109  
  27 50       107  
  27 50       109  
  27 50       143  
  27 50       108  
  27 50       127  
  27 50       106  
  27 50       108  
  27 50       111  
  27 50       110  
  27 50       102  
  27 50       120  
  27 50       106  
  27 50       120  
  27 50       103  
  27 50       108  
  27 50       112  
  27 50       98  
  27 50       109  
  27 50       102  
  27 50       105  
  27 50       100  
  27 50       99  
  27 50       109  
  27 50       105  
  27 50       115  
  27 50       118  
  27 50       108  
  27 50       108  
  27 50       105  
  27 50       109  
  27 50       110  
  27 50       100  
  27 50       111  
  27 50       110  
  27 50       108  
  27 50       105  
  27 50       161  
  27 50       113  
  27 50       102  
  27 50       98  
  27 50       121  
  27 50       103  
  27 50       109  
  27 50       101  
  27 50       109  
  27 50       138  
  27 50       105  
  27 50       116  
  27 50       104  
  27 50       111  
  27 50       110  
  27 50       106  
  27 50       108  
  27 50       102  
  27 50       114  
  27 50       103  
  27 50       100  
  27 50       110  
  27 50       102  
  27 50       109  
  27 50       171  
  27 50       104  
  27 50       108  
  27 50       106  
  27 50       105  
  27 50       106  
  27 50       104  
  27 50       100  
  27 50       109  
  27 50       104  
  27 50       108  
  27 50       107  
  27 50       104  
  27 50       107  
  27 50       96  
  27 50       108  
  27 50       611  
  27 50       111  
  27 50       104  
  27 50       104  
  27 50       107  
  27 50       111  
  27 50       114  
  27 50       106  
  27 50       111  
  27 50       112  
  27 50       110  
  27 50       106  
  27 50       103  
  27 50       102  
  27 50       150  
  27 50       99  
  27 50       105  
  27 50       112  
  27 50       105  
  27 50       103  
  27 50       110  
  27 50       100  
  27 50       120  
  27 50       108  
  27 50       113  
  27 50       108  
  27 50       111  
  27 50       110  
  27 50       109  
  27 50       105  
  27 50       116  
  27 50       113  
  27 50       113  
  27 50       104  
  27 50       111  
  27 50       107  
  27 50       102  
  27 50       107  
  27 50       112  
  27 50       107  
  27 50       115  
  27 50       119  
  27 50       106  
  27 50       108  
  27 50       114  
  27 50       116  
  27 50       107  
  27 50       110  
  27 50       102  
  27 50       116  
  27 50       105  
  27 50       100  
  27 50       110  
  27 50       113  
  27 50       107  
  27 50       106  
  27 50       105  
  27 50       108  
  27 50       107  
  27 50       110  
  27 50       110  
  27 50       102  
  27 50       106  
  27 50       113  
  27 50       101  
  27 50       111  
  27 50       109  
  27 50       109  
  27 50       105  
  27 50       105  
  27 50       101  
  27 50       109  
  27 50       111  
  27 50       103  
  27 50       106  
  27 50       101  
  27 50       107  
  27 50       109  
  27 50       104  
  27 50       105  
  27 50       117  
  27 50       106  
  27 50       112  
  27 50       108  
  27 50       109  
  27 50       103  
  27 50       109  
  27 50       102  
  27 50       104  
  27 50       109  
  27 50       109  
  27 50       111  
  27 50       101  
  27 50       108  
  27 50       96  
  27 50       107  
  27 50       96  
  27 50       104  
  27 50       108  
  27 50       102  
  27 50       106  
  27 50       106  
  27 50       100  
  27 50       101  
  27 50       110  
  27 50       106  
  27 50       156  
  27 50       108  
  27 50       120  
  27 50       144  
  27 50       114  
  27 50       107  
  27 50       126  
  27 50       107  
  27 50       114  
  27 50       115  
  27 50       113  
  27 50       110  
  27 50       108  
  27 50       108  
  27 50       107  
  27 50       107  
  27 50       108  
  27 50       107  
  27 50       105  
  27 50       113  
  27 50       105  
  27 50       113  
  27 50       112  
  27 50       105  
  27 50       112  
  27 50       109  
  27 50       106  
  27 50       115  
  27 50       109  
  27 50       100  
  27 50       105  
  27 50       107  
  27 50       109  
  27 50       107  
  27 50       106  
  27 50       115  
  27 50       102  
  27 50       149  
  27 100       119  
  27 50       113  
  27 50       130  
  24 50       154  
  24 50       106  
  24 50       104  
  24 50       98  
  24 50       105  
  24 50       96  
  24 50       102  
  24 50       105  
  24 50       102  
  24 50       99  
  24 50       99  
  24 50       100  
  24 50       101  
  24 50       94  
  24 50       101  
  24 50       101  
  24 50       101  
  24 50       98  
  24 50       102  
  24 50       96  
  24 50       104  
  24 50       104  
  24 50       97  
  24 50       93  
  24 50       97  
  24 50       102  
  24 50       96  
  24 50       99  
  24 50       94  
  24 50       99  
  24 50       95  
  24 50       91  
  24 50       89  
  24 50       97  
  24 50       90  
  24 50       89  
  24 50       98  
  24 50       91  
  24 50       91  
  24 50       93  
  24 50       90  
  24 50       90  
  24 50       97  
  24 50       94  
  24 50       99  
  24 50       100  
  24 50       92  
  24 50       98  
  24 50       100  
  24 50       283  
  24 50       109  
  24 50       98  
  24 50       103  
  24 50       146  
  24 50       110  
  24 50       105  
  24 50       102  
  24 50       100  
  24 50       104  
  24 50       104  
  24 50       97  
  24 50       105  
  24 50       102  
  24 50       101  
  24 50       102  
  24 50       103  
  24 50       109  
  24 50       102  
  24 50       102  
  24 50       95  
  24 50       99  
  24 50       101  
  24 50       96  
  24 50       104  
  24 50       106  
  24 50       110  
  24 50       95  
  24 50       92  
  24 50       102  
  24 50       104  
  24 50       98  
  24 50       93  
  24 50       95  
  24 50       102  
  24 50       103  
  24 50       102  
  24 50       96  
  24 50       99  
  24 50       99  
  24 50       102  
  24 50       142  
  24 50       98  
  24 50       102  
  24 50       96  
  24 50       92  
  24 50       102  
  24 50       99  
  24 50       98  
  24 50       99  
  24 50       96  
  24 50       99  
  24 50       100  
  24 50       97  
  24 50       98  
  24 50       95  
  24 50       89  
  24 50       100  
  24 50       89  
  24 50       106  
  24 50       147  
  24 50       103  
  24 50       96  
  24 50       99  
  24 50       99  
  24 50       100  
  24 50       96  
  24 50       95  
  24 50       93  
  24 50       96  
  24 50       96  
  24 50       139  
  24 50       104  
  24 50       97  
  24 50       103  
  24 50       97  
  24 50       92  
  24 50       98  
  24 50       103  
  24 50       92  
  24 50       96  
  24 50       98  
  24 50       101  
  24 50       93  
  24 50       97  
  24 50       93  
  24 50       93  
  24 50       96  
  24 50       92  
  24 50       95  
  24 50       96  
  24 50       94  
  24 50       96  
  24 50       91  
  24 50       98  
  24 50       97  
  24 50       99  
  24 50       91  
  24 50       96  
  24 50       95  
  24 50       91  
  24 50       96  
  24 50       89  
  24 50       96  
  24 50       91  
  24 50       100  
  24 50       102  
  24 50       98  
  24 50       98  
  24 50       94  
  24 50       100  
  24 50       86  
  24 50       94  
  24 50       95  
  24 50       96  
  24 50       94  
  24 50       103  
  24 50       88  
  24 50       97  
  24 50       97  
  24 50       99  
  24 50       92  
  24 50       93  
  24 50       92  
  24 50       96  
  24 50       95  
  24 50       91  
  24 50       92  
  24 50       88  
  24 50       89  
  24 100       97  
  24 50       95  
  24 50       107  
  23 50       90  
  23 50       91  
  23 50       90  
  23 100       91  
  23 100       94  
  23 50       132  
  21 50       100  
  19 100       112  
  19 50       70  
  19 50       86  
  18 50       67  
  18 50       66  
  18 50       69  
  18 50       66  
  18 50       69  
  18 50       70  
  18 50       70  
  18 50       72  
  18 50       69  
  18 50       74  
  18 50       72  
  18 50       70  
  18 50       68  
  18 50       71  
  18 50       72  
  18 50       74  
  18 50       66  
  18 50       71  
  18 50       74  
  18 50       68  
  18 50       68  
  18 50       66  
  18 50       69  
  18 50       77  
  18 50       345  
  18 50       72  
  18 50       70  
  18 50       74  
  18 50       68  
  18 50       73  
  18 50       69  
  18 50       67  
  18 50       76  
  18 50       66  
  18 50       73  
  18 50       67  
  18 50       70  
  18 50       66  
  18 50       72  
  18 50       71  
  18 50       68  
  18 50       68  
  18 50       68  
  18 50       63  
  18 50       73  
  18 50       74  
  18 50       70  
  18 50       66  
  18 50       71  
  18 50       68  
  18 50       77  
  18 50       69  
  18 50       68  
  18 50       67  
  18 50       122  
  18 50       71  
  18 50       98  
  18 50       72  
  18 50       108  
  18 50       73  
  18 50       65  
  18 50       69  
  18 50       73  
  18 50       70  
  18 50       67  
  18 50       73  
  18 50       64  
  18 50       69  
  18 50       72  
  18 50       116  
  18 50       75  
  18 50       66  
  18 50       66  
  18 50       72  
  18 50       68  
  18 50       71  
  18 50       67  
  18 50       68  
  18 50       72  
  18 50       72  
  18 50       68  
  18 50       71  
  18 50       67  
  18 50       73  
  18 50       70  
  18 50       67  
  18 50       65  
  18 50       131  
  18 50       62  
  18 50       113  
  18 50       73  
  18 50       108  
  18 50       74  
  18 50       97  
  18 50       72  
  18 50       75  
  18 50       71  
  18 50       122  
  18 50       78  
  18 50       68  
  18 100       82  
  18 100       77  
  18 50       95  
  15 50       66  
  14 50       58  
  14 50       58  
  14 50       58  
  14 50       109  
  14 50       61  
  14 50       102  
  14 50       60  
  14 50       57  
  14 50       55  
  14 50       55  
  14 50       51  
  14 50       57  
  14 100       54  
  14 50       56  
  14 50       54  
  13 50       53  
  13 50       49  
  13 50       51  
  13 50       52  
  13 50       49  
  13 50       91  
  13 50       52  
  13 50       55  
  13 50       55  
  13 50       49  
  13 50       52  
  13 50       48  
  13 50       53  
  13 50       50  
  13 50       52  
  13 50       47  
  13 50       49  
  13 50       51  
  13 50       51  
  13 50       51  
  13 50       52  
  13 50       49  
  13 50       53  
  13 50       52  
  13 50       54  
  13 50       53  
  13 50       51  
  13 50       52  
  13 50       54  
  13 50       49  
  13 50       54  
  13 50       45  
  13 50       48  
  13 50       45  
  13 50       55  
  13 50       48  
  13 50       49  
  13 50       50  
  13 50       50  
  13 50       50  
  13 50       51  
  13 50       49  
  13 50       53  
  13 50       49  
  13 50       50  
  13 50       48  
  13 50       47  
  13 50       52  
  13 50       52  
  13 50       54  
  13 50       49  
  13 50       52  
  13 50       50  
  13 50       52  
  13 50       55  
  13 50       49  
  13 50       52  
  13 50       50  
  13 50       54  
  13 50       55  
  13 50       54  
  13 50       51  
  13 50       51  
  13 50       49  
  13 50       53  
  13 50       49  
  13 50       51  
  13 50       52  
  13 50       49  
  13 50       49  
  13 50       52  
  13 50       52  
  13 50       50  
  13 50       50  
  13 50       53  
  13 50       50  
  13 50       50  
  13 50       49  
  13 50       50  
  13 50       50  
  13 50       51  
  13 50       54  
  13 50       50  
  13 50       52  
  13 50       50  
  13 50       50  
  13 50       54  
  13 50       47  
  13 50       55  
  13 50       55  
  13 50       48  
  13 50       49  
  13 50       53  
  13 50       51  
  13 50       54  
  13 50       51  
  13 50       53  
  13 50       53  
  13 50       50  
  13 50       58  
  13 50       54  
  13 50       51  
  13 50       52  
  13 50       52  
  13 50       53  
  13 50       52  
  13 50       53  
  13 50       47  
  13 50       52  
  13 50       51  
  13 50       50  
  13 50       49  
  13 50       51  
  13 50       56  
  13 50       53  
  13 50       52  
  13 50       52  
  13 50       52  
  13 50       53  
  13 50       55  
  13 50       50  
  13 50       49  
  13 50       103  
  13 50       49  
  13 50       56  
  13 50       47  
  13 50       59  
  13 50       53  
  13 50       57  
  13 50       56  
  13 50       56  
  13 50       54  
  13 50       49  
  13 50       92  
  13 50       59  
  13 50       52  
  13 50       62  
  13 50       62  
  13 50       55  
  13 50       58  
  13 50       55  
  13 50       58  
  13 100       51  
  13 100       56  
  13 50       93  
  9 50       60  
  6 50       29  
  6 50       29  
  6 50       27  
  6 50       27  
  6 50       25  
  6 50       28  
  6         24  
  6         25  
  6         39  
44 6 50       2247 carp $@ if $@;
45 6         121 $self->{transmo} = undef;
46             }
47              
48 15         103 my @hash_items = $self->_parse_to_hash($string);
49 15         49 my @object_items;
50              
51 15         55 foreach my $item (@hash_items) {
52 22         192 my $error_object = Parse::ErrorString::Perl::ErrorItem->new($item);
53 22         78 push @object_items, $error_object;
54             }
55              
56 15         97 return @object_items;
57             }
58              
59             sub _prepare_diagnostics {
60 6     6   19 my $self = shift;
61              
62 6         104 my $perldiag;
63 6         9111 my $pod_filename = Pod::Find::pod_where( { -inc => 1 }, 'perldiag' );
64              
65 6 50       58 if ( !$pod_filename ) {
66 0         0 carp "Could not locate perldiag, diagnostic info will no be added";
67 0         0 return;
68             }
69              
70 6         74 my $parser = Pod::POM->new();
71 6         159 my $pom = $parser->parse_file($pod_filename);
72 6 50       4077875 if ( !$pom ) {
73 0         0 carp $parser->error();
74 0         0 return;
75             }
76              
77 6         77 my %transfmt = ();
78 6         23 my %errors;
79 6         101 foreach my $item ( $pom->head1->[1]->over->[0]->item ) {
80 5946         522357 my $header = $item->title;
81 5946         136443 $header =~ s/\n/ /g;
82              
83 5946         502274 my $content = $item->content;
84 5946         130536 $content =~ s/\s*$//;
85 5946         3234216 $errors{$header} = $content;
86              
87              
88             ### CODE FROM SPLAIN
89              
90             #$header =~ s/[A-Z]<(.*?)>/$1/g;
91              
92 5946         372442 my @toks = split( /(%l?[dx]|%c|%(?:\.\d+)?s)/, $header );
93 5946 100       384781 if ( @toks > 1 ) {
94 3402         8135 my $conlen = 0;
95 3402         12949 for my $i ( 0 .. $#toks ) {
96 11628 100       38967 if ( $i % 2 ) {
    100          
97 4650 100       19678 if ( $toks[$i] eq '%c' ) {
    100          
    100          
    50          
    100          
98 348         992 $toks[$i] = '.';
99             } elsif ( $toks[$i] eq '%d' ) {
100 282         830 $toks[$i] = '\d+';
101             } elsif ( $toks[$i] eq '%s' ) {
102 3954 100       13847 $toks[$i] = $i == $#toks ? '.*' : '.*?';
103             } elsif ( $toks[$i] =~ '%.(\d+)s' ) {
104 0         0 $toks[$i] = ".{$1}";
105             } elsif ( $toks[$i] =~ '^%l*x$' ) {
106 54         191 $toks[$i] = '[\da-f]+';
107             }
108             } elsif ( length( $toks[$i] ) ) {
109 6798         20372 $toks[$i] = quotemeta $toks[$i];
110 6798         17058 $conlen += length( $toks[$i] );
111             }
112             }
113 3402         11509 my $lhs = join( '', @toks );
114 3402         17772 $transfmt{$header}{pat} = " s<^$lhs>\n <\Q$header\E>s\n\t&& return 1;\n";
115 3402         408705 $transfmt{$header}{len} = $conlen;
116             } else {
117 2544         11159 $transfmt{$header}{pat} = " m<^\Q$header\E> && return 1;\n";
118 2544         299056 $transfmt{$header}{len} = length($header);
119             }
120             }
121              
122 6         2248 $self->{errors} = \%errors;
123              
124             # Apply patterns in order of decreasing sum of lengths of fixed parts
125             # Seems the best way of hitting the right one.
126 6         30 my $transmo = '';
127 6         2633 for my $hdr ( sort { $transfmt{$b}{len} <=> $transfmt{$a}{len} } keys %transfmt ) {
  51649         109694  
128 5946         14905 $transmo .= $transfmt{$hdr}{pat};
129             }
130 6         1068 $transmo = "sub transmo {\n study;\n $transmo; return 0;\n}\n";
131 6         510 $self->{transmo} = $transmo;
132              
133 6         2743 return;
134             }
135              
136             sub _get_diagnostics {
137 28     28   86 my $self = shift;
138 28         107 local $_ = shift;
139 28         86 eval { transmo(); };
  28         1186  
140 28 50       129 if ($@) {
141 0         0 cluck($@);
142             }
143 28 50       273 return $self->{localized_errors}{$_} ? $self->{localized_errors}{$_} : $self->{errors}{$_};
144             }
145              
146              
147             # GOTCHAS OF "USE DIAGNOSTICS":
148             # 1. if error explanations are enabled (i.e. no '-traceonly'),
149             # consecutive numbering at the end of the error message (e.g. "(#1)",
150             # "(#2)", etc) will be appended
151             # 2. if error explanations are enabled, the original error messages
152             # will be split into two lines if they exceed 79 characters
153             # 3. if a stack trace is to be printed, the error message will have
154             # a tab prepended and will follow "Uncaught exception from user code:\n\t".
155             # This message may have been been printed already as part of the
156             # explanations.
157              
158             sub _parse_to_hash {
159 15     15   53 my $self = shift;
160 15         49 my $string = shift;
161              
162 15 50       75 if ( !$string ) {
163 0         0 carp "parse_string called without an argument";
164 0         0 return;
165             }
166              
167 15         114 my $error_pattern = qr/
168             ^\s* # optional whitespace
169             (.*) # $1 - the error message
170             \sat\s(.*) # $2 - the filename or eval
171             \sline\s(\d+) # $3 - the line number
172             (?:
173             \. # end of error message
174             |(?: # or start collecting additional information
175             (?: # option 1: we have a "near" message
176             ,\snear\s\"(.*?)# $4 - the "near" message
177             (\")? # $5 - does the near message end on this line?
178             )
179             |(?: # option 2: we have an "at" message
180             ,\sat\s(.*) # $6 - the "at" message
181             )
182             )
183             )?
184             (?:\s\(\#\d+\))? # "use diagnostics" appends "(#1)" at the end of error messages
185             $/x;
186              
187 15         53 my @error_list;
188              
189             # check if error messages were split by diagnostics
190 15         377 my @unchecked_lines = split( /\n/, $string );
191 15         54 my @checked_lines;
192              
193             # lines after the start of the stack trace
194             my @stack_trace;
195              
196 15         111 for ( my $i = 0; $i <= $#unchecked_lines; $i++ ) {
197 118         296 my $current_line = $unchecked_lines[$i];
198 118 100       426 if ( $current_line eq "Uncaught exception from user code:" ) {
    100          
199 6         43 @stack_trace = @unchecked_lines[ ++$i .. $#unchecked_lines ];
200 6         23 last;
201             } elsif ( $i == $#unchecked_lines ) {
202 9         52 push @checked_lines, $current_line;
203             } else {
204 103         254 my $next_line = $unchecked_lines[ $i + 1 ];
205 103         297 my $test_line = $current_line . " " . $next_line;
206 103 100 100     721 if ( length($current_line) <= 79
      100        
207             and length($test_line) > 79
208             and $next_line =~ /^\t.*\(\#\d+\)$/
209              
210             #and $test_line =~ $error_pattern
211             )
212             {
213 2         9 $next_line =~ s/^\s*/ /;
214 2         6 my $real_line = $current_line . $next_line;
215 2         5 push @checked_lines, $real_line;
216 2         6 $i++;
217             } else {
218 101         432 push @checked_lines, $current_line;
219             }
220             }
221             }
222              
223             # file and line number where the fatal error occurred
224 15         104 my ( $die_at_file, $die_at_line );
225              
226             # the items in the stack trace list
227 15         0 my @trace_items;
228              
229             # the fatal error(s)
230 15         0 my @stack_trace_errors;
231              
232 15 100       77 if (@stack_trace) {
233 6         33 for ( my $i = 0; $i <= $#stack_trace; $i++ ) {
234 20 100       123 if ( $stack_trace[$i] =~ /^\sat\s(.*)\sline\s(\d+)$/ ) {
235 6         33 $die_at_file = $1;
236 6         26 $die_at_line = $2;
237 6         27 @trace_items = @stack_trace[ ++$i .. $#stack_trace ];
238 6         21 last;
239             } else {
240 14         66 push @stack_trace_errors, $stack_trace[$i];
241             }
242             }
243             }
244              
245             # used to check if we are in a multi-line 'near' message
246 15         45 my $in_near;
247              
248 15         58 foreach my $line ( @checked_lines, @stack_trace_errors ) {
249              
250             # carriage returns may remain in multi-line 'near' messages and cause problems
251             # $line =~ s/\r/ /g;
252             # $line =~ s/\s+/ /g;
253 126 100       380 if ( !$in_near ) {
254 120 100       1021 if ( $line =~ $error_pattern ) {
255 28         254 my %err_item = (
256             message => $1,
257             line => $3,
258             );
259 28         154 my $diagnostics = $self->_get_diagnostics($1);
260 28 100       121 if ($diagnostics) {
261 22         127 my $err_type = $self->_get_error_type($diagnostics);
262 22         104 my $err_desc = $self->_get_error_desc($err_type);
263              
264 22         93 $err_item{diagnostics} = $diagnostics;
265 22         79 $err_item{type} = $err_type;
266 22         75 $err_item{type_description} = $err_desc;
267             }
268 28         136 my $file = $2;
269 28 100       124 if ( $file =~ /^\(eval\s\d+\)$/ ) {
270 1         4 $err_item{file_msgpath} = $file;
271 1         4 $err_item{file} = "eval";
272             } else {
273 27         95 $err_item{file_msgpath} = $file;
274 27         1096 $err_item{file_abspath} = File::Spec->rel2abs($file);
275 27         153 $err_item{file} = $self->_get_short_path($file);
276             }
277 28         124 my $near = $4;
278 28         87 my $near_end = $5;
279              
280 28 100       136 $err_item{at} = $6 if $6;
281              
282 28 100 100     245 if ( $near and !$near_end ) {
    100 66        
283 3         14 $in_near = ( $near . "\n" );
284             } elsif ( $near and $near_end ) {
285 1         5 $err_item{near} = $near;
286             }
287              
288 28 100       181 if (!grep {
289             $_->{message} eq $err_item{message}
290             and $_->{line} eq $err_item{line}
291             and $_->{file_msgpath} eq $err_item{file_msgpath}
292 18 100 66     211 } @error_list
293             )
294             {
295 22         118 push @error_list, \%err_item;
296             }
297             }
298             } else {
299 6 100       36 if ( $line =~ /^(.*)\"$/ ) {
300 3         14 $in_near .= $1;
301 3         13 $error_list[-1]->{near} = $in_near;
302 3         11 undef $in_near;
303             } else {
304 3         15 $in_near .= ( $line . "\n" );
305             }
306             }
307             }
308              
309 15 100       77 if (@trace_items) {
310 1         2 my @parsed_stack_trace;
311 1         3 foreach my $line (@trace_items) {
312 2 50       13 if ( $line =~ /^\s*(.*)\scalled\sat\s(.*)\sline\s(\d+)$/ ) {
313 2         26 my %trace_item = (
314             sub => $1,
315             file_msgpath => $2,
316             file_abspath => File::Spec->rel2abs($2),
317             file => $self->_get_short_path($2),
318             line => $3,
319             );
320 2         12 my $stack_object = Parse::ErrorString::Perl::StackItem->new( \%trace_item );
321 2         5 push @parsed_stack_trace, $stack_object;
322             }
323             }
324              
325 1         4 for ( my $i = $#error_list; $i >= 0; $i-- ) {
326 1 50 33     10 if ( $error_list[$i]->{file_msgpath} eq $die_at_file and $error_list[$i]->{line} == $die_at_line ) {
327 1         3 $error_list[$i]->{stack} = \@parsed_stack_trace;
328 1         2 last;
329             }
330             }
331             }
332              
333 15         208 return @error_list;
334             }
335              
336             sub _get_error_type {
337 22     22   94 my ( $self, $description ) = @_;
338 22 50       244 if ( $description =~ /^\(\u(\w)\|\u(\w)\W/ ) {
    50          
339 0 0       0 return wantarray ? ( $1, $2 ) : "$1|$2";
340             } elsif ( $description =~ /^\(\u(\w)\W/ ) {
341 22         143 return $1;
342             }
343             }
344              
345             sub _get_error_desc {
346 22     22   85 my ( $self, $error_type ) = @_;
347 22 50       119 if ( $error_type =~ /^\u\w$/ ) {
    0          
348 22         121 return $self->{error_desc_hash}->{$error_type};
349             } elsif ( $error_type =~ /^\u(\w)\|\u(\w)$/ ) {
350 0         0 return $self->{error_desc_hash}->{$1} . " or " . $self->{error_desc_hash}->{$2};
351             }
352             }
353              
354             sub _get_short_path {
355 29     29   108 my ( $self, $path ) = @_;
356              
357             # my ($volume, $directories, $file) = File::Spec->splitpath($filename);
358             # my @dirs = File::Spec->splitdir($directories);
359              
360 29         909 my ( $filename, $directories, $suffix ) = File::Basename::fileparse($path);
361 29 50       145 if ( $suffix eq '.pm' ) {
362 0         0 foreach my $inc_dir (@INC) {
363 0 0       0 if ( $path =~ /^\Q$_\E(.+)$/ ) {
364 0         0 return $1;
365             }
366             }
367              
368 0         0 return $path;
369              
370             } else {
371 29         182 return $filename . $suffix;
372             }
373             }
374              
375             sub _prepare_localized_diagnostics {
376 6     6   36 my $self = shift;
377 6         41 my %options = @_;
378              
379 6 50       64 return unless $options{lang};
380              
381 0           my $perldiag;
382             my $pod_filename;
383              
384 0           $perldiag = 'POD2::' . $options{lang} . '::perldiag';
385 0           $pod_filename = Pod::Find::pod_where( { -inc => 1 }, $perldiag );
386              
387 0 0         if ( !$pod_filename ) {
388 0           carp "Could not locate localised perldiag, will use perldiag in English";
389 0           return;
390             }
391              
392 0           my $parser = Pod::POM->new();
393 0           my $pom = $parser->parse_file($pod_filename);
394 0 0         if ( !$pom ) {
395 0           carp $parser->error();
396 0           return;
397             }
398              
399 0           my %localized_errors;
400 0           foreach my $item ( $pom->head1->[1]->over->[0]->item ) {
401 0           my $header = $item->title;
402              
403 0           my $content = $item->content;
404 0           $content =~ s/\s*$//;
405 0           $localized_errors{$header} = $content;
406             }
407              
408 0           $self->{localized_errors} = \%localized_errors;
409             }
410              
411             1;
412              
413             __END__