update repo to point to github
[gitmo/Moo.git] / lib / Method / Generate / Constructor.pm
index e0746d7..c116eff 100644 (file)
@@ -5,6 +5,7 @@ use Sub::Quote;
 use base qw(Moo::Object);
 use Sub::Defer;
 use B 'perlstring';
+use Moo::_Utils qw(_getstash);
 
 sub register_attribute_specs {
   my ($self, @new_specs) = @_;
@@ -14,10 +15,18 @@ sub register_attribute_specs {
       die "has '+${name}' given but no ${name} attribute already exists"
         unless my $old_spec = $specs->{$name};
       foreach my $key (keys %$old_spec) {
-        $new_spec->{$key} = $old_spec->{$key}
-          unless exists $new_spec->{$key};
+        if (!exists $new_spec->{$key}) {
+          $new_spec->{$key} = $old_spec->{$key}
+            unless $key eq 'handles';
+        }
+        elsif ($key eq 'moosify') {
+          $new_spec->{$key} = [
+            map { ref $_ eq 'ARRAY' ? @$_ : $_ }
+              ($old_spec->{$key}, $new_spec->{$key})
+          ];
         }
       }
+    }
     $new_spec->{index} = scalar keys %$specs
       unless defined $new_spec->{index};
     $specs->{$name} = $new_spec;
@@ -36,9 +45,13 @@ sub accessor_generator {
 sub construction_string {
   my ($self) = @_;
   $self->{construction_string}
-    or 'bless('
-       .$self->accessor_generator->default_construction_string
-       .', $class);'
+    ||= $self->_build_construction_string;
+}
+
+sub _build_construction_string {
+  'bless('
+    .$_[0]->accessor_generator->default_construction_string
+    .', $class);'
 }
 
 sub install_delayed {
@@ -136,34 +149,21 @@ _EOA
 
 sub _assign_new {
   my ($self, $spec) = @_;
-  my (@init, @slots, %test);
   my $ag = $self->accessor_generator;
+  my %test;
   NAME: foreach my $name (sort keys %$spec) {
     my $attr_spec = $spec->{$name};
-    unless ($ag->is_simple_attribute($name, $attr_spec)) {
-      next NAME unless defined($attr_spec->{init_arg})
-                         or $ag->has_eager_default($name, $attr_spec);
-      $test{$name} = $attr_spec->{init_arg};
-      next NAME;
-    }
-    next NAME unless defined(my $i = $attr_spec->{init_arg});
-    push @init, $i;
-    push @slots, $name;
+    next NAME unless defined($attr_spec->{init_arg})
+                       or $ag->has_eager_default($name, $attr_spec);
+    $test{$name} = $attr_spec->{init_arg};
   }
-  return '' unless @init or %test;
-  join '', (
-    @init
-      ? '    '.$self->_cap_call($ag->generate_multi_set(
-          '$new', [ @slots ], '@{$args}{qw('.join(' ',@init).')}', $spec
-        )).";\n"
-      : ''
-  ), map {
+  join '', map {
     my $arg_key = perlstring($test{$_});
     my $test = "exists \$args->{$arg_key}";
     my $source = "\$args->{$arg_key}";
     my $attr_spec = $spec->{$_};
     $self->_cap_call($ag->generate_populate_set(
-      '$new', $_, $attr_spec, $source, $test
+      '$new', $_, $attr_spec, $source, $test, $test{$_},
     ));
   } sort keys %test;
 }
@@ -172,8 +172,10 @@ sub _check_required {
   my ($self, $spec) = @_;
   my @required_init =
     map $spec->{$_}{init_arg},
-      grep $spec->{$_}{required},
-        sort keys %$spec;
+      grep {
+        my %s = %{$spec->{$_}}; # ignore required if default or builder set
+        $s{required} and not($s{builder} or $s{default})
+      } sort keys %$spec;
   return '' unless @required_init;
   '    if (my @missing = grep !exists $args->{$_}, qw('
     .join(' ',@required_init).')) {'."\n"
@@ -181,44 +183,16 @@ sub _check_required {
     ."    }\n";
 }
 
-sub _check_isa {
-  my ($self, $spec) = @_;
-  my $acc = $self->accessor_generator;
-  my $captures = $self->{captures};
-  my $check = '';
-  foreach my $name (sort keys %$spec) {
-    my ($init, $isa) = @{$spec->{$name}}{qw(init_arg isa)};
-    next unless $init and $isa;
-    my $init_str = perlstring($init);
-    my ($code, $add_captures) = $acc->generate_isa_check(
-      $name, "\$args->{${init_str}}", $isa
-    );
-    @{$captures}{keys %$add_captures} = values %$add_captures;
-    $check .= "    ${code}".(
-      (not($spec->{lazy}) and ($spec->{default} or $spec->{builder})
-        ? ";\n"
-        : "if exists \$args->{${init_str}};\n"
-      )
-    );
-  }
-  return $check;
-}
-
-sub _fire_triggers {
-  my ($self, $spec) = @_;
-  my $acc = $self->accessor_generator;
-  my $captures = $self->{captures};
-  my $fire = '';
-  foreach my $name (sort keys %$spec) {
-    my ($init, $trigger) = @{$spec->{$name}}{qw(init_arg trigger)};
-    next unless $init && $trigger;
-    my ($code, $add_captures) = $acc->generate_trigger(
-      $name, '$new', $acc->generate_simple_get('$new', $name, $spec), $trigger
-    );
-    @{$captures}{keys %$add_captures} = values %$add_captures;
-    $fire .= "    ${code} if exists \$args->{${\perlstring $init}};\n";
-  }
-  return $fire;
-}
+use Moo;
+Moo->_constructor_maker_for(__PACKAGE__)->register_attribute_specs(
+  attribute_specs => {
+    is => 'ro',
+    reader => 'all_attribute_specs',
+  },
+  accessor_generator => { is => 'ro' },
+  construction_string => { is => 'lazy' },
+  subconstructor_handler => { is => 'ro' },
+  package => { is => 'ro' },
+);
 
 1;