Opened 4 years ago

Closed 3 years ago

#1209 closed enhancement (fixed)

Enable MooseX::Declare Method Modifiers in OutLine

Reported by: bowtie Owned by:
Priority: minor Milestone:
Component: Outline Version: 0.85
Keywords: MooseX::Declare Cc:

Description (last modified by Sewi)

Enable MooseX::Declare Method Modifiers in OutLine

  • with reference to revision r14225

before / after / around / override / augment

    before   foo ($x, $y, $z) { ... }
    after    bar ($x, $y, $z) { ... }
    around   baz ($x, $y, $z) { ... }
    override moo ($x, $y, $z) { ... }
    augment  kuh ($x, $y, $z) { ... }

FunctionList.pm

  • lib/Padre/Document/Perl/FunctionList.pm

     
    2121        | 
    2222        $n$n=\w+.*?$n$n=cut\b(?=.*?$n$n) 
    2323        | 
    24         (?:^|$n)\s*(?:sub|func|method)\s+(\w+(?:::\w+)*) 
     24        (?:^|$n)\s*(?:sub|func|method|before|after|around|override|augment)\s+(\w+(?:::\w+)*) 
    2525        ) 
    2626    /sx; 
    2727 

Perl.pm

  • lib/Padre/Document/Perl.pm

     
    295295# triggering a "Variable length lookbehind not implemented" error. 
    296296# return qr/(?:(?<=^)\s*sub\s+$_[1]|(?<=[\012\015])\s*sub\s+$_[1])\b/; 
    297297sub get_function_regex { 
    298     qr/(?:^|[^# \t])[ \t]*((?:sub|func|method)\s+$_[1])\b/; 
     298    qr/(?:^|[^# \t])[ \t]*((?:sub|func|method|before|after|around|override|augment)\s+$_[1])\b/; 
    299299} 
    300300 
    301301sub get_functions { 
     
    310310        | 
    311311        $n$n=\w+.*?$n$n=cut\b(?=.*?$n$n) 
    312312        | 
    313         (?:^|$n)\s*(?:sub|func|method)\s+(\w+(?:::\w+)*) 
     313        (?:^|$n)\s*(?:sub|func|method|before|after|around|override|augment)\s+(\w+(?:::\w+)*) 
    314314        ) 
    315315    /sgx; 
    316316} 
     
    758758                    close $fh; 
    759759                    my @subs = $lines =~ /sub\s+(\w+)/g; 
    760760                    if ( $lines =~ /use MooseX::Declare;/ ) { 
    761                         push @subs, ( $lines =~ /\bmethod\s+(\w+)/g ); 
     761                        push @subs, ( $lines =~ /\b(method|before|after|around|override|augment)\s+(\w+)/g ); 
    762762                    } 
    763763 
    764764                    if ( $lines =~ /use (?:MooseX::)?Method::Signatures;/ ) { 

OutLine.pm

  • PPIx-EditorTools/lib/PPIx/EditorTools/Outline.pm

     
    128128        $ppi->find( 
    129129            sub { 
    130130                $_[1]->isa('PPI::Token::Word') or return 0; 
    131                 $_[1]->content =~ /^(?:func|method)\z/ or return 0; 
     131                $_[1]->content =~ /^(?:func|method|before|after|around|override|augment)\z/ or return 0; 
    132132                $_[1]->next_sibling->isa('PPI::Token::Whitespace') or return 0; 
    133133                my $sib_content = $_[1]->next_sibling->next_sibling->content or return 0; 
    134134 

Attachments (4)

Outline.pm (6.0 KB) - added by bowtie 3 years ago.
suggested upgrade to Outline.pm
09-outline.t (4.0 KB) - added by bowtie 3 years ago.
upgraded test file for Moose outline
Mooclass.pm (449 bytes) - added by bowtie 3 years ago.
test file Moose class
Moorole.pm (316 bytes) - added by bowtie 3 years ago.
test file Moose role

Download all attachments as: .zip

Change History (13)

comment:1 Changed 4 years ago by bowtie

Opps revision 14225

comment:2 Changed 4 years ago by bowtie

Outline.pm markII inc Moose Attributes correction

ignore Data::Dumper as this is a rem-lent of poking around.

node name: 'account'
modified node neme: account

node name: [qw/ warned start_time times_up running/]
modified node neme: warned start_time times_up running

node name: qw( sound )
modified node neme: sound

node name: qw/ sound /
modified node neme: sound

node name: ['label2','proggress','bbutWarn']
modified node neme: label2 proggress bbutWarn

Moose Attributes displayed correctly in Outline,

  • PPIx-EditorTools/lib/PPIx/EditorTools/Outline.pm

     
    66use strict; 
    77use warnings; 
    88use Carp; 
    9  
     9use Data::Dumper; 
    1010use base 'PPIx::EditorTools'; 
    1111use Class::XSAccessor accessors => {}; 
    1212 
     
    112112 
    113113            # Moose attribute declaration 
    114114            if ( $node1->isa('PPI::Token::Word') && $node1->content eq 'has' ) { 
     115                # tidy up Moose attributes for Outline display 
     116                my $name_node2 = $node2->content; 
     117                my $space = q{ }; 
     118                $name_node2 =~ s/^\[?(qw(\/|\())?$space?//; # remove leading 'quote word' 
     119                $name_node2 =~ s/(\/|\))?\]?$//; # remove traling 'quote word' 
     120                $name_node2 =~ s/(\'$space?)//g; # remove Single-Quoted String Literals 
     121                $name_node2 =~ s/($space?\,$space?)/$space/g; # remove commers add space 
    115122                push @{ $cur_pkg->{attributes} }, { name => $node2->content, line => $thing->location->[0] }; 
    116123                next; 
    117124            } 
     
    128135        $ppi->find( 
    129136            sub { 
    130137                $_[1]->isa('PPI::Token::Word') or return 0; 
    131                 $_[1]->content =~ /^(?:func|method)\z/ or return 0; 
     138                $_[1]->content =~ /^(?:func|method|before|after|around|override|augment)\z/ or return 0; 
    132139                $_[1]->next_sibling->isa('PPI::Token::Whitespace') or return 0; 
    133140                my $sib_content = $_[1]->next_sibling->next_sibling->content or return 0; 
    134141 
     
    147154    } 
    148155 
    149156    push @outline, $cur_pkg; 
    150  
     157#   say Dumper @outline; 
    151158    return \@outline; 
    152159} 

comment:3 Changed 4 years ago by bowtie

Opps missed a line

{{{#! perl

# Moose attribute declaration
if ( $node1->isa('PPI::Token::Word') && $node1->content eq 'has' ) {

# tidy up Moose attributes for Outline display
my $name_node2 = $node2->content;
my $space = q{ };
$name_node2 =~ s/\[?(qw(\/|\())?$space?; # remove leading 'quote word'
$name_node2 =~ s/(\/|\))?\]?$
; # remove traling 'quote word'
$name_node2 =~ s/(\'$space?)g; # remove Single-Quoted String Literals
$name_node2 =~ s/($space?\,$space?)/$space/g; # remove commers add space
push @{ $cur_pkg->{attributes} }, { name => $name_node2, line => $thing->location->[0] };
next;

}

}}}

comment:4 Changed 3 years ago by bowtie

Outline.pm markIII it works needs testing

  • class and role support
  • attribute support
  • method support
  • only uses first class or role as package name
  • observation, why does padre check file being edited after every key stroke, can we not wait until no changes for say 3 seconds then update Outline, Syntax checker etc..
  • PPIx-EditorTools/lib/PPIx/EditorTools/Outline.pm

     
    11package PPIx::EditorTools::Outline; 
     2BEGIN { 
     3  $PPIx::EditorTools::Outline::VERSION = '0.13'; 
     4} 
    25 
    36# ABSTRACT: Collect use pragmata, modules, subroutiones 
    47 
     
    69use strict; 
    710use warnings; 
    811use Carp; 
    9  
     12use Data::Dumper; 
    1013use base 'PPIx::EditorTools'; 
    1114use Class::XSAccessor accessors => {}; 
    1215 
    1316use PPI; 
    1417 
    15 =pod 
    1618 
    17 =head1 SYNOPSIS 
    1819 
    19   my $outline = PPIx::EditorTools::Outline->new->find( 
    20         code => "package TestPackage;\nsub x { 1;\n" 
    21       ); 
    22  print Dumper $outline; 
    23  
    24 =head1 DESCRIPTION 
    25  
    26 Return a list of pragmatas, modules, methods of a C<PPI::Document>. 
    27  
    28 =head1 METHODS 
    29  
    30 =over 4 
    31  
    32 =item new() 
    33  
    34 Constructor. Generally shouldn't be called with any arguments. 
    35  
    36 =item find( ppi => PPI::Document $ppi ) 
    37 =item find( code => Str $code ) 
    38  
    39 Accepts either a C<PPI::Document> to process or a string containing 
    40 the code (which will be converted into a C<PPI::Document>) to process. 
    41 Return a reference to a hash. 
    42  
    43 =back 
    44  
    45 =cut 
    46  
    47  
    4820sub find { 
    4921    my ( $self, %args ) = @_; 
    5022    $self->process_doc(%args); 
     
    7446    my @outline       = (); 
    7547    my $cur_pkg       = {}; 
    7648    my $not_first_one = 0; 
     49    my $pkg_main = 1;   # add flag for package called main 
     50    #my $mod_mxd = 0;   # add flag for module MooseX::Declare 
    7751    foreach my $thing (@things) { 
    7852        if ( ref $thing eq 'PPI::Statement::Package' ) { 
    7953            if ($not_first_one) { 
    8054                if ( not $cur_pkg->{name} ) { 
    8155                    $cur_pkg->{name} = 'main'; 
     56                    # this never runs as MooseX-Declare does not contain a StatementPkg 
     57                    $pkg_main = 1;  # set flag for package called main 
     58                    print "1 pkg main: $pkg_main\n"; 
    8259                } 
    8360                push @outline, $cur_pkg; 
    8461                $cur_pkg = {}; 
     
    8663            $not_first_one   = 1; 
    8764            $cur_pkg->{name} = $thing->namespace; 
    8865            $cur_pkg->{line} = $thing->location->[0]; 
    89         } elsif ( ref $thing eq 'PPI::Statement::Include' ) { 
     66 
     67            if ( $thing->namespace ) { $pkg_main = 0} 
     68            ##print "2 pkg main: $pkg_main\t".$thing->namespace."\n"; 
     69         
     70        } 
     71 
     72        elsif ( ref $thing eq 'PPI::Statement::Include' ) { 
    9073            next if $thing->type eq 'no'; 
    9174            if ( $thing->pragma ) { 
    9275                push @{ $cur_pkg->{pragmata} }, { name => $thing->pragma, line => $thing->location->[0] }; 
    93             } elsif ( $thing->module ) { 
     76            } 
     77            elsif ( $thing->module ) { 
    9478                push @{ $cur_pkg->{modules} }, { name => $thing->module, line => $thing->location->[0] }; 
    9579                unless ($check_alternate_sub_decls) { 
    9680                    $check_alternate_sub_decls = 1 
     
    9983                        'MooseX::Declare', 
    10084                        'MooseX::Method::Signatures' 
    10185                        ); 
     86                        ## print "what have I found:". $thing->module; 
     87                        # s/.*MooseX::Declare.*/1/; 
     88                        # $mod_mxd = 1; 
    10289                } 
    10390            } 
    104         } elsif ( ref $thing eq 'PPI::Statement::Sub' ) { 
     91        } 
     92         
     93        elsif ( ref $thing eq 'PPI::Statement::Sub' ) { 
    10594            push @{ $cur_pkg->{methods} }, { name => $thing->name, line => $thing->location->[0] }; 
    106         } elsif ( ref $thing eq 'PPI::Statement' ) { 
     95        } 
     96         
     97        elsif ( ref $thing eq 'PPI::Statement' ) { 
    10798 
    10899            # last resort, let's analyse further down... 
    109100            my $node1 = $thing->first_element; 
     
    112103 
    113104            # Moose attribute declaration 
    114105            if ( $node1->isa('PPI::Token::Word') && $node1->content eq 'has' ) { 
    115                 push @{ $cur_pkg->{attributes} }, { name => $node2->content, line => $thing->location->[0] }; 
     106                # tidy up Moose attributes for Outline display 
     107                my $name_node2 = $node2->content; 
     108                my $space = q{ }; 
     109                $name_node2 =~ s/^\[?(qw(\/|\())?$space?//; # remove leading 'quote word' 
     110                $name_node2 =~ s/(\/|\))?\]?$//; # remove traling 'quote word' 
     111                $name_node2 =~ s/(\'$space?)//g; # remove Single-Quoted String Literals 
     112                $name_node2 =~ s/($space?\,$space?)/$space/g; # remove commers add space 
     113                push @{ $cur_pkg->{attributes} }, { name => $name_node2, line => $thing->location->[0] }; 
    116114                next; 
    117115            } 
    118116 
     
    128126        $ppi->find( 
    129127            sub { 
    130128                $_[1]->isa('PPI::Token::Word') or return 0; 
    131                 $_[1]->content =~ /^(?:func|method)\z/ or return 0; 
     129                $_[1]->content =~ /^(?:func|method|before|after|around|override|augment|class|role)\z/ or return 0; 
    132130                $_[1]->next_sibling->isa('PPI::Token::Whitespace') or return 0; 
    133131                my $sib_content = $_[1]->next_sibling->next_sibling->content or return 0; 
    134132 
    135133                $sib_content =~ m/^\b(\w+)\b/; 
    136134                return 0 unless defined $1; 
     135                # test for MooseX::Declare attributes class, role 
     136                if ( $_[1]->content =~ m/(class|role)/){ 
     137                    ##print "method type:". $_[1]->content; 
     138                    ##print " method name: $sib_content \n"; 
     139                    if ($cur_pkg->{name}){return 1;} 
     140                    if ( $pkg_main eq 1 ){ 
     141                        $cur_pkg->{name} = $sib_content; 
     142                        $cur_pkg->{line} = $_[1]->line_number; 
     143                    } 
     144                    return 1; # break out so we don't write Packae name as method 
     145                } 
    137146 
    138147                push @{ $cur_pkg->{methods} }, { name => $1, line => $_[1]->line_number }; 
    139148 
     
    147156    } 
    148157 
    149158    push @outline, $cur_pkg; 
    150  
     159##  print Dumper @outline; 
    151160    return \@outline; 
    152161} 
    153162 
    1541631; 
    155164 
    156 __END__ 
    157165 
     166 
     167=pod 
     168 
     169=head1 NAME 
     170 
     171PPIx::EditorTools::Outline - Collect use pragmata, modules, subroutiones 
     172 
     173=head1 VERSION 
     174 
     175version 0.13 
     176 
     177=head1 SYNOPSIS 
     178 
     179  my $outline = PPIx::EditorTools::Outline->new->find( 
     180        code => "package TestPackage;\nsub x { 1;\n" 
     181      ); 
     182 print Dumper $outline; 
     183 
     184=head1 DESCRIPTION 
     185 
     186Return a list of pragmatas, modules, methods of a C<PPI::Document>. 
     187 
     188=head1 METHODS 
     189 
     190=over 4 
     191 
     192=item new() 
     193 
     194Constructor. Generally shouldn't be called with any arguments. 
     195 
     196=item find( ppi => PPI::Document $ppi ) 
     197=item find( code => Str $code ) 
     198 
     199Accepts either a C<PPI::Document> to process or a string containing 
     200the code (which will be converted into a C<PPI::Document>) to process. 
     201Return a reference to a hash. 
     202 
     203=back 
     204 
    158205=head1 SEE ALSO 
    159206 
    160207This class inherits from C<PPIx::EditorTools>. 
    161208Also see L<App::EditorTools>, L<Padre>, and L<PPI>. 
    162209 
     210=head1 AUTHORS 
     211 
     212=over 4 
     213 
     214=item * 
     215 
     216Steffen Mueller C<smueller@cpan.org> 
     217 
     218=item * 
     219 
     220Repackaged by Mark Grimes C<mgrimes@cpan.org> 
     221 
     222=item * 
     223 
     224Ahmad M. Zawawi <ahmad.zawawi@gmail.com> 
     225 
     226=back 
     227 
     228=head1 COPYRIGHT AND LICENSE 
     229 
     230This software is copyright (c) 2011 by The Padre development team as listed in Padre.pm. 
     231 
     232This is free software; you can redistribute it and/or modify it under 
     233the same terms as the Perl 5 programming language system itself. 
     234 
    163235=cut 
    164236 
     237 
     238__END__ 
     239 
     240 
    165241# Copyright 2008-2011 The Padre development team as listed in Padre.pm. 
    166242# LICENSE 
    167243# This program is free software; you can redistribute it and/or 

comment:5 Changed 3 years ago by Sewi

  • Description modified (diff)

comment:6 Changed 3 years ago by szabgab

I am happy to see you are working on the issue.

1 Please don't move around the pods to make it easier to see what is the real change.
2 In t/09-outline.t there is the beginning of automated tests for the outline. There is where you should add test cases and make sure they work.

If you need help with 2 let us know.

comment:7 Changed 3 years ago by szabgab

And another comment related to discussion on IRC

I think the module should be able to parse Moose-ish files. It can first check for use Moose; or similar and spend the extra cycles only if Moose is loaded. The same should work for other accessor generator modules as well. The parser could also check if Moose is installed but I would like to be able to process Moose-ish files even if Moose itself is not installed. So that should be done based on some parameter.

Changed 3 years ago by bowtie

suggested upgrade to Outline.pm

Changed 3 years ago by bowtie

upgraded test file for Moose outline

Changed 3 years ago by bowtie

test file Moose class

Changed 3 years ago by bowtie

test file Moose role

comment:8 Changed 3 years ago by bowtie

szabdgab

I have tidy up code in PPIx::EditorTools::Outline (peto)

created two tests, plus test files.

all additional actions in peto us the existing Moose test, hence they only run when requested.

Deve::Cover

File:t/09-outline.t
Coverage:42.9%

line%coveragebranch
1550TFif ($PPI::VERSION =~ /_/)
142100TFif ($$c{'file'})
14350TFunless open my $fh, '<', $$c{'file'}
1500TFunless is_deeply($outline, $$c{'expected'})
26950TFif ($$c{'file'})
27050TFunless open my $fh, '<', $$c{'file'}
2750TFunless is_deeply($outline, $$c{'expected'})

As for the Regex testing in

  • lib/Padre/Document/Perl/FunctionList.pm
    • line 24 no moose test $sub_search_re
  • lib/Padre/Document/Perl.pm
    • line 298/313 on moose test
    • line 761 moose test

Could we not just have one test here, for Moose rather than two?

foreach my $f (@files) {
    if ( open my $fh, '<', $f ) {
        my $lines = do { local $/ = undef; <$fh> };
        close $fh;
        my @subs = $lines =~ /sub\s+(\w+)/g;
        if ( $lines =~ /use MooseX::Declare;/ ) {
            push @subs,
              ( $lines =~
                  /\b(method|before|after|around|override|augment)\s+(\w+)/g );
        }

        if ( $lines =~ /use (?:MooseX::)?Method::Signatures;/ ) {
            my @subs = $lines =~ /\b(?:method|func)\s+(\w+)/g;
        }

        $self->{_methods_}->{$_} = $f for @subs;
    }
}

Enc the four files.
bowtie

comment:9 Changed 3 years ago by szabgab

  • Resolution set to fixed
  • Status changed from new to closed

applied with slight modifications in r14312, will be in release 0.15 soon

Note: See TracTickets for help on using tickets.