my $method;
try {
if ( $method_ctx ) {
- my $desc = "accessor $accessor";
+ my $desc = "accessor " . $self->associated_class->name . "::$accessor";
if ( $accessor ne $self->name ) {
$desc .= " of attribute " . $self->name;
}
sub make_immutable {
my ( $self, @args ) = @_;
+ my ($file, $line) = (caller)[1..2];
if ( $self->is_mutable ) {
- $self->_initialize_immutable( $self->_immutable_options(@args) );
+ $self->_initialize_immutable(
+ $self->_immutable_options(@args),
+ file => $file,
+ line => $line,
+ );
$self->_rebless_as_immutable(@args);
return $self;
}
is_inline => 1,
package_name => $self->name,
name => $name,
+ definition_context => {
+ description => "constructor " . $self->name . "::" . $name,
+ file => $args{file},
+ line => $args{line},
+ },
);
if ( $args{replace_constructor} or $constructor->can_be_inlined ) {
options => \%args,
metaclass => $self,
package_name => $self->name,
- name => 'DESTROY'
+ name => 'DESTROY',
+ definition_context => {
+ description => "destructor " . $self->name . "::DESTROY",
+ file => $args{file},
+ line => $args{line},
+ },
);
if ( $args{replace_destructor} or $destructor->can_be_inlined ) {
'name' => $options{name},
'options' => $options{options},
'associated_metaclass' => $meta,
+ 'definition_context' => $options{definition_context},
'_expected_method_class' => $options{_expected_method_class} || 'Moose::Object',
} => $class;
'name' => $options{name},
# ...
'options' => $options{options},
+ 'definition_context' => $options{definition_context},
'associated_metaclass' => $options{metaclass},
} => $class;
--- /dev/null
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+use Test::Fatal;
+
+{
+ use Moose::Util::TypeConstraints;
+ use Carp 'confess';
+ subtype 'Death', as 'Int', where { $_ == 1 };
+ coerce 'Death', from 'Any', via { confess };
+}
+
+{
+ my ($attr_foo_line, $attr_bar_line, $ctor_line);
+ {
+ package Foo;
+ use Moose;
+
+ has foo => (
+ is => 'rw',
+ isa => 'Death',
+ coerce => 1,
+ );
+ $attr_foo_line = __LINE__ - 5;
+
+ has bar => (
+ accessor => 'baz',
+ isa => 'Death',
+ coerce => 1,
+ );
+ $attr_bar_line = __LINE__ - 5;
+
+ __PACKAGE__->meta->make_immutable;
+ $ctor_line = __LINE__ - 1;
+ }
+
+ like(
+ exception { Foo->new(foo => 2) },
+ qr/called at constructor Foo::new \(defined at $0 line $ctor_line\)/,
+ "got definition context for the constructor"
+ );
+
+ like(
+ exception { my $f = Foo->new(foo => 1); $f->foo(2) },
+ qr/called at accessor Foo::foo \(defined at $0 line $attr_foo_line\)/,
+ "got definition context for the accessor"
+ );
+
+ like(
+ exception { my $f = Foo->new(foo => 1); $f->baz(2) },
+ qr/called at accessor Foo::baz of attribute bar \(defined at $0 line $attr_bar_line\)/,
+ "got definition context for the accessor"
+ );
+}
+
+{
+ my ($dtor_line);
+ {
+ package Bar;
+ use Moose;
+
+ # just dying here won't work, because perl's exception handling is
+ # terrible
+ sub DEMOLISH { try { confess } catch { warn $_ } }
+
+ __PACKAGE__->meta->make_immutable;
+ $dtor_line = __LINE__ - 1;
+ }
+
+ {
+ my $warning = '';
+ local $SIG{__WARN__} = sub { $warning .= $_[0] };
+ { Bar->new }
+ like(
+ $warning,
+ qr/called at destructor Bar::DESTROY \(defined at $0 line $dtor_line\)/,
+ "got definition context for the destructor"
+ );
+ }
+}
+
+done_testing;