sub apply_methods {
my ($self, $role, $class) = @_;
+ my @implicitly_overridden;
+
foreach my $method_name ($role->get_method_list) {
-
unless ($self->is_method_excluded($method_name)) {
# it if it has one already
if ($class->has_method($method_name) &&
# and if they are not the same thing ...
$class->get_method($method_name)->body != $role->get_method($method_name)->body) {
+ push @implicitly_overridden, $method_name;
next;
}
else {
);
}
}
+
+ if (@implicitly_overridden) {
+ my $plural = @implicitly_overridden > 1 ? "s" : "";
+ # we use \n because we have no hope of guessing the right stack frame,
+ # it's almost certainly never going to be the one above us
+ warn "The " . $class->name . " class has implicitly overridden the method$plural (" . join(', ', @implicitly_overridden) . ") from role " . $role->name . ". If this is intentional, please exclude the method$plural from composition to silence this warning (see Moose::Cookbook::Roles::Recipe2)\n";
+ }
+
# we must reset the cache here since
# we are just aliasing methods, otherwise
# the modifiers go wonky.
use strict;
use warnings;
-use Test::More tests => 86;
+use Test::More tests => 87;
use Test::Exception;
+use Test::Output;
{
package FooRole;
use Moose;
extends 'BarClass';
- with 'FooRole';
+
+ ::stderr_like {
+ with 'FooRole';
+ } qr/The FooClass class has implicitly overridden the method \(goo\) from role FooRole\. If this is intentional, please exclude the method from composition to silence this warning \(see Moose::Cookbook::Roles::Recipe2\)/;
sub blau {'FooClass::blau'} # << the role wraps this ...
use strict;
use warnings;
-use Test::More tests => 87; # it's really 124 with kolibrie's tests;
+use Test::More tests => 89;
use Test::Exception;
+use Test::Output;
=pod
::lives_ok {
with 'Role::Bling';
- with 'Role::Bling::Bling';
+
+ ::stderr_like {
+ with 'Role::Bling::Bling';
+ } qr/The My::Test4 class has implicitly overridden the method \(bling\) from role Role::Bling::Bling\./;
+
} '... role methods didnt conflict when manually combined';
package My::Test5;
::lives_ok {
with 'Role::Bling::Bling';
- with 'Role::Bling';
+
+ ::stderr_like {
+ with 'Role::Bling';
+ } qr/The My::Test5 class has implicitly overridden the method \(bling\) from role Role::Bling\./;
} '... role methods didnt conflict when manually combined (in opposite order)';
package My::Test6;
use strict;
use warnings;
-use Test::More tests => 39;
+use Test::More tests => 44;
use Test::Exception;
+use Test::Output;
use Moose;
::lives_ok {
- with qw(Role::C);
+ ::stderr_like {
+ with qw(Role::C);
+ } qr/The Class::A class has implicitly overridden the method \(zot\) from role Role::C\./;
} "define class A";
sub zot { 'Class::A::zot' }
use Moose;
::lives_ok {
- with 'Role::A::Conflict';
+ ::stderr_like {
+ with 'Role::A::Conflict';
+ } qr/The Class::A::Resolved class has implicitly overridden the method \(bar\) from role Role::A::Conflict\./;
} '... did fufill the requirement of &bar method';
sub bar { 'Class::A::Resolved::bar' }
use Moose;
::lives_ok {
- with qw(Role::F);
+ ::stderr_like {
+ with qw(Role::F);
+ } qr/The Class::B class has implicitly overridden the method \(zot\) from role Role::F\./;
} "define class Class::B";
sub zot { 'Class::B::zot' }
use Moose;
::lives_ok {
- with qw(Role::I);
+ ::stderr_like {
+ with qw(Role::I);
+ } qr/The Class::E class has implicitly overridden the method \(zot\) from role Role::I\./;
} "resolved with method";
sub foo { 'Class::E::foo' }
sub zot { 'Class::D::zot' }
- with qw(Role::I);
+ ::stderr_like {
+ with qw(Role::I);
+ } qr/The Class::D class has implicitly overridden the method \(zot\) from role Role::I\./;
} "resolved with attr";
#!/usr/bin/env perl
use strict;
use warnings;
-use Test::More tests => 6;
+use Test::More tests => 8;
# this test script ensures that my idiom of:
# role: sub BUILD, after BUILD
};
do {
+ package ExplicitClassWithBUILD;
+ use Moose;
+ with 'TestRole' => { excludes => 'BUILD' };
+
+ sub BUILD { push @CALLS, 'ExplicitClassWithBUILD::BUILD' }
+};
+
+do {
package ClassWithoutBUILD;
use Moose;
with 'TestRole';
'TestRole::BUILD:after',
]);
+ ExplicitClassWithBUILD->new;
+
+ is_deeply([splice @CALLS], [
+ 'TestRole::BUILD:before',
+ 'ExplicitClassWithBUILD::BUILD',
+ 'TestRole::BUILD:after',
+ ]);
+
ClassWithoutBUILD->new;
is_deeply([splice @CALLS], [
if (ClassWithBUILD->meta->is_mutable) {
ClassWithBUILD->meta->make_immutable;
+ ExplicitClassWithBUILD->meta->make_immutable;
ClassWithoutBUILD->meta->make_immutable;
redo;
}
use strict;
use warnings;
-use Test::More tests => 20;
+use Test::More tests => 22;
use Test::Exception;
+use Test::Output;
package Constraint::AtLeast;
use Moose;
- with 'Constraint';
+ ::stderr_is {
+ with 'Constraint' => { excludes => 'error_message' };
+ } "";
sub validate {
my ($self, $field) = @_;
package Constraint::NoMoreThan;
use Moose;
- with 'Constraint';
+ ::stderr_is {
+ with 'Constraint' => { excludes => 'error_message' };
+ } '';
sub validate {
my ($self, $field) = @_;
use strict;
use warnings;
-use Test::More tests => 39;
+use Test::More tests => 40;
use Test::Exception;
+use Test::Output;
sub req_or_has ($$) {
my ( $role, $method ) = @_;
package Foo;
use Moose;
- with qw(Bar);
+ ::stderr_like {
+ with qw(Bar);
+ } qr/The Foo class has implicitly overridden the method \(xxy\) from role Bar\./;
has oink => (
is => "rw",
{
local our $TODO = "attrs and methods from a role should clash";
+ local $SIG{__WARN__} = sub { 'Ignore!' };
::dies_ok { with qw(Tree Dog) }
}
}