Skip to content

Commit

Permalink
add inspect method to Mojo::Exception
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Feb 26, 2016
1 parent 2ac8721 commit 73c0bc6
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 51 deletions.
3 changes: 2 additions & 1 deletion Changes
@@ -1,5 +1,6 @@

6.49 2016-02-25
6.49 2016-02-26
- Added inspect method to Mojo::Exception.
- Improved check_box and radio_button helpers with support for "on" default
values.
- Improved val method in Mojo::DOM with support for "on" default values.
Expand Down
89 changes: 48 additions & 41 deletions lib/Mojo/Exception.pm
Expand Up @@ -8,9 +8,32 @@ has [qw(frames line lines_before lines_after)] => sub { [] };
has message => 'Exception!';
has 'verbose';

sub new { @_ > 1 ? shift->SUPER::new->_detect(@_) : shift->SUPER::new }
sub inspect {
my ($self, @files) = @_;

sub throw { die shift->new->trace(2)->_detect(@_) }
# Extract file and line from message
my @trace;
my $msg = $self->message;
while ($msg =~ /at\s+(.+?)\s+line\s+(\d+)/g) { unshift @trace, [$1, $2] }

# Extract file and line from stack trace
my $first = $self->frames->[0];
push @trace, [$first->[1], $first->[2]] if $first;

# Search for context in files
for my $frame (@trace) {
next unless -r $frame->[0] && open my $handle, '<:utf8', $frame->[0];
$self->_context($frame->[1], [[<$handle>]]);
return $self;
}
$self->_context($trace[-1][1], [map { [split "\n"] } @files]) if @files;

return $self;
}

sub new { @_ > 1 ? shift->SUPER::new(message => shift) : shift->SUPER::new }

sub throw { die shift->new(shift)->trace(2)->inspect(@_) }

sub to_string {
my $self = shift;
Expand Down Expand Up @@ -69,33 +92,6 @@ sub _context {
}
}

sub _detect {
my ($self, $msg, $files) = @_;

return $msg if blessed $msg && $msg->isa('Mojo::Exception');
$self->message($msg);

# Extract file and line from message
my @trace;
while ($msg =~ /at\s+(.+?)\s+line\s+(\d+)/g) { unshift @trace, [$1, $2] }

# Extract file and line from stack trace
my $first = $self->frames->[0];
push @trace, [$first->[1], $first->[2]] if $first;

# Search for context in files
for my $frame (@trace) {
next unless -r $frame->[0] && open my $handle, '<:utf8', $frame->[0];
$self->_context($frame->[1], [[<$handle>]]);
return $self;
}

# More context
$self->_context($trace[-1][1], [map { [split "\n"] } @$files]) if $files;

return $self;
}

1;

=encoding utf8
Expand All @@ -109,12 +105,15 @@ Mojo::Exception - Exceptions with context
use Mojo::Exception;
# Throw exception and show stack trace
eval { Mojo::Exception->throw('Died at test.pl line 3.') };
say "$_->[1]: $_->[2]" for @{$@->frames};
eval { Mojo::Exception->throw('Something went wrong!') };
say "$_->[1]:$_->[2]" for @{$@->frames};
# Customize exception
eval { die Mojo::Exception->new('Died at test.pl line 3.')->trace(2) };
say $@->verbose(1);
eval {
my $e = Mojo::Exception->new('Died at test.pl line 3.');
die $e->trace(2)->inspect->verbose(1);
};
say $@;
=head1 DESCRIPTION
Expand All @@ -129,7 +128,7 @@ L<Mojo::Exception> implements the following attributes.
my $frames = $e->frames;
$e = $e->frames([$frame1, $frame2]);
Stack trace.
Stack trace if available.
# Extract information from the last frame
my ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext,
Expand Down Expand Up @@ -175,22 +174,30 @@ Render exception with context.
L<Mojo::Exception> inherits all methods from L<Mojo::Base> and implements the
following new ones.
=head2 inspect
$e = $e->inspect;
$e = $e->inspect($file1, $file2);
Inspect L</"message"> and L</"frames"> to fill L</"lines_before">, L</"line">
and L</"lines_after"> with context information.
=head2 new
my $e = Mojo::Exception->new;
my $e = Mojo::Exception->new('Died at test.pl line 3.');
my $e = Mojo::Exception->new('Died at test.pl line 3.', [$file1, $file2]);
Construct a new L<Mojo::Exception> object and extract context information from
additional files if necessary.
Construct a new L<Mojo::Exception> object.
=head2 throw
Mojo::Exception->throw('Died at test.pl line 3.');
Mojo::Exception->throw('Died at test.pl line 3.', [$file1, $file2]);
Mojo::Exception->throw('Something went wrong!');
Mojo::Exception->throw('Something went wrong!', $file1, $file2);
Throw exception from the current execution context.
Throw exception with stack trace and extract context information from additional
files if necessary.
# Longer version
die Mojo::Exception->new('Something went wrong!')->trace->inspect;
=head2 to_string
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Loader.pm
Expand Up @@ -53,7 +53,7 @@ sub load_class {
return 1 if $@ =~ /^Can't locate \Q@{[class_to_path $class]}\E in \@INC/;

# Real error
return Mojo::Exception->new($@);
return Mojo::Exception->new($@)->inspect;
}

sub _all {
Expand Down
10 changes: 4 additions & 6 deletions lib/Mojo/Template.pm
Expand Up @@ -92,7 +92,8 @@ sub compile {
$self->compiled($compiled) and return undef unless $@;

# Use local stack trace for compile exceptions
return Mojo::Exception->new($@, [$self->unparsed, $code])->trace->verbose(1);
return Mojo::Exception->new($@)->inspect($self->unparsed, $code)
->trace->verbose(1);
}

sub interpret {
Expand All @@ -101,15 +102,12 @@ sub interpret {
# Stack trace
local $SIG{__DIE__} = sub {
CORE::die($_[0]) if ref $_[0];
Mojo::Exception->throw(shift, [$self->unparsed, $self->code]);
Mojo::Exception->throw(shift, $self->unparsed, $self->code);
};

return undef unless my $compiled = $self->compiled;
my $output;
return $output if eval { $output = $compiled->(@_); 1 };

# Exception with template context
return Mojo::Exception->new($@, [$self->unparsed])->verbose(1);
return eval { $output = $compiled->(@_); 1 } ? $output : $@;
}

sub parse {
Expand Down
5 changes: 3 additions & 2 deletions lib/Mojolicious/Plugin/DefaultHelpers.pm
Expand Up @@ -87,7 +87,8 @@ sub _development {
my ($page, $c, $e) = @_;

my $app = $c->app;
$app->log->error($e = Mojo::Exception->new($e)) if $page eq 'exception';
$app->log->error($e = ref $e ? $e : Mojo::Exception->new($e)->inspect)
if $page eq 'exception';

# Filtered stash snapshot
my $stash = $c->stash;
Expand Down Expand Up @@ -414,7 +415,7 @@ C<Range>, C<If-Modified-Since> and C<If-None-Match> headers.
=head2 reply->exception
$c = $c->reply->exception('Oops!');
$c = $c->reply->exception(Mojo::Exception->new('Oops!'));
$c = $c->reply->exception(Mojo::Exception->new);
Render the exception template C<exception.$mode.$format.*> or
C<exception.$format.*> and set the response status code to C<500>. Also sets
Expand Down

0 comments on commit 73c0bc6

Please sign in to comment.