From: Matt S Trout Date: Fri, 25 Feb 2011 15:54:08 +0000 (+0000) Subject: handle non-lazy default and builder when init_arg is undef X-Git-Tag: release_0.009006~4 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d02da2bc41a7f450a64ef79a571a889e73f690d6;p=gitmo%2FMoo.git handle non-lazy default and builder when init_arg is undef We were skipping attributes entirely in new if there's no init_arg, but this is not correct - given a non-lazy default or builder the attribute should be initialized during new(). To handle this, I've re-ordered the checks slightly in Constructor.pm to do the "is_simple" check first - an attribute with a default or builder will fail that check, then we skip anyway if no init_arg and no default or builder (yes, this is hardcoded-ish, but in that case we're definitely not constructing anything so far as I can see). default and builder are disregarded if lazy so as not to try and populate pure-lazy attributes. Accessor also needed tweaking so it could handle the concept of a thing to build without an init_arg to populate from. This only needs to happen in one branch since the other branch is for "no default or builder" and thus never reached. --- diff --git a/Changes b/Changes index f34fbce..d37e4cd 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,4 @@ + - handle non-lazy default and builder when init_arg is undef - add copyright and license info for downstream packagers - weak ref checking for Sub::Quote to avoid bugs on refaddr reuse - Switch composed role names to be a valid package name diff --git a/lib/Method/Generate/Accessor.pm b/lib/Method/Generate/Accessor.pm index 7015ada..d4112bf 100644 --- a/lib/Method/Generate/Accessor.pm +++ b/lib/Method/Generate/Accessor.pm @@ -275,12 +275,15 @@ sub _generate_populate_set { if (!$spec->{lazy} and ($spec->{default} or $spec->{builder})) { my $get_indent = ' ' x ($spec->{isa} ? 6 : 4); + my $get_default = $self->_generate_get_default( + '$new', $_, $spec + ); my $get_value = - "(\n${get_indent} ${test}\n${get_indent} ? ${source}\n${get_indent} : " - .$self->_generate_get_default( - '$new', $_, $spec - ) - ."\n${get_indent})"; + defined($spec->{init_arg}) + ? "(\n${get_indent} ${test}\n${get_indent} ? ${source}\n${get_indent} : " + .$get_default + ."\n${get_indent})" + : $get_default; ($spec->{isa} ? " {\n my \$value = ".$get_value.";\n " .$self->_generate_isa_check( diff --git a/lib/Method/Generate/Constructor.pm b/lib/Method/Generate/Constructor.pm index c7138a1..5d459b6 100644 --- a/lib/Method/Generate/Constructor.pm +++ b/lib/Method/Generate/Constructor.pm @@ -77,11 +77,14 @@ sub _assign_new { my $ag = $self->accessor_generator; NAME: foreach my $name (sort keys %$spec) { my $attr_spec = $spec->{$name}; - next NAME unless defined(my $i = $attr_spec->{init_arg}); unless ($ag->is_simple_attribute($name, $attr_spec)) { - $test{$name} = $i; + next NAME unless defined($attr_spec->{init_arg}) + or (($attr_spec->{default} or $attr_spec->{builder}) + and not $attr_spec->{lazy}); + $test{$name} = $attr_spec->{init_arg}; next NAME; } + next NAME unless defined(my $i = $attr_spec->{init_arg}); push @init, $i; push @slots, $name; } diff --git a/t/accessor-default.t b/t/accessor-default.t index 2cec9c0..1f3fbac 100644 --- a/t/accessor-default.t +++ b/t/accessor-default.t @@ -13,6 +13,7 @@ use Test::More; has three => (is => 'ro', default => quote_sub q{ {} }); has four => (is => 'ro', builder => '_build_four'); sub _build_four { {} } + has five => (is => 'ro', init_arg => undef, default => sub { {} }); } sub check { @@ -31,4 +32,6 @@ check three => map Foo->new->{three}, 1..2; check four => map Foo->new->{four}, 1..2; +check five => map Foo->new->{five}, 1..2; + done_testing;