| line | stmt | bran | cond | sub | pod | time | code | 
| 1 | 27 |  |  | 27 |  | 10141460 | use strict; | 
|  | 27 |  |  |  |  | 66 |  | 
|  | 27 |  |  |  |  | 5179 |  | 
| 2 | 27 |  |  | 27 |  | 332 | use warnings; | 
|  | 27 |  |  |  |  | 225 |  | 
|  | 27 |  |  |  |  | 3509 |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  | package MooseX::Method::Signatures; | 
| 5 |  |  |  |  |  |  | { | 
| 6 |  |  |  |  |  |  | $MooseX::Method::Signatures::VERSION = '0.47'; | 
| 7 |  |  |  |  |  |  | } | 
| 8 |  |  |  |  |  |  | # git description: v0.46-8-ga38401b | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | BEGIN { | 
| 11 | 27 |  |  | 27 |  | 696 | $MooseX::Method::Signatures::AUTHORITY = 'cpan:ETHER'; | 
| 12 |  |  |  |  |  |  | } | 
| 13 |  |  |  |  |  |  | # ABSTRACT: Method declarations with type constraints and no source filter | 
| 14 |  |  |  |  |  |  |  | 
| 15 | 27 |  |  | 27 |  | 11348 | use Moose 0.89; | 
|  | 27 |  |  |  |  | 5794936 |  | 
|  | 27 |  |  |  |  | 216 |  | 
| 16 | 27 |  |  | 27 |  | 225823 | use Devel::Declare 0.005011 (); | 
|  | 27 |  |  |  |  | 146102 |  | 
|  | 27 |  |  |  |  | 927 |  | 
| 17 | 27 |  |  | 27 |  | 241 | use B::Hooks::EndOfScope 0.10; | 
|  | 27 |  |  |  |  | 564 |  | 
|  | 27 |  |  |  |  | 251 |  | 
| 18 | 27 |  |  | 27 |  | 2499 | use Moose::Meta::Class; | 
|  | 27 |  |  |  |  | 71 |  | 
|  | 27 |  |  |  |  | 960 |  | 
| 19 | 27 |  |  | 27 |  | 43044 | use MooseX::LazyRequire 0.06; | 
|  | 27 |  |  |  |  | 581286 |  | 
|  | 27 |  |  |  |  | 191 |  | 
| 20 | 27 |  |  | 27 |  | 360563 | use MooseX::Types::Moose 0.19 qw/Str Bool CodeRef/; | 
|  | 27 |  |  |  |  | 1549907 |  | 
|  | 27 |  |  |  |  | 331 |  | 
| 21 | 27 |  |  | 27 |  | 198283 | use Text::Balanced qw/extract_quotelike/; | 
|  | 27 |  |  |  |  | 564643 |  | 
|  | 27 |  |  |  |  | 3203 |  | 
| 22 | 27 |  |  | 27 |  | 21700 | use MooseX::Method::Signatures::Meta::Method; | 
|  | 27 |  |  |  |  | 128 |  | 
|  | 27 |  |  |  |  | 1642 |  | 
| 23 | 27 |  |  | 27 |  | 287 | use MooseX::Method::Signatures::Types qw/PrototypeInjections/; | 
|  | 27 |  |  |  |  | 97 |  | 
|  | 27 |  |  |  |  | 318 |  | 
| 24 | 27 |  |  | 27 |  | 40680 | use Sub::Name; | 
|  | 27 |  |  |  |  | 67 |  | 
|  | 27 |  |  |  |  | 1798 |  | 
| 25 | 27 |  |  | 27 |  | 168 | use Moose::Util 'find_meta'; | 
|  | 27 |  |  |  |  | 62 |  | 
|  | 27 |  |  |  |  | 265 |  | 
| 26 | 27 |  |  | 27 |  | 5523 | use Module::Runtime 'use_module'; | 
|  | 27 |  |  |  |  | 75 |  | 
|  | 27 |  |  |  |  | 225 |  | 
| 27 | 27 |  |  | 27 |  | 1075 | use Carp; | 
|  | 27 |  |  |  |  | 59 |  | 
|  | 27 |  |  |  |  | 1815 |  | 
| 28 |  |  |  |  |  |  |  | 
| 29 | 27 |  |  | 27 |  | 243 | use aliased 'Devel::Declare::Context::Simple', 'ContextSimple'; | 
|  | 27 |  |  |  |  | 60 |  | 
|  | 27 |  |  |  |  | 260 |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 | 27 |  |  | 27 |  | 124219 | use namespace::autoclean; | 
|  | 27 |  |  |  |  | 69 |  | 
|  | 27 |  |  |  |  | 327 |  | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | has package => ( | 
| 34 |  |  |  |  |  |  | is            => 'ro', | 
| 35 |  |  |  |  |  |  | isa           => Str, | 
| 36 |  |  |  |  |  |  | lazy_required => 1, | 
| 37 |  |  |  |  |  |  | ); | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | has context => ( | 
| 40 |  |  |  |  |  |  | is      => 'ro', | 
| 41 |  |  |  |  |  |  | isa     => ContextSimple, | 
| 42 |  |  |  |  |  |  | lazy    => 1, | 
| 43 |  |  |  |  |  |  | builder => '_build_context', | 
| 44 |  |  |  |  |  |  | ); | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | has initialized_context => ( | 
| 47 |  |  |  |  |  |  | is      => 'ro', | 
| 48 |  |  |  |  |  |  | isa     => Bool, | 
| 49 |  |  |  |  |  |  | default => 0, | 
| 50 |  |  |  |  |  |  | ); | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | has custom_method_application => ( | 
| 53 |  |  |  |  |  |  | is        => 'ro', | 
| 54 |  |  |  |  |  |  | isa       => CodeRef, | 
| 55 |  |  |  |  |  |  | predicate => 'has_custom_method_application', | 
| 56 |  |  |  |  |  |  | ); | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | has prototype_injections => ( | 
| 59 |  |  |  |  |  |  | is        => 'ro', | 
| 60 |  |  |  |  |  |  | isa       => PrototypeInjections, | 
| 61 |  |  |  |  |  |  | predicate => 'has_prototype_injections', | 
| 62 |  |  |  |  |  |  | ); | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | sub _build_context { | 
| 65 | 87 |  |  | 87 |  | 6321 | my ($self) = @_; | 
| 66 | 87 |  |  |  |  | 4039 | return ContextSimple->new(into => $self->package); | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | sub import { | 
| 70 | 88 |  |  | 88 |  | 547413 | my ($class, %args) = @_; | 
| 71 | 88 |  |  |  |  | 298 | my $caller = caller(); | 
| 72 | 88 |  |  |  |  | 539 | $class->setup_for($caller, \%args); | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | sub setup_for { | 
| 76 | 88 |  |  | 88 | 0 | 332 | my ($class, $pkg, $args) = @_; | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | # process arguments to import | 
| 79 | 88 |  |  |  |  | 233 | while (my ($declarator, $injections) = each %{ $args }) { | 
|  | 91 |  |  |  |  | 637 |  | 
| 80 | 3 |  |  |  |  | 143 | my $obj = $class->new( | 
| 81 |  |  |  |  |  |  | package              => $pkg, | 
| 82 |  |  |  |  |  |  | prototype_injections => { | 
| 83 |  |  |  |  |  |  | declarator => $declarator, | 
| 84 |  |  |  |  |  |  | injections => $injections, | 
| 85 |  |  |  |  |  |  | }, | 
| 86 |  |  |  |  |  |  | ); | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | Devel::Declare->setup_for($pkg, { | 
| 89 | 3 |  |  | 3 |  | 572 | $declarator => { const => sub { $obj->parser(@_) } }, | 
| 90 | 3 |  |  |  |  | 37 | }); | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | { | 
| 93 | 27 |  |  | 27 |  | 11144 | no strict 'refs'; | 
|  | 27 |  |  |  |  | 61 |  | 
|  | 27 |  |  |  |  | 3537 |  | 
|  | 3 |  |  |  |  | 83 |  | 
| 94 | 3 |  |  | 0 |  | 11 | *{ "${pkg}::$declarator" } = sub {}; | 
|  | 3 |  |  |  |  | 27 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 95 |  |  |  |  |  |  | } | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 88 |  |  |  |  | 4459 | my $self = $class->new(package => $pkg); | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | Devel::Declare->setup_for($pkg, { | 
| 101 | 152 |  |  | 152 |  | 226367 | method => { const => sub { $self->parser(@_) } }, | 
| 102 | 88 |  |  |  |  | 1452 | }); | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | { | 
| 105 | 27 |  |  | 27 |  | 150 | no strict 'refs'; | 
|  | 27 |  |  |  |  | 56 |  | 
|  | 27 |  |  |  |  | 62705 |  | 
|  | 88 |  |  |  |  | 3873 |  | 
| 106 | 88 |  |  | 1 |  | 476 | *{ "${pkg}::method" } = sub {}; | 
|  | 88 |  |  |  |  | 614 |  | 
|  | 1 |  |  |  |  | 36 |  | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  |  | 
| 109 | 88 |  |  |  |  | 7639 | return; | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | sub strip_name { | 
| 113 | 155 |  |  | 155 | 0 | 352 | my ($self) = @_; | 
| 114 | 155 |  |  |  |  | 6599 | my $ctx = $self->context; | 
| 115 | 155 |  |  |  |  | 829 | my $ret = $ctx->strip_name; | 
| 116 | 155 | 100 |  |  |  | 6037 | return $ret if defined $ret; | 
| 117 |  |  |  |  |  |  |  | 
| 118 | 20 |  |  |  |  | 64 | my $line = $ctx->get_linestr; | 
| 119 | 20 |  |  |  |  | 148 | my $offset = $ctx->offset; | 
| 120 | 20 |  |  |  |  | 82 | local $@; | 
| 121 | 20 |  |  |  |  | 60 | my $copy = substr($line, $offset); | 
| 122 | 20 |  |  |  |  | 124 | my ($str) = extract_quotelike($copy); | 
| 123 | 20 | 100 |  |  |  | 1906 | return unless defined $str; | 
| 124 |  |  |  |  |  |  |  | 
| 125 | 2 | 50 | 33 |  |  | 12 | return if ($@ && $@ =~ /^No quotelike operator found/); | 
| 126 | 2 | 50 |  |  |  | 8 | die $@ if $@; | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 2 |  |  |  |  | 5 | substr($line, $offset, length $str) = ''; | 
| 129 | 2 |  |  |  |  | 9 | $ctx->set_linestr($line); | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 2 |  |  |  |  | 15 | return \$str; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | sub strip_traits { | 
| 135 | 155 |  |  | 155 | 0 | 313 | my ($self) = @_; | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 155 |  |  |  |  | 7684 | my $ctx = $self->context; | 
| 138 | 155 |  |  |  |  | 564 | my $linestr = $ctx->get_linestr; | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 155 | 100 | 100 |  |  | 1249 | unless (substr($linestr, $ctx->offset, 2) eq 'is' || | 
| 141 |  |  |  |  |  |  | substr($linestr, $ctx->offset, 4) eq 'does') { | 
| 142 |  |  |  |  |  |  | # No 'is' means no traits | 
| 143 | 148 |  |  |  |  | 2469 | return; | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 7 |  |  |  |  | 85 | my @traits; | 
| 147 |  |  |  |  |  |  |  | 
| 148 | 7 |  |  |  |  | 10 | while (1) { | 
| 149 | 17 | 100 |  |  |  | 93 | if (substr($linestr, $ctx->offset, 2) eq 'is') { | 
|  |  | 100 |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | # Eat the 'is' so we can call strip_names_and_args | 
| 151 | 6 |  |  |  |  | 51 | substr($linestr, $ctx->offset, 2) = ''; | 
| 152 |  |  |  |  |  |  | } elsif (substr($linestr, $ctx->offset, 4) eq 'does') { | 
| 153 |  |  |  |  |  |  | # Eat the 'does' so we can call strip_names_and_args | 
| 154 | 4 |  |  |  |  | 46 | substr($linestr, $ctx->offset, 4) = ''; | 
| 155 |  |  |  |  |  |  | } else { | 
| 156 | 7 |  |  |  |  | 66 | last; | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 10 |  |  |  |  | 60 | $ctx->set_linestr($linestr); | 
| 160 | 10 |  |  |  |  | 44 | push @traits, @{ $ctx->strip_names_and_args }; | 
|  | 10 |  |  |  |  | 38 |  | 
| 161 |  |  |  |  |  |  | # Get the current linestr so that the loop can look for more 'is' | 
| 162 | 10 |  |  |  |  | 740 | $ctx->skipspace; | 
| 163 | 10 |  |  |  |  | 90 | $linestr = $ctx->get_linestr; | 
| 164 |  |  |  |  |  |  | } | 
| 165 |  |  |  |  |  |  |  | 
| 166 | 7 | 50 |  |  |  | 25 | confess "expected traits after 'is' or 'does', found nothing" | 
| 167 |  |  |  |  |  |  | unless scalar(@traits); | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | # Let's check to make sure these traits aren't aliased locally | 
| 170 | 7 |  |  |  |  | 16 | for my $t (@traits) { | 
| 171 | 12 | 50 |  |  |  | 37 | next if $t->[0] =~ /::/; | 
| 172 | 12 |  |  |  |  | 35 | my $class = $ctx->get_curstash_name; | 
| 173 | 12 |  | 33 |  |  | 75 | my $meta = find_meta($class) || Moose::Meta::Class->initialize($class); | 
| 174 | 12 |  |  |  |  | 170 | my $func = $meta->get_package_symbol('&' . $t->[0]); | 
| 175 | 12 | 100 |  |  |  | 163 | next unless $func; | 
| 176 |  |  |  |  |  |  |  | 
| 177 | 7 |  |  |  |  | 16 | my $proto = prototype $func; | 
| 178 | 7 | 50 | 33 |  |  | 47 | next if !defined $proto || length $proto; | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 7 |  |  |  |  | 27 | $t->[0] = $func->(); | 
| 181 |  |  |  |  |  |  | } | 
| 182 |  |  |  |  |  |  |  | 
| 183 | 7 |  |  |  |  | 29 | return \@traits; | 
| 184 |  |  |  |  |  |  | } | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | sub strip_return_type_constraint { | 
| 187 | 155 |  |  | 155 | 0 | 309 | my ($self) = @_; | 
| 188 | 155 |  |  |  |  | 6286 | my $ctx = $self->context; | 
| 189 | 155 |  |  |  |  | 2325 | my $returns = $ctx->strip_name; | 
| 190 | 155 | 100 |  |  |  | 3955 | return unless defined $returns; | 
| 191 | 2 | 50 |  |  |  | 8 | confess "expected 'returns', found '${returns}'" | 
| 192 |  |  |  |  |  |  | unless $returns eq 'returns'; | 
| 193 | 2 |  |  |  |  | 7 | return $ctx->strip_proto; | 
| 194 |  |  |  |  |  |  | } | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | sub parser { | 
| 197 | 155 |  |  | 155 | 0 | 381 | my $self = shift; | 
| 198 | 155 |  |  |  |  | 294 | my $err; | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | # Keep any previous compile errors from getting stepped on. But report | 
| 201 |  |  |  |  |  |  | # errors from inside MXMS nicely. | 
| 202 |  |  |  |  |  |  | { | 
| 203 | 155 |  |  |  |  | 505 | local $@; | 
|  | 155 |  |  |  |  | 337 |  | 
| 204 | 155 |  |  |  |  | 404 | eval { $self->_parser(@_) }; | 
|  | 155 |  |  |  |  | 787 |  | 
| 205 | 155 |  |  |  |  | 79652 | $err = $@; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  |  | 
| 208 | 155 | 100 |  |  |  | 5279 | die $err if $err; | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | my $anon_counter = 1; | 
| 212 |  |  |  |  |  |  | sub _parser { | 
| 213 | 155 |  |  | 155 |  | 328 | my $self = shift; | 
| 214 | 155 |  |  |  |  | 8670 | my $ctx = $self->context; | 
| 215 | 155 | 50 |  |  |  | 7454 | $ctx->init(@_) unless $self->initialized_context; | 
| 216 |  |  |  |  |  |  |  | 
| 217 | 155 |  |  |  |  | 2363 | $ctx->skip_declarator; | 
| 218 | 155 |  |  |  |  | 5936 | my $name   = $self->strip_name; | 
| 219 | 155 |  |  |  |  | 1019 | my $proto  = $ctx->strip_proto; | 
| 220 | 155 |  | 100 |  |  | 7499 | my $attrs  = $ctx->strip_attrs || ''; | 
| 221 | 155 |  |  |  |  | 4356 | my $traits = $self->strip_traits; | 
| 222 | 155 |  |  |  |  | 609 | my $ret_tc = $self->strip_return_type_constraint; | 
| 223 |  |  |  |  |  |  |  | 
| 224 | 155 |  |  |  |  | 698 | my $compile_stash = $ctx->get_curstash_name; | 
| 225 |  |  |  |  |  |  |  | 
| 226 | 155 |  |  |  |  | 1142 | my %args = ( | 
| 227 |  |  |  |  |  |  | # This might get reset later, but its where we search for exported | 
| 228 |  |  |  |  |  |  | # symbols at compile time | 
| 229 |  |  |  |  |  |  | package_name => $compile_stash, | 
| 230 |  |  |  |  |  |  | ); | 
| 231 | 155 | 100 |  |  |  | 878 | $args{ signature        } = qq{($proto)} if defined $proto; | 
| 232 | 155 | 100 |  |  |  | 513 | $args{ traits           } = $traits      if $traits; | 
| 233 | 155 | 100 |  |  |  | 491 | $args{ return_signature } = $ret_tc      if defined $ret_tc; | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | # Class::MOP::Method requires a name | 
| 236 | 155 |  | 66 |  |  | 783 | $args{ name             } = $name || '__ANON__'.($anon_counter++).'__'; | 
| 237 |  |  |  |  |  |  |  | 
| 238 | 155 | 100 |  |  |  | 17489 | if ($self->has_prototype_injections) { | 
| 239 | 3 | 50 |  |  |  | 18 | confess('Configured declarator does not match context declarator') | 
| 240 |  |  |  |  |  |  | if $ctx->declarator ne $self->prototype_injections->{declarator}; | 
| 241 | 3 |  |  |  |  | 135 | $args{prototype_injections} = $self->prototype_injections->{injections}; | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 | 155 |  |  |  |  | 377 | my $meth_class = 'MooseX::Method::Signatures::Meta::Method'; | 
| 245 | 155 | 100 |  |  |  | 546 | if ($args{traits}) { | 
| 246 | 7 |  |  |  |  | 15 | my @traits = (); | 
| 247 | 7 |  |  |  |  | 20 | foreach my $t (@{$args{traits}}) { | 
|  | 7 |  |  |  |  | 20 |  | 
| 248 | 12 |  |  |  |  | 50 | use_module($t->[0]); | 
| 249 | 12 | 100 |  |  |  | 335 | if ($t->[1]) { | 
| 250 | 1 |  |  |  |  | 75 | %args = (%args, eval $t->[1]); | 
| 251 |  |  |  |  |  |  | }; | 
| 252 | 12 |  |  |  |  | 44 | push @traits, $t->[0]; | 
| 253 |  |  |  |  |  |  | } | 
| 254 | 7 |  |  |  |  | 69 | my $meta = Moose::Meta::Class->create_anon_class( | 
| 255 |  |  |  |  |  |  | superclasses => [ $meth_class  ], | 
| 256 |  |  |  |  |  |  | roles        => [ @traits ], | 
| 257 |  |  |  |  |  |  | cache        => 1, | 
| 258 |  |  |  |  |  |  | ); | 
| 259 | 7 |  |  |  |  | 42825 | $meth_class = $meta->name; | 
| 260 | 7 |  |  |  |  | 30 | delete $args{traits}; | 
| 261 |  |  |  |  |  |  | } | 
| 262 |  |  |  |  |  |  |  | 
| 263 | 155 |  |  | 0 |  | 2270 | my $proto_method = $meth_class->wrap(sub { }, %args); | 
|  | 0 |  |  |  |  | 0 |  | 
| 264 |  |  |  |  |  |  |  | 
| 265 | 152 |  |  |  |  | 616 | my $after_block = ')'; | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 152 | 100 |  |  |  | 592 | if ($traits) { | 
| 268 | 7 | 100 |  |  |  | 13 | if (my @trait_args = grep { defined } map { $_->[1] } @{ $traits }) { | 
|  | 12 |  |  |  |  | 44 |  | 
|  | 12 |  |  |  |  | 30 |  | 
|  | 7 |  |  |  |  | 21 |  | 
| 269 | 1 |  |  |  |  | 4 | $after_block = q{, } . join(q{,} => @trait_args) . $after_block; | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  |  | 
| 273 | 152 | 100 |  |  |  | 572 | if (defined $name) { | 
| 274 | 136 | 100 |  |  |  | 802 | my $name_arg = q{, } . (ref $name ? ${$name} : qq{q[${name}]}); | 
|  | 2 |  |  |  |  | 9 |  | 
| 275 | 136 |  |  |  |  | 458 | $after_block = $name_arg . $after_block . q{;}; | 
| 276 |  |  |  |  |  |  | } | 
| 277 |  |  |  |  |  |  |  | 
| 278 | 152 |  |  |  |  | 8027 | my $inject = $proto_method->injectable_code; | 
| 279 | 152 |  |  |  |  | 1019 | $inject = $self->scope_injector_call($after_block) . $inject; | 
| 280 |  |  |  |  |  |  |  | 
| 281 | 152 |  |  |  |  | 1498 | $ctx->inject_if_block($inject, "(sub ${attrs} "); | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | my $create_meta_method = sub { | 
| 284 | 154 |  |  | 154 |  | 428 | my ($code, $pkg, $meth_name, @args) = @_; | 
| 285 | 154 |  |  |  |  | 1382 | subname $pkg . "::" .$meth_name, $code; | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | # we want to reinitialize with all the args, | 
| 288 |  |  |  |  |  |  | # so we give the opportunity for traits to wrap the correct | 
| 289 |  |  |  |  |  |  | # closure. | 
| 290 | 154 |  |  |  |  | 325 | my %other_args = %{$proto_method}; | 
|  | 154 |  |  |  |  | 7939 |  | 
| 291 | 154 |  |  |  |  | 597 | delete $other_args{body}; | 
| 292 | 154 |  |  |  |  | 314 | delete $other_args{actual_body}; | 
| 293 |  |  |  |  |  |  |  | 
| 294 | 154 |  |  |  |  | 1476 | my $ret = $meth_class->wrap( | 
| 295 |  |  |  |  |  |  | $code, | 
| 296 |  |  |  |  |  |  | %other_args, @args | 
| 297 |  |  |  |  |  |  | ); | 
| 298 | 152 |  |  |  |  | 9454 | }; | 
| 299 |  |  |  |  |  |  |  | 
| 300 | 152 | 100 |  |  |  | 510 | if (defined $name) { | 
| 301 |  |  |  |  |  |  | my $apply = $self->has_custom_method_application | 
| 302 |  |  |  |  |  |  | ? $self->custom_method_application | 
| 303 |  |  |  |  |  |  | : sub { | 
| 304 | 136 |  |  | 136 |  | 374 | my ($meta, $name, $method) = @_; | 
| 305 |  |  |  |  |  |  |  | 
| 306 | 136 | 100 | 100 |  |  | 23622 | if (warnings::enabled("redefine") && (my $meta_meth = $meta->get_method($name))) { | 
| 307 | 2 | 100 |  |  |  | 238 | warnings::warn("redefine", "Method $name redefined on package ${ \$meta->name }") | 
|  | 1 |  |  |  |  | 303 |  | 
| 308 |  |  |  |  |  |  | if $meta_meth->isa('MooseX::Method::Signatures::Meta::Method'); | 
| 309 |  |  |  |  |  |  | } | 
| 310 |  |  |  |  |  |  |  | 
| 311 | 136 |  |  |  |  | 11871 | $meta->add_method($name => $method); | 
| 312 | 136 | 50 |  |  |  | 9833 | }; | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | $ctx->shadow(sub { | 
| 315 | 136 |  |  | 136 |  | 9405 | my ($code, $name, @args) = @_; | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 136 |  |  |  |  | 312 | my $pkg = $compile_stash; | 
| 318 | 136 | 50 |  |  |  | 578 | ($pkg, $name) = $name =~ /^(.*)::([^:]+)$/ | 
| 319 |  |  |  |  |  |  | if $name =~ /::/; | 
| 320 |  |  |  |  |  |  |  | 
| 321 | 136 |  |  |  |  | 579 | my $meth = $create_meta_method->($code, $pkg, $name, @args); | 
| 322 | 136 |  |  |  |  | 1075 | my $meta = Moose::Meta::Class->initialize($pkg); | 
| 323 |  |  |  |  |  |  |  | 
| 324 | 136 |  |  |  |  | 7491 | $meta->$apply($name, $meth); | 
| 325 | 136 |  |  |  |  | 13583 | return; | 
| 326 | 136 |  |  |  |  | 1768 | }); | 
| 327 |  |  |  |  |  |  | } | 
| 328 |  |  |  |  |  |  | else { | 
| 329 |  |  |  |  |  |  | $ctx->shadow(sub { | 
| 330 | 18 |  |  | 18 |  | 9067 | return $create_meta_method->(shift, $compile_stash, '__ANON__', @_); | 
| 331 | 16 |  |  |  |  | 133 | }); | 
| 332 |  |  |  |  |  |  | } | 
| 333 |  |  |  |  |  |  | } | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | sub scope_injector_call { | 
| 336 | 152 |  |  | 152 | 0 | 354 | my ($self, $code) = @_; | 
| 337 | 152 |  |  |  |  | 406 | $code =~ s/'/\\'/g; # we're generating code that's quoted with single quotes | 
| 338 | 152 |  |  |  |  | 248 | return qq[BEGIN { ${\ref $self}->inject_scope('${code}') }]; | 
|  | 152 |  |  |  |  | 934 |  | 
| 339 |  |  |  |  |  |  | } | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | sub inject_scope { | 
| 342 | 152 |  |  | 152 | 0 | 23733 | my ($class, $inject) = @_; | 
| 343 |  |  |  |  |  |  | on_scope_end { | 
| 344 | 152 |  |  | 152 |  | 11801 | my $line = Devel::Declare::get_linestr(); | 
| 345 | 152 | 50 |  |  |  | 957 | return unless defined $line; | 
| 346 | 152 |  |  |  |  | 1683 | my $offset = Devel::Declare::get_linestr_offset(); | 
| 347 | 152 |  |  |  |  | 1600 | substr($line, $offset, 0) = $inject; | 
| 348 | 152 |  |  |  |  | 2427 | Devel::Declare::set_linestr($line); | 
| 349 | 152 |  |  |  |  | 2158 | }; | 
| 350 |  |  |  |  |  |  | } | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | __PACKAGE__->meta->make_immutable; | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | 1; | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | __END__ | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | =pod | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | =encoding UTF-8 | 
| 361 |  |  |  |  |  |  |  | 
| 362 |  |  |  |  |  |  | =for :stopwords Florian Ragwitz Ash Rolsky Hakim Cassimally Jesse Luehrs Jonathan Rockway | 
| 363 |  |  |  |  |  |  | Scott Duff Justin Berlin Hunter Karen Etheridge Kent Fredric Lukas Mai Maik | 
| 364 |  |  |  |  |  |  | Hentsche Matt Cory Kraai Nicholas Perez Rhesa Rozendaal Ricardo SIGNES | 
| 365 |  |  |  |  |  |  | Sebastian Willert Steffen Watson Schwigon Yanick Champoux Dagfinn Ilmari | 
| 366 |  |  |  |  |  |  | Mannsåker Daniel Ruoso Dave Invocant sigil | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | =head1 NAME | 
| 369 |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  | MooseX::Method::Signatures - Method declarations with type constraints and no source filter | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | =head1 VERSION | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | version 0.47 | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | package Foo; | 
| 379 |  |  |  |  |  |  |  | 
| 380 |  |  |  |  |  |  | use Moose; | 
| 381 |  |  |  |  |  |  | use MooseX::Method::Signatures; | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | method morning (Str $name) { | 
| 384 |  |  |  |  |  |  | $self->say("Good morning ${name}!"); | 
| 385 |  |  |  |  |  |  | } | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | method hello (Str :$who, Int :$age where { $_ > 0 }) { | 
| 388 |  |  |  |  |  |  | $self->say("Hello ${who}, I am ${age} years old!"); | 
| 389 |  |  |  |  |  |  | } | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | method greet (Str $name, Bool :$excited = 0) { | 
| 392 |  |  |  |  |  |  | if ($excited) { | 
| 393 |  |  |  |  |  |  | $self->say("GREETINGS ${name}!"); | 
| 394 |  |  |  |  |  |  | } | 
| 395 |  |  |  |  |  |  | else { | 
| 396 |  |  |  |  |  |  | $self->say("Hi ${name}!"); | 
| 397 |  |  |  |  |  |  | } | 
| 398 |  |  |  |  |  |  | } | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | $foo->morning('Resi');                          # This works. | 
| 401 |  |  |  |  |  |  |  | 
| 402 |  |  |  |  |  |  | $foo->hello(who => 'world', age => 42);         # This too. | 
| 403 |  |  |  |  |  |  |  | 
| 404 |  |  |  |  |  |  | $foo->greet('Resi', excited => 1);              # And this as well. | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | $foo->hello(who => 'world', age => 'fortytwo'); # This doesn't. | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  | $foo->hello(who => 'world', age => -23);        # This neither. | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | $foo->morning;                                  # Won't work. | 
| 411 |  |  |  |  |  |  |  | 
| 412 |  |  |  |  |  |  | $foo->greet;                                    # Will fail. | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | Provides a proper method keyword, like "sub" but specifically for making methods | 
| 417 |  |  |  |  |  |  | and validating their arguments against Moose type constraints. | 
| 418 |  |  |  |  |  |  |  | 
| 419 |  |  |  |  |  |  | =head1 SIGNATURE SYNTAX | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | The signature syntax is heavily based on Perl 6. However not the full Perl 6 | 
| 422 |  |  |  |  |  |  | signature syntax is supported yet and some of it never will be. | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | =head2 Type Constraints | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | method foo (             $affe) # no type checking | 
| 427 |  |  |  |  |  |  | method bar (Animal       $affe) # $affe->isa('Animal') | 
| 428 |  |  |  |  |  |  | method baz (Animal|Human $affe) # $affe->isa('Animal') || $affe->isa('Human') | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | =head2 Positional vs. Named | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  | method foo ( $a,  $b,  $c) # positional | 
| 433 |  |  |  |  |  |  | method bar (:$a, :$b, :$c) # named | 
| 434 |  |  |  |  |  |  | method baz ( $a,  $b, :$c) # combined | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | =head2 Required vs. Optional | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | method foo ($a , $b!, :$c!, :$d!) # required | 
| 439 |  |  |  |  |  |  | method bar ($a?, $b?, :$c , :$d?) # optional | 
| 440 |  |  |  |  |  |  |  | 
| 441 |  |  |  |  |  |  | =head2 Defaults | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | method foo ($a = 42) # defaults to 42 | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  | =head2 Constraints | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | method foo ($foo where { $_ % 2 == 0 }) # only even | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  | =head2 Invocant | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | method foo (        $moo) # invocant is called $self and is required | 
| 452 |  |  |  |  |  |  | method bar ($self:  $moo) # same, but explicit | 
| 453 |  |  |  |  |  |  | method baz ($class: $moo) # invocant is called $class | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | =head2 Labels | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  | method foo (:     $affe ) # called as $obj->foo(affe => $value) | 
| 458 |  |  |  |  |  |  | method bar (:apan($affe)) # called as $obj->foo(apan => $value) | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | =head2 Traits | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | method foo (Affe $bar does trait) | 
| 463 |  |  |  |  |  |  | method foo (Affe $bar is trait) | 
| 464 |  |  |  |  |  |  |  | 
| 465 |  |  |  |  |  |  | The only currently supported trait is C<coerce>, which will attempt to coerce | 
| 466 |  |  |  |  |  |  | the value provided if it doesn't satisfy the requirements of the type | 
| 467 |  |  |  |  |  |  | constraint. | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | =head2 Placeholders | 
| 470 |  |  |  |  |  |  |  | 
| 471 |  |  |  |  |  |  | method foo ($bar, $, $baz) | 
| 472 |  |  |  |  |  |  |  | 
| 473 |  |  |  |  |  |  | Sometimes you don't care about some parameters you're being called with. Just put | 
| 474 |  |  |  |  |  |  | the bare sigil instead of a full variable name into the signature to avoid an | 
| 475 |  |  |  |  |  |  | extra lexical variable to be created. | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | =head2 Complex Example | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | method foo ( SomeClass $thing where { $_->can('stuff') }: | 
| 480 |  |  |  |  |  |  | Str  $bar  = "apan", | 
| 481 |  |  |  |  |  |  | Int :$baz! = 42 where { $_ % 2 == 0 } where { $_ > 10 } ) | 
| 482 |  |  |  |  |  |  |  | 
| 483 |  |  |  |  |  |  | # the invocant is called $thing, must be an instance of SomeClass and | 
| 484 |  |  |  |  |  |  | has to implement a 'stuff' method | 
| 485 |  |  |  |  |  |  | # $bar is positional, required, must be a string and defaults to "apan" | 
| 486 |  |  |  |  |  |  | # $baz is named, required, must be an integer, defaults to 42 and needs | 
| 487 |  |  |  |  |  |  | #      to be even and greater than 10 | 
| 488 |  |  |  |  |  |  |  | 
| 489 |  |  |  |  |  |  | =head1 BUGS, CAVEATS AND NOTES | 
| 490 |  |  |  |  |  |  |  | 
| 491 |  |  |  |  |  |  | This module is as stable now, but this is not to say that it is entirely bug | 
| 492 |  |  |  |  |  |  | free. If you notice any odd behaviour (messages not being as good as they could | 
| 493 |  |  |  |  |  |  | for example) then please raise a bug. | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | =head2 Fancy signatures | 
| 496 |  |  |  |  |  |  |  | 
| 497 |  |  |  |  |  |  | L<Parse::Method::Signatures> is used to parse the signatures. However, some | 
| 498 |  |  |  |  |  |  | signatures that can be parsed by it aren't supported by this module (yet). | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  | =head2 No source filter | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | While this module does rely on the hairy black magic of L<Devel::Declare> it | 
| 503 |  |  |  |  |  |  | does not depend on a source filter. As such, it doesn't try to parse and | 
| 504 |  |  |  |  |  |  | rewrite your source code and there should be no weird side effects. | 
| 505 |  |  |  |  |  |  |  | 
| 506 |  |  |  |  |  |  | Devel::Declare only effects compilation. After that, it's a normal subroutine. | 
| 507 |  |  |  |  |  |  | As such, for all that hairy magic, this module is surprisingly stable. | 
| 508 |  |  |  |  |  |  |  | 
| 509 |  |  |  |  |  |  | =head2 What about regular subroutines? | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | L<Devel::Declare> cannot yet change the way C<sub> behaves. However, the | 
| 512 |  |  |  |  |  |  | L<signatures|signatures> module can. Right now it only provides very basic | 
| 513 |  |  |  |  |  |  | signatures, but it's extendable enough that plugging MooseX::Method::Signatures | 
| 514 |  |  |  |  |  |  | signatures into that should be quite possible. | 
| 515 |  |  |  |  |  |  |  | 
| 516 |  |  |  |  |  |  | =head2 What about the return value? | 
| 517 |  |  |  |  |  |  |  | 
| 518 |  |  |  |  |  |  | Type constraints for return values can be declared using | 
| 519 |  |  |  |  |  |  |  | 
| 520 |  |  |  |  |  |  | method foo (Int $x, Str $y) returns (Bool) { ... } | 
| 521 |  |  |  |  |  |  |  | 
| 522 |  |  |  |  |  |  | however, this feature only works with scalar return values and is still | 
| 523 |  |  |  |  |  |  | considered to be experimental. | 
| 524 |  |  |  |  |  |  |  | 
| 525 |  |  |  |  |  |  | =head2 Interaction with L<Moose::Role> | 
| 526 |  |  |  |  |  |  |  | 
| 527 |  |  |  |  |  |  | =head3 Methods not seen by a role's C<requires> | 
| 528 |  |  |  |  |  |  |  | 
| 529 |  |  |  |  |  |  | Because the processing of the L<MooseX::Method::Signatures> | 
| 530 |  |  |  |  |  |  | C<method> and the L<Moose> C<with> keywords are both | 
| 531 |  |  |  |  |  |  | done at runtime, it can happen that a role will require | 
| 532 |  |  |  |  |  |  | a method before it is declared (which will cause | 
| 533 |  |  |  |  |  |  | Moose to complain very loudly and abort the program). | 
| 534 |  |  |  |  |  |  |  | 
| 535 |  |  |  |  |  |  | For example, the following will not work: | 
| 536 |  |  |  |  |  |  |  | 
| 537 |  |  |  |  |  |  | # in file Canine.pm | 
| 538 |  |  |  |  |  |  |  | 
| 539 |  |  |  |  |  |  | package Canine; | 
| 540 |  |  |  |  |  |  |  | 
| 541 |  |  |  |  |  |  | use Moose; | 
| 542 |  |  |  |  |  |  | use MooseX::Method::Signatures; | 
| 543 |  |  |  |  |  |  |  | 
| 544 |  |  |  |  |  |  | with 'Watchdog'; | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | method bark { print "Woof!\n"; } | 
| 547 |  |  |  |  |  |  |  | 
| 548 |  |  |  |  |  |  | 1; | 
| 549 |  |  |  |  |  |  |  | 
| 550 |  |  |  |  |  |  |  | 
| 551 |  |  |  |  |  |  | # in file Watchdog.pm | 
| 552 |  |  |  |  |  |  |  | 
| 553 |  |  |  |  |  |  | package Watchdog; | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | use Moose::Role; | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | requires 'bark';  # will assert! evaluated before 'method' is processed | 
| 558 |  |  |  |  |  |  |  | 
| 559 |  |  |  |  |  |  | sub warn_intruder { | 
| 560 |  |  |  |  |  |  | my $self = shift; | 
| 561 |  |  |  |  |  |  | my $intruder = shift; | 
| 562 |  |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  | $self->bark until $intruder->gone; | 
| 564 |  |  |  |  |  |  | } | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | 1; | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | A workaround for this problem is to use C<with> only | 
| 569 |  |  |  |  |  |  | after the methods have been defined.  To take our previous | 
| 570 |  |  |  |  |  |  | example, B<Canine> could be reworked thus: | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | package Canine; | 
| 573 |  |  |  |  |  |  |  | 
| 574 |  |  |  |  |  |  | use Moose; | 
| 575 |  |  |  |  |  |  | use MooseX::Method::Signatures; | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | method bark { print "Woof!\n"; } | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | with 'Watchdog'; | 
| 580 |  |  |  |  |  |  |  | 
| 581 |  |  |  |  |  |  | 1; | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | A better solution is to use L<MooseX::Declare> instead of plain | 
| 584 |  |  |  |  |  |  | L<MooseX::Method::Signatures>. It defers application of roles until the end | 
| 585 |  |  |  |  |  |  | of the class definition. With it, our example would becomes: | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | # in file Canine.pm | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | use MooseX::Declare; | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | class Canine with Watchdog { | 
| 592 |  |  |  |  |  |  | method bark { print "Woof!\n"; } | 
| 593 |  |  |  |  |  |  | } | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | 1; | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | # in file Watchdog.pm | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | use MooseX::Declare; | 
| 600 |  |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | role Watchdog { | 
| 602 |  |  |  |  |  |  | requires 'bark'; | 
| 603 |  |  |  |  |  |  |  | 
| 604 |  |  |  |  |  |  | method warn_intruder ( $intruder ) { | 
| 605 |  |  |  |  |  |  | $self->bark until $intruder->gone; | 
| 606 |  |  |  |  |  |  | } | 
| 607 |  |  |  |  |  |  | } | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | 1; | 
| 610 |  |  |  |  |  |  |  | 
| 611 |  |  |  |  |  |  | =head3 I<Subroutine redefined> warnings | 
| 612 |  |  |  |  |  |  |  | 
| 613 |  |  |  |  |  |  | When composing a L<Moose::Role> into a class that uses | 
| 614 |  |  |  |  |  |  | L<MooseX::Method::Signatures>, you may get a "Subroutine redefined" | 
| 615 |  |  |  |  |  |  | warning. This happens when both the role and the class define a | 
| 616 |  |  |  |  |  |  | method/subroutine of the same name. (The way roles work, the one | 
| 617 |  |  |  |  |  |  | defined in the class takes precedence.) To eliminate this warning, | 
| 618 |  |  |  |  |  |  | make sure that your C<with> declaration happens after any | 
| 619 |  |  |  |  |  |  | method/subroutine declarations that may have the same name as a | 
| 620 |  |  |  |  |  |  | method/subroutine within a role. | 
| 621 |  |  |  |  |  |  |  | 
| 622 |  |  |  |  |  |  | =head1 CAVEATS | 
| 623 |  |  |  |  |  |  |  | 
| 624 |  |  |  |  |  |  | You are encouraged to read the L<MooseX::Declare/WARNING>. | 
| 625 |  |  |  |  |  |  |  | 
| 626 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 627 |  |  |  |  |  |  |  | 
| 628 |  |  |  |  |  |  | L<MooseX::Declare> | 
| 629 |  |  |  |  |  |  |  | 
| 630 |  |  |  |  |  |  | L<Method::Signatures::Simple> | 
| 631 |  |  |  |  |  |  |  | 
| 632 |  |  |  |  |  |  | L<Method::Signatures> | 
| 633 |  |  |  |  |  |  |  | 
| 634 |  |  |  |  |  |  | L<Devel::Declare> | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | L<Parse::Method::Signatures> | 
| 637 |  |  |  |  |  |  |  | 
| 638 |  |  |  |  |  |  | L<Moose> | 
| 639 |  |  |  |  |  |  |  | 
| 640 |  |  |  |  |  |  | L<signatures> | 
| 641 |  |  |  |  |  |  |  | 
| 642 |  |  |  |  |  |  | =head1 AUTHOR | 
| 643 |  |  |  |  |  |  |  | 
| 644 |  |  |  |  |  |  | Florian Ragwitz <rafl@debian.org> | 
| 645 |  |  |  |  |  |  |  | 
| 646 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 647 |  |  |  |  |  |  |  | 
| 648 |  |  |  |  |  |  | This software is copyright (c) 2013 by Florian Ragwitz. | 
| 649 |  |  |  |  |  |  |  | 
| 650 |  |  |  |  |  |  | This is free software; you can redistribute it and/or modify it under | 
| 651 |  |  |  |  |  |  | the same terms as the Perl 5 programming language system itself. | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  | =head1 CONTRIBUTORS | 
| 654 |  |  |  |  |  |  |  | 
| 655 |  |  |  |  |  |  | =over 4 | 
| 656 |  |  |  |  |  |  |  | 
| 657 |  |  |  |  |  |  | =item * | 
| 658 |  |  |  |  |  |  |  | 
| 659 |  |  |  |  |  |  | Ash Berlin <ash@cpan.org> | 
| 660 |  |  |  |  |  |  |  | 
| 661 |  |  |  |  |  |  | =item * | 
| 662 |  |  |  |  |  |  |  | 
| 663 |  |  |  |  |  |  | Cory Watson <gphat@cpan.org> | 
| 664 |  |  |  |  |  |  |  | 
| 665 |  |  |  |  |  |  | =item * | 
| 666 |  |  |  |  |  |  |  | 
| 667 |  |  |  |  |  |  | Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | =item * | 
| 670 |  |  |  |  |  |  |  | 
| 671 |  |  |  |  |  |  | Daniel Ruoso <daniel@ruoso.com> | 
| 672 |  |  |  |  |  |  |  | 
| 673 |  |  |  |  |  |  | =item * | 
| 674 |  |  |  |  |  |  |  | 
| 675 |  |  |  |  |  |  | Dave Rolsky <autarch@urth.org> | 
| 676 |  |  |  |  |  |  |  | 
| 677 |  |  |  |  |  |  | =item * | 
| 678 |  |  |  |  |  |  |  | 
| 679 |  |  |  |  |  |  | Hakim Cassimally <osfameron@cpan.org> | 
| 680 |  |  |  |  |  |  |  | 
| 681 |  |  |  |  |  |  | =item * | 
| 682 |  |  |  |  |  |  |  | 
| 683 |  |  |  |  |  |  | Jesse Luehrs <doy@tozt.net> | 
| 684 |  |  |  |  |  |  |  | 
| 685 |  |  |  |  |  |  | =item * | 
| 686 |  |  |  |  |  |  |  | 
| 687 |  |  |  |  |  |  | Jonathan Rockway <jon@jrock.us> | 
| 688 |  |  |  |  |  |  |  | 
| 689 |  |  |  |  |  |  | =item * | 
| 690 |  |  |  |  |  |  |  | 
| 691 |  |  |  |  |  |  | Jonathan Scott Duff <duff@pobox.com> | 
| 692 |  |  |  |  |  |  |  | 
| 693 |  |  |  |  |  |  | =item * | 
| 694 |  |  |  |  |  |  |  | 
| 695 |  |  |  |  |  |  | Justin Hunter <justin.d.hunter@gmail.com> | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | =item * | 
| 698 |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  | Karen Etheridge <ether@cpan.org> | 
| 700 |  |  |  |  |  |  |  | 
| 701 |  |  |  |  |  |  | =item * | 
| 702 |  |  |  |  |  |  |  | 
| 703 |  |  |  |  |  |  | Kent Fredric <kentfredric@gmail.com> | 
| 704 |  |  |  |  |  |  |  | 
| 705 |  |  |  |  |  |  | =item * | 
| 706 |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  | Lukas Mai <l.mai@web.de> | 
| 708 |  |  |  |  |  |  |  | 
| 709 |  |  |  |  |  |  | =item * | 
| 710 |  |  |  |  |  |  |  | 
| 711 |  |  |  |  |  |  | Maik Hentsche <maik.hentsche@amd.com> | 
| 712 |  |  |  |  |  |  |  | 
| 713 |  |  |  |  |  |  | =item * | 
| 714 |  |  |  |  |  |  |  | 
| 715 |  |  |  |  |  |  | Matt Kraai <kraai@ftbfs.org> | 
| 716 |  |  |  |  |  |  |  | 
| 717 |  |  |  |  |  |  | =item * | 
| 718 |  |  |  |  |  |  |  | 
| 719 |  |  |  |  |  |  | Nicholas Perez <nperez@cpan.org> | 
| 720 |  |  |  |  |  |  |  | 
| 721 |  |  |  |  |  |  | =item * | 
| 722 |  |  |  |  |  |  |  | 
| 723 |  |  |  |  |  |  | Rhesa Rozendaal <rhesa@cpan.org> | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | =item * | 
| 726 |  |  |  |  |  |  |  | 
| 727 |  |  |  |  |  |  | Ricardo SIGNES <rjbs@cpan.org> | 
| 728 |  |  |  |  |  |  |  | 
| 729 |  |  |  |  |  |  | =item * | 
| 730 |  |  |  |  |  |  |  | 
| 731 |  |  |  |  |  |  | Sebastian Willert <willert@cpan.org> | 
| 732 |  |  |  |  |  |  |  | 
| 733 |  |  |  |  |  |  | =item * | 
| 734 |  |  |  |  |  |  |  | 
| 735 |  |  |  |  |  |  | Steffen Schwigon <ss5@renormalist.net> | 
| 736 |  |  |  |  |  |  |  | 
| 737 |  |  |  |  |  |  | =item * | 
| 738 |  |  |  |  |  |  |  | 
| 739 |  |  |  |  |  |  | Yanick Champoux <yanick@babyl.dyndns.org> | 
| 740 |  |  |  |  |  |  |  | 
| 741 |  |  |  |  |  |  | =back | 
| 742 |  |  |  |  |  |  |  | 
| 743 |  |  |  |  |  |  | =cut |