handles => "RoleName" should try to load the module
[gitmo/Moo.git] / lib / Method / Generate / Accessor.pm
index 73ad15d..1a13a56 100644 (file)
@@ -7,6 +7,7 @@ use Sub::Quote;
 use B 'perlstring';
 use Scalar::Util 'blessed';
 use overload ();
+use Module::Runtime qw(use_module);
 BEGIN {
   our $CAN_HAZ_XS =
     !$ENV{MOO_XS_DISABLE}
@@ -24,7 +25,8 @@ sub generate_method {
   if ($is eq 'ro') {
     $spec->{reader} = $name unless exists $spec->{reader};
   } elsif ($is eq 'rw') {
-    $spec->{accessor} = $name unless exists $spec->{accessor};
+    $spec->{accessor} = $name unless exists $spec->{accessor}
+      or ( $spec->{reader} and $spec->{writer} );
   } elsif ($is eq 'lazy') {
     $spec->{reader} = $name unless exists $spec->{reader};
     $spec->{lazy} = 1;
@@ -35,10 +37,19 @@ sub generate_method {
   } elsif ($is ne 'bare') {
     die "Unknown is ${is}";
   }
-  $spec->{builder} = '_build_'.$name if ($spec->{builder}||0) eq 1;
-  die "Invalid builder for $into->$name - not a valid method name"
-    if exists $spec->{builder} and (ref $spec->{builder}
-      or $spec->{builder} !~ /\A[A-Za-z_][A-Za-z0-9_]*(?:::[A-Za-z_][A-Za-z0-9_]*)*\z/);
+  if (exists $spec->{builder}) {
+    if(ref $spec->{builder}) {
+      die "Invalid builder for $into->$name - not a method name, coderef or"
+        . " code-convertible object"
+        unless ref $spec->{builder} eq 'CODE'
+        or (blessed($spec->{builder}) and eval { \&{$spec->{builder}} });
+      $spec->{builder_sub} = $spec->{builder};
+      $spec->{builder} = 1;
+    }
+    $spec->{builder} = '_build_'.$name if ($spec->{builder}||0) eq 1;
+    die "Invalid builder for $into->$name - not a valid method name"
+      if $spec->{builder} !~ /\A[A-Za-z_][A-Za-z0-9_]*(?:::[A-Za-z_][A-Za-z0-9_]*)*\z/;
+  }
   if (($spec->{predicate}||0) eq 1) {
     $spec->{predicate} = $name =~ /^_/ ? "_has${name}" : "has_${name}";
   }
@@ -117,6 +128,9 @@ sub generate_method {
         '    '.$self->_generate_simple_has('$_[0]', $name, $spec)."\n"
       ;
   }
+  if (my $pred = $spec->{builder_sub}) {
+    _install_coderef( "${into}::$spec->{builder}" => $spec->{builder_sub} );
+  }
   if (my $cl = $spec->{clearer}) {
     $methods{$cl} =
       quote_sub "${into}::${cl}" => 
@@ -132,7 +146,7 @@ sub generate_method {
         map [ $_ => ref($hspec->{$_}) ? @{$hspec->{$_}} : $hspec->{$_} ],
           keys %$hspec;
       } elsif (!ref($hspec)) {
-        map [ $_ => $_ ], Role::Tiny->methods_provided_by($hspec);
+        map [ $_ => $_ ], use_module('Role::Tiny')->methods_provided_by(use_module($hspec))
       } else {
         die "You gave me a handles of ${hspec} and I have no idea why";
       }