use Scalar::Util 'blessed', 'weaken';
use overload ();
-our $VERSION = '0.83';
+our $VERSION = '0.91';
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Method::Accessor;
));
__PACKAGE__->meta->add_attribute('handles' => (
reader => 'handles',
+ writer => '_set_handles',
predicate => 'has_handles',
));
__PACKAGE__->meta->add_attribute('documentation' => (
sub new {
my ($class, $name, %options) = @_;
$class->_process_options($name, \%options) unless $options{__hack_no_process_options}; # used from clone()... YECHKKK FIXME ICKY YUCK GROSS
+
+ delete $options{__hack_no_process_options};
+
+ my %attrs =
+ ( map { $_ => 1 }
+ grep { defined }
+ map { $_->init_arg() }
+ $class->meta()->get_all_attributes()
+ );
+
+ my @bad = sort grep { ! $attrs{$_} } keys %options;
+
+ if (@bad)
+ {
+ Carp::cluck "Found unknown argument(s) passed to '$name' attribute constructor in '$class': @bad";
+ }
+
return $class->SUPER::new($name, %options);
}
sub interpolate_class_and_new {
- my ($class, $name, @args) = @_;
+ my ($class, $name, %args) = @_;
- my ( $new_class, @traits ) = $class->interpolate_class(@args);
+ my ( $new_class, @traits ) = $class->interpolate_class(\%args);
- $new_class->new($name, @args, ( scalar(@traits) ? ( traits => \@traits ) : () ) );
+ $new_class->new($name, %args, ( scalar(@traits) ? ( traits => \@traits ) : () ) );
}
sub interpolate_class {
- my ($class, %options) = @_;
+ my ($class, $options) = @_;
$class = ref($class) || $class;
- if ( my $metaclass_name = delete $options{metaclass} ) {
+ if ( my $metaclass_name = delete $options->{metaclass} ) {
my $new_class = Moose::Util::resolve_metaclass_alias( Attribute => $metaclass_name );
if ( $class ne $new_class ) {
if ( $new_class->can("interpolate_class") ) {
- return $new_class->interpolate_class(%options);
+ return $new_class->interpolate_class($options);
} else {
$class = $new_class;
}
my @traits;
- if (my $traits = $options{traits}) {
+ if (my $traits = $options->{traits}) {
my $i = 0;
while ($i < @$traits) {
my $trait = $traits->[$i++];
documentation lazy handles
builder type_constraint
definition_context
- lazy_build
+ lazy_build weak_ref
);
sub legal_options_for_inheritance { @legal_options_for_inheritance }
# so we can ignore it for them.
# - SL
if ($self->can('interpolate_class')) {
- ( $actual_options{metaclass}, my @traits ) = $self->interpolate_class(%options);
+ ( $actual_options{metaclass}, my @traits ) = $self->interpolate_class(\%options);
my %seen;
my @all_traits = grep { $seen{$_}++ } @{ $self->applied_traits || [] }, @traits;
sub clone {
my ( $self, %params ) = @_;
- my $class = $params{metaclass} || ref $self;
+ my $class = delete $params{metaclass} || ref $self;
my ( @init, @non_init );
my $meta_instance = Class::MOP::Class->initialize(blessed($instance))
->get_meta_instance;
+ my @old;
+ if ( $self->has_trigger && $self->has_value($instance) ) {
+ @old = $self->get_value($instance, 'for trigger');
+ }
+
$meta_instance->set_slot_value($instance, $attr_name, $value);
if (ref $value && $self->is_weak_ref) {
}
if ($self->has_trigger) {
- $self->trigger->($instance, $value);
+ $self->trigger->($instance, $value, @old);
}
}
sub get_value {
- my ($self, $instance) = @_;
+ my ($self, $instance, $for_trigger) = @_;
if ($self->is_lazy) {
unless ($self->has_value($instance)) {
}
}
- if ($self->should_auto_deref) {
+ if ( $self->should_auto_deref && ! $for_trigger ) {
my $type_constraint = $self->type_constraint;
my $self = shift;
$self->SUPER::install_accessors(@_);
$self->install_delegation if $self->has_handles;
+ return;
+}
+
+sub _check_associated_methods {
+ my $self = shift;
unless (
@{ $self->associated_methods }
|| ($self->_is_metadata || '') eq 'bare'
) {
Carp::cluck(
- 'Attribute (' . $self->name . ') has no associated methods'
+ 'Attribute (' . $self->name . ') of class '
+ . $self->associated_class->name
+ . ' has no associated methods'
. ' (did you mean to provide an "is" argument?)'
. "\n"
)
}
- return;
+}
+
+sub _process_accessors {
+ my $self = shift;
+ my ($type, $accessor, $generate_as_inline_methods) = @_;
+ $accessor = (keys %$accessor)[0] if (ref($accessor)||'') eq 'HASH';
+ my $method = $self->associated_class->get_method($accessor);
+ if ($method && !$method->isa('Class::MOP::Method::Accessor')
+ && (!$self->definition_context
+ || $method->package_name eq $self->definition_context->{package})) {
+ Carp::cluck(
+ "You are overwriting a locally defined method ($accessor) with "
+ . "an accessor"
+ );
+ }
+ $self->SUPER::_process_accessors(@_);
}
sub remove_accessors {
(blessed $role_meta && $role_meta->isa('Moose::Meta::Role'))
|| $self->throw_error("Unable to canonicalize the 'handles' option with $handles because its metaclass is not a Moose::Meta::Role", data => $handles);
- return map { $_ => $_ } (
+ return map { $_ => $_ }
+ grep { $_ ne 'meta' } (
$role_meta->get_method_list,
map { $_->name } $role_meta->get_required_method_list,
- );
+ );
}
}
$method_body = $method_to_call
if 'CODE' eq ref($method_to_call);
+ my @curried_arguments;
+
+ ($method_to_call, @curried_arguments) = @$method_to_call
+ if 'ARRAY' eq ref($method_to_call);
+
return $self->delegation_metaclass->new(
name => $handle_name,
package_name => $self->associated_class->name,
attribute => $self,
delegate_to_method => $method_to_call,
+ curried_arguments => \@curried_arguments,
);
}