Mouse::Role improved
gfx [Mon, 21 Sep 2009 05:33:39 +0000 (14:33 +0900)]
* More compatibility
* implement with $role => (-excludes => [...])
* implement dummy Meta::Method and get_method()

42 files changed:
lib/Mouse.pm
lib/Mouse/Meta/Class.pm
lib/Mouse/Meta/Method.pm [new file with mode: 0755]
lib/Mouse/Meta/Module.pm
lib/Mouse/Meta/Role.pm
lib/Mouse/Meta/Role/Method.pm [new file with mode: 0755]
lib/Mouse/Util.pm
lib/Test/Mouse.pm [new file with mode: 0755]
t/030_roles/001_meta_role.t [new file with mode: 0755]
t/030_roles/002_role.t
t/030_roles/003_apply_role.t
t/030_roles/009_more_role_edge_cases.t [new file with mode: 0644]
t/030_roles/019_build.t [changed mode: 0644->0755]
t/030_roles/031_roles_applied_in_create.t [changed mode: 0644->0755]
t/030_roles/041_empty_method_modifiers_meta_bug.t [new file with mode: 0755]
t/030_roles/042_compose_overloading.t [new file with mode: 0755]
t/030_roles/failing/006_role_exclusion.t
t/030_roles/failing/007_roles_and_req_method_edge_cases.t
t/030_roles/failing/008_role_conflict_edge_cases.t
t/030_roles/failing/010_run_time_role_composition.t
t/030_roles/failing/012_method_exclusion_in_composition.t
t/030_roles/failing/013_method_aliasing_in_composition.t
t/030_roles/failing/014_more_alias_and_exclude.t
t/030_roles/failing/015_runtime_roles_and_attrs.t
t/030_roles/failing/016_runtime_roles_and_nonmoose.t
t/030_roles/failing/017_extending_role_attrs.t
t/030_roles/failing/018_runtime_roles_w_params.t
t/030_roles/failing/020_role_composite.t
t/030_roles/failing/021_role_composite_exclusion.t
t/030_roles/failing/022_role_composition_req_methods.t
t/030_roles/failing/023_role_composition_attributes.t
t/030_roles/failing/024_role_composition_methods.t
t/030_roles/failing/025_role_composition_override.t
t/030_roles/failing/026_role_composition_method_mods.t
t/030_roles/failing/032_roles_and_method_cloning.t
t/030_roles/failing/033_role_exclusion_and_alias_bug.t
t/030_roles/failing/035_anonymous_roles.t
t/030_roles/failing/038_new_meta_role.t [new file with mode: 0755]
t/030_roles/failing/039_application_toclass.t [new file with mode: 0755]
t/030_roles/failing/040_role_for_combination.t [new file with mode: 0755]
t/030_roles/failing/043_conflict_many_methods.t [new file with mode: 0755]
t/036-with-method-alias.t

index d006137..4f6e8f9 100644 (file)
@@ -8,7 +8,7 @@ our $VERSION = '0.30';
 
 use Carp 'confess';
 use Scalar::Util 'blessed';
-use Mouse::Util;
+use Mouse::Util qw(load_class is_class_loaded);
 
 use Mouse::Meta::Attribute;
 use Mouse::Meta::Module; # class_of()
@@ -189,57 +189,6 @@ sub unimport {
     }
 }
 
-sub load_class {
-    my $class = shift;
-
-    if (!Mouse::Util::is_valid_class_name($class)) {
-        my $display = defined($class) ? $class : 'undef';
-        confess "Invalid class name ($display)";
-    }
-
-    return 1 if is_class_loaded($class);
-
-    (my $file = "$class.pm") =~ s{::}{/}g;
-
-    eval { CORE::require($file) };
-    confess "Could not load class ($class) because : $@" if $@;
-
-    return 1;
-}
-
-my %is_class_loaded_cache;
-sub is_class_loaded {
-    my $class = shift;
-
-    return 0 if ref($class) || !defined($class) || !length($class);
-
-    return 1 if exists $is_class_loaded_cache{$class};
-
-    # walk the symbol table tree to avoid autovififying
-    # \*{${main::}{"Foo::"}} == \*main::Foo::
-
-    my $pack = \*::;
-    foreach my $part (split('::', $class)) {
-        return 0 unless exists ${$$pack}{"${part}::"};
-        $pack = \*{${$$pack}{"${part}::"}};
-    }
-
-    # check for $VERSION or @ISA
-    return ++$is_class_loaded_cache{$class} if exists ${$$pack}{VERSION}
-             && defined *{${$$pack}{VERSION}}{SCALAR};
-    return ++$is_class_loaded_cache{$class} if exists ${$$pack}{ISA}
-             && defined *{${$$pack}{ISA}}{ARRAY};
-
-    # check for any method
-    foreach ( keys %{$$pack} ) {
-        next if substr($_, -2, 2) eq '::';
-        return ++$is_class_loaded_cache{$class} if defined *{${$$pack}{$_}}{CODE};
-    }
-
-    # fail
-    return 0;
-}
-
 1;
 
 __END__
index 7d4cdcd..6fcb576 100644 (file)
@@ -9,6 +9,7 @@ use Mouse::Util qw/get_linear_isa not_supported/;
 
 use base qw(Mouse::Meta::Module);
 
