MooseX-Extended
view release on metacpan or search on metacpan
lib/MooseX/Extended/Core.pm view on Meta::CPAN
class_name => $meta->name,
messsage => "Illegal attribute name, '$name'",
);
}
state $shortcut_for = {
predicate => sub ($value) {"has_$value"},
clearer => sub ($value) {"clear_$value"},
builder => sub ($value) {"_build_$value"},
writer => sub ($value) {"set_$value"},
reader => sub ($value) {"get_$value"},
};
if ( is_coderef( $opt_for{builder} ) ) {
my $builder_code = $opt_for{builder};
my $builder_name = $shortcut_for->{builder}->($name);
if ( _is_valid_method_name($builder_name) ) {
$meta->add_method( $builder_name => $builder_code );
$opt_for{builder} = $builder_name;
}
}
OPTION: foreach my $option ( keys $shortcut_for->%* ) {
next unless exists $opt_for{$option};
no warnings 'numeric'; ## no critic (TestingAndDebugging::ProhibitNoWarning)
if ( 1 == length( $opt_for{$option} ) && 1 == $opt_for{$option} ) {
my $option_name = $shortcut_for->{$option}->($name);
$opt_for{$option} = $option_name;
}
unless ( _is_valid_method_name( $opt_for{$option} ) ) {
throw_exception(
'InvalidAttributeDefinition',
attribute_name => $orig_name,
class_name => $meta->name,
messsage => "Attribute '$orig_name' has an invalid option name, $option => '$opt_for{$option}'",
);
}
}
if ( 'rwp' eq $opt_for{is} ) {
$opt_for{writer} = "_set_$name";
}
if ( exists $opt_for{writer} && defined $opt_for{writer} ) {
$opt_for{is} = 'rw';
}
%opt_for = _maybe_add_cloning_method( $meta, $name, %opt_for );
if ( not exists $opt_for{accessor}
and not exists $opt_for{writer}
and not exists $opt_for{default}
and not exists $opt_for{builder}
and not defined $opt_for{init_arg}
and $opt_for{is} eq 'ro' )
{
my $call_level = 1 + $opt_for{_call_level};
my ( undef, $filename, $line ) = caller($call_level);
Carp::carp("$attr_type '$name' is read-only and has no init_arg or default, defined at $filename line $line\n")
if $] ge '5.028'
and warnings::enabled_at_level( 'MooseX::Extended::naked_fields', $call_level );
}
delete $opt_for{_call_level};
_debug( "Setting $attr_type, '$orig_name'", \%opt_for );
$meta->add_attribute( $orig_name, %opt_for );
}
sub _is_valid_method_name ($name) {
return if ref $name;
return $name =~ qr/\A[a-z_]\w*\z/ai;
}
sub _maybe_add_cloning_method ( $meta, $name, %opt_for ) {
return %opt_for unless my $clone = delete $opt_for{clone};
no warnings 'numeric'; ## no critic (TestingAndDebugging::ProhibitNoWarning)
my ( $use_dclone, $use_coderef, $use_method );
if ( 1 == length($clone) && 1 == $clone ) {
$use_dclone = 1;
}
elsif ( _is_valid_method_name($clone) ) {
$use_method = 1;
}
elsif ( is_coderef($clone) ) {
$use_coderef = 1;
}
else {
throw_exception(
'InvalidAttributeDefinition',
attribute_name => $name,
class_name => $meta->name,
messsage => "Attribute '$name' has an invalid option value, clone => '$clone'",
);
}
# here be dragons ...
_debug("Adding cloning for $name");
my $reader = delete( $opt_for{reader} ) // $name;
my $writer = delete( $opt_for{writer} ) // $reader;
my $is = $opt_for{is};
$opt_for{is} = 'bare';
my $reader_method = sub ($self) {
_debug("Calling reader method for $name");
my $attr = $meta->get_attribute($name);
my $value = $attr->get_value($self);
return $value unless ref $value;
return
$use_dclone ? dclone($value)
: $use_method || $use_coderef ? $self->$clone( $name, $value )
: croak("PANIC: this should never happen. Do not know how to clone '$name'");
};
my $writer_method = sub ( $self, $new_value ) {
_debug("Calling writer method for $name");
my $attr = $meta->get_attribute($name);
$new_value
= !ref $new_value ? $new_value
( run in 0.963 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )