File Coverage

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


line stmt bran cond sub pod time code
1             package Parse::ErrorString::Perl;
2              
3 6     6   107705 use v5.8.7;
  6         30  
4 6     6   41 use strict;
  6         15  
  6         170  
5 6     6   40 use warnings;
  6         21  
  6         332  
6              
7             our $VERSION = '0.27';
8              
9 6     6   38 use Carp qw(carp cluck);
  6         15  
  6         418  
10 6     6   39 use Pod::Find ();
  6         17  
  6         132  
11 6     6   3637 use Pod::POM 0.27 ();
  6         151807  
  6         165  
12 6     6   54 use File::Spec ();
  6         18  
  6         105  
13 6     6   35 use File::Basename ();
  6         15  
  6         91  
14 6     6   3300 use Parse::ErrorString::Perl::ErrorItem ();
  6         21  
  6         143  
15 6     6   2306 use Parse::ErrorString::Perl::StackItem ();
  6         20  
  6         697  
16              
17             sub new {
18 6     6 1 107 my $class = shift;
19 6         24 my %options = @_;
20 6   33     52 my $self = bless {}, ref $class || $class;
21 6         32 $self->_prepare_diagnostics;
22 6         792028 $self->_prepare_localized_diagnostics(%options);
23 6         67 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         28 $self->{error_desc_hash} = \%error_desc_hash;
33 6         44 return $self;
34             }
35              
36             sub parse_string {
37 15     15 1 34294 my $self = shift;
38 15         41 my $string = shift;
39              
40             # installs a sub named 'transmo', which returns the type of the error message
41 15 100       78 if ( $self->{transmo} ) {
42 6     6   43 no warnings 'redefine';
  6         13  
  6         13340  
43 6 50   28 0 109105 eval $self->{transmo};
  28 50       95  
  28 50       110  
  28 50       104  
  28 50       102  
  28 50       98  
  28 50       93  
  28 50       102  
  28 50       108  
  28 50       94  
  28 50       94  
  28 50       92  
  28 50       100  
  28 50       90  
  28 50       96  
  28 50       87  
  28 50       90  
  28 50       89  
  28 50       94  
  28 50       87  
  28 50       91  
  28 50       93  
  28 50       88  
  28 50       93  
  28 50       89  
  28 50       87  
  28 50       92  
  28 50       89  
  28 50       80  
  28 50       86  
  28 50       86  
  28 50       89  
  28 50       80  
  28 50       90  
  28 50       84  
  28 50       108  
  28 50       87  
  28 50       93  
  28 50       131  
  28 50       107  
  28 50       209  
  28 50       101  
  28 50       158  
  28 50       103  
  28 50       88  
  28 50       192  
  28 50       90  
  28 50       121  
  28 50       90  
  28 50       105  
  28 100       94  
  28 50       112  
  28 50       103  
  27 50       92  
  27 50       82  
  27 50       78  
  27 50       87  
  27 50       90  
  27 50       96  
  27 50       112  
  27 50       88  
  27 50       88  
  27 50       85  
  27 50       83  
  27 50       79  
  27 50       74  
  27 50       83  
  27 50       75  
  27 50       83  
  27 50       76  
  27 50       73  
  27 50       78  
  27 50       73  
  27 50       74  
  27 50       76  
  27 50       77  
  27 50       79  
  27 50       78  
  27 50       84  
  27 50       80  
  27 50       74  
  27 50       77  
  27 50       79  
  27 50       81  
  27 50       81  
  27 50       81  
  27 50       76  
  27 50       80  
  27 50       82  
  27 50       76  
  27 50       80  
  27 50       79  
  27 50       83  
  27 50       74  
  27 50       643  
  27 50       78  
  27 50       74  
  27 50       78  
  27 50       76  
  27 50       77  
  27 50       75  
  27 50       81  
  27 50       81  
  27 50       83  
  27 50       81  
  27 50       79  
  27 50       85  
  27 50       74  
  27 50       71  
  27 50       81  
  27 50       81  
  27 50       76  
  27 50       78  
  27 50       73  
  27 50       75  
  27 50       71  
  27 50       115  
  27 50       78  
  27 50       78  
  27 50       79  
  27 50       83  
  27 50       79  
  27 50       81  
  27 50       79  
  27 50       78  
  27 50       73  
  27 50       72  
  27 50       73  
  27 50       74  
  27 50       74  
  27 50       79  
  27 50       76  
  27 50       74  
  27 50       73  
  27 50       72  
  27 50       68  
  27 50       75  
  27 50       77  
  27 50       79  
  27 50       76  
  27 50       78  
  27 50       71  
  27 50       77  
  27 50       74  
  27 50       79  
  27 50       70  
  27 50       74  
  27 50       76  
  27 50       77  
  27 50       88  
  27 50       75  
  27 50       78  
  27 50       75  
  27 50       78  
  27 50       74  
  27 50       85  
  27 50       78  
  27 50       72  
  27 50       77  
  27 50       100  
  27 50       75  
  27 50       74  
  27 50       88  
  27 50       74  
  27 50       79  
  27 50       72  
  27 50       75  
  27 50       82  
  27 50       73  
  27 50       72  
  27 50       77  
  27 50       75  
  27 50       81  
  27 50       129  
  27 50       82  
  27 50       77  
  27 50       82  
  27 50       78  
  27 50       73  
  27 50       78  
  27 50       84  
  27 50       77  
  27 50       86  
  27 50       77  
  27 50       77  
  27 50       102  
  27 50       78  
  27 50       72  
  27 50       77  
  27 50       78  
  27 50       81  
  27 50       82  
  27 50       79  
  27 50       78  
  27 50       76  
  27 50       78  
  27 50       87  
  27 50       78  
  27 50       78  
  27 50       80  
  27 50       82  
  27 50       79  
  27 50       79  
  27 50       84  
  27 50       83  
  27 50       82  
  27 50       75  
  27 50       86  
  27 50       81  
  27 50       79  
  27 50       78  
  27 50       82  
  27 50       82  
  27 50       83  
  27 50       79  
  27 50       89  
  27 50       80  
  27 50       78  
  27 50       77  
  27 50       80  
  27 50       74  
  27 50       76  
  27 50       79  
  27 50       82  
  27 50       77  
  27 50       81  
  27 50       72  
  27 50       75  
  27 50       74  
  27 50       76  
  27 50       73  
  27 50       91  
  27 50       78  
  27 50       84  
  27 50       79  
  27 50       71  
  27 50       75  
  27 50       88  
  27 50       73  
  27 50       72  
  27 50       78  
  27 50       72  
  27 50       78  
  27 50       83  
  27 50       73  
  27 50       81  
  27 50       89  
  27 50       84  
  27 50       78  
  27 50       81  
  27 50       81  
  27 50       78  
  27 50       80  
  27 50       71  
  27 50       82  
  27 50       81  
  27 50       77  
  27 50       79  
  27 50       77  
  27 50       82  
  27 50       77  
  27 50       81  
  27 50       78  
  27 50       77  
  27 50       90  
  27 50       85  
  27 50       78  
  27 50       82  
  27 50       86  
  27 50       78  
  27 50       92  
  27 50       86  
  27 50       75  
  27 50       85  
  27 50       81  
  27 50       88  
  27 50       84  
  27 50       87  
  27 50       77  
  27 50       84  
  27 50       79  
  27 50       80  
  27 50       88  
  27 50       76  
  27 50       92  
  27 50       86  
  27 50       81  
  27 50       88  
  27 50       90  
  27 50       81  
  27 50       83  
  27 50       102  
  27 50       85  
  27 50       95  
  27 50       94  
  27 50       94  
  27 50       83  
  27 50       98  
  27 50       84  
  27 50       91  
  27 50       83  
  27 50       93  
  27 50       76  
  27 50       80  
  27 50       75  
  27 50       77  
  27 50       72  
  27 50       98  
  27 50       79  
  27 50       96  
  27 50       88  
  27 50       86  
  27 50       77  
  27 50       89  
  27 50       83  
  27 50       114  
  27 50       84  
  27 50       99  
  27 50       73  
  27 50       81  
  27 50       75  
  27 50       77  
  27 50       86  
  27 50       77  
  27 50       81  
  27 50       81  
  27 50       84  
  27 50       77  
  27 50       81  
  27 50       82  
  27 50       76  
  27 50       79  
  27 50       77  
  27 50       76  
  27 50       81  
  27 50       73  
  27 50       73  
  27 50       76  
  27 50       82  
  27 50       80  
  27 50       76  
  27 50       77  
  27 50       81  
  27 50       78  
  27 50       118  
  27 50       78  
  27 50       80  
  27 50       81  
  27 50       73  
  27 50       81  
  27 50       82  
  27 50       80  
  27 50       80  
  27 50       81  
  27 50       83  
  27 50       76  
  27 50       82  
  27 50       83  
  27 50       76  
  27 50       92  
  27 50       81  
  27 50       76  
  27 50       79  
  27 50       72  
  27 50       78  
  27 50       73  
  27 50       84  
  27 50       77  
  27 50       78  
  27 50       75  
  27 50       78  
  27 50       77  
  27 50       75  
  27 50       82  
  27 50       71  
  27 50       78  
  27 50       83  
  27 50       76  
  27 50       80  
  27 50       78  
  27 50       83  
  27 50       83  
  27 50       78  
  27 50       78  
  27 50       74  
  27 50       88  
  27 50       75  
  27 50       80  
  27 50       78  
  27 50       113  
  27 50       85  
  27 50       86  
  27 50       81  
  27 50       77  
  27 50       79  
  27 50       77  
  27 50       72  
  27 50       78  
  27 50       82  
  27 50       75  
  27 50       76  
  27 50       79  
  27 50       81  
  27 50       83  
  27 50       80  
  27 50       85  
  27 50       81  
  27 50       78  
  27 50       84  
  27 50       83  
  27 50       81  
  27 50       74  
  27 50       78  
  27 50       82  
  27 50       85  
  27 50       78  
  27 50       80  
  27 50       74  
  27 50       81  
  27 50       82  
  27 50       82  
  27 50       77  
  27 50       81  
  27 50       80  
  27 50       78  
  27 50       102  
  27 50       81  
  27 50       82  
  27 50       75  
  27 50       74  
  27 50       75  
  27 50       78  
  27 50       76  
  27 50       75  
  27 50       80  
  27 50       79  
  27 50       73  
  27 50       74  
  27 50       78  
  27 50       76  
  27 50       77  
  27 50       74  
  27 50       86  
  27 50       76  
  27 50       77  
  27 50       79  
  27 50       77  
  27 50       74  
  27 50       80  
  27 50       77  
  27 50       74  
  27 50       73  
  27 50       74  
  27 50       74  
  27 50       77  
  27 50       78  
  27 50       86  
  27 50       83  
  27 50       81  
  27 50       81  
  27 50       77  
  27 50       83  
  27 50       81  
  27 50       78  
  27 50       84  
  27 50       75  
  27 50       91  
  27 50       76  
  27 50       75  
  27 50       80  
  27 50       81  
  27 50       82  
  27 50       81  
  27 50       77  
  27 50       75  
  27 50       126  
  27 50       77  
  27 50       75  
  27 50       80  
  27 50       81  
  27 50       82  
  27 50       78  
  27 50       84  
  27 50       83  
  27 50       78  
  27 50       79  
  27 50       81  
  27 50       114  
  27 50       76  
  27 50       102  
  27 50       98  
  27 50       86  
  27 50       80  
  27 50       97  
  27 50       79  
  27 50       81  
  27 50       74  
  27 50       82  
  27 50       73  
  27 50       86  
  27 50       83  
  27 50       79  
  27 50       80  
  27 50       76  
  27 50       80  
  27 50       82  
  27 50       77  
  27 50       85  
  27 50       75  
  27 100       82  
  27 50       86  
  27 50       86  
  25 50       75  
  25 50       70  
  25 50       73  
  25 50       73  
  25 50       76  
  25 50       73  
  25 50       73  
  25 50       77  
  25 50       74  
  25 50       80  
  25 50       72  
  25 50       74  
  25 50       75  
  25 50       72  
  25 50       80  
  25 50       74  
  25 50       74  
  25 50       80  
  25 50       77  
  25 50       76  
  25 100       81  
  25 50       79  
  25 50       83  
  24 50       68  
  24 50       68  
  24 50       71  
  24 50       74  
  24 50       69  
  24 50       70  
  24 50       72  
  24 50       68  
  24 50       72  
  24 50       75  
  24 50       67  
  24 50       72  
  24 50       67  
  24 50       75  
  24 50       68  
  24 50       71  
  24 50       69  
  24 50       78  
  24 50       69  
  24 50       70  
  24 50       75  
  24 50       77  
  24 50       77  
  24 50       76  
  24 50       74  
  24 50       75  
  24 50       71  
  24 50       96  
  24 50       70  
  24 50       67  
  24 50       73  
  24 50       66  
  24 50       74  
  24 50       65  
  24 50       72  
  24 50       67  
  24 50       67  
  24 50       68  
  24 50       65  
  24 50       66  
  24 50       70  
  24 50       68  
  24 50       73  
  24 50       74  
  24 50       71  
  24 50       71  
  24 50       73  
  24 50       80  
  24 50       77  
  24 50       81  
  24 50       124  
  24 50       78  
  24 50       72  
  24 50       75  
  24 50       76  
  24 50       72  
  24 50       74  
  24 50       68  
  24 50       70  
  24 50       74  
  24 50       65  
  24 50       76  
  24 50       68  
  24 50       72  
  24 50       68  
  24 50       64  
  24 50       66  
  24 50       71  
  24 50       69  
  24 50       69  
  24 50       72  
  24 50       73  
  24 50       72  
  24 50       66  
  24 50       78  
  24 50       74  
  24 50       75  
  24 50       66  
  24 50       73  
  24 50       71  
  24 50       67  
  24 50       71  
  24 50       68  
  24 50       69  
  24 50       78  
  24 50       77  
  24 50       67  
  24 50       77  
  24 50       68  
  24 50       71  
  24 50       77  
  24 50       72  
  24 50       79  
  24 50       73  
  24 50       65  
  24 50       75  
  24 50       68  
  24 50       74  
  24 50       65  
  24 50       74  
  24 50       67  
  24 50       74  
  24 50       66  
  24 50       69  
  24 50       66  
  24 50       79  
  24 50       70  
  24 50       75  
  24 50       73  
  24 50       70  
  24 50       72  
  24 50       69  
  24 50       72  
  24 50       67  
  24 50       75  
  24 50       66  
  24 50       70  
  24 50       72  
  24 50       69  
  24 50       110  
  24 50       70  
  24 50       71  
  24 50       71  
  24 50       65  
  24 50       71  
  24 50       67  
  24 50       71  
  24 50       67  
  24 50       76  
  24 50       72  
  24 50       76  
  24 50       68  
  24 50       72  
  24 50       68  
  24 50       63  
  24 50       73  
  24 50       112  
  24 50       83  
  24 50       71  
  24 50       69  
  24 50       68  
  24 50       70  
  24 50       70  
  24 50       66  
  24 50       72  
  24 50       91  
  24 50       71  
  24 50       67  
  24 50       73  
  24 50       71  
  24 50       71  
  24 50       71  
  24 50       75  
  24 50       68  
  24 50       71  
  24 50       72  
  24 50       69  
  24 50       71  
  24 50       75  
  24 50       76  
  24 50       69  
  24 50       83  
  24 50       73  
  24 50       78  
  24 50       357  
  24 50       72  
  24 100       79  
  24 50       76  
  24 50       107  
  22 50       65  
  22 50       66  
  22 50       63  
  22 100       65  
  22 50       68  
  22 50       72  
  21 50       65  
  21 50       61  
  21 50       68  
  21 50       58  
  21 50       60  
  21 100       62  
  21 50       61  
  21 50       81  
  20 50       64  
  20 50       56  
  20 50       62  
  20 50       66  
  20 100       67  
  20 50       67  
  20 50       75  
  18 50       57  
  18 50       55  
  18 50       61  
  18 50       56  
  18 50       58  
  18 50       55  
  18 50       56  
  18 50       51  
  18 50       58  
  18 50       55  
  18 50       60  
  18 50       53  
  18 50       55  
  18 50       62  
  18 50       57  
  18 50       54  
  18 50       52  
  18 50       49  
  18 50       91  
  18 50       55  
  18 50       59  
  18 50       50  
  18 50       51  
  18 50       59  
  18 50       54  
  18 50       54  
  18 50       53  
  18 50       58  
  18 50       56  
  18 50       54  
  18 50       54  
  18 50       54  
  18 50       54  
  18 50       52  
  18 50       55  
  18 50       54  
  18 50       53  
  18 50       56  
  18 50       49  
  18 50       53  
  18 50       54  
  18 50       52  
  18 50       60  
  18 50       54  
  18 50       50  
  18 50       52  
  18 50       54  
  18 50       53  
  18 50       53  
  18 50       93  
  18 50       52  
  18 50       80  
  18 50       51  
  18 50       52  
  18 50       54  
  18 50       53  
  18 50       53  
  18 50       55  
  18 50       60  
  18 50       55  
  18 50       57  
  18 50       55  
  18 50       54  
  18 50       54  
  18 50       57  
  18 50       59  
  18 50       50  
  18 50       49  
  18 50       49  
  18 50       54  
  18 50       52  
  18 50       50  
  18 50       53  
  18 50       53  
  18 50       48  
  18 50       51  
  18 50       53  
  18 50       51  
  18 50       60  
  18 50       52  
  18 50       48  
  18 50       54  
  18 50       90  
  18 50       53  
  18 50       80  
  18 50       57  
  18 50       88  
  18 50       59  
  18 50       78  
  18 50       50  
  18 50       57  
  18 50       51  
  18 50       54  
  18 100       57  
  18 50       54  
  18 50       68  
  17 50       50  
  17 50       53  
  17 50       50  
  17 100       75  
  17 50       48  
  17 50       58  
  16 50       90  
  16 50       46  
  16 50       75  
  16 50       47  
  16 50       45  
  16 50       48  
  16 50       46  
  16 50       44  
  16 50       44  
  16 100       46  
  16 50       44  
  16 50       60  
  14 50       41  
  14 50       44  
  14 50       42  
  14 50       40  
  14 100       41  
  14 50       39  
  14 50       50  
  13 50       37  
  13 50       39  
  13 50       35  
  13 50       38  
  13 50       39  
  13 50       35  
  13 50       41  
  13 50       38  
  13 50       43  
  13 50       40  
  13 50       36  
  13 50       43  
  13 50       40  
  13 50       38  
  13 50       36  
  13 50       38  
  13 50       36  
  13 50       38  
  13 50       36  
  13 50       39  
  13 50       35  
  13 50       50  
  13 50       37  
  13 50       44  
  13 50       36  
  13 50       36  
  13 50       36  
  13 50       40  
  13 50       39  
  13 50       38  
  13 50       37  
  13 50       34  
  13 50       40  
  13 50       38  
  13 50       34  
  13 50       35  
  13 50       39  
  13 50       38  
  13 50       38  
  13 50       37  
  13 50       56  
  13 50       40  
  13 50       36  
  13 50       36  
  13 50       34  
  13 50       38  
  13 50       36  
  13 50       33  
  13 50       36  
  13 50       36  
  13 50       36  
  13 50       37  
  13 50       38  
  13 50       37  
  13 50       37  
  13 50       38  
  13 50       35  
  13 50       39  
  13 50       40  
  13 50       40  
  13 50       41  
  13 50       37  
  13 50       32  
  13 50       42  
  13 50       35  
  13 50       37  
  13 50       34  
  13 50       33  
  13 50       32  
  13 50       38  
  13 50       35  
  13 50       35  
  13 50       37  
  13 50       35  
  13 50       36  
  13 50       34  
  13 50       39  
  13 50       37  
  13 50       37  
  13 50       40  
  13 50       36  
  13 50       42  
  13 50       37  
  13 50       35  
  13 50       40  
  13 50       40  
  13 50       35  
  13 50       38  
  13 50       39  
  13 50       37  
  13 50       39  
  13 50       39  
  13 50       40  
  13 50       39  
  13 50       34  
  13 50       36  
  13 50       41  
  13 50       39  
  13 50       37  
  13 50       38  
  13 50       35  
  13 50       35  
  13 50       37  
  13 50       37  
  13 50       39  
  13 50       36  
  13 50       35  
  13 50       38  
  13 50       38  
  13 50       38  
  13 50       35  
  13 50       37  
  13 50       37  
  13 50       36  
  13 50       37  
  13 50       31  
  13 50       39  
  13 50       34  
  13 50       36  
  13 50       40  
  13 50       34  
  13 50       35  
  13 50       36  
  13 50       36  
  13 50       34  
  13 50       37  
  13 50       30  
  13 50       37  
  13 50       41  
  13 50       33  
  13 50       35  
  13 50       35  
  13 50       44  
  13 50       37  
  13 50       34  
  13 50       35  
  13 50       38  
  13 100       38  
  13 50       35  
  13 50       100  
  6 50       16  
  6 50       18  
  6 50       18  
  6 50       16  
  6 50       17  
  6         17  
  6         19  
  6         29  
44 6 50       1457 carp $@ if $@;
45 6         84 $self->{transmo} = undef;
46             }
47              
48 15         90 my @hash_items = $self->_parse_to_hash($string);
49 15         35 my @object_items;
50              
51 15         54 foreach my $item (@hash_items) {
52 22         147 my $error_object = Parse::ErrorString::Perl::ErrorItem->new($item);
53 22         60 push @object_items, $error_object;
54             }
55              
56 15         83 return @object_items;
57             }
58              
59             sub _prepare_diagnostics {
60 6     6   14 my $self = shift;
61              
62 6         93 my $perldiag;
63 6         6156 my $pod_filename = Pod::Find::pod_where( { -inc => 1 }, 'perldiag' );
64              
65 6 50       49 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         66 my $parser = Pod::POM->new();
71 6         134 my $pom = $parser->parse_file($pod_filename);
72 6 50       3198542 if ( !$pom ) {
73 0         0 carp $parser->error();
74 0         0 return;
75             }
76              
77 6         53 my %transfmt = ();
78 6         13 my %errors;
79 6         79 foreach my $item ( $pom->head1->[1]->over->[0]->item ) {
80 5946         356985 my $header = $item->title;
81 5946         96995 $header =~ s/\n/ /g;
82              
83 5946         341912 my $content = $item->content;
84 5946         91708 $content =~ s/\s*$//;
85 5946         2252989 $errors{$header} = $content;
86              
87              
88             ### CODE FROM SPLAIN
89              
90             #$header =~ s/[A-Z]<(.*?)>/$1/g;
91              
92 5946         259301 my @toks = split( /(%l?[dx]|%c|%(?:\.\d+)?s)/, $header );
93 5946 100       262350 if ( @toks > 1 ) {
94 3402         6036 my $conlen = 0;
95 3402         9168 for my $i ( 0 .. $#toks ) {
96 11628 100       29578 if ( $i % 2 ) {
    100          
97 4650 100       13507 if ( $toks[$i] eq '%c' ) {
    100          
    100          
    50          
    100          
98 348         712 $toks[$i] = '.';
99             } elsif ( $toks[$i] eq '%d' ) {
100 282         666 $toks[$i] = '\d+';
101             } elsif ( $toks[$i] eq '%s' ) {
102 3954 100       9812 $toks[$i] = $i == $#toks ? '.*' : '.*?';
103             } elsif ( $toks[$i] =~ '%.(\d+)s' ) {
104 0         0 $toks[$i] = ".{$1}";
105             } elsif ( $toks[$i] =~ '^%l*x$' ) {
106 54         142 $toks[$i] = '[\da-f]+';
107             }
108             } elsif ( length( $toks[$i] ) ) {
109 6798         15738 $toks[$i] = quotemeta $toks[$i];
110 6798         12928 $conlen += length( $toks[$i] );
111             }
112             }
113 3402         8231 my $lhs = join( '', @toks );
114 3402         11979 $transfmt{$header}{pat} = " s<^$lhs>\n <\Q$header\E>s\n\t&& return 1;\n";
115 3402         286944 $transfmt{$header}{len} = $conlen;
116             } else {
117 2544         6577 $transfmt{$header}{pat} = " m<^\Q$header\E> && return 1;\n";
118 2544         204601 $transfmt{$header}{len} = length($header);
119             }
120             }
121              
122 6         1743 $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         31 my $transmo = '';
127 6         2128 for my $hdr ( sort { $transfmt{$b}{len} <=> $transfmt{$a}{len} } keys %transfmt ) {
  51567         94261  
128 5946         12665 $transmo .= $transfmt{$hdr}{pat};
129             }
130 6         997 $transmo = "sub transmo {\n study;\n $transmo; return 0;\n}\n";
131 6         522 $self->{transmo} = $transmo;
132              
133 6         1888 return;
134             }
135              
136             sub _get_diagnostics {
137 28     28   71 my $self = shift;
138 28         83 local $_ = shift;
139 28         67 eval { transmo(); };
  28         918  
140 28 50       109 if ($@) {
141 0         0 cluck($@);
142             }
143 28 50       242 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   44 my $self = shift;
160 15         44 my $string = shift;
161              
162 15 50       114 if ( !$string ) {
163 0         0 carp "parse_string called without an argument";
164 0         0 return;
165             }
166              
167 15         93 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         43 my @error_list;
188              
189             # check if error messages were split by diagnostics
190 15         317 my @unchecked_lines = split( /\n/, $string );
191 15         45 my @checked_lines;
192              
193             # lines after the start of the stack trace
194             my @stack_trace;
195              
196 15         95 for ( my $i = 0; $i <= $#unchecked_lines; $i++ ) {
197 118         208 my $current_line = $unchecked_lines[$i];
198 118 100       329 if ( $current_line eq "Uncaught exception from user code:" ) {
    100          
199 6         37 @stack_trace = @unchecked_lines[ ++$i .. $#unchecked_lines ];
200 6         23 last;
201             } elsif ( $i == $#unchecked_lines ) {
202 9         39 push @checked_lines, $current_line;
203             } else {
204 103         188 my $next_line = $unchecked_lines[ $i + 1 ];
205 103         214 my $test_line = $current_line . " " . $next_line;
206 103 100 100     563 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         7 my $real_line = $current_line . $next_line;
215 2         6 push @checked_lines, $real_line;
216 2         6 $i++;
217             } else {
218 101         296 push @checked_lines, $current_line;
219             }
220             }
221             }
222              
223             # file and line number where the fatal error occurred
224 15         79 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       64 if (@stack_trace) {
233 6         23 for ( my $i = 0; $i <= $#stack_trace; $i++ ) {
234 20 100       94 if ( $stack_trace[$i] =~ /^\sat\s(.*)\sline\s(\d+)$/ ) {
235 6         24 $die_at_file = $1;
236 6         17 $die_at_line = $2;
237 6         18 @trace_items = @stack_trace[ ++$i .. $#stack_trace ];
238 6         14 last;
239             } else {
240 14         43 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         34 my $in_near;
247              
248 15         52 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       264 if ( !$in_near ) {
254 120 100       730 if ( $line =~ $error_pattern ) {
255 28         203 my %err_item = (
256             message => $1,
257             line => $3,
258             );
259 28         103 my $diagnostics = $self->_get_diagnostics($1);
260 28 100       104 if ($diagnostics) {
261 22         101 my $err_type = $self->_get_error_type($diagnostics);
262 22         83 my $err_desc = $self->_get_error_desc($err_type);
263              
264 22         84 $err_item{diagnostics} = $diagnostics;
265 22         59 $err_item{type} = $err_type;
266 22         63 $err_item{type_description} = $err_desc;
267             }
268 28         100 my $file = $2;
269 28 100       97 if ( $file =~ /^\(eval\s\d+\)$/ ) {
270 1         5 $err_item{file_msgpath} = $file;
271 1         3 $err_item{file} = "eval";
272             } else {
273 27         77 $err_item{file_msgpath} = $file;
274 27         831 $err_item{file_abspath} = File::Spec->rel2abs($file);
275 27         109 $err_item{file} = $self->_get_short_path($file);
276             }
277 28         97 my $near = $4;
278 28         67 my $near_end = $5;
279              
280 28 100       112 $err_item{at} = $6 if $6;
281              
282 28 100 100     187 if ( $near and !$near_end ) {
    100 66        
283 3         9 $in_near = ( $near . "\n" );
284             } elsif ( $near and $near_end ) {
285 1         3 $err_item{near} = $near;
286             }
287              
288 28 100       183 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     141 } @error_list
293             )
294             {
295 22         111 push @error_list, \%err_item;
296             }
297             }
298             } else {
299 6 100       26 if ( $line =~ /^(.*)\"$/ ) {
300 3         14 $in_near .= $1;
301 3         12 $error_list[-1]->{near} = $in_near;
302 3         12 undef $in_near;
303             } else {
304 3         10 $in_near .= ( $line . "\n" );
305             }
306             }
307             }
308              
309 15 100       64 if (@trace_items) {
310 1         2 my @parsed_stack_trace;
311 1         3 foreach my $line (@trace_items) {
312 2 50       14 if ( $line =~ /^\s*(.*)\scalled\sat\s(.*)\sline\s(\d+)$/ ) {
313 2         28 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         6 for ( my $i = $#error_list; $i >= 0; $i-- ) {
326 1 50 33     8 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         3 last;
329             }
330             }
331             }
332              
333 15         137 return @error_list;
334             }
335              
336             sub _get_error_type {
337 22     22   76 my ( $self, $description ) = @_;
338 22 50       201 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         117 return $1;
342             }
343             }
344              
345             sub _get_error_desc {
346 22     22   60 my ( $self, $error_type ) = @_;
347 22 50       94 if ( $error_type =~ /^\u\w$/ ) {
    0          
348 22         87 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   80 my ( $self, $path ) = @_;
356              
357             # my ($volume, $directories, $file) = File::Spec->splitpath($filename);
358             # my @dirs = File::Spec->splitdir($directories);
359              
360 29         735 my ( $filename, $directories, $suffix ) = File::Basename::fileparse($path);
361 29 50       115 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         139 return $filename . $suffix;
372             }
373             }
374              
375             sub _prepare_localized_diagnostics {
376 6     6   27 my $self = shift;
377 6         40 my %options = @_;
378              
379 6 50       56 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__