+sub method_metaclass(){ 'Mouse::Meta::Method' } # required for get_method()
 
 sub _new {
     my($class, %args) = @_;
@@ -209,7 +210,8 @@ sub make_immutable {
 
 sub make_mutable { not_supported }
 
-sub is_immutable { $_[0]->{is_immutable} }
+sub is_immutable {  $_[0]->{is_immutable} }
+sub is_mutable   { !$_[0]->{is_immutable} }
 
 sub _install_modifier {
     my ( $self, $into, $type, $name, $code ) = @_;
@@ -237,6 +239,8 @@ sub _install_modifier {
                 $name,
                 $code
             );
+            $self->{methods}{$name}++; # register it to the method map
+            return;
         };
     }
 
@@ -262,16 +266,12 @@ sub add_after_method_modifier {
 sub add_override_method_modifier {
     my ($self, $name, $code) = @_;
 
-    my $pkg = $self->name;
-    my $method = "${pkg}::${name}";
+    my $package = $self->name;
 
-    # Class::Method::Modifiers won't do this for us, so do it ourselves
+    my $body = $package->can($name)
+        or $self->throw_error("You cannot override '$name' because it has no super method");
 
-    my $body = $pkg->can($name)
-        or $self->throw_error("You cannot override '$method' because it has no super method");
-
-    no strict 'refs';
-    *$method = sub { $code->($pkg, $body, @_) };
+    $self->add_method($name => sub { $code->($package, $body, @_) });
 }
 
 sub does_role {
diff --git a/lib/Mouse/Meta/Method.pm b/lib/Mouse/Meta/Method.pm
new file mode 100755 (executable)
index 0000000..763e532
--- /dev/null
@@ -0,0 +1,23 @@
+package Mouse::Meta::Method;\r
+use strict;\r
+use warnings;\r
+\r
+use overload\r
+    '&{}' => 'body',\r
+    fallback => 1,\r
+;\r
+\r
+sub new{\r
+    my($class, %args) = @_;\r
+\r
+    return bless \%args, $class;\r
+}\r
+\r
+sub body   { $_[0]->{body} }\r
+sub name   { $_[0]->{name} }\r
+sub package{ $_[0]->{name} }\r
+\r
+\r
+1;\r
+\r
+__END__\r
index fa99e17..12b0453 100755 (executable)
@@ -2,7 +2,7 @@ package Mouse::Meta::Module;
 use strict;
 use warnings;
 
-use Mouse::Util qw/get_code_info not_supported/;
+use Mouse::Util qw/get_code_info not_supported load_class/;
 use Scalar::Util qw/blessed/;
 
 
@@ -69,6 +69,7 @@ sub get_attribute_map {        $_[0]->{attributes}          }
 sub has_attribute     { exists $_[0]->{attributes}->{$_[1]} }
 sub get_attribute     {        $_[0]->{attributes}->{$_[1]} }
 sub get_attribute_list{ keys %{$_[0]->{attributes}}         }
+sub remove_attribute  { delete $_[0]->{attributes}->{$_[1]} }
 
 sub namespace{
     my $name = $_[0]->{package};
@@ -113,7 +114,21 @@ sub has_method {
 }
 
 sub get_method{
-    Carp::croak("get_method() is not yet implemented");
+    my($self, $method_name) = @_;
+
+    if($self->has_method($method_name)){
+        my $method_metaclass = $self->method_metaclass;
+        load_class($method_metaclass);
+
+        my $package = $self->name;
+        return $method_metaclass->new(
+            body    => $package->can($method_name),
+            name    => $method_name,
+            package => $package,
+        );
+    }
+
+    return undef;
 }
 
 sub get_method_list {\r
index b9f6b38..05faacf 100644 (file)
@@ -5,6 +5,8 @@ use warnings;
 use Mouse::Util qw(not_supported);
 use base qw(Mouse::Meta::Module);
 
+sub method_metaclass(){ 'Mouse::Meta::Role::Method' } # required for get_method()
+
 sub _new {
     my $class = shift;
     my %args  = @_;
@@ -19,6 +21,9 @@ sub _new {
 
 sub get_roles { $_[0]->{roles} }
 
+sub get_required_method_list{
+    return @{ $_[0]->{required_methods} };
+}
 
 sub add_required_methods {
     my $self = shift;
@@ -26,11 +31,16 @@ sub add_required_methods {
     push @{$self->{required_methods}}, @methods;
 }
 
+sub requires_method {
+    my($self, $name) = @_;
+    return scalar( grep{ $_ eq $name } @{ $self->{required_methods} } ) != 0;
+}
+
 sub add_attribute {
     my $self = shift;
     my $name = shift;
-    my $spec = shift;
-    $self->{attributes}->{$name} = $spec;
+
+    $self->{attributes}->{$name} = (@_ == 1) ? $_[0] : { @_ };
 }
 
 sub _check_required_methods{
@@ -65,23 +75,38 @@ sub _apply_methods{
 
     my $role_name  = $role->name;
     my $class_name = $class->name;
-    my $alias      = $args->{alias};
+
+    my $alias    = (exists $args->{alias}    && !exists $args->{-alias})    ? $args->{alias}    : $args->{-alias};
+    my $excludes = (exists $args->{excludes} && !exists $args->{-excludes}) ? $args->{excludes} : $args->{-excludes};
+
+    my %exclude_map;
+
+    if(defined $excludes){
+        if(ref $excludes){
+            %exclude_map = map{ $_ => undef } @{$excludes};
+        }
+        else{
+            $exclude_map{$excludes} = undef;
+        }
+    }
 
     foreach my $method_name($role->get_method_list){
         next if $method_name eq 'meta';
 
         my $code = $role_name->can($method_name);
-        if(do{ no strict 'refs'; defined &{$class_name . '::' . $method_name} }){
-            # XXX what's Moose's behavior?
-        }
-        else{
-            $class->add_method($method_name => $code);
+
+        if(!exists $exclude_map{$method_name}){
+            if(!$class->has_method($method_name)){
+                $class->add_method($method_name => $code);
+            }
         }
 
         if($alias && $alias->{$method_name}){
             my $dstname = $alias->{$method_name};
-            if(do{ no strict 'refs'; defined &{$class_name . '::' . $dstname} }){
-                # XXX wat's Moose's behavior?
+
+            my $slot = do{ no strict 'refs'; \*{$class_name . '::' . $dstname} };
+            if(defined(*{$slot}{CODE}) && *{$slot}{CODE} != $code){
+                $class->throw_error("Cannot create a method alias if a local method of the same name exists");
             }
             else{
                 $class->add_method($dstname => $code);
@@ -133,7 +158,7 @@ sub _apply_modifiers{
         my $modifiers    = $role->{"${modifier_type}_method_modifiers"};
 
         while(my($method_name, $modifier_codes) = each %{$modifiers}){
-            foreach my $code(@{$modifier_codes}){
+            foreach my $code(ref($modifier_codes) eq 'ARRAY' ? @{$modifier_codes} : $modifier_codes){
                 $class->$add_modifier($method_name => $code);
             }
         }
@@ -187,7 +212,7 @@ sub combine_apply {
     return;
 }
 
-for my $modifier_type (qw/before after around override/) {
+for my $modifier_type (qw/before after around/) {
 
     my $modifier = "${modifier_type}_method_modifiers";
     my $add_method_modifier =  sub {
@@ -212,6 +237,32 @@ for my $modifier_type (qw/before after around override/) {
     *{ 'get_' . $modifier_type . '_method_modifiers' } = $get_method_modifiers;
 }
 
+sub add_override_method_modifier{
+    my($self, $method_name, $method) = @_;
+
+    (!$self->has_method($method_name))\r
+        || $self->throw_error("Cannot add an override of method '$method_name' " .\r
+                   "because there is a local version of '$method_name'");
+
+    $self->{override_method_modifiers}->{$method_name} = $method;
+}
+
+sub has_override_method_modifier {\r
+    my ($self, $method_name) = @_;\r
+    return exists $self->{override_method_modifiers}->{$method_name};\r
+}\r
+\r
+sub get_override_method_modifier {\r
+    my ($self, $method_name) = @_;\r
+    return $self->{override_method_modifiers}->{$method_name};\r
+}
+
+sub get_method_modifier_list {
+    my($self, $modifier_type) = @_;
+
+    return keys %{ $self->{$modifier_type . '_method_modifiers'} };
+}
+
 # This is currently not passing all the Moose tests.
 sub does_role {
     my ($self, $role_name) = @_;
diff --git a/lib/Mouse/Meta/Role/Method.pm b/lib/Mouse/Meta/Role/Method.pm
new file mode 100755 (executable)
index 0000000..eb94651
--- /dev/null
@@ -0,0 +1,10 @@
+package Mouse::Meta::Role::Method;\r
+use strict;\r
+use warnings;\r
+\r
+use base qw(Mouse::Meta::Method);\r
+\r
+1;\r
+\r
+__END__\r
+\r
index 73e76ba..9f3ecf9 100644 (file)
@@ -6,6 +6,8 @@ use Carp qw(confess);
 use B ();
 
 our @EXPORT_OK = qw(
+    load_class
+    is_class_loaded
     get_linear_isa
     apply_all_roles
     get_code_info
@@ -107,7 +109,6 @@ sub is_valid_class_name {
 
     return 0 if ref($class);
     return 0 unless defined($class);
-    return 0 unless length($class);
 
     return 1 if $class =~ /^\w+(?:::\w+)*$/;
 
@@ -122,11 +123,6 @@ sub load_first_existing_class {
     my $found;
     my %exceptions;
     for my $class (@classes) {
-        unless ( is_valid_class_name($class) ) {
-            my $display = defined($class) ? $class : 'undef';
-            confess "Invalid class name ($display)";
-        }
-
         my $e = _try_load_one_class($class);
 
         if ($e) {
@@ -152,7 +148,12 @@ sub load_first_existing_class {
 sub _try_load_one_class {
     my $class = shift;
 
-    return if Mouse::is_class_loaded($class);
+    unless ( is_valid_class_name($class) ) {
+        my $display = defined($class) ? $class : 'undef';
+        confess "Invalid class name ($display)";
+    }
+
+    return if is_class_loaded($class);
 
     my $file = $class . '.pm';
     $file =~ s{::}{/}g;
@@ -164,6 +165,49 @@ sub _try_load_one_class {
     };
 }
 
+
+sub load_class {
+    my $class = shift;
+    my $e = _try_load_one_class($class);
+    confess "Could not load class ($class) because : $e" if $e;
+
+    return 1;
+}
+
+my %is_class_loaded_cache;
+sub is_class_loaded {
+    my $class = shift;
+
+    return 0 if ref($class) || !defined($class) || !length($class);
+
+    return 1 if exists $is_class_loaded_cache{$class};
+
+    # walk the symbol table tree to avoid autovififying
+    # \*{${main::}{"Foo::"}} == \*main::Foo::
+
+    my $pack = \*::;
+    foreach my $part (split('::', $class)) {
+        return 0 unless exists ${$$pack}{"${part}::"};
+        $pack = \*{${$$pack}{"${part}::"}};
+    }
+
+    # check for $VERSION or @ISA
+    return ++$is_class_loaded_cache{$class} if exists ${$$pack}{VERSION}
+             && defined *{${$$pack}{VERSION}}{SCALAR};
+    return ++$is_class_loaded_cache{$class} if exists ${$$pack}{ISA}
+             && defined *{${$$pack}{ISA}}{ARRAY};
+
+    # check for any method
+    foreach ( keys %{$$pack} ) {
+        next if substr($_, -2, 2) eq '::';
+        return ++$is_class_loaded_cache{$class} if defined *{${$$pack}{$_}}{CODE};
+    }
+
+    # fail
+    return 0;
+}
+
+
 sub apply_all_roles {
     my $meta = Mouse::Meta::Class->initialize(shift);
 
diff --git a/lib/Test/Mouse.pm b/lib/Test/Mouse.pm
new file mode 100755 (executable)
index 0000000..6348746
--- /dev/null
@@ -0,0 +1,75 @@
+package Test::Mouse;\r
+\r
+use strict;\r
+use warnings;\r
+use Mouse ();\r
+\r
+use base qw(Test::Builder::Module);\r
+\r
+our @EXPORT = qw(meta_ok does_ok has_attribute_ok);\r
+\r
+sub find_meta{ Mouse::class_of($class_or_obj) }\r
+\r
+sub meta_ok ($;$) {\r
+    my ($class_or_obj, $message) = @_;\r
+\r
+    $message ||= "The object has a meta";\r
+\r
+    if (find_meta($class_or_obj)) {\r
+        return __PACKAGE__->builder->ok(1, $message)\r
+    }\r
+    else {\r
+        return __PACKAGE__->builder->ok(0, $message);\r
+    }\r
+}\r
+\r
+sub does_ok ($$;$) {\r
+    my ($class_or_obj, $does, $message) = @_;\r
+\r
+    $message ||= "The object does $does";\r
+\r
+    my $meta = find_meta($class_or_obj);\r
+    if ($meta && $meta->does_role($does)) {\r
+        return __PACKAGE__->builder->ok(1, $message)\r
+    }\r
+    else {\r
+        return __PACKAGE__->builder->ok(0, $message);\r
+    }\r
+}\r
+\r
+sub has_attribute_ok ($$;$) {\r
+    my ($class_or_obj, $attr_name, $message) = @_;\r
+\r
+    $message ||= "The object does has an attribute named $attr_name";\r
+\r
+    my $meta = find_meta($class_or_obj);\r
+\r
+    if ($meta->find_attribute_by_name($attr_name)) {\r
+        return __PACKAGE__->builder->ok(1, $message)\r
+    }\r
+    else {\r
+        return __PACKAGE__->builder->ok(0, $message);\r
+    }\r
+}\r
+\r
+1;\r
+\r
+__END__\r
+\r
+=pod\r
+\r
+=head1 NAME\r
+\r
+Test::Mouse - Test functions for Mouse specific features\r
+\r
+=head1 SYNOPSIS\r
+\r
+  use Test::More plan => 1;\r
+  use Test::Mouse;\r
+\r
+  meta_ok($class_or_obj, "... Foo has a ->meta");\r
+  does_ok($class_or_obj, $role, "... Foo does the Baz role");\r
+  has_attribute_ok($class_or_obj, $attr_name, "... Foo has the 'bar' attribute");\r
+\r
+=cut\r
+\r
diff --git a/t/030_roles/001_meta_role.t b/t/030_roles/001_meta_role.t
new file mode 100755 (executable)
index 0000000..b6acf2b
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 26;
+use Test::Exception;
+
+use Mouse::Meta::Role;
+
+{
+    package FooRole;
+
+    our $VERSION = '0.01';
+
+    sub foo { 'FooRole::foo' }
+}
+
+my $foo_role = Mouse::Meta::Role->initialize('FooRole');
+isa_ok($foo_role, 'Mouse::Meta::Role');
+#isa_ok($foo_role, 'Class::MOP::Module');
+
+is($foo_role->name, 'FooRole', '... got the right name of FooRole');
+is($foo_role->version, '0.01', '... got the right version of FooRole');
+
+# methods ...
+
+ok($foo_role->has_method('foo'), '... FooRole has the foo method');
+is($foo_role->get_method('foo')->body, \&FooRole::foo, '... FooRole got the foo method');
+
+isa_ok($foo_role->get_method('foo'), 'Mouse::Meta::Role::Method');
+
+is_deeply(
+    [ $foo_role->get_method_list() ],
+    [ 'foo' ],
+    '... got the right method list');
+
+# attributes ...
+
+is_deeply(
+    [ $foo_role->get_attribute_list() ],
+    [],
+    '... got the right attribute list');
+
+ok(!$foo_role->has_attribute('bar'), '... FooRole does not have the bar attribute');
+
+lives_ok {
+    $foo_role->add_attribute('bar' => (is => 'rw', isa => 'Foo'));
+} '... added the bar attribute okay';
+
+is_deeply(
+    [ $foo_role->get_attribute_list() ],
+    [ 'bar' ],
+    '... got the right attribute list');
+
+ok($foo_role->has_attribute('bar'), '... FooRole does have the bar attribute');
+
+is_deeply(
+    join('|', %{$foo_role->get_attribute('bar')}),
+    join('|', %{+{ is => 'rw', isa => 'Foo' }}),
+    '... got the correct description of the bar attribute');
+
+lives_ok {
+    $foo_role->add_attribute('baz' => (is => 'ro'));
+} '... added the baz attribute okay';
+
+is_deeply(
+    [ sort $foo_role->get_attribute_list() ],
+    [ 'bar', 'baz' ],
+    '... got the right attribute list');
+
+ok($foo_role->has_attribute('baz'), '... FooRole does have the baz attribute');
+
+is_deeply(
+    $foo_role->get_attribute('baz'),
+    { is => 'ro' },
+    '... got the correct description of the baz attribute');
+
+lives_ok {
+    $foo_role->remove_attribute('bar');
+} '... removed the bar attribute okay';
+
+is_deeply(
+    [ $foo_role->get_attribute_list() ],
+    [ 'baz' ],
+    '... got the right attribute list');
+
+ok(!$foo_role->has_attribute('bar'), '... FooRole does not have the bar attribute');
+ok($foo_role->has_attribute('baz'), '... FooRole does still have the baz attribute');
+
+# method modifiers
+
+ok(!$foo_role->has_before_method_modifiers('boo'), '... no boo:before modifier');
+
+my $method = sub { "FooRole::boo:before" };
+lives_ok {
+    $foo_role->add_before_method_modifier('boo' => $method);
+} '... added a method modifier okay';
+
+ok($foo_role->has_before_method_modifiers('boo'), '... now we have a boo:before modifier');
+is(($foo_role->get_before_method_modifiers('boo'))[0], $method, '... got the right method back');
+
+is_deeply(
+    [ $foo_role->get_method_modifier_list('before') ],
+    [ 'boo' ],
+    '... got the right list of before method modifiers');
index 448d492..577c2ef 100755 (executable)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 36;
+use Test::More tests => 40;
 use Test::Exception;
 
 =pod
@@ -11,7 +11,7 @@ use Test::Exception;
 NOTE:
 
 Should we be testing here that the has & override
-are injecting their methods correctly? In other 
+are injecting their methods correctly? In other
 words, should 'has_method' return true for them?
 
 =cut
@@ -19,46 +19,44 @@ words, should 'has_method' return true for them?
 {
     package FooRole;
     use Mouse::Role;
-    
+
     our $VERSION = '0.01';
-    
+
     has 'bar' => (is => 'rw', isa => 'Foo');
-    has 'baz' => (is => 'ro');    
-    
+    has 'baz' => (is => 'ro');
+
     sub foo { 'FooRole::foo' }
-    sub boo { 'FooRole::boo' }    
-    
+    sub boo { 'FooRole::boo' }
+
     before 'boo' => sub { "FooRole::boo:before" };
-    
-    after  'boo' => sub { "FooRole::boo:after1"  }; 
-    after  'boo' => sub { "FooRole::boo:after2"  };        
-    
-    around 'boo' => sub { "FooRole::boo:around" };  
-    
-    override 'bling' => sub { "FooRole::bling:override" };   
-    override 'fling' => sub { "FooRole::fling:override" };  
-    
+
+    after  'boo' => sub { "FooRole::boo:after1"  };
+    after  'boo' => sub { "FooRole::boo:after2"  };
+
+    around 'boo' => sub { "FooRole::boo:around" };
+
+    override 'bling' => sub { "FooRole::bling:override" };
+    override 'fling' => sub { "FooRole::fling:override" };
+
     ::dies_ok { extends() } '... extends() is not supported';
-    ::dies_ok { augment() } '... augment() is not supported';    
-    ::dies_ok { inner()   } '... inner() is not supported';        
+    ::dies_ok { augment() } '... augment() is not supported';
+    ::dies_ok { inner()   } '... inner() is not supported';
 
     no Mouse::Role;
 }
 
 my $foo_role = FooRole->meta;
 isa_ok($foo_role, 'Mouse::Meta::Role');
-SKIP: { skip "Mouse: doesn't use Class::MOP" => 1;
-isa_ok($foo_role, 'Class::MOP::Module');
-}
+#isa_ok($foo_role, 'Class::MOP::Module');
 
 is($foo_role->name, 'FooRole', '... got the right name of FooRole');
-is($foo_role->version, '0.01', '... got the right version of FooRole'); 
+is($foo_role->version, '0.01', '... got the right version of FooRole');
 
 # methods ...
 
-TODO: { todo_skip "Mouse: not yet implemented" => 6;
-ok($foo_role->has_method('foo'), '... FooRole has the foo method'); 
-is($foo_role->get_method('foo')->body, \&FooRole::foo, '... FooRole got the foo method'); 
+
+ok($foo_role->has_method('foo'), '... FooRole has the foo method');
+is($foo_role->get_method('foo')->body, \&FooRole::foo, '... FooRole got the foo method');
 
 isa_ok($foo_role->get_method('foo'), 'Mouse::Meta::Role::Method');
 
@@ -66,7 +64,6 @@ ok($foo_role->has_method('boo'), '... FooRole has the boo method');
 is($foo_role->get_method('boo')->body, \&FooRole::boo, '... FooRole got the boo method');
 
 isa_ok($foo_role->get_method('boo'), 'Mouse::Meta::Role::Method');
-}
 
 is_deeply(
     [ sort $foo_role->get_method_list() ],
@@ -85,21 +82,34 @@ is_deeply(
 
 ok($foo_role->has_attribute('bar'), '... FooRole does have the bar attribute');
 
-is $foo_role->get_attribute('bar')->{is}, 'rw', '... got the correct description of the bar attribute';
+{
+local $TODO = 'definition_context is not yet implemented';
+my $bar_attr = $foo_role->get_attribute('bar');
+is($bar_attr->{is}, 'rw',
+   'bar attribute is rw');
+is($bar_attr->{isa}, 'Foo',
+   'bar attribute isa Foo');
+is(ref($bar_attr->{definition_context}), 'HASH',
+   'bar\'s definition context is a hash');
+is($bar_attr->{definition_context}->{package}, 'FooRole',
+   'bar was defined in FooRole');
 
 ok($foo_role->has_attribute('baz'), '... FooRole does have the baz attribute');
 
-is(
-    $foo_role->get_attribute('baz')->{is},
-    'ro',
-    '... got the correct description of the baz attribute');
+my $baz_attr = $foo_role->get_attribute('baz');
+is($baz_attr->{is}, 'ro',
+   'baz attribute is ro');
+is(ref($baz_attr->{definition_context}), 'HASH',
+   'bar\'s definition context is a hash');
+is($baz_attr->{definition_context}->{package}, 'FooRole',
+   'baz was defined in FooRole');
+} # end of TODO (definition_context)
 
 # method modifiers
-TODO: { todo_skip  "Mouse: not yet implemented" => 15;
 
 ok($foo_role->has_before_method_modifiers('boo'), '... now we have a boo:before modifier');
-is(($foo_role->get_before_method_modifiers('boo'))[0]->(), 
-    "FooRole::boo:before", 
+is(($foo_role->get_before_method_modifiers('boo'))[0]->(),
+    "FooRole::boo:before",
     '... got the right method back');
 
 is_deeply(
@@ -108,21 +118,21 @@ is_deeply(
     '... got the right list of before method modifiers');
 
 ok($foo_role->has_after_method_modifiers('boo'), '... now we have a boo:after modifier');
-is(($foo_role->get_after_method_modifiers('boo'))[0]->(), 
-    "FooRole::boo:after1", 
+is(($foo_role->get_after_method_modifiers('boo'))[0]->(),
+    "FooRole::boo:after1",
+    '... got the right method back');
+is(($foo_role->get_after_method_modifiers('boo'))[1]->(),
+    "FooRole::boo:after2",
     '... got the right method back');
-is(($foo_role->get_after_method_modifiers('boo'))[1]->(), 
-    "FooRole::boo:after2", 
-    '... got the right method back');    
 
 is_deeply(
     [ $foo_role->get_method_modifier_list('after') ],
     [ 'boo' ],
     '... got the right list of after method modifiers');
-    
+
 ok($foo_role->has_around_method_modifiers('boo'), '... now we have a boo:around modifier');
-is(($foo_role->get_around_method_modifiers('boo'))[0]->(), 
-    "FooRole::boo:around", 
+is(($foo_role->get_around_method_modifiers('boo'))[0]->(),
+    "FooRole::boo:around",
     '... got the right method back');
 
 is_deeply(
@@ -130,17 +140,16 @@ is_deeply(
     [ 'boo' ],
     '... got the right list of around method modifiers');
 
-
 ## overrides
 
 ok($foo_role->has_override_method_modifier('bling'), '... now we have a bling:override modifier');
-is($foo_role->get_override_method_modifier('bling')->(), 
-    "FooRole::bling:override", 
+is($foo_role->get_override_method_modifier('bling')->(),
+    "FooRole::bling:override",
     '... got the right method back');
 
 ok($foo_role->has_override_method_modifier('fling'), '... now we have a fling:override modifier');
-is($foo_role->get_override_method_modifier('fling')->(), 
-    "FooRole::fling:override", 
+is($foo_role->get_override_method_modifier('fling')->(),
+    "FooRole::fling:override",
     '... got the right method back');
 
 is_deeply(
@@ -148,4 +157,3 @@ is_deeply(
     [ 'bling', 'fling' ],
     '... got the right list of override method modifiers');
 
-}
index 3aaee4f..b4d2b38 100755 (executable)
@@ -2,18 +2,8 @@
 
 use strict;
 use warnings;
-use Test::More;
-BEGIN {
-    plan skip_all => 
-            "This test requires Class::Method::Modifiers or Class::Method::Modifiers::Fast" 
-        unless eval { 
-            require Class::Method::Modifiers::Fast;
-        } or   eval {
-            require Class::Method::Modifiers;
-        };
-}
 
-plan tests => 86;
+use Test::More tests => 86;
 use Test::Exception;
 
 {
@@ -27,7 +17,6 @@ use Test::Exception;
     sub foo {'FooRole::foo'}
 
     override 'boo' => sub { 'FooRole::boo -> ' . super() };
-#    sub boo { 'FooRole::boo -> ' . shift->SUPER::boo() }
 
     around 'blau' => sub {
         my $c = shift;
@@ -103,19 +92,16 @@ ok( !$foobar_class_meta->does_role('OtherRole'),
     '... the FooBarClass->meta !does_role OtherRole' );
 
 foreach my $method_name (qw(bar baz foo boo blau goo)) {
-#    ok( $foo_class_meta->has_method($method_name), ## Mouse: no ->has_method
-    ok( FooClass->can($method_name),
+    #use Data::Dumper; $Data::Dumper::Maxdepth=1; diag(Dumper $foo_class_meta->{methods});
+    ok( $foo_class_meta->has_method($method_name),
         '... FooClass has the method ' . $method_name );
-#    ok( $foobar_class_meta->has_method($method_name), ## Mouse: no ->has_method
-    ok( FooClass->can($method_name),
+    ok( $foobar_class_meta->has_method($method_name),
         '... FooBarClass has the method ' . $method_name );
 }
 
-#ok( !$foo_class_meta->has_method('woot'), ## Mouse: no ->has_method
-ok( !FooClass->can('woot'),
+ok( !$foo_class_meta->has_method('woot'),
     '... FooClass lacks the method woot' );
-#ok( $foobar_class_meta->has_method('woot'), ## Mouse: no ->has_method
-ok( FooBarClass->can('woot'),
+ok( $foobar_class_meta->has_method('woot'),
     '... FooBarClass has the method woot' );
 
 foreach my $attr_name (qw(bar baz)) {
diff --git a/t/030_roles/009_more_role_edge_cases.t b/t/030_roles/009_more_role_edge_cases.t
new file mode 100644 (file)
index 0000000..d7c95a4
--- /dev/null
@@ -0,0 +1,256 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 74;
+use Test::Exception;
+
+
+
+{
+    # NOTE:
+    # this tests that repeated role
+    # composition will not cause
+    # a conflict between two methods
+    # which are actually the same anyway
+
+    {
+        package RootA;
+        use Mouse::Role;
+
+        sub foo { "RootA::foo" }
+
+        package SubAA;
+        use Mouse::Role;
+
+        with "RootA";
+
+        sub bar { "SubAA::bar" }
+
+        package SubAB;
+        use Mouse;
+
+        ::lives_ok {
+            with "SubAA", "RootA";
+        } '... role was composed as expected';
+    }
+
+    ok( SubAB->does("SubAA"), "does SubAA");
+    ok( SubAB->does("RootA"), "does RootA");
+
+    isa_ok( my $i = SubAB->new, "SubAB" );
+
+    can_ok( $i, "bar" );
+    is( $i->bar, "SubAA::bar", "... got thr right bar rv" );
+
+    can_ok( $i, "foo" );
+    my $foo_rv;
+    lives_ok {
+        $foo_rv = $i->foo;
+    } '... called foo successfully';
+    is($foo_rv, "RootA::foo", "... got the right foo rv");
+}
+
+{
+    # NOTE:
+    # this edge cases shows the application of
+    # an after modifier over a method which
+    # was added during role composotion.
+    # The way this will work is as follows:
+    #    role SubBA will consume RootB and
+    #    get a local copy of RootB::foo, it
+    #    will also store a deferred after modifier
+    #    to be applied to whatever class SubBA is
+    #    composed into.
+    #    When class SubBB comsumed role SubBA, the
+    #    RootB::foo method is added to SubBB, then
+    #    the deferred after modifier from SubBA is
+    #    applied to it.
+    # It is important to note that the application
+    # of the after modifier does not happen until
+    # role SubBA is composed into SubAA.
+
+    {
+        package RootB;
+        use Mouse::Role;
+
+        sub foo { "RootB::foo" }
+
+        package SubBA;
+        use Mouse::Role;
+
+        with "RootB";
+
+        has counter => (
+            isa => "Num",
+            is  => "rw",
+            default => 0,
+        );
+
+        after foo => sub {
+            $_[0]->counter( $_[0]->counter + 1 );
+        };
+
+        package SubBB;
+        use Mouse;
+
+        ::lives_ok {
+            with "SubBA";
+        } '... composed the role successfully';
+    }
+
+    ok( SubBB->does("SubBA"), "BB does SubBA" );
+    ok( SubBB->does("RootB"), "BB does RootB" );
+
+    isa_ok( my $i = SubBB->new, "SubBB" );
+
+    can_ok( $i, "foo" );
+
+    my $foo_rv;
+    lives_ok {
+        $foo_rv = $i->foo
+    } '... called foo successfully';
+    is( $foo_rv, "RootB::foo", "foo rv" );
+    is( $i->counter, 1, "after hook called" );
+
+    lives_ok { $i->foo } '... called foo successfully (again)';
+    is( $i->counter, 2, "after hook called (again)" );
+
+    ok(SubBA->meta->has_method('foo'), '... this has the foo method');
+    #my $subba_foo_rv;
+    #lives_ok {
+    #    $subba_foo_rv = SubBA::foo();
+    #} '... called the sub as a function correctly';
+    #is($subba_foo_rv, 'RootB::foo', '... the SubBA->foo is still the RootB version');
+}
+
+{
+    # NOTE:
+    # this checks that an override method
+    # does not try to trample over a locally
+    # composed in method. In this case the
+    # RootC::foo, which is composed into
+    # SubCA cannot be trampled with an
+    # override of 'foo'
+    {
+        package RootC;
+        use Mouse::Role;
+
+        sub foo { "RootC::foo" }
+
+        package SubCA;
+        use Mouse::Role;
+
+        with "RootC";
+
+        ::dies_ok {
+            override foo => sub { "overridden" };
+        } '... cannot compose an override over a local method';
+    }
+}
+
+# NOTE:
+# need to talk to Yuval about the motivation behind
+# this test, I am not sure we are testing anything
+# useful here (although more tests cant hurt)
+
+{
+    use List::Util qw/shuffle/;
+
+    {
+        package Abstract;
+        use Mouse::Role;
+
+        requires "method";
+        requires "other";
+
+        sub another { "abstract" }
+
+        package ConcreteA;
+        use Mouse::Role;
+        with "Abstract";
+
+        sub other { "concrete a" }
+
+        package ConcreteB;
+        use Mouse::Role;
+        with "Abstract";
+
+        sub method { "concrete b" }
+
+        package ConcreteC;
+        use Mouse::Role;
+        with "ConcreteA";
+
+        # NOTE:
+        # this was originally override, but
+        # that wont work (see above set of tests)
+        # so I switched it to around.
+        # However, this may not be testing the
+        # same thing that was originally intended
+        around other => sub {
+            return ( (shift)->() . " + c" );
+        };
+
+        package SimpleClassWithSome;
+        use Mouse;
+
+        eval { with ::shuffle qw/ConcreteA ConcreteB/ };
+        ::ok( !$@, "simple composition without abstract" ) || ::diag $@;
+
+        package SimpleClassWithAll;
+        use Mouse;
+
+        eval { with ::shuffle qw/ConcreteA ConcreteB Abstract/ };
+        ::ok( !$@, "simple composition with abstract" ) || ::diag $@;
+    }
+
+    foreach my $class (qw/SimpleClassWithSome SimpleClassWithAll/) {
+        foreach my $role (qw/Abstract ConcreteA ConcreteB/) {
+            ok( $class->does($role), "$class does $role");
+        }
+
+        foreach my $method (qw/method other another/) {
+            can_ok( $class, $method );
+        }
+
+        is( eval { $class->another }, "abstract", "provided by abstract" );
+        is( eval { $class->other }, "concrete a", "provided by concrete a" );
+        is( eval { $class->method }, "concrete b", "provided by concrete b" );
+    }
+
+    {
+        package ClassWithSome;
+        use Mouse;
+
+        eval { with ::shuffle qw/ConcreteC ConcreteB/ };
+        ::ok( !$@, "composition without abstract" ) || ::diag $@;
+
+        package ClassWithAll;
+        use Mouse;
+
+        eval { with ::shuffle qw/ConcreteC Abstract ConcreteB/ };
+        ::ok( !$@, "composition with abstract" ) || ::diag $@;
+
+        package ClassWithEverything;
+        use Mouse;
+
+        eval { with ::shuffle qw/ConcreteC Abstract ConcreteA ConcreteB/ }; # this should clash
+        ::ok( !$@, "can compose ConcreteA and ConcreteC together" );
+    }
+
+    foreach my $class (qw/ClassWithSome ClassWithAll ClassWithEverything/) {
+        foreach my $role (qw/Abstract ConcreteA ConcreteB ConcreteC/) {
+            ok( $class->does($role), "$class does $role");
+        }
+
+        foreach my $method (qw/method other another/) {
+            can_ok( $class, $method );
+        }
+
+        is( eval { $class->another }, "abstract", "provided by abstract" );
+        is( eval { $class->other }, "concrete a + c", "provided by concrete c + a" );
+        is( eval { $class->method }, "concrete b", "provided by concrete b" );
+    }
+}
old mode 100644 (file)
new mode 100755 (executable)
index 8d3a4a4..475e4fb
@@ -3,18 +3,11 @@ use strict;
 use warnings;
 use Test::More;
 BEGIN {
-    plan skip_all => 
-            "This test requires Class::Method::Modifiers or Class::Method::Modifiers::Fast" 
-        unless eval { 
-            require Class::Method::Modifiers::Fast;
-        } or   eval {
-            require Class::Method::Modifiers;
-        };
+    eval "use Test::Output;";
+    plan skip_all => "Test::Output is required for this test" if $@;
+    plan tests => 8;
 }
 
-plan tests => 6;
-
-
 # this test script ensures that my idiom of:
 # role: sub BUILD, after BUILD
 # continues to work to run code after object initialization, whether the class
@@ -34,53 +27,54 @@ do {
 do {
     package ClassWithBUILD;
     use Mouse;
-    with 'TestRole';
+
+    ::stderr_is {
+        with 'TestRole';
+    } '';
 
     sub BUILD { push @CALLS, 'ClassWithBUILD::BUILD' }
 };
 
 do {
-    package ClassWithoutBUILD;
+    package ExplicitClassWithBUILD;
     use Mouse;
-    with 'TestRole';
-};
-
-is_deeply([splice @CALLS], [], "no calls to BUILD yet");
 
-ClassWithBUILD->new;
+    ::stderr_is {
+        with 'TestRole' => { excludes => 'BUILD' };
+    } '';
 
-is_deeply([splice @CALLS], [
-    'TestRole::BUILD:before',
-    'ClassWithBUILD::BUILD',
-    'TestRole::BUILD:after',
-]);
-
-ClassWithoutBUILD->new;
+    sub BUILD { push @CALLS, 'ExplicitClassWithBUILD::BUILD' }
+};
 
-is_deeply([splice @CALLS], [
-    'TestRole::BUILD:before',
-    'TestRole::BUILD',
-    'TestRole::BUILD:after',
-]);
+do {
+    package ClassWithoutBUILD;
+    use Mouse;
+    with 'TestRole';
+};
 
-ClassWithBUILD->meta->make_immutable;
-ClassWithoutBUILD->meta->make_immutable;
+{
+    is_deeply([splice @CALLS], [], "no calls to BUILD yet");
 
-is_deeply([splice @CALLS], [], "no calls to BUILD yet");
+    ClassWithBUILD->new;
 
-ClassWithBUILD->new;
+    is_deeply([splice @CALLS], [
+        'TestRole::BUILD:before',
+        'ClassWithBUILD::BUILD',
+        'TestRole::BUILD:after',
+    ]);
 
-is_deeply([splice @CALLS], [
-    'TestRole::BUILD:before',
-    'ClassWithBUILD::BUILD',
-    'TestRole::BUILD:after',
-]);
+    ClassWithoutBUILD->new;
 
-ClassWithoutBUILD->new;
+    is_deeply([splice @CALLS], [
+        'TestRole::BUILD:before',
+        'TestRole::BUILD',
+        'TestRole::BUILD:after',
+    ]);
 
-is_deeply([splice @CALLS], [
-    'TestRole::BUILD:before',
-    'TestRole::BUILD',
-    'TestRole::BUILD:after',
-]);
+    if (ClassWithBUILD->meta->is_mutable) {
+        ClassWithBUILD->meta->make_immutable;
+        ClassWithoutBUILD->meta->make_immutable;
+        redo;
+    }
+}
 
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/t/030_roles/041_empty_method_modifiers_meta_bug.t b/t/030_roles/041_empty_method_modifiers_meta_bug.t
new file mode 100755 (executable)
index 0000000..c6c5faa
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 6;
+
+# test role and class
+package SomeRole;
+use Mouse::Role;
+
+requires 'foo';
+
+package SomeClass;
+use Mouse;
+has 'foo' => (is => 'rw');
+with 'SomeRole';
+
+package main;
+
+#my $c = SomeClass->new;
+#isa_ok( $c, 'SomeClass');
+
+for my $modifier_type (qw[ before around after ]) {
+    my $get_func = "get_${modifier_type}_method_modifiers";
+    my @mms = eval{ SomeRole->meta->$get_func('foo') };
+    is($@, '', "$get_func for no method mods does not die");
+    is(scalar(@mms),0,'is an empty list');
+}
diff --git a/t/030_roles/042_compose_overloading.t b/t/030_roles/042_compose_overloading.t
new file mode 100755 (executable)
index 0000000..b79fbde
--- /dev/null
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+use Test::More tests => 1;
+
+{
+    package Foo;
+    use Mouse::Role;
+
+    use overload
+        q{""}    => sub { 42 },
+        fallback => 1;
+
+    no Mouse::Role;
+}
+
+{
+    package Bar;
+    use Mouse;
+    with 'Foo';
+    no Mouse;
+}
+
+my $bar = Bar->new;
+
+TODO: {
+    local $TODO = "the special () method isn't properly composed into the class";
+    is("$bar", 42, 'overloading can be composed');
+}
index 5b69ee2..e60a768 100644 (file)
@@ -13,10 +13,10 @@ from the Fortress spec.
 
 http://research.sun.com/projects/plrg/fortress0903.pdf
 
-trait OrganicMolecule extends Molecule 
-    excludes { InorganicMolecule } 
-end 
-trait InorganicMolecule extends Molecule end 
+trait OrganicMolecule extends Molecule
+    excludes { InorganicMolecule }
+end
+trait InorganicMolecule extends Molecule end
 
 =cut
 
@@ -26,25 +26,25 @@ trait InorganicMolecule extends Molecule end
 
     package Molecule::Organic;
     use Mouse::Role;
-    
+
     with 'Molecule';
     excludes 'Molecule::Inorganic';
-    
+
     package Molecule::Inorganic;
-    use Mouse::Role;     
-    
-    with 'Molecule';       
+    use Mouse::Role;
+
+    with 'Molecule';
 }
 
 ok(Molecule::Organic->meta->excludes_role('Molecule::Inorganic'), '... Molecule::Organic exludes Molecule::Inorganic');
 is_deeply(
-   [ Molecule::Organic->meta->get_excluded_roles_list() ], 
+   [ Molecule::Organic->meta->get_excluded_roles_list() ],
    [ 'Molecule::Inorganic' ],
    '... Molecule::Organic exludes Molecule::Inorganic');
 
 =pod
 
-Check some basic conflicts when combining  
+Check some basic conflicts when combining
 the roles into the same class
 
 =cut
@@ -52,30 +52,30 @@ the roles into the same class
 {
     package My::Test1;
     use Mouse;
-    
+
     ::lives_ok {
         with 'Molecule::Organic';
     } '... adding the role (w/ excluded roles) okay';
 
     package My::Test2;
     use Mouse;
-    
+
     ::throws_ok {
         with 'Molecule::Organic', 'Molecule::Inorganic';
-    } qr/Conflict detected: Role Molecule::Organic excludes role 'Molecule::Inorganic'/, 
-    '... adding the role w/ excluded role conflict dies okay';    
-    
+    } qr/Conflict detected: Role Molecule::Organic excludes role 'Molecule::Inorganic'/,
+    '... adding the role w/ excluded role conflict dies okay';
+
     package My::Test3;
     use Mouse;
-    
+
     ::lives_ok {
         with 'Molecule::Organic';
-    } '... adding the role (w/ excluded roles) okay';   
-    
+    } '... adding the role (w/ excluded roles) okay';
+
     ::throws_ok {
         with 'Molecule::Inorganic';
-    } qr/Conflict detected: My::Test3 excludes role 'Molecule::Inorganic'/, 
-    '... adding the role w/ excluded role conflict dies okay'; 
+    } qr/Conflict detected: My::Test3 excludes role 'Molecule::Inorganic'/,
+    '... adding the role w/ excluded role conflict dies okay';
 }
 
 ok(My::Test1->does('Molecule::Organic'), '... My::Test1 does Molecule::Organic');
@@ -92,7 +92,7 @@ ok(!My::Test3->does('Molecule::Inorganic'), '... ! My::Test3 does Molecule::Inor
 
 =pod
 
-Check some basic conflicts when combining  
+Check some basic conflicts when combining
 the roles into the a superclass
 
 =cut
@@ -100,16 +100,16 @@ the roles into the a superclass
 {
     package Methane;
     use Mouse;
-    
+
     with 'Molecule::Organic';
-    
+
     package My::Test4;
     use Mouse;
-    
-    extends 'Methane';    
-    
+
+    extends 'Methane';
+
     ::throws_ok {
-        with 'Molecule::Inorganic';    
+        with 'Molecule::Inorganic';
     } qr/Conflict detected: My::Test4 excludes role \'Molecule::Inorganic\'/,
     '... cannot add exculded role into class which extends Methane';
 }
index f6efa6e..5e45d89 100644 (file)
@@ -9,15 +9,15 @@ use Test::Exception;
 =pod
 
 NOTE:
-A fair amount of these tests will likely be irrelevant 
+A fair amount of these tests will likely be irrelevant
 once we have more fine grained control over the class
 building process. A lot of the edge cases tested here
-are actually related to class construction order and 
+are actually related to class construction order and
 not any real functionality.
 - SL
 
-Role which requires a method implemented 
-in another role as an override (it does 
+Role which requires a method implemented
+in another role as an override (it does
 not remove the requirement)
 
 =cut
@@ -27,31 +27,31 @@ not remove the requirement)
     use strict;
     use warnings;
     use Mouse::Role;
-    
+
     requires 'foo';
-    
+
     package Role::ProvideFoo;
     use strict;
     use warnings;
     use Mouse::Role;
-    
+
     ::lives_ok {
         with 'Role::RequireFoo';
     } '... the required "foo" method will not exist yet (but we will live)';
-    
-    override 'foo' => sub { 'Role::ProvideFoo::foo' };    
+
+    override 'foo' => sub { 'Role::ProvideFoo::foo' };
 }
 
 is_deeply(
-    [ Role::ProvideFoo->meta->get_required_method_list ], 
-    [ 'foo' ], 
+    [ Role::ProvideFoo->meta->get_required_method_list ],
+    [ 'foo' ],
     '... foo method is still required for Role::ProvideFoo');
 
 =pod
 
-Role which requires a method implemented 
-in the consuming class as an override. 
-It will fail since method modifiers are 
+Role which requires a method implemented
+in the consuming class as an override.
+It will fail since method modifiers are
 second class citizens.
 
 =cut
@@ -61,25 +61,25 @@ second class citizens.
     use Mouse;
 
     sub foo { 'Class::ProvideFoo::Base::foo' }
-        
+
     package Class::ProvideFoo::Override1;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
+
     ::lives_ok {
         with 'Role::RequireFoo';
     } '... the required "foo" method will be found in the superclass';
-    
-    override 'foo' => sub { 'Class::ProvideFoo::foo' };    
-    
+
+    override 'foo' => sub { 'Class::ProvideFoo::foo' };
+
     package Class::ProvideFoo::Override2;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
-    override 'foo' => sub { 'Class::ProvideFoo::foo' };     
-    
+
+    override 'foo' => sub { 'Class::ProvideFoo::foo' };
+
     ::lives_ok {
         with 'Role::RequireFoo';
     } '... the required "foo" method exists, although it is overriden locally';
@@ -88,7 +88,7 @@ second class citizens.
 
 =pod
 
-Now same thing, but with a before 
+Now same thing, but with a before
 method modifier.
 
 =cut
@@ -96,55 +96,55 @@ method modifier.
 {
     package Class::ProvideFoo::Before1;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
+
     ::lives_ok {
         with 'Role::RequireFoo';
     } '... the required "foo" method will be found in the superclass';
-    
-    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };    
-    
+
+    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
+
     package Class::ProvideFoo::Before2;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
-    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };     
-    
+
+    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
+
     ::lives_ok {
         with 'Role::RequireFoo';
-    } '... the required "foo" method exists, although it is a before modifier locally';    
-    
+    } '... the required "foo" method exists, although it is a before modifier locally';
+
     package Class::ProvideFoo::Before3;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
+
     sub foo { 'Class::ProvideFoo::foo' }
-    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };    
-    
+    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
+
     ::lives_ok {
         with 'Role::RequireFoo';
-    } '... the required "foo" method exists locally, and it is modified locally';    
-    
+    } '... the required "foo" method exists locally, and it is modified locally';
+
     package Class::ProvideFoo::Before4;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
-    sub foo { 'Class::ProvideFoo::foo' }    
-    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };     
+
+    sub foo { 'Class::ProvideFoo::foo' }
+    before 'foo' => sub { 'Class::ProvideFoo::foo:before' };
 
     ::isa_ok(__PACKAGE__->meta->get_method('foo'), 'Class::MOP::Method::Wrapped');
-    ::is(__PACKAGE__->meta->get_method('foo')->get_original_method->package_name, __PACKAGE__, 
+    ::is(__PACKAGE__->meta->get_method('foo')->get_original_method->package_name, __PACKAGE__,
     '... but the original method is from our package');
-    
+
     ::lives_ok {
         with 'Role::RequireFoo';
-    } '... the required "foo" method exists in the symbol table (and we will live)'; 
-           
-}    
+    } '... the required "foo" method exists in the symbol table (and we will live)';
+
+}
 
 =pod
 
@@ -154,63 +154,63 @@ method modifier.
 =cut
 
 {
-    
+
     package Class::ProvideFoo::Attr1;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
+
     ::lives_ok {
         with 'Role::RequireFoo';
     } '... the required "foo" method will be found in the superclass (but then overriden)';
-    
+
     has 'foo' => (is => 'ro');
-    
+
     package Class::ProvideFoo::Attr2;
     use Mouse;
-    
+
     extends 'Class::ProvideFoo::Base';
-    
-    has 'foo' => (is => 'ro');     
-    
+
+    has 'foo' => (is => 'ro');
+
     ::lives_ok {
         with 'Role::RequireFoo';
     } '... the required "foo" method exists, and is an accessor';
-}    
+}
 
 # ...
-# a method required in a role, but then 
-# implemented in the superclass (as an 
+# a method required in a role, but then
+# implemented in the superclass (as an
 # attribute accessor too)
-    
+
 {
     package Foo::Class::Base;
     use Mouse;
-    
-    has 'bar' =>  ( 
-        isa     => 'Int', 
-        is      => 'rw', 
+
+    has 'bar' =>  (
+        isa     => 'Int',
+        is      => 'rw',
         default => sub { 1 }
     );
 }
 {
     package Foo::Role;
     use Mouse::Role;
-    
+
     requires 'bar';
-    
-    has 'foo' => ( 
-        isa     => 'Int', 
-        is      => 'rw', 
-        lazy    => 1, 
-        default => sub { (shift)->bar + 1 } 
+
+    has 'foo' => (
+        isa     => 'Int',
+        is      => 'rw',
+        lazy    => 1,
+        default => sub { (shift)->bar + 1 }
     );
 }
 {
     package Foo::Class::Child;
     use Mouse;
     extends 'Foo::Class::Base';
-    
+
     ::lives_ok {
         with 'Foo::Role';
     } '... our role combined successfully';
index 57824f4..ad1b908 100644 (file)
@@ -8,8 +8,8 @@ use Test::Exception;
 
 =pod
 
-Check for repeated inheritance causing 
-a method conflict (which is not really 
+Check for repeated inheritance causing
+a method conflict (which is not really
 a conflict)
 
 =cut
@@ -17,24 +17,24 @@ a conflict)
 {
     package Role::Base;
     use Mouse::Role;
-    
+
     sub foo { 'Role::Base::foo' }
-    
+
     package Role::Derived1;
-    use Mouse::Role;  
-    
+    use Mouse::Role;
+
     with 'Role::Base';
-    
+
     package Role::Derived2;
-    use Mouse::Role; 
+    use Mouse::Role;
 
     with 'Role::Base';
-    
+
     package My::Test::Class1;
-    use Mouse;      
-    
+    use Mouse;
+
     ::lives_ok {
-        with 'Role::Derived1', 'Role::Derived2';   
+        with 'Role::Derived1', 'Role::Derived2';
     } '... roles composed okay (no conflicts)';
 }
 
@@ -47,8 +47,8 @@ is(My::Test::Class1->foo, 'Role::Base::foo', '... got the right value from metho
 
 =pod
 
-Check for repeated inheritance causing 
-a method conflict with method modifiers 
+Check for repeated inheritance causing
+a method conflict with method modifiers
 (which is not really a conflict)
 
 =cut
@@ -56,31 +56,31 @@ a method conflict with method modifiers
 {
     package Role::Base2;
     use Mouse::Role;
-    
+
     override 'foo' => sub { super() . ' -> Role::Base::foo' };
-    
+
     package Role::Derived3;
-    use Mouse::Role;  
-    
+    use Mouse::Role;
+
     with 'Role::Base2';
-    
+
     package Role::Derived4;
-    use Mouse::Role; 
+    use Mouse::Role;
 
     with 'Role::Base2';
 
     package My::Test::Class2::Base;
     use Mouse;
-    
+
     sub foo { 'My::Test::Class2::Base' }
-    
+
     package My::Test::Class2;
-    use Mouse;  
-    
-    extends 'My::Test::Class2::Base';    
-    
+    use Mouse;
+
+    extends 'My::Test::Class2::Base';
+
     ::lives_ok {
-        with 'Role::Derived3', 'Role::Derived4';   
+        with 'Role::Derived3', 'Role::Derived4';
     } '... roles composed okay (no conflicts)';
 }
 
@@ -97,11 +97,11 @@ is(My::Test::Class2->foo, 'My::Test::Class2::Base -> Role::Base::foo', '... got
 
 =pod
 
-Check for repeated inheritance of the 
-same code. There are no conflicts with 
+Check for repeated inheritance of the
+same code. There are no conflicts with
 before/around/after method modifiers.
 
-This tests around, but should work the 
+This tests around, but should work the
 same for before/afters as well
 
 =cut
@@ -109,31 +109,31 @@ same for before/afters as well
 {
     package Role::Base3;
     use Mouse::Role;
-    
+
     around 'foo' => sub { 'Role::Base::foo(' . (shift)->() . ')' };
-    
+
     package Role::Derived5;
-    use Mouse::Role;  
-    
+    use Mouse::Role;
+
     with 'Role::Base3';
-    
+
     package Role::Derived6;
-    use Mouse::Role; 
+    use Mouse::Role;
 
     with 'Role::Base3';
 
     package My::Test::Class3::Base;
     use Mouse;
-    
+
     sub foo { 'My::Test::Class3::Base' }
-    
+
     package My::Test::Class3;
-    use Mouse;  
-    
-    extends 'My::Test::Class3::Base';    
-    
+    use Mouse;
+
+    extends 'My::Test::Class3::Base';
+
     ::lives_ok {
-        with 'Role::Derived5', 'Role::Derived6';   
+        with 'Role::Derived5', 'Role::Derived6';
     } '... roles composed okay (no conflicts)';
 }
 
@@ -150,8 +150,8 @@ is(My::Test::Class3->foo, 'Role::Base::foo(My::Test::Class3::Base)', '... got th
 
 =pod
 
-Check for repeated inheritance causing 
-a attr conflict (which is not really 
+Check for repeated inheritance causing
+a attr conflict (which is not really
 a conflict)
 
 =cut
@@ -159,24 +159,24 @@ a conflict)
 {
     package Role::Base4;
     use Mouse::Role;
-    
+
     has 'foo' => (is => 'ro', default => 'Role::Base::foo');
-    
+
     package Role::Derived7;
-    use Mouse::Role;  
-    
+    use Mouse::Role;
+
     with 'Role::Base4';
-    
+
     package Role::Derived8;
-    use Mouse::Role; 
+    use Mouse::Role;
 
     with 'Role::Base4';
-    
+
     package My::Test::Class4;
-    use Mouse;      
-    
+    use Mouse;
+
     ::lives_ok {
-        with 'Role::Derived7', 'Role::Derived8';   
+        with 'Role::Derived7', 'Role::Derived8';
     } '... roles composed okay (no conflicts)';
 }
 
index df873d3..6731d06 100644 (file)
@@ -12,7 +12,7 @@ use Scalar::Util qw(blessed);
 =pod
 
 This test can be used as a basis for the runtime role composition.
-Apparently it is not as simple as just making an anon class. One of 
+Apparently it is not as simple as just making an anon class. One of
 the problems is the way that anon classes are DESTROY-ed, which is
 not very compatible with how instances are dealt with.
 
@@ -37,35 +37,35 @@ not very compatible with how instances are dealt with.
 }
 
 my $obj = My::Class->new;
-isa_ok($obj, 'My::Class');    
-    
+isa_ok($obj, 'My::Class');
+
 my $obj2 = My::Class->new;
-isa_ok($obj2, 'My::Class');    
+isa_ok($obj2, 'My::Class');
 
 {
     ok(!$obj->can( 'talk' ), "... the role is not composed yet");
-    
+
     ok(!$obj->does('Bark'), '... we do not do any roles yet');
-    
+
     Bark->meta->apply($obj);
 
     ok($obj->does('Bark'), '... we now do the Bark role');
-    ok(!My::Class->does('Bark'), '... the class does not do the Bark role');    
+    ok(!My::Class->does('Bark'), '... the class does not do the Bark role');
 
     isa_ok($obj, 'My::Class');
     isnt(blessed($obj), 'My::Class', '... but it is no longer blessed into My::Class');
 
     ok(!My::Class->can('talk'), "... the role is not composed at the class level");
     ok($obj->can('talk'), "... the role is now composed at the object level");
-    
+
     is($obj->talk, 'woof', '... got the right return value for the newly composed method');
 }
 
 {
     ok(!$obj2->does('Bark'), '... we do not do any roles yet');
-    
+
     Bark->meta->apply($obj2);
-    
+
     ok($obj2->does('Bark'), '... we now do the Bark role');
     is(blessed($obj), blessed($obj2), '... they share the same anon-class/role thing');
 }
@@ -78,25 +78,25 @@ isa_ok($obj2, 'My::Class');
     Sleeper->meta->apply($obj);
 
     ok($obj->does('Bark'), '... we still do the Bark role');
-    ok($obj->does('Sleeper'), '... we now do the Sleeper role too');   
-    
-    ok(!My::Class->does('Sleeper'), '... the class does not do the Sleeper role');     
-    
-    isnt(blessed($obj), blessed($obj2), '... they no longer share the same anon-class/role thing');        
-    
+    ok($obj->does('Sleeper'), '... we now do the Sleeper role too');
+
+    ok(!My::Class->does('Sleeper'), '... the class does not do the Sleeper role');
+
+    isnt(blessed($obj), blessed($obj2), '... they no longer share the same anon-class/role thing');
+
     isa_ok($obj, 'My::Class');
 
     is(My::Class->sleep, 'nite-nite', '... the original method still responds as expected');
 
     is($obj->sleep, 'snore', '... got the right return value for the newly composed method');
-    is($obj->talk, 'zzz', '... got the right return value for the newly composed method');    
+    is($obj->talk, 'zzz', '... got the right return value for the newly composed method');
 }
 
 {
     ok(!$obj2->does('Sleeper'), '... we do not do any roles yet');
-    
+
     Sleeper->meta->apply($obj2);
-    
+
     ok($obj2->does('Sleeper'), '... we now do the Bark role');
     is(blessed($obj), blessed($obj2), '... they share the same anon-class/role thing again');
 }
index 1ea0858..d852b17 100644 (file)
@@ -19,7 +19,7 @@ use Test::Exception;
     package My::Class;
     use Mouse;
 
-    with 'My::Role' => { excludes => 'bar' };
+    with 'My::Role' => { -excludes => 'bar' };
 }
 
 ok(My::Class->meta->has_method($_), "we have a $_ method") for qw(foo baz);
@@ -29,7 +29,7 @@ ok(!My::Class->meta->has_method('bar'), '... but we excluded bar');
     package My::OtherRole;
     use Mouse::Role;
 
-    with 'My::Role' => { excludes => 'foo' };
+    with 'My::Role' => { -excludes => 'foo' };
 
     sub foo { 'My::OtherRole::foo' }
     sub bar { 'My::OtherRole::bar' }
@@ -60,8 +60,8 @@ ok(My::OtherRole->meta->requires_method('bar'), '... and the &bar method is requ
     use Mouse;
 
     ::lives_ok {
-        with 'Foo::Role' => { excludes => 'foo' },
-             'Bar::Role' => { excludes => 'foo' },
+        with 'Foo::Role' => { -excludes => 'foo' },
+             'Bar::Role' => { -excludes => 'foo' },
              'Baz::Role';
     } '... composed our roles correctly';
 
@@ -70,7 +70,7 @@ ok(My::OtherRole->meta->requires_method('bar'), '... and the &bar method is requ
 
     ::throws_ok {
         with 'Foo::Role',
-             'Bar::Role' => { excludes => 'foo' },
+             'Bar::Role' => { -excludes => 'foo' },
              'Baz::Role';
     } qr/Due to a method name conflict in roles 'Baz::Role' and 'Foo::Role', the method 'foo' must be implemented or excluded by 'My::Foo::Class::Broken'/,
       '... composed our roles correctly';
@@ -88,8 +88,8 @@ ok(My::OtherRole->meta->requires_method('bar'), '... and the &bar method is requ
     use Mouse::Role;
 
     ::lives_ok {
-        with 'Foo::Role' => { excludes => 'foo' },
-             'Bar::Role' => { excludes => 'foo' },
+        with 'Foo::Role' => { -excludes => 'foo' },
+             'Bar::Role' => { -excludes => 'foo' },
              'Baz::Role';
     } '... composed our roles correctly';
 }
@@ -103,7 +103,7 @@ ok(!My::Foo::Role->meta->requires_method('foo'), '... and the &foo method is not
 
     ::lives_ok {
         with 'Foo::Role',
-             'Bar::Role' => { excludes => 'foo' },
+             'Bar::Role' => { -excludes => 'foo' },
              'Baz::Role';
     } '... composed our roles correctly';
 }
index bbe7d7d..c4e5962 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 35;
+use Test::More tests => 46;
 use Test::Exception;
 
 
@@ -22,14 +22,14 @@ use Test::Exception;
     use Mouse;
 
     ::lives_ok {
-        with 'My::Role' => { alias => { bar => 'role_bar' } };
+        with 'My::Role' => { -alias => { bar => 'role_bar' } };
     } '... this succeeds';
 
     package My::Class::Failure;
     use Mouse;
 
     ::throws_ok {
-        with 'My::Role' => { alias => { bar => 'role_bar' } };
+        with 'My::Role' => { -alias => { bar => 'role_bar' } };
     } qr/Cannot create a method alias if a local method of the same name exists/, '... this succeeds';
 
     sub role_bar { 'FAIL' }
@@ -42,7 +42,7 @@ ok(My::Class->meta->has_method($_), "we have a $_ method") for qw(foo baz bar ro
     use Mouse::Role;
 
     ::lives_ok {
-        with 'My::Role' => { alias => { bar => 'role_bar' } };
+        with 'My::Role' => { -alias => { bar => 'role_bar' } };
     } '... this succeeds';
 
     sub bar { 'My::OtherRole::bar' }
@@ -51,14 +51,14 @@ ok(My::Class->meta->has_method($_), "we have a $_ method") for qw(foo baz bar ro
     use Mouse::Role;
 
     ::throws_ok {
-        with 'My::Role' => { alias => { bar => 'role_bar' } };
-    } qr/Cannot create a method alias if a local method of the same name exists/, '... this succeeds';
+        with 'My::Role' => { -alias => { bar => 'role_bar' } };
+    } qr/Cannot create a method alias if a local method of the same name exists/, '... cannot alias to a name that exists';
 
     sub role_bar { 'FAIL' }
 }
 
 ok(My::OtherRole->meta->has_method($_), "we have a $_ method") for qw(foo baz role_bar);
-ok(!My::OtherRole->meta->requires_method('bar'), '... and the &bar method is not required');
+ok(My::OtherRole->meta->requires_method('bar'), '... and the &bar method is required');
 ok(!My::OtherRole->meta->requires_method('role_bar'), '... and the &role_bar method is not required');
 
 {
@@ -66,12 +66,12 @@ ok(!My::OtherRole->meta->requires_method('role_bar'), '... and the &role_bar met
     use Mouse::Role;
 
     ::lives_ok {
-        with 'My::Role' => { alias => { bar => 'role_bar' } };
+        with 'My::Role' => { -alias => { bar => 'role_bar' } };
     } '... this succeeds';
 }
 
 ok(My::AliasingRole->meta->has_method($_), "we have a $_ method") for qw(foo baz role_bar);
-ok(My::AliasingRole->meta->requires_method('bar'), '... and the &bar method is required');
+ok(!My::AliasingRole->meta->requires_method('bar'), '... and the &bar method is not required');
 
 {
     package Foo::Role;
@@ -93,8 +93,8 @@ ok(My::AliasingRole->meta->requires_method('bar'), '... and the &bar method is r
     use Mouse;
 
     ::lives_ok {
-        with 'Foo::Role' => { alias => { 'foo' => 'foo_foo' }, excludes => 'foo' },
-             'Bar::Role' => { alias => { 'foo' => 'bar_foo' }, excludes => 'foo' },
+        with 'Foo::Role' => { -alias => { 'foo' => 'foo_foo' }, -excludes => 'foo' },
+             'Bar::Role' => { -alias => { 'foo' => 'bar_foo' }, -excludes => 'foo' },
              'Baz::Role';
     } '... composed our roles correctly';
 
@@ -102,8 +102,8 @@ ok(My::AliasingRole->meta->requires_method('bar'), '... and the &bar method is r
     use Mouse;
 
     ::throws_ok {
-        with 'Foo::Role' => { alias => { 'foo' => 'foo_foo' }, excludes => 'foo' },
-             'Bar::Role' => { alias => { 'foo' => 'foo_foo' }, excludes => 'foo' },
+        with 'Foo::Role' => { -alias => { 'foo' => 'foo_foo' }, -excludes => 'foo' },
+             'Bar::Role' => { -alias => { 'foo' => 'foo_foo' }, -excludes => 'foo' },
              'Baz::Role';
     } qr/Due to a method name conflict in roles 'Bar::Role' and 'Foo::Role', the method 'foo_foo' must be implemented or excluded by 'My::Foo::Class::Broken'/,
       '... composed our roles correctly';
@@ -123,8 +123,8 @@ ok(My::AliasingRole->meta->requires_method('bar'), '... and the &bar method is r
     use Mouse::Role;
 
     ::lives_ok {
-        with 'Foo::Role' => { alias => { 'foo' => 'foo_foo' }, excludes => 'foo' },
-             'Bar::Role' => { alias => { 'foo' => 'bar_foo' }, excludes => 'foo' },
+        with 'Foo::Role' => { -alias => { 'foo' => 'foo_foo' }, -excludes => 'foo' },
+             'Bar::Role' => { -alias => { 'foo' => 'bar_foo' }, -excludes => 'foo' },
              'Baz::Role';
     } '... composed our roles correctly';
 }
@@ -138,8 +138,8 @@ ok(!My::Foo::Role->meta->requires_method('foo'), '... and the &foo method is not
     use Mouse::Role;
 
     ::lives_ok {
-        with 'Foo::Role' => { alias => { 'foo' => 'foo_foo' }, excludes => 'foo' },
-             'Bar::Role' => { alias => { 'foo' => 'foo_foo' }, excludes => 'foo' },
+        with 'Foo::Role' => { -alias => { 'foo' => 'foo_foo' }, -excludes => 'foo' },
+             'Bar::Role' => { -alias => { 'foo' => 'foo_foo' }, -excludes => 'foo' },
              'Baz::Role';
     } '... composed our roles correctly';
 }
@@ -147,3 +147,68 @@ ok(!My::Foo::Role->meta->requires_method('foo'), '... and the &foo method is not
 ok(!My::Foo::Role::Other->meta->has_method('foo_foo'), "we dont have a foo_foo method");
 ok(My::Foo::Role::Other->meta->requires_method('foo_foo'), '... and the &foo method is required');
 
+{
+    package My::Foo::AliasOnly;
+    use Mouse;
+
+    ::lives_ok {
+        with 'Foo::Role' => { -alias => { 'foo' => 'foo_foo' } },
+    } '... composed our roles correctly';
+}
+
+ok(My::Foo::AliasOnly->meta->has_method('foo'), 'we have a foo method');
+ok(My::Foo::AliasOnly->meta->has_method('foo_foo'), '.. and the aliased foo_foo method');
+
+{
+    package Role::Foo;
+    use Mouse::Role;
+
+    sub x1 {}
+    sub y1 {}
+}
+
+{
+    package Role::Bar;
+    use Mouse::Role;
+
+    use Test::Exception;
+
+    lives_ok {
+        with 'Role::Foo' => {
+            -alias    => { x1 => 'foo_x1' },
+            -excludes => ['y1'],
+        };
+    }
+    'Compose Role::Foo into Role::Bar with alias and exclude';
+
+    sub x1 {}
+    sub y1 {}
+}
+
+{
+    my $bar = Role::Bar->meta;
+    ok( $bar->has_method($_), "has $_ method" )
+        for qw( x1 y1 foo_x1 );
+}
+
+{
+    package Role::Baz;
+    use Mouse::Role;
+
+    use Test::Exception;
+
+    lives_ok {
+        with 'Role::Foo' => {
+            -alias    => { x1 => 'foo_x1' },
+            -excludes => ['y1'],
+        };
+    }
+    'Compose Role::Foo into Role::Baz with alias and exclude';
+}
+
+{
+    my $baz = Role::Baz->meta;
+    ok( $baz->has_method($_), "has $_ method" )
+        for qw( x1 foo_x1 );
+    ok( ! $baz->has_method('y1'), 'Role::Baz has no y1 method' );
+}
index b9c9189..e1d271d 100644 (file)
@@ -11,46 +11,46 @@ use Test::Exception;
 {
     package Foo;
     use Mouse::Role;
-    
+
     sub foo   { 'Foo::foo'   }
     sub bar   { 'Foo::bar'   }
     sub baz   { 'Foo::baz'   }
-    sub gorch { 'Foo::gorch' }            
-    
+    sub gorch { 'Foo::gorch' }
+
     package Bar;
     use Mouse::Role;
 
     sub foo   { 'Bar::foo'   }
     sub bar   { 'Bar::bar'   }
     sub baz   { 'Bar::baz'   }
-    sub gorch { 'Bar::gorch' }    
+    sub gorch { 'Bar::gorch' }
 
     package Baz;
     use Mouse::Role;
-    
+
     sub foo   { 'Baz::foo'   }
     sub bar   { 'Baz::bar'   }
     sub baz   { 'Baz::baz'   }
-    sub gorch { 'Baz::gorch' }            
-    
+    sub gorch { 'Baz::gorch' }
+
     package Gorch;
     use Mouse::Role;
-    
+
     sub foo   { 'Gorch::foo'   }
     sub bar   { 'Gorch::bar'   }
     sub baz   { 'Gorch::baz'   }
-    sub gorch { 'Gorch::gorch' }        
+    sub gorch { 'Gorch::gorch' }
 }
 
 {
     package My::Class;
     use Mouse;
-    
+
     ::lives_ok {
-        with 'Foo'   => { excludes => [qw/bar baz gorch/], alias => { gorch => 'foo_gorch' } },
-             'Bar'   => { excludes => [qw/foo baz gorch/] },
-             'Baz'   => { excludes => [qw/foo bar gorch/], alias => { foo => 'baz_foo', bar => 'baz_bar' } },
-             'Gorch' => { excludes => [qw/foo bar baz/] };
+        with 'Foo'   => { -excludes => [qw/bar baz gorch/], -alias => { gorch => 'foo_gorch' } },
+             'Bar'   => { -excludes => [qw/foo baz gorch/] },
+             'Baz'   => { -excludes => [qw/foo bar gorch/], -alias => { foo => 'baz_foo', bar => 'baz_bar' } },
+             'Gorch' => { -excludes => [qw/foo bar baz/] };
     } '... everything works out all right';
 }
 
index 8d6bfc2..d1c0e4d 100644 (file)
@@ -32,7 +32,7 @@ use Scalar::Util 'blessed';
 }
 
 my $obj = Foo->new;
-isa_ok($obj, 'Foo');    
+isa_ok($obj, 'Foo');
 
 ok(!$obj->can( 'talk' ), "... the role is not composed yet");
 ok(!$obj->can( 'fur' ), 'ditto');
index 6a39f77..1f6ec9b 100644 (file)
@@ -34,10 +34,10 @@ use Scalar::Util 'blessed';
 }
 
 my $bar = Bar->new;
-isa_ok($bar, 'Bar');    
+isa_ok($bar, 'Bar');
 
 my $foo = Foo->new;
-isa_ok($foo, 'Foo');  
+isa_ok($foo, 'Foo');
 
 ok(!$bar->can( 'talk' ), "... the role is not composed yet");
 
index de47ece..80d14fd 100644 (file)
@@ -10,7 +10,7 @@ use Test::Exception;
 
 =pod
 
-This basically just makes sure that using +name 
+This basically just makes sure that using +name
 on role attributes works right.
 
 =cut
@@ -18,21 +18,21 @@ on role attributes works right.
 {
     package Foo::Role;
     use Mouse::Role;
-    
+
     has 'bar' => (
         is      => 'rw',
-        isa     => 'Int',   
+        isa     => 'Int',
         default => sub { 10 },
     );
-    
+
     package Foo;
     use Mouse;
-    
+
     with 'Foo::Role';
-    
+
     ::lives_ok {
         has '+bar' => (default => sub { 100 });
-    } '... extended the attribute successfully';  
+    } '... extended the attribute successfully';
 }
 
 my $foo = Foo->new;
@@ -151,6 +151,7 @@ is_deeply($quux->quux, ["hi"], "... still has the old ArrayRef value");
     for (1..3) {
         has "err$_" => (
             isa => 'Str | Int',
+            is => 'bare',
         );
     }
 
index 16d97f7..3bce166 100644 (file)
@@ -12,11 +12,11 @@ use Test::Exception;
     package Foo;
     use Mouse;
     has 'bar' => (is => 'ro');
-    
+
     package Bar;
     use Mouse::Role;
-    
-    has 'baz' => (is => 'ro', default => 'BAZ');    
+
+    has 'baz' => (is => 'ro', default => 'BAZ');
 }
 
 # normal ...
index 788b352..49ba0a3 100644 (file)
@@ -12,15 +12,15 @@ use Mouse::Meta::Role::Composite;
 {
     package Role::Foo;
     use Mouse::Role;
-    
+
     package Role::Bar;
     use Mouse::Role;
 
     package Role::Baz;
-    use Mouse::Role;      
-    
+    use Mouse::Role;
+
     package Role::Gorch;
-    use Mouse::Role;       
+    use Mouse::Role;
 }
 
 {
@@ -28,7 +28,7 @@ use Mouse::Meta::Role::Composite;
         roles => [
             Role::Foo->meta,
             Role::Bar->meta,
-            Role::Baz->meta,            
+            Role::Baz->meta,
         ]
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
@@ -38,22 +38,22 @@ use Mouse::Meta::Role::Composite;
     is_deeply($c->get_roles, [
         Role::Foo->meta,
         Role::Bar->meta,
-        Role::Baz->meta,        
+        Role::Baz->meta,
     ], '... got the right roles');
-    
+
     ok($c->does_role($_), '... our composite does the role ' . $_)
         for qw(
             Role::Foo
             Role::Bar
-            Role::Baz            
+            Role::Baz
         );
-    
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this composed okay';   
-    
+    } '... this composed okay';
+
     ##... now nest 'em
-    { 
+    {
         my $c2 = Mouse::Meta::Role::Composite->new(
             roles => [
                 $c,
@@ -66,15 +66,15 @@ use Mouse::Meta::Role::Composite;
 
         is_deeply($c2->get_roles, [
             $c,
-            Role::Gorch->meta,  
+            Role::Gorch->meta,
         ], '... got the right roles');
 
         ok($c2->does_role($_), '... our composite does the role ' . $_)
             for qw(
                 Role::Foo
                 Role::Bar
-                Role::Baz     
-                Role::Gorch                        
-            );     
+                Role::Baz
+                Role::Gorch
+            );
     }
 }
index 4d0a8d3..ba4d3bc 100644 (file)
@@ -12,21 +12,21 @@ use Mouse::Meta::Role::Composite;
 {
     package Role::Foo;
     use Mouse::Role;
-    
+
     package Role::Bar;
     use Mouse::Role;
-    
+
     package Role::ExcludesFoo;
     use Mouse::Role;
     excludes 'Role::Foo';
-    
+
     package Role::DoesExcludesFoo;
     use Mouse::Role;
-    with 'Role::ExcludesFoo';  
-    
+    with 'Role::ExcludesFoo';
+
     package Role::DoesFoo;
     use Mouse::Role;
-    with 'Role::Foo';    
+    with 'Role::Foo';
 }
 
 ok(Role::ExcludesFoo->meta->excludes_role('Role::Foo'), '... got the right exclusions');
@@ -55,10 +55,10 @@ dies_ok {
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
     is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');
-    
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this lives as expected';    
+    } '... this lives as expected';
 }
 
 # test no conflicts w/exclusion
@@ -66,18 +66,18 @@ dies_ok {
     my $c = Mouse::Meta::Role::Composite->new(
         roles => [
             Role::Bar->meta,
-            Role::ExcludesFoo->meta,            
+            Role::ExcludesFoo->meta,
         ]
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
     is($c->name, 'Role::Bar|Role::ExcludesFoo', '... got the composite role name');
-    
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this lives as expected';    
-    
-    is_deeply([$c->get_excluded_roles_list], ['Role::Foo'], '... has excluded roles');    
+    } '... this lives as expected';
+
+    is_deeply([$c->get_excluded_roles_list], ['Role::Foo'], '... has excluded roles');
 }
 
 
@@ -91,15 +91,15 @@ dies_ok {
             ]
         )
     );
-    
+
 } '... this fails as expected';
 
 # test conflict with an "inherited" exclusion of an "inherited" role
 dies_ok {
     Mouse::Meta::Role::Application::RoleSummation->new->apply(
-        Mouse::Meta::Role::Composite->new(        
+        Mouse::Meta::Role::Composite->new(
             roles => [
-                Role::DoesFoo->meta,            
+                Role::DoesFoo->meta,
                 Role::DoesExcludesFoo->meta,
             ]
         )
index c0ff4f9..3843153 100644 (file)
@@ -11,20 +11,20 @@ use Mouse::Meta::Role::Composite;
 
 {
     package Role::Foo;
-    use Mouse::Role;    
+    use Mouse::Role;
     requires 'foo';
-    
+
     package Role::Bar;
     use Mouse::Role;
     requires 'bar';
-    
+
     package Role::ProvidesFoo;
-    use Mouse::Role;    
+    use Mouse::Role;
     sub foo { 'Role::ProvidesFoo::foo' }
-    
+
     package Role::ProvidesBar;
-    use Mouse::Role;    
-    sub bar { 'Role::ProvidesBar::bar' }     
+    use Mouse::Role;
+    sub bar { 'Role::ProvidesBar::bar' }
 }
 
 # test simple requirement
@@ -33,16 +33,16 @@ use Mouse::Meta::Role::Composite;
         roles => [
             Role::Foo->meta,
             Role::Bar->meta,
-        ]        
+        ]
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_required_method_list ],
         [ 'bar', 'foo' ],
@@ -60,12 +60,12 @@ use Mouse::Meta::Role::Composite;
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::ProvidesFoo', '... got the composite role name');    
-    
-    lives_ok { 
+    is($c->name, 'Role::Foo|Role::ProvidesFoo', '... got the composite role name');
+
+    lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_required_method_list ],
         [],
@@ -79,17 +79,17 @@ use Mouse::Meta::Role::Composite;
         roles => [
             Role::Foo->meta,
             Role::ProvidesFoo->meta,
-            Role::Bar->meta,            
+            Role::Bar->meta,
         ]
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::ProvidesFoo|Role::Bar', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::ProvidesFoo|Role::Bar', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_required_method_list ],
         [ 'bar' ],
@@ -103,18 +103,18 @@ use Mouse::Meta::Role::Composite;
         roles => [
             Role::Foo->meta,
             Role::ProvidesFoo->meta,
-            Role::ProvidesBar->meta,            
-            Role::Bar->meta,            
+            Role::ProvidesBar->meta,
+            Role::Bar->meta,
         ]
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::ProvidesFoo|Role::ProvidesBar|Role::Bar', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::ProvidesFoo|Role::ProvidesBar|Role::Bar', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_required_method_list ],
         [ ],
index 69852dc..9785463 100644 (file)
@@ -11,23 +11,23 @@ use Mouse::Meta::Role::Composite;
 
 {
     package Role::Foo;
-    use Mouse::Role;    
+    use Mouse::Role;
     has 'foo' => (is => 'rw');
-    
+
     package Role::Bar;
     use Mouse::Role;
     has 'bar' => (is => 'rw');
-    
+
     package Role::FooConflict;
-    use Mouse::Role;    
+    use Mouse::Role;
     has 'foo' => (is => 'rw');
-    
+
     package Role::BarConflict;
     use Mouse::Role;
     has 'bar' => (is => 'rw');
-    
+
     package Role::AnotherFooConflict;
-    use Mouse::Role;    
+    use Mouse::Role;
     with 'Role::FooConflict';
 }
 
@@ -41,12 +41,12 @@ use Mouse::Meta::Role::Composite;
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_attribute_list ],
         [ 'bar', 'foo' ],
@@ -72,9 +72,9 @@ dies_ok {
         Mouse::Meta::Role::Composite->new(
             roles => [
                 Role::Foo->meta,
-                Role::Bar->meta,            
+                Role::Bar->meta,
                 Role::FooConflict->meta,
-                Role::BarConflict->meta,            
+                Role::BarConflict->meta,
             ]
         )
     );
index 355e56b..2f60d0d 100644 (file)
@@ -12,26 +12,26 @@ use Mouse::Meta::Role::Composite;
 {
     package Role::Foo;
     use Mouse::Role;
-    
-    sub foo { 'Role::Foo::foo' }    
-    
+
+    sub foo { 'Role::Foo::foo' }
+
     package Role::Bar;
     use Mouse::Role;
 
     sub bar { 'Role::Bar::bar' }
-    
+
     package Role::FooConflict;
-    use Mouse::Role;    
-    
-    sub foo { 'Role::FooConflict::foo' }    
-    
+    use Mouse::Role;
+
+    sub foo { 'Role::FooConflict::foo' }
+
     package Role::BarConflict;
     use Mouse::Role;
-    
+
     sub bar { 'Role::BarConflict::bar' }
-    
+
     package Role::AnotherFooConflict;
-    use Mouse::Role;    
+    use Mouse::Role;
     with 'Role::FooConflict';
 
     sub baz { 'Role::AnotherFooConflict::baz' }
@@ -47,12 +47,12 @@ use Mouse::Meta::Role::Composite;
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_method_list ],
         [ 'bar', 'foo' ],
@@ -70,23 +70,23 @@ use Mouse::Meta::Role::Composite;
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::FooConflict', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::FooConflict', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_method_list ],
         [],
         '... got the right list of methods'
-    );    
-    
+    );
+
     is_deeply(
         [ sort $c->get_required_method_list ],
         [ 'foo' ],
         '... got the right list of required methods'
-    );    
+    );
 }
 
 # test complex conflict
@@ -94,14 +94,14 @@ use Mouse::Meta::Role::Composite;
     my $c = Mouse::Meta::Role::Composite->new(
         roles => [
             Role::Foo->meta,
-            Role::Bar->meta,            
+            Role::Bar->meta,
             Role::FooConflict->meta,
-            Role::BarConflict->meta,            
+            Role::BarConflict->meta,
         ]
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::Bar|Role::FooConflict|Role::BarConflict', '... got the composite role name');    
+    is($c->name, 'Role::Foo|Role::Bar|Role::FooConflict|Role::BarConflict', '... got the composite role name');
 
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
@@ -111,13 +111,13 @@ use Mouse::Meta::Role::Composite;
         [ sort $c->get_method_list ],
         [],
         '... got the right list of methods'
-    );    
-    
+    );
+
     is_deeply(
         [ sort $c->get_required_method_list ],
         [ 'bar', 'foo' ],
         '... got the right list of required methods'
-    );    
+    );
 }
 
 # test simple conflict
@@ -130,22 +130,22 @@ use Mouse::Meta::Role::Composite;
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::AnotherFooConflict', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::AnotherFooConflict', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
-    
+    } '... this succeeds as expected';
+
     is_deeply(
         [ sort $c->get_method_list ],
         [ 'baz' ],
         '... got the right list of methods'
-    );    
-    
+    );
+
     is_deeply(
         [ sort $c->get_required_method_list ],
         [ 'foo' ],
         '... got the right list of required methods'
-    );    
+    );
 }
 
index 31f4caf..4396ce5 100644 (file)
@@ -12,27 +12,27 @@ use Mouse::Meta::Role::Composite;
 {
     package Role::Foo;
     use Mouse::Role;
-    
+
     override foo => sub { 'Role::Foo::foo' };
-    
+
     package Role::Bar;
     use Mouse::Role;
 
     override bar => sub { 'Role::Bar::bar' };
-    
+
     package Role::FooConflict;
-    use Mouse::Role;    
-    
+    use Mouse::Role;
+
     override foo => sub { 'Role::FooConflict::foo' };
-    
+
     package Role::FooMethodConflict;
-    use Mouse::Role;    
-    
-    sub foo { 'Role::FooConflict::foo' }    
-    
+    use Mouse::Role;
+
+    sub foo { 'Role::FooConflict::foo' }
+
     package Role::BarMethodConflict;
     use Mouse::Role;
-    
+
     sub bar { 'Role::BarConflict::bar' }
 }
 
@@ -46,12 +46,12 @@ use Mouse::Meta::Role::Composite;
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');    
-    
+    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');
+
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this lives ok';    
-    
+    } '... this lives ok';
+
     is_deeply(
         [ sort $c->get_method_modifier_list('override') ],
         [ 'bar', 'foo' ],
@@ -74,7 +74,7 @@ dies_ok {
 # test simple overrides w/ conflicts
 dies_ok {
     Mouse::Meta::Role::Application::RoleSummation->new->apply(
-        Mouse::Meta::Role::Composite->new(        
+        Mouse::Meta::Role::Composite->new(
             roles => [
                 Role::Foo->meta,
                 Role::FooMethodConflict->meta,
@@ -90,8 +90,8 @@ dies_ok {
         Mouse::Meta::Role::Composite->new(
             roles => [
                 Role::Foo->meta,
-                Role::Bar->meta,            
-                Role::FooConflict->meta,         
+                Role::Bar->meta,
+                Role::FooConflict->meta,
             ]
         )
     );
@@ -101,11 +101,11 @@ dies_ok {
 # test simple overrides w/ conflicts
 dies_ok {
     Mouse::Meta::Role::Application::RoleSummation->new->apply(
-        Mouse::Meta::Role::Composite->new(        
+        Mouse::Meta::Role::Composite->new(
             roles => [
                 Role::Foo->meta,
-                Role::Bar->meta,            
-                Role::FooMethodConflict->meta,          
+                Role::Bar->meta,
+                Role::FooMethodConflict->meta,
             ]
         )
     );
index 86816f3..909c1ff 100644 (file)
@@ -14,16 +14,16 @@ use Mouse::Meta::Role::Composite;
     use Mouse::Role;
 
     before foo => sub { 'Role::Foo::foo' };
-    around foo => sub { 'Role::Foo::foo' };    
-    after  foo => sub { 'Role::Foo::foo' };        
+    around foo => sub { 'Role::Foo::foo' };
+    after  foo => sub { 'Role::Foo::foo' };
     around baz => sub { [ 'Role::Foo', @{shift->(@_)} ] };
 
     package Role::Bar;
     use Mouse::Role;
 
     before bar => sub { 'Role::Bar::bar' };
-    around bar => sub { 'Role::Bar::bar' };    
-    after  bar => sub { 'Role::Bar::bar' };    
+    around bar => sub { 'Role::Bar::bar' };
+    after  bar => sub { 'Role::Bar::bar' };
 
     package Role::Baz;
     use Mouse::Role;
@@ -60,11 +60,11 @@ use Mouse::Meta::Role::Composite;
     );
     isa_ok($c, 'Mouse::Meta::Role::Composite');
 
-    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');    
+    is($c->name, 'Role::Foo|Role::Bar', '... got the composite role name');
 
     lives_ok {
         Mouse::Meta::Role::Application::RoleSummation->new->apply($c);
-    } '... this succeeds as expected';    
+    } '... this succeeds as expected';
 
     is_deeply(
         [ sort $c->get_method_modifier_list('before') ],
@@ -76,11 +76,11 @@ use Mouse::Meta::Role::Composite;
         [ sort $c->get_method_modifier_list('after') ],
         [ 'bar', 'foo' ],
         '... got the right list of methods'
-    );    
+    );
 
     is_deeply(
         [ sort $c->get_method_modifier_list('around') ],
         [ 'bar', 'baz', 'foo' ],
         '... got the right list of methods'
-    );    
+    );
 }
index bc5950a..2b4e615 100644 (file)
@@ -3,14 +3,14 @@
 use strict;
 use warnings;
 
-use Test::More tests => 14;
+use Test::More tests => 17;
 
 
 {
     package Role::Foo;
     use Mouse::Role;
 
-    sub foo { }
+    sub foo { (caller(0))[3] }
 }
 
 {
@@ -70,3 +70,12 @@ use Test::More tests => 14;
     is( $meth->original_fully_qualified_name, 'Role::Foo::foo',
         'original fq name is Role::Foo::foo' );
 }
+
+isnt( ClassA->foo, "ClassB::foo", "ClassA::foo is not confused with ClassB::foo");
+
+{
+    local $TODO =
+      "multiply-consumed roles' subs take on their most recently used name";
+    is( ClassB->foo, 'ClassB::foo', 'ClassB::foo knows its name' );
+    is( ClassA->foo, 'ClassA::foo', 'ClassA::foo knows its name' );
+}
index 837dc50..673bddd 100644 (file)
@@ -9,18 +9,18 @@ use Test::Mouse;
 {
     package My::Role;
     use Mouse::Role;
-    
+
     sub foo { "FOO" }
-    sub bar { "BAR" }    
+    sub bar { "BAR" }
 }
 
 {
     package My::Class;
     use Mouse;
-    
+
     with 'My::Role' => {
-        alias    => { foo => 'baz', bar => 'gorch' },
-        excludes => ['foo', 'bar'],        
+        -alias    => { foo => 'baz', bar => 'gorch' },
+        -excludes => ['foo', 'bar'],
     };
 }
 
@@ -40,15 +40,15 @@ use Test::Mouse;
 {
     package My::Role::Again;
     use Mouse::Role;
-    
+
     with 'My::Role' => {
-        alias    => { foo => 'baz', bar => 'gorch' },
-        excludes => ['foo', 'bar'],        
+        -alias    => { foo => 'baz', bar => 'gorch' },
+        -excludes => ['foo', 'bar'],
     };
-    
+
     package My::Class::Again;
     use Mouse;
-    
+
     with 'My::Role::Again';
 }
 
index 28bbde2..c254d4c 100644 (file)
@@ -31,5 +31,5 @@ like($role->name, qr/^Mouse::Meta::Role::__ANON__::SERIAL::\d+$/, "");
 ok($role->is_anon_role, "the role knows it's anonymous");
 
 ok(Class::MOP::is_class_loaded(Mouse::Meta::Role->create_anon_role->name), "creating an anonymous role satisifes is_class_loaded");
-ok(Class::MOP::load_class(Mouse::Meta::Role->create_anon_role->name), "creating an anonymous role satisifes load_class");
+ok(Class::MOP::class_of(Mouse::Meta::Role->create_anon_role->name), "creating an anonymous role satisifes class_of");
 
diff --git a/t/030_roles/failing/038_new_meta_role.t b/t/030_roles/failing/038_new_meta_role.t
new file mode 100755 (executable)
index 0000000..e0ebe03
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 1;
+
+do {
+    package My::Meta::Role;
+    use Mouse;
+    BEGIN { extends 'Mouse::Meta::Role' };
+};
+
+do {
+    package My::Role;
+    use Mouse::Role -metaclass => 'My::Meta::Role';
+};
+
+is(My::Role->meta->meta->name, 'My::Meta::Role');
+
diff --git a/t/030_roles/failing/039_application_toclass.t b/t/030_roles/failing/039_application_toclass.t
new file mode 100755 (executable)
index 0000000..e6984fc
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 24;
+
+do {
+    package Role::Foo;
+    use Mouse::Role;
+
+    sub foo { }
+
+
+    package Consumer::Basic;
+    use Mouse;
+
+    with 'Role::Foo';
+
+    package Consumer::Excludes;
+    use Mouse;
+
+    with 'Role::Foo' => { -excludes => 'foo' };
+
+    package Consumer::Aliases;
+    use Mouse;
+
+    with 'Role::Foo' => { -alias => { 'foo' => 'role_foo' } };
+
+    package Consumer::Overrides;
+    use Mouse;
+
+    with 'Role::Foo';
+
+    sub foo { }
+};
+
+my @basic     = Consumer::Basic->meta->role_applications;
+my @excludes  = Consumer::Excludes->meta->role_applications;
+my @aliases   = Consumer::Aliases->meta->role_applications;
+my @overrides = Consumer::Overrides->meta->role_applications;
+
+is(@basic,     1);
+is(@excludes,  1);
+is(@aliases,   1);
+is(@overrides, 1);
+
+my $basic     = $basic[0];
+my $excludes  = $excludes[0];
+my $aliases   = $aliases[0];
+my $overrides = $overrides[0];
+
+isa_ok($basic,     'Mouse::Meta::Role::Application::ToClass');
+isa_ok($excludes,  'Mouse::Meta::Role::Application::ToClass');
+isa_ok($aliases,   'Mouse::Meta::Role::Application::ToClass');
+isa_ok($overrides, 'Mouse::Meta::Role::Application::ToClass');
+
+is($basic->role,     Role::Foo->meta);
+is($excludes->role,  Role::Foo->meta);
+is($aliases->role,   Role::Foo->meta);
+is($overrides->role, Role::Foo->meta);
+
+is($basic->class,     Consumer::Basic->meta);
+is($excludes->class,  Consumer::Excludes->meta);
+is($aliases->class,   Consumer::Aliases->meta);
+is($overrides->class, Consumer::Overrides->meta);
+
+is_deeply($basic->get_method_aliases,     {});
+is_deeply($excludes->get_method_aliases,  {});
+is_deeply($aliases->get_method_aliases,   { foo => 'role_foo' });
+is_deeply($overrides->get_method_aliases, {});
+
+is_deeply($basic->get_method_exclusions,     []);
+is_deeply($excludes->get_method_exclusions,  ['foo']);
+is_deeply($aliases->get_method_exclusions,   []);
+is_deeply($overrides->get_method_exclusions, []);
+
diff --git a/t/030_roles/failing/040_role_for_combination.t b/t/030_roles/failing/040_role_for_combination.t
new file mode 100755 (executable)
index 0000000..3e7642d
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+my $OPTS;
+do {
+    package My::Singleton::Role;
+    use Mouse::Role;
+
+    sub foo { 'My::Singleton::Role' }
+
+    package My::Role::Metaclass;
+    use Mouse;
+    BEGIN { extends 'Mouse::Meta::Role' };
+
+    sub _role_for_combination {
+        my ($self, $opts) = @_;
+        $OPTS = $opts;
+        return My::Singleton::Role->meta;
+    }
+
+    package My::Special::Role;
+    use Mouse::Role -metaclass => 'My::Role::Metaclass';
+
+    sub foo { 'My::Special::Role' }
+
+    package My::Usual::Role;
+    use Mouse::Role;
+
+    sub bar { 'My::Usual::Role' }
+
+    package My::Class;
+    use Mouse;
+
+    with (
+        'My::Special::Role' => { number => 1 },
+        'My::Usual::Role' => { number => 2 },
+    );
+};
+
+is(My::Class->foo, 'My::Singleton::Role', 'role_for_combination applied');
+is(My::Class->bar, 'My::Usual::Role', 'collateral role');
+is_deeply($OPTS, { number => 1 });
+
diff --git a/t/030_roles/failing/043_conflict_many_methods.t b/t/030_roles/failing/043_conflict_many_methods.t
new file mode 100755 (executable)
index 0000000..b8eb2c9
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+use Test::Exception;
+
+{
+    package Bomb;
+    use Mouse::Role;
+
+    sub fuse { }
+    sub explode { }
+
+    package Spouse;
+    use Mouse::Role;
+
+    sub fuse { }
+    sub explode { }
+
+    package Caninish;
+    use Mouse::Role;
+
+    sub bark { }
+
+    package Treeve;
+    use Mouse::Role;
+
+    sub bark { }
+}
+
+package PracticalJoke;
+use Mouse;
+
+::throws_ok {
+    with 'Bomb', 'Spouse';
+} qr/Due to method name conflicts in roles 'Bomb' and 'Spouse', the methods 'explode' and 'fuse' must be implemented or excluded by 'PracticalJoke'/;
+
+::throws_ok {
+    with (
+        'Bomb', 'Spouse',
+        'Caninish', 'Treeve',
+    );
+} qr/Due to a method name conflict in roles 'Caninish' and 'Treeve', the method 'bark' must be implemented or excluded by 'PracticalJoke'/;
+
index bb77df5..9d0ca72 100644 (file)
@@ -1,6 +1,6 @@
 use strict;
 use warnings;
-use Test::More tests => 5;
+use Test::More tests => 6;
 
 {
     package Animal;
@@ -12,7 +12,8 @@ use Test::More tests => 5;
     package Cat;
     use Mouse::Role;
     with 'Animal', {
-        alias => { eat => 'drink' },
+        -alias    => { eat => 'drink' },
+        -excludes => [qw(eat)],
     };
     sub eat { 'good!' }
 }
@@ -27,7 +28,7 @@ use Test::More tests => 5;
     package Dog;
     use Mouse;
     with 'Animal', {
-        alias => { eat => 'drink' }
+        -alias    => { eat => 'drink' },
     };
 }
 
@@ -36,6 +37,7 @@ ok(Dog->can('drink'));
 
 my $d = Dog->new();
 is($d->drink(), 'delicious');
+is($d->eat(),   'delicious');
 
 my $t = Tama->new;
 is $t->drink(), 'delicious';