From: Cory Watson Date: Wed, 20 May 2009 13:59:21 +0000 (-0500) Subject: Add strip_names_and_args X-Git-Tag: 0.005003~2^2~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=01fadf71d4d8248a714b8639f2d661dc17badc80;p=p5sagit%2FDevel-Declare.git Add strip_names_and_args --- diff --git a/lib/Devel/Declare/Context/Simple.pm b/lib/Devel/Declare/Context/Simple.pm index 5fe25df..8d83cdf 100644 --- a/lib/Devel/Declare/Context/Simple.pm +++ b/lib/Devel/Declare/Context/Simple.pm @@ -113,6 +113,82 @@ sub strip_proto { return; } +sub strip_names_and_args { + my $self = shift; + $self->skipspace; + + my @args; + + my $linestr = $self->get_linestr; + if (substr($linestr, $self->offset, 1) eq '(') { + # We had a leading paren, so we will now expect comma separated + # arguments + substr($linestr, $self->offset, 1) = ''; + $self->set_linestr($linestr); + $self->skipspace; + + # At this point we expect to have a comma-separated list of + # barewords with optional protos afterward, so loop until we + # run out of comma-separated values + while (1) { + # Get the bareword + my $thing = $self->strip_name; + # If there's no bareword here, bail the caller can check if + # we returned anything. + return unless defined $thing; + + $linestr = $self->get_linestr; + if (substr($linestr, $self->offset, 1) eq '(') { + # This one had a proto, pull it out + push(@args, [ $thing, $self->strip_proto ]); + } else { + # This had no proto, so store it with an undef + push(@args, [ $thing, undef ]); + } + $self->skipspace; + $linestr = $self->get_linestr; + + if (substr($linestr, $self->offset, 1) eq ',') { + # We found a comma, strip it out and set things up for + # another iteration + substr($linestr, $self->offset, 1) = ''; + $self->set_linestr($linestr); + $self->skipspace; + } else { + # No comma, get outta here + last; + } + } + + # look for the final closing paren of the list + if (substr($linestr, $self->offset, 1) eq ')') { + substr($linestr, $self->offset, 1) = ''; + $self->set_linestr($linestr); + $self->skipspace; + } + else { + # fail if it isn't there + #FIXME + } + } else { + # No parens, so expect a single arg + my $thing = $self->strip_name; + # If there's no bareword here, bail the caller can check if + # we returned anything. + return unless defined $thing; + $linestr = $self->get_linestr; + if (substr($linestr, $self->offset, 1) eq '(') { + # This one had a proto, pull it out + push(@args, [ $thing, $self->strip_proto ]); + } else { + # This had no proto, so store it with an undef + push(@args, [ $thing, undef ]); + } + } + + return \@args; +} + sub get_curstash_name { return Devel::Declare::get_curstash_name; } diff --git a/t/ctx-simple.t b/t/ctx-simple.t index 14f80f4..7b1b888 100644 --- a/t/ctx-simple.t +++ b/t/ctx-simple.t @@ -30,6 +30,14 @@ use Devel::Declare (); $ctx->skip_declarator; my $name = $ctx->strip_name; my $proto = $ctx->strip_proto; + + # Check for an 'is' to test strip_name_and_args + my $word = $ctx->strip_name; + my $traits; + if (defined($word) && ($word eq 'is')) { + $traits = $ctx->strip_names_and_args; + } + my $inject = make_proto_unwrap($proto); if (defined $name) { $inject = $ctx->scope_injector_call().$inject; @@ -38,7 +46,14 @@ use Devel::Declare (); if (defined $name) { $name = join('::', Devel::Declare::get_curstash_name(), $name) unless ($name =~ /::/); - $ctx->shadow(sub (&) { no strict 'refs'; *{$name} = shift; }); + # for trait testing we're just interested in the trait parse result, not + # the method body and its injections + $ctx->shadow(sub (&) { + no strict 'refs'; + *{$name} = $traits + ? sub { $traits } + : shift; + }); } else { $ctx->shadow(sub (&) { shift }); } @@ -69,6 +84,14 @@ my ($test_method1, $test_method2, @test_list); return (ref $self).': Foo: '.$foo; } + method has_many_traits() is (Trait1, Trait2(foo => 'bar'), Baz(one, two)) { + return 1; + } + + method has_a_trait() is Foo1 { + return 1; + } + method upgrade(){ # no spaces to make case pathological bless($self, 'DeclareTest2'); } @@ -124,6 +147,18 @@ is($o->multiline1(3), '33', 'multiline1 proto ok'); is($o->multiline2(1,2), '1 2', 'multiline2 proto ok'); is($o->multiline3(4,5), '5 4', 'multiline3 proto ok'); +is_deeply( + $o->has_many_traits, + [['Trait1', undef], ['Trait2', q[foo => 'bar']], ['Baz', 'one, two']], + 'extracting multiple traits', +); + +is_deeply( + $o->has_a_trait, + [['Foo1', undef]], + 'extract one trait without arguments', +); + $o->upgrade; isa_ok($o, 'DeclareTest2');