[libmoo-perl] 19/43: make has +attr in roles consistent with classes

gregor herrmann gregoa at debian.org
Mon Dec 26 17:56:14 UTC 2016


This is an automated email from the git hooks/post-receive script.

gregoa pushed a commit to branch master
in repository libmoo-perl.

commit c57ed0008cc7a3f22ceb7120166697171b4a8794
Author: Graham Knop <haarg at haarg.org>
Date:   Sun Nov 27 14:33:24 2016 -0500

    make has +attr in roles consistent with classes
    
    has '+attr' should be prohibited if the attribute doesn't exist, and it
    should properly merge with the existing attribute spec.
---
 lib/Moo/Role.pm    | 18 +++++++++++++++---
 t/accessor-roles.t |  2 +-
 t/has-plus.t       | 25 +++++++++++++++++++++++++
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/lib/Moo/Role.pm b/lib/Moo/Role.pm
index 5859956..bbc1d37 100644
--- a/lib/Moo/Role.pm
+++ b/lib/Moo/Role.pm
@@ -71,11 +71,23 @@ sub _install_subs {
     my %spec = @_;
     foreach my $name (@name_proto) {
       my $spec_ref = @name_proto > 1 ? +{%spec} : \%spec;
-      ($INFO{$target}{accessor_maker} ||= do {
+      my $ag = $INFO{$target}{accessor_maker} ||= do {
         require Method::Generate::Accessor;
         Method::Generate::Accessor->new
-      })->generate_method($target, $name, $spec_ref);
-      push @{$INFO{$target}{attributes}||=[]}, $name, $spec_ref;
+      };
+      my $attrs = $INFO{$target}{attributes}||=[];
+      if ($name =~ /^\+(.*)/) {
+        my $attr_name = $1;
+        my ($old_spec) =
+          map $attrs->[$_+1],
+          grep $attrs->[$_] eq $attr_name,
+          0 .. @$attrs/2 - 1;
+        croak "has '${name}' given but no ${attr_name} attribute already exists"
+          unless $old_spec;
+        $ag->merge_specs($spec_ref, $old_spec);
+      }
+      $ag->generate_method($target, $name, $spec_ref);
+      push @$attrs, $name, $spec_ref;
       $me->_maybe_reset_handlemoose($target);
     }
   };
diff --git a/t/accessor-roles.t b/t/accessor-roles.t
index 51ffb31..1546ebf 100644
--- a/t/accessor-roles.t
+++ b/t/accessor-roles.t
@@ -15,7 +15,7 @@ use Sub::Quote;
   has four => (is => 'ro', lazy => 1, default => sub { 'four' }, predicate => 1);
 
   package One::P3; use Moo::Role;
-  has '+three' => (is => 'ro', default => sub { 'three' });
+  has 'three' => (is => 'ro', default => sub { 'three' });
 }
 
 my $combined = Moo::Role->create_class_with_roles('One', qw(One::P1 One::P2));
diff --git a/t/has-plus.t b/t/has-plus.t
index 1287a20..27c65cf 100644
--- a/t/has-plus.t
+++ b/t/has-plus.t
@@ -48,6 +48,22 @@ use Test::Fatal;
 }
 
 {
+  package RoleWithTheRole;
+  use Moo::Role;
+
+  with 'RollyRole';
+
+  has '+f' => (default => sub { 4 });
+}
+
+{
+  package UsesTheOtherRole;
+  use Moo;
+
+  with 'RoleWithTheRole';
+}
+
+{
   package BlowsUp;
 
   use Moo;
@@ -56,6 +72,14 @@ use Test::Fatal;
 }
 
 {
+  package RoleBlowsUp;
+
+  use Moo::Role;
+
+  ::like(::exception { has '+f' => () }, qr/\Qhas '+f'/, 'Kaboom');
+}
+
+{
   package ClassyClass2;
   use Moo;
   has d => (is => 'ro', default => sub { 4 });
@@ -78,5 +102,6 @@ is(UsesTheRole->new->f, 0, 'role attr');
 is(ClassyClass->new->f, 1, 'class attr');
 is(UsesTheRole2->new->f, 2, 'role attr with +');
 is(ExtendsTheClass->new->f, 3, 'class attr with +');
+is(UsesTheOtherRole->new->f, 4, 'role attr with + in role');
 
 done_testing;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmoo-perl.git



More information about the Pkg-perl-cvs-commits mailing list