| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package MooseX::Method::Signatures::Meta::Method; | 
| 2 |  |  |  |  |  |  | { | 
| 3 |  |  |  |  |  |  | $MooseX::Method::Signatures::Meta::Method::VERSION = '0.47'; | 
| 4 |  |  |  |  |  |  | } | 
| 5 |  |  |  |  |  |  | BEGIN { | 
| 6 | 28 |  |  | 38 |  | 38885 | $MooseX::Method::Signatures::Meta::Method::AUTHORITY = 'cpan:ETHER'; | 
| 7 |  |  |  |  |  |  | } | 
| 8 |  |  |  |  |  |  | # ABSTRACT: Provides the metaclass for methods with signatures | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 28 |  |  | 28 |  | 1193 | use Moose; | 
|  | 28 |  |  |  |  | 501460 |  | 
|  | 28 |  |  |  |  | 516 |  | 
| 11 | 28 |  |  | 28 |  | 210881 | use Carp qw/cluck/; | 
|  | 28 |  |  |  |  | 94 |  | 
|  | 28 |  |  |  |  | 1989 |  | 
| 12 | 28 |  |  | 28 |  | 33105 | use Context::Preserve; | 
|  | 28 |  |  |  |  | 14729 |  | 
|  | 28 |  |  |  |  | 1631 |  | 
| 13 | 28 |  |  | 28 |  | 28656 | use Parse::Method::Signatures 1.003014; | 
|  | 28 |  |  |  |  | 12175916 |  | 
|  | 28 |  |  |  |  | 1369 |  | 
| 14 | 28 |  |  | 28 |  | 36820 | use Parse::Method::Signatures::TypeConstraint; | 
|  | 28 |  |  |  |  | 1943037 |  | 
|  | 28 |  |  |  |  | 1362 |  | 
| 15 | 28 |  |  | 28 |  | 299 | use Scalar::Util qw/weaken/; | 
|  | 28 |  |  |  |  | 65 |  | 
|  | 28 |  |  |  |  | 1947 |  | 
| 16 | 28 |  |  | 28 |  | 206 | use Moose::Util qw/does_role/; | 
|  | 28 |  |  |  |  | 61 |  | 
|  | 28 |  |  |  |  | 353 |  | 
| 17 | 28 |  |  | 28 |  | 8719 | use Moose::Util::TypeConstraints; | 
|  | 28 |  |  |  |  | 66 |  | 
|  | 28 |  |  |  |  | 300 |  | 
| 18 | 28 |  |  | 28 |  | 94584 | use MooseX::Meta::TypeConstraint::ForceCoercion; | 
|  | 28 |  |  |  |  | 497980 |  | 
|  | 28 |  |  |  |  | 1374 |  | 
| 19 | 28 |  |  | 28 |  | 276 | use MooseX::Types::Util qw/has_available_type_export/; | 
|  | 28 |  |  |  |  | 111 |  | 
|  | 28 |  |  |  |  | 2077 |  | 
| 20 | 28 |  |  | 28 |  | 33584 | use MooseX::Types::Structured qw/Tuple Dict Optional slurpy/; | 
|  | 28 |  |  |  |  | 12613367 |  | 
|  | 28 |  |  |  |  | 270 |  | 
| 21 | 28 |  |  | 28 |  | 16122 | use MooseX::Types::Moose qw/ArrayRef Str Maybe Object Any CodeRef Bool/; | 
|  | 28 |  |  |  |  | 70 |  | 
|  | 28 |  |  |  |  | 314 |  | 
| 22 | 28 |  |  | 28 |  | 217733 | use MooseX::Method::Signatures::Types qw/Injections Params/; | 
|  | 28 |  |  |  |  | 139 |  | 
|  | 28 |  |  |  |  | 260 |  | 
| 23 | 28 |  |  | 28 |  | 46153 | use aliased 'Parse::Method::Signatures::Param::Named'; | 
|  | 28 |  |  |  |  | 796 |  | 
|  | 28 |  |  |  |  | 271 |  | 
| 24 | 28 |  |  | 28 |  | 422371 | use aliased 'Parse::Method::Signatures::Param::Placeholder'; | 
|  | 28 |  |  |  |  | 80 |  | 
|  | 28 |  |  |  |  | 248 |  | 
| 25 |  |  |  |  |  |  |  | 
| 26 | 28 |  |  | 28 |  | 214588 | use namespace::autoclean; | 
|  | 28 |  |  |  |  | 79 |  | 
|  | 28 |  |  |  |  | 635 |  | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | extends 'Moose::Meta::Method'; | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | has signature => ( | 
| 31 |  |  |  |  |  |  | is       => 'ro', | 
| 32 |  |  |  |  |  |  | isa      => Str, | 
| 33 |  |  |  |  |  |  | default  => '(@)', | 
| 34 |  |  |  |  |  |  | required => 1, | 
| 35 |  |  |  |  |  |  | ); | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | has parsed_signature => ( | 
| 38 |  |  |  |  |  |  | is      => 'ro', | 
| 39 |  |  |  |  |  |  | isa     => class_type('Parse::Method::Signatures::Sig'), | 
| 40 |  |  |  |  |  |  | lazy    => 1, | 
| 41 |  |  |  |  |  |  | builder => '_build_parsed_signature', | 
| 42 |  |  |  |  |  |  | ); | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | sub _parsed_signature { | 
| 45 | 0 |  |  | 0 |  | 0 | cluck '->_parsed_signature is deprecated. use ->parsed_signature instead.'; | 
| 46 | 0 |  |  |  |  | 0 | shift->parsed_signature; | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | has _lexicals => ( | 
| 50 |  |  |  |  |  |  | is      => 'ro', | 
| 51 |  |  |  |  |  |  | isa     => ArrayRef[Str], | 
| 52 |  |  |  |  |  |  | lazy    => 1, | 
| 53 |  |  |  |  |  |  | builder => '_build__lexicals', | 
| 54 |  |  |  |  |  |  | ); | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | has injectable_code => ( | 
| 57 |  |  |  |  |  |  | is      => 'ro', | 
| 58 |  |  |  |  |  |  | isa     => Str, | 
| 59 |  |  |  |  |  |  | lazy    => 1, | 
| 60 |  |  |  |  |  |  | builder => '_build_injectable_code', | 
| 61 |  |  |  |  |  |  | ); | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | has _positional_args => ( | 
| 64 |  |  |  |  |  |  | is      => 'ro', | 
| 65 |  |  |  |  |  |  | isa     => ArrayRef, | 
| 66 |  |  |  |  |  |  | lazy    => 1, | 
| 67 |  |  |  |  |  |  | builder => '_build__positional_args', | 
| 68 |  |  |  |  |  |  | ); | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | has _named_args => ( | 
| 71 |  |  |  |  |  |  | is      => 'ro', | 
| 72 |  |  |  |  |  |  | isa     => ArrayRef, | 
| 73 |  |  |  |  |  |  | lazy    => 1, | 
| 74 |  |  |  |  |  |  | builder => '_build__named_args', | 
| 75 |  |  |  |  |  |  | ); | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | has _has_slurpy_positional => ( | 
| 78 |  |  |  |  |  |  | is   => 'rw', | 
| 79 |  |  |  |  |  |  | isa  => Bool, | 
| 80 |  |  |  |  |  |  | ); | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | has type_constraint => ( | 
| 83 |  |  |  |  |  |  | is      => 'ro', | 
| 84 |  |  |  |  |  |  | isa     => class_type('Moose::Meta::TypeConstraint'), | 
| 85 |  |  |  |  |  |  | lazy    => 1, | 
| 86 |  |  |  |  |  |  | builder => '_build_type_constraint', | 
| 87 |  |  |  |  |  |  | ); | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | has return_signature => ( | 
| 90 |  |  |  |  |  |  | is        => 'ro', | 
| 91 |  |  |  |  |  |  | isa       => Str, | 
| 92 |  |  |  |  |  |  | predicate => 'has_return_signature', | 
| 93 |  |  |  |  |  |  | ); | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | has _return_type_constraint => ( | 
| 96 |  |  |  |  |  |  | is      => 'ro', | 
| 97 |  |  |  |  |  |  | isa     => class_type('Moose::Meta::TypeConstraint'), | 
| 98 |  |  |  |  |  |  | lazy    => 1, | 
| 99 |  |  |  |  |  |  | builder => '_build__return_type_constraint', | 
| 100 |  |  |  |  |  |  | ); | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | has actual_body => ( | 
| 103 |  |  |  |  |  |  | is        => 'ro', | 
| 104 |  |  |  |  |  |  | isa       => CodeRef, | 
| 105 |  |  |  |  |  |  | predicate => '_has_actual_body', | 
| 106 |  |  |  |  |  |  | ); | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | has prototype_injections => ( | 
| 109 |  |  |  |  |  |  | is          => 'rw', | 
| 110 |  |  |  |  |  |  | isa         => Injections, | 
| 111 |  |  |  |  |  |  | trigger     => \&_parse_prototype_injections | 
| 112 |  |  |  |  |  |  | ); | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | has _parsed_prototype_injections => ( | 
| 115 |  |  |  |  |  |  | is          => 'ro', | 
| 116 |  |  |  |  |  |  | isa         => Params, | 
| 117 |  |  |  |  |  |  | predicate   => '_has_parsed_prototype_injections', | 
| 118 |  |  |  |  |  |  | writer      => '_set_parsed_prototype_injections', | 
| 119 |  |  |  |  |  |  | ); | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | before actual_body => sub { | 
| 122 |  |  |  |  |  |  | my ($self) = @_; | 
| 123 |  |  |  |  |  |  | confess "method doesn't have an actual body yet" | 
| 124 |  |  |  |  |  |  | unless $self->_has_actual_body; | 
| 125 |  |  |  |  |  |  | }; | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | around name => sub { | 
| 128 |  |  |  |  |  |  | my ($next, $self) = @_; | 
| 129 |  |  |  |  |  |  | my $ret = $self->$next; | 
| 130 |  |  |  |  |  |  | confess "method doesn't have a name yet" | 
| 131 |  |  |  |  |  |  | unless defined $ret; | 
| 132 |  |  |  |  |  |  | return $ret; | 
| 133 |  |  |  |  |  |  | }; | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | sub _wrapped_body { | 
| 136 | 313 |  |  | 313 |  | 1700 | my ($class, $self, %args) = @_; | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 313 | 100 |  |  |  | 1498 | if (exists $args{return_signature}) { | 
| 139 |  |  |  |  |  |  | return sub { | 
| 140 | 3 |  |  | 3 |  | 2008 | my @args = ${ $self }->validate(\@_); | 
|  | 3 |  |  |  |  | 14 |  | 
| 141 | 2 |  |  |  |  | 29 | return preserve_context { ${ $self }->actual_body->(@args) } | 
|  | 2 |  |  |  |  | 17 |  | 
| 142 |  |  |  |  |  |  | after => sub { | 
| 143 | 2 | 100 |  |  |  | 22 | if (defined (my $msg = ${ $self }->_return_type_constraint->validate(\@_))) { | 
|  | 2 |  |  |  |  | 101 |  | 
| 144 | 1 |  |  |  |  | 3419 | confess $msg; | 
| 145 |  |  |  |  |  |  | } | 
| 146 | 2 |  |  |  |  | 32 | }; | 
| 147 | 4 |  |  |  |  | 32 | }; | 
| 148 |  |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 309 |  |  |  |  | 455 | my $actual_body; | 
| 151 |  |  |  |  |  |  | return sub { | 
| 152 | 133 |  |  | 133 |  | 180296 | @_ = ${ $self }->validate(\@_); | 
|  | 133 |  |  | 115 |  | 703 |  | 
|  |  |  |  | 101 |  |  |  | 
|  |  |  |  | 90 |  |  |  | 
|  |  |  |  | 74 |  |  |  | 
|  |  |  |  | 60 |  |  |  | 
|  |  |  |  | 91 |  |  |  | 
|  |  |  |  | 32 |  |  |  | 
|  |  |  |  | 32 |  |  |  | 
|  |  |  |  | 32 |  |  |  | 
|  |  |  |  | 30 |  |  |  | 
|  |  |  |  | 32 |  |  |  | 
|  |  |  |  | 30 |  |  |  | 
|  |  |  |  | 32 |  |  |  | 
|  |  |  |  | 32 |  |  |  | 
|  |  |  |  | 30 |  |  |  | 
|  |  |  |  | 32 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
|  |  |  |  | 0 |  |  |  | 
| 153 | 88 |  | 66 |  |  | 562 | $actual_body ||= ${ $self }->actual_body; | 
|  | 67 |  |  |  |  | 536 |  | 
| 154 | 88 |  |  |  |  | 166 | goto &{ $actual_body }; | 
|  | 88 |  |  |  |  | 559 |  | 
| 155 | 309 |  |  |  |  | 2693 | }; | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | around wrap => sub { | 
| 160 |  |  |  |  |  |  | my $orig = shift; | 
| 161 |  |  |  |  |  |  | my $self; | 
| 162 |  |  |  |  |  |  | my ($class, $code, %args); | 
| 163 |  |  |  |  |  |  | if (ref $_[1]) { | 
| 164 |  |  |  |  |  |  | ($class, $code, %args) = @_; | 
| 165 |  |  |  |  |  |  | } else { | 
| 166 |  |  |  |  |  |  | ($class, %args) = @_; | 
| 167 |  |  |  |  |  |  | $code = delete $args{body}; | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | my $wrapped = $class->_wrapped_body(\$self, %args); | 
| 171 |  |  |  |  |  |  | $self = $class->$orig($wrapped, %args, $code ? (actual_body => $code) : ()); | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | # Vivify the type constraints so TC lookups happen before namespace::clean | 
| 174 |  |  |  |  |  |  | # removes them | 
| 175 |  |  |  |  |  |  | $self->type_constraint; | 
| 176 |  |  |  |  |  |  | $self->_return_type_constraint if $self->has_return_signature; | 
| 177 |  |  |  |  |  |  |  | 
| 178 |  |  |  |  |  |  | weaken($self->{associated_metaclass}) | 
| 179 |  |  |  |  |  |  | if $self->{associated_metaclass}; | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | return $self; | 
| 182 |  |  |  |  |  |  | }; | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | sub reify { | 
| 185 | 1 |  |  | 1 | 0 | 754 | my $self = shift; | 
| 186 | 1 |  |  |  |  | 3 | my %args = @_; | 
| 187 |  |  |  |  |  |  |  | 
| 188 | 1 |  |  |  |  | 3 | my %other_args = %{$self}; | 
|  | 1 |  |  |  |  | 12 |  | 
| 189 | 1 |  |  |  |  | 3 | delete $other_args{body}; | 
| 190 | 1 |  |  |  |  | 4 | delete $other_args{actual_body}; | 
| 191 |  |  |  |  |  |  |  | 
| 192 | 1 |  | 33 |  |  | 24 | my $body = delete $args{body} || delete $args{actual_body} || $self->body; | 
| 193 | 1 |  |  |  |  | 9 | my %final_args = (%other_args, %args); | 
| 194 |  |  |  |  |  |  |  | 
| 195 | 1 |  |  |  |  | 9 | return $self->meta->name->wrap($body, %final_args); | 
| 196 |  |  |  |  |  |  | } | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | sub _build_parsed_signature { | 
| 199 | 158 |  |  | 158 |  | 320 | my ($self) = @_; | 
| 200 | 158 |  |  |  |  | 8027 | return Parse::Method::Signatures->signature( | 
| 201 |  |  |  |  |  |  | input => $self->signature, | 
| 202 |  |  |  |  |  |  | from_namespace => $self->package_name, | 
| 203 |  |  |  |  |  |  | ); | 
| 204 |  |  |  |  |  |  | } | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | sub _build__return_type_constraint { | 
| 207 | 2 |  |  | 2 |  | 5 | my ($self) = @_; | 
| 208 | 2 | 50 |  |  |  | 127 | confess 'no return type constraint' | 
| 209 |  |  |  |  |  |  | unless $self->has_return_signature; | 
| 210 |  |  |  |  |  |  |  | 
| 211 | 2 |  |  |  |  | 120 | my $parser = Parse::Method::Signatures->new( | 
| 212 |  |  |  |  |  |  | input => $self->return_signature, | 
| 213 |  |  |  |  |  |  | from_namespace => $self->package_name, | 
| 214 |  |  |  |  |  |  | ); | 
| 215 |  |  |  |  |  |  |  | 
| 216 | 2 |  |  |  |  | 6912 | my $param = $parser->_param_typed({}); | 
| 217 | 2 | 50 |  |  |  | 3343 | confess 'failed to parse return value type constraint' | 
| 218 |  |  |  |  |  |  | unless exists $param->{type_constraints}; | 
| 219 |  |  |  |  |  |  |  | 
| 220 | 2 |  |  |  |  | 89 | return Tuple[$param->{type_constraints}->tc]; | 
| 221 |  |  |  |  |  |  | } | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | sub _param_to_spec { | 
| 224 | 210 |  |  | 210 |  | 9447 | my ($self, $param) = @_; | 
| 225 |  |  |  |  |  |  |  | 
| 226 | 210 |  |  |  |  | 813 | my $tc = Any; | 
| 227 |  |  |  |  |  |  | { | 
| 228 |  |  |  |  |  |  | # Ensure errors get reported from the right place | 
| 229 | 210 |  |  |  |  | 31924 | local $Carp::Internal{'MooseX::Method::Signatures::Meta::Method'} = 1; | 
|  | 210 |  |  |  |  | 874 |  | 
| 230 | 210 |  |  |  |  | 636 | local $Carp::Internal{'Moose::Meta::Method::Delegation'} = 1; | 
| 231 | 210 |  |  |  |  | 857 | local $Carp::Internal{'Moose::Meta::Method::Accessor'} = 1; | 
| 232 | 210 |  |  |  |  | 633 | local $Carp::Internal{'MooseX::Method::Signatures'} = 1; | 
| 233 | 210 |  |  |  |  | 663 | local $Carp::Internal{'Devel::Declare'} = 1; | 
| 234 | 210 | 100 |  |  |  | 14230 | $tc = $param->meta_type_constraint | 
| 235 |  |  |  |  |  |  | if $param->has_type_constraints; | 
| 236 |  |  |  |  |  |  | } | 
| 237 |  |  |  |  |  |  |  | 
| 238 | 210 | 100 |  |  |  | 125829 | if ($param->has_constraints) { | 
| 239 | 31 |  |  |  |  | 1579 | my $cb = join ' && ', map { "sub {${_}}->(\\\@_)" } $param->constraints; | 
|  | 34 |  |  |  |  | 467 |  | 
| 240 | 31 |  |  |  |  | 5574 | my $code = eval "sub {${cb}}"; | 
| 241 | 31 |  |  |  |  | 280 | $tc = subtype({ as => $tc, where => $code }); | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 | 210 |  |  |  |  | 38220 | my %spec; | 
| 245 | 210 | 100 |  |  |  | 9028 | if ($param->sigil ne '$') { | 
| 246 | 23 |  |  |  |  | 221 | $spec{slurpy} = 1; | 
| 247 | 23 |  |  |  |  | 131 | $tc = slurpy ArrayRef[$tc]; | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  |  | 
| 250 | 209 | 100 |  |  |  | 193979 | $spec{tc} = $param->required | 
| 251 |  |  |  |  |  |  | ? $tc | 
| 252 |  |  |  |  |  |  | : Optional[$tc]; | 
| 253 |  |  |  |  |  |  |  | 
| 254 | 209 | 100 |  |  |  | 340737 | $spec{default} = $param->default_value | 
| 255 |  |  |  |  |  |  | if $param->has_default_value; | 
| 256 |  |  |  |  |  |  |  | 
| 257 | 209 | 100 |  |  |  | 12160 | if ($param->has_traits) { | 
| 258 | 34 |  |  |  |  | 316 | for my $trait (@{ $param->param_traits }) { | 
|  | 34 |  |  |  |  | 1434 |  | 
| 259 | 34 | 50 |  |  |  | 393 | next unless $trait->[1] eq 'coerce'; | 
| 260 | 34 |  |  |  |  | 153 | $spec{coerce} = 1; | 
| 261 |  |  |  |  |  |  | } | 
| 262 |  |  |  |  |  |  | } | 
| 263 |  |  |  |  |  |  |  | 
| 264 | 209 |  |  |  |  | 1771 | return \%spec; | 
| 265 |  |  |  |  |  |  | } | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | sub _parse_prototype_injections { | 
| 268 | 6 |  |  | 6 |  | 38834 | my $self = shift; | 
| 269 |  |  |  |  |  |  |  | 
| 270 | 6 |  |  |  |  | 18 | my @params; | 
| 271 | 6 |  |  |  |  | 27 | for my $inject (@{ $self->prototype_injections }) { | 
|  | 6 |  |  |  |  | 314 |  | 
| 272 | 6 |  |  |  |  | 10 | my $param; | 
| 273 | 6 |  |  |  |  | 16 | eval { | 
| 274 | 6 |  |  |  |  | 55 | $param = Parse::Method::Signatures->param($inject); | 
| 275 |  |  |  |  |  |  | }; | 
| 276 |  |  |  |  |  |  |  | 
| 277 | 6 | 50 | 33 |  |  | 412622 | confess "There was a problem parsing the prototype injection '$inject': $@" | 
| 278 |  |  |  |  |  |  | if $@ || !defined $param; | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 6 |  |  |  |  | 30 | push @params, $param; | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | 
| 283 | 6 |  |  |  |  | 23 | my @return = reverse @params; | 
| 284 | 6 |  |  |  |  | 369 | $self->_set_parsed_prototype_injections(\@return); | 
| 285 |  |  |  |  |  |  | } | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | sub _build__lexicals { | 
| 288 | 152 |  |  | 152 |  | 335 | my ($self) = @_; | 
| 289 | 152 |  |  |  |  | 7760 | my ($sig) = $self->parsed_signature; | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 152 |  |  |  |  | 349 | my @lexicals; | 
| 292 |  |  |  |  |  |  |  | 
| 293 | 152 | 100 |  |  |  | 9482 | if ($self->_has_parsed_prototype_injections) { | 
| 294 | 3 |  |  |  |  | 160 | push @lexicals, $_->variable_name | 
| 295 | 3 |  |  |  |  | 6 | for @{ $self->_parsed_prototype_injections }; | 
| 296 |  |  |  |  |  |  | } | 
| 297 |  |  |  |  |  |  |  | 
| 298 | 152 | 100 |  |  |  | 7533 | push @lexicals, $sig->has_invocant | 
| 299 |  |  |  |  |  |  | ? $sig->invocant->variable_name | 
| 300 |  |  |  |  |  |  | : '$self'; | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | push @lexicals, | 
| 303 |  |  |  |  |  |  | (does_role($_, Placeholder) | 
| 304 |  |  |  |  |  |  | ? 'undef' | 
| 305 |  |  |  |  |  |  | : $_->variable_name) | 
| 306 | 152 | 100 |  |  |  | 3753 | for (($sig->has_positional_params ? $sig->positional_params : ()), | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | ($sig->has_named_params      ? $sig->named_params      : ())); | 
| 308 |  |  |  |  |  |  |  | 
| 309 | 152 |  |  |  |  | 175774 | return \@lexicals; | 
| 310 |  |  |  |  |  |  | } | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | sub _build_injectable_code { | 
| 313 | 152 |  |  | 152 |  | 312 | my ($self) = @_; | 
| 314 | 152 |  |  |  |  | 302 | my $vars = join q{,}, @{ $self->_lexicals }; | 
|  | 152 |  |  |  |  | 7657 |  | 
| 315 | 152 |  |  |  |  | 7882 | return "my (${vars}) = \@_;"; | 
| 316 |  |  |  |  |  |  | } | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | sub _build__positional_args { | 
| 319 | 158 |  |  | 158 |  | 469 | my ($self) = @_; | 
| 320 | 158 |  |  |  |  | 7974 | my $sig = $self->parsed_signature; | 
| 321 |  |  |  |  |  |  |  | 
| 322 | 157 |  |  |  |  | 385 | my @positional; | 
| 323 | 157 | 100 |  |  |  | 10003 | if ($self->_has_parsed_prototype_injections) { | 
| 324 | 3 |  |  |  |  | 14 | push @positional, map { | 
| 325 | 3 |  |  |  |  | 166 | $self->_param_to_spec($_) | 
| 326 | 3 |  |  |  |  | 7 | } @{ $self->_parsed_prototype_injections }; | 
| 327 |  |  |  |  |  |  | } | 
| 328 |  |  |  |  |  |  |  | 
| 329 | 157 | 100 |  |  |  | 7191 | push @positional, $sig->has_invocant | 
| 330 |  |  |  |  |  |  | ? $self->_param_to_spec($sig->invocant) | 
| 331 |  |  |  |  |  |  | : { tc => Object }; | 
| 332 |  |  |  |  |  |  |  | 
| 333 | 157 |  |  |  |  | 28393 | my $slurpy = 0; | 
| 334 | 157 | 100 |  |  |  | 952 | if ($sig->has_positional_params) { | 
| 335 | 101 |  |  |  |  | 24476 | for my $param ($sig->positional_params) { | 
| 336 | 126 |  |  |  |  | 10524 | my $spec = $self->_param_to_spec($param); | 
| 337 | 125 | 100 | 50 |  |  | 714 | $slurpy ||= 1 if $spec->{slurpy}; | 
| 338 | 125 |  |  |  |  | 446 | push @positional, $spec; | 
| 339 |  |  |  |  |  |  | } | 
| 340 |  |  |  |  |  |  | } | 
| 341 |  |  |  |  |  |  |  | 
| 342 | 156 |  |  |  |  | 12449 | $self->_has_slurpy_positional($slurpy); | 
| 343 | 156 |  |  |  |  | 7590 | return \@positional; | 
| 344 |  |  |  |  |  |  | } | 
| 345 |  |  |  |  |  |  |  | 
| 346 |  |  |  |  |  |  | sub _build__named_args { | 
| 347 | 156 |  |  | 156 |  | 329 | my ($self) = @_; | 
| 348 | 156 |  |  |  |  | 13564 | my $sig = $self->parsed_signature; | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | # triggering building of positionals before named params is important | 
| 351 |  |  |  |  |  |  | # because the latter needs to know if there have been any slurpy | 
| 352 |  |  |  |  |  |  | # positionals to report errors | 
| 353 | 156 |  |  |  |  | 8210 | $self->_positional_args; | 
| 354 |  |  |  |  |  |  |  | 
| 355 | 156 |  |  |  |  | 272 | my @named; | 
| 356 |  |  |  |  |  |  |  | 
| 357 | 156 | 100 |  |  |  | 891 | if ($sig->has_named_params) { | 
| 358 | 52 | 100 |  |  |  | 12344 | confess 'Named parameters cannot be combined with slurpy positionals' | 
| 359 |  |  |  |  |  |  | if $self->_has_slurpy_positional; | 
| 360 | 51 |  |  |  |  | 202 | for my $param ($sig->named_params) { | 
| 361 | 61 |  |  |  |  | 7954 | push @named, $param->label => $self->_param_to_spec($param); | 
| 362 |  |  |  |  |  |  | } | 
| 363 |  |  |  |  |  |  | } | 
| 364 |  |  |  |  |  |  |  | 
| 365 | 155 |  |  |  |  | 13452 | return \@named; | 
| 366 |  |  |  |  |  |  | } | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | sub _build_type_constraint { | 
| 369 | 158 |  |  | 158 |  | 317 | my ($self) = @_; | 
| 370 | 158 |  |  |  |  | 438 | my ($positional, $named) = map { $self->$_ } map { "_${_}_args" } qw/positional named/; | 
|  | 314 |  |  |  |  | 27653 |  | 
|  | 316 |  |  |  |  | 1205 |  | 
| 371 |  |  |  |  |  |  |  | 
| 372 | 281 |  |  |  |  | 965 | my $tc = Tuple[ | 
| 373 | 155 | 100 |  |  |  | 361 | Tuple[ map { $_->{tc}               } @{ $positional } ], | 
|  | 122 |  |  |  |  | 687 |  | 
| 374 | 155 |  |  |  |  | 512 | Dict[  map { ref $_ ? $_->{tc} : $_ } @{ $named      } ], | 
|  | 155 |  |  |  |  | 950 |  | 
| 375 |  |  |  |  |  |  | ]; | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | my $coerce_param = sub { | 
| 378 | 313 |  |  | 313 |  | 548 | my ($spec, $value) = @_; | 
| 379 | 313 | 100 |  |  |  | 1513 | return $value unless exists $spec->{coerce}; | 
| 380 | 7 |  |  |  |  | 53 | return $spec->{tc}->coerce($value); | 
| 381 | 155 |  |  |  |  | 2185006 | }; | 
| 382 |  |  |  |  |  |  |  | 
| 383 | 155 |  |  |  |  | 472 | my %named = @{ $named }; | 
|  | 155 |  |  |  |  | 596 |  | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | coerce $tc, | 
| 386 |  |  |  |  |  |  | from ArrayRef, | 
| 387 |  |  |  |  |  |  | via { | 
| 388 | 136 |  |  | 136 |  | 760995 | my (@positional_args, %named_args); | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 136 |  |  |  |  | 318 | my $i = 0; | 
| 391 | 136 |  |  |  |  | 253 | for my $param (@{ $positional }) { | 
|  | 136 |  |  |  |  | 432 |  | 
| 392 | 260 |  |  |  |  | 687 | push @positional_args, map { $coerce_param->($param, $_) } | 
|  | 291 |  |  |  |  | 1772 |  | 
| 393 | 291 | 100 |  |  |  | 414 | $#{ $_ } < $i | 
|  |  | 100 |  |  |  |  |  | 
| 394 |  |  |  |  |  |  | ? (exists $param->{default} ? eval $param->{default} : ()) | 
| 395 |  |  |  |  |  |  | : $_->[$i]; | 
| 396 | 291 |  |  |  |  | 3600 | $i++; | 
| 397 |  |  |  |  |  |  | } | 
| 398 |  |  |  |  |  |  |  | 
| 399 | 136 | 100 |  |  |  | 481 | if (%named) { | 
|  | 89 | 100 |  |  |  | 360 |  | 
| 400 | 47 |  |  |  |  | 132 | my @rest = @{ $_ }[$i .. $#{ $_ }]; | 
|  | 47 |  |  |  |  | 205 |  | 
|  | 47 |  |  |  |  | 127 |  | 
| 401 | 47 | 100 |  |  |  | 796 | confess "Expected named arguments but didn't find an even-sized list" | 
| 402 |  |  |  |  |  |  | unless @rest % 2 == 0; | 
| 403 | 44 |  |  |  |  | 172 | my %rest = @rest; | 
| 404 |  |  |  |  |  |  |  | 
| 405 | 44 |  |  |  |  | 254 | while (my ($key, $spec) = each %named) { | 
| 406 | 68 | 100 |  |  |  | 201 | if (exists $rest{$key}) { | 
| 407 | 48 |  |  |  |  | 159 | $named_args{$key} = $coerce_param->($spec, delete $rest{$key}); | 
| 408 | 48 |  |  |  |  | 1573 | next; | 
| 409 |  |  |  |  |  |  | } | 
| 410 |  |  |  |  |  |  |  | 
| 411 | 20 | 100 |  |  |  | 106 | if (exists $spec->{default}) { | 
| 412 | 5 |  |  |  |  | 410 | $named_args{$key} = $coerce_param->($spec, eval $spec->{default}); | 
| 413 |  |  |  |  |  |  | } | 
| 414 |  |  |  |  |  |  | } | 
| 415 |  |  |  |  |  |  |  | 
| 416 | 44 |  |  |  |  | 178 | @named_args{keys %rest} = values %rest; | 
| 417 |  |  |  |  |  |  | } | 
| 418 |  |  |  |  |  |  | elsif ($#{ $_ } >= $i) { | 
| 419 | 8 |  |  |  |  | 20 | push @positional_args, @{ $_ }[$i .. $#{ $_ }]; | 
|  | 8 |  |  |  |  | 22 |  | 
|  | 8 |  |  |  |  | 19 |  | 
| 420 |  |  |  |  |  |  | } | 
| 421 |  |  |  |  |  |  |  | 
| 422 | 133 |  |  |  |  | 1154 | return [\@positional_args, \%named_args]; | 
| 423 | 155 |  |  |  |  | 780 | }; | 
| 424 |  |  |  |  |  |  |  | 
| 425 | 155 |  |  |  |  | 403707 | return MooseX::Meta::TypeConstraint::ForceCoercion->new( | 
| 426 |  |  |  |  |  |  | type_constraint => $tc, | 
| 427 |  |  |  |  |  |  | ); | 
| 428 |  |  |  |  |  |  | } | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | sub validate { | 
| 431 | 136 |  |  | 136 | 0 | 309 | my ($self, $args) = @_; | 
| 432 |  |  |  |  |  |  |  | 
| 433 | 136 |  |  |  |  | 267 | my @named = grep { !ref $_ } @{ $self->_named_args }; | 
|  | 142 |  |  |  |  | 411 |  | 
|  | 136 |  |  |  |  | 7216 |  | 
| 434 |  |  |  |  |  |  |  | 
| 435 | 136 |  |  |  |  | 277 | my $coerced; | 
| 436 | 136 | 100 |  |  |  | 6564 | if (defined (my $msg = $self->type_constraint->validate($args, \$coerced))) { | 
| 437 | 43 |  |  |  |  | 271253 | confess $msg; | 
| 438 |  |  |  |  |  |  | } | 
| 439 |  |  |  |  |  |  |  | 
| 440 | 90 |  |  |  |  | 291385 | return @{ $coerced->[0] }, map { $coerced->[1]->{$_} } @named; | 
|  | 90 |  |  |  |  | 584 |  | 
|  | 37 |  |  |  |  | 233 |  | 
| 441 |  |  |  |  |  |  | } | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | __PACKAGE__->meta->make_immutable; | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | 1; | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | __END__ | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | =pod | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | =encoding UTF-8 | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | =for :stopwords Florian Ragwitz metaclass | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | =head1 NAME | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | MooseX::Method::Signatures::Meta::Method - Provides the metaclass for methods with signatures | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | =head1 VERSION | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | version 0.47 | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | =head1 AUTHOR | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | Florian Ragwitz <rafl@debian.org> | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 469 |  |  |  |  |  |  |  | 
| 470 |  |  |  |  |  |  | This software is copyright (c) 2013 by Florian Ragwitz. | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  | This is free software; you can redistribute it and/or modify it under | 
| 473 |  |  |  |  |  |  | the same terms as the Perl 5 programming language system itself. | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | =cut |