From: Jesse Luehrs Date: Sat, 17 Sep 2011 20:01:09 +0000 (-0500) Subject: be more verbose in the required method error (RT#60583) X-Git-Tag: 2.0300~35 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8d57392a58b5d0caa0578b63dcaf13a4495f564d;p=gitmo%2FMoose.git be more verbose in the required method error (RT#60583) --- diff --git a/Changes b/Changes index d5a6d53..5069373 100644 --- a/Changes +++ b/Changes @@ -39,11 +39,9 @@ for, noteworthy changes. this will no longer throw an error. Reported by Mark-Jason Dominus. Fixes RT 69988. (Dave Rolsky) - [BUG FIXES] - - * A subtype of a union type did not return the right results when you called - ->is_subtype_of or ->is_a_type_of on it. This has been fixed. RT - #70322. (Dave Rolsky) + * The error generated by unfulfilled method requirements during role + composition now mentions how to work around imported methods not being + recognized. Reported by Michael Schwern. Fixes RT 60583. (doy) [OTHER] diff --git a/lib/Moose/Meta/Role/Application/ToClass.pm b/lib/Moose/Meta/Role/Application/ToClass.pm index 704310b..822d1e5 100644 --- a/lib/Moose/Meta/Role/Application/ToClass.pm +++ b/lib/Moose/Meta/Role/Application/ToClass.pm @@ -4,6 +4,7 @@ use strict; use warnings; use metaclass; +use List::MoreUtils 'firstval'; use Moose::Util 'english_list'; use Scalar::Util 'weaken', 'blessed'; @@ -116,6 +117,12 @@ sub check_required_methods { . "' requires the $noun $list " . "to be implemented by '" . $class->name . q{'}; + + if (my $meth = firstval { $class->name->can($_) } @missing) { + $error .= ". If you imported functions intending to use them as " + . "methods, you need to explicitly mark them as such, via " + . $class->name . "->meta->add_method($meth => \\\&$meth)"; + } } $class->throw_error($error); diff --git a/t/roles/imported_required_method.t b/t/roles/imported_required_method.t new file mode 100644 index 0000000..ce44640 --- /dev/null +++ b/t/roles/imported_required_method.t @@ -0,0 +1,56 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use Test::More; +use Test::Fatal; +use Test::Moose; + +BEGIN { + package ExportsFoo; + use Sub::Exporter -setup => { + exports => ['foo'], + }; + + sub foo { 'FOO' } + + $INC{'ExportsFoo.pm'} = 1; +} + +{ + package Foo; + use Moose::Role; + requires 'foo'; +} + +{ + package Bar; + use Moose::Role; + requires 'bar'; +} + +{ + package Class; + use Moose; + use ExportsFoo 'foo'; + ::like( + ::exception { with 'Foo' }, + qr/^\Q'Foo' requires the method 'foo' to be implemented by 'Class'. If you imported functions intending to use them as methods, you need to explicitly mark them as such, via Class->meta->add_method(foo => \&foo)/, + "imported 'method' isn't seen" + ); + Class->meta->add_method(foo => \&foo); + ::is( + ::exception { with 'Foo' }, + undef, + "now it's a method" + ); + + ::like( + ::exception { with 'Bar' }, + qr/^\Q'Bar' requires the method 'bar' to be implemented by 'Class' at/, + "requirement isn't imported, so don't give the extra info in the error" + ); +} + +does_ok('Class', 'Foo'); + +done_testing;