Ticket #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) (diff)
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
21 21 | 22 22 $n$n=\w+.*?$n$n=cut\b(?=.*?$n$n) 23 23 | 24 (?:^|$n)\s*(?:sub|func|method )\s+(\w+(?:::\w+)*)24 (?:^|$n)\s*(?:sub|func|method|before|after|around|override|augment)\s+(\w+(?:::\w+)*) 25 25 ) 26 26 /sx; 27 27
Perl.pm
-
lib/Padre/Document/Perl.pm
295 295 # triggering a "Variable length lookbehind not implemented" error. 296 296 # return qr/(?:(?<=^)\s*sub\s+$_[1]|(?<=[\012\015])\s*sub\s+$_[1])\b/; 297 297 sub 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/; 299 299 } 300 300 301 301 sub get_functions { … … 310 310 | 311 311 $n$n=\w+.*?$n$n=cut\b(?=.*?$n$n) 312 312 | 313 (?:^|$n)\s*(?:sub|func|method )\s+(\w+(?:::\w+)*)313 (?:^|$n)\s*(?:sub|func|method|before|after|around|override|augment)\s+(\w+(?:::\w+)*) 314 314 ) 315 315 /sgx; 316 316 } … … 758 758 close $fh; 759 759 my @subs = $lines =~ /sub\s+(\w+)/g; 760 760 if ( $lines =~ /use MooseX::Declare;/ ) { 761 push @subs, ( $lines =~ /\b method\s+(\w+)/g );761 push @subs, ( $lines =~ /\b(method|before|after|around|override|augment)\s+(\w+)/g ); 762 762 } 763 763 764 764 if ( $lines =~ /use (?:MooseX::)?Method::Signatures;/ ) {
OutLine.pm
-
PPIx-EditorTools/lib/PPIx/EditorTools/Outline.pm
128 128 $ppi->find( 129 129 sub { 130 130 $_[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; 132 132 $_[1]->next_sibling->isa('PPI::Token::Whitespace') or return 0; 133 133 my $sib_content = $_[1]->next_sibling->next_sibling->content or return 0; 134 134
Attachments
Change History
comment:2 Changed 2 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
6 6 use strict; 7 7 use warnings; 8 8 use Carp; 9 9 use Data::Dumper; 10 10 use base 'PPIx::EditorTools'; 11 11 use Class::XSAccessor accessors => {}; 12 12 … … 112 112 113 113 # Moose attribute declaration 114 114 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 115 122 push @{ $cur_pkg->{attributes} }, { name => $node2->content, line => $thing->location->[0] }; 116 123 next; 117 124 } … … 128 135 $ppi->find( 129 136 sub { 130 137 $_[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; 132 139 $_[1]->next_sibling->isa('PPI::Token::Whitespace') or return 0; 133 140 my $sib_content = $_[1]->next_sibling->next_sibling->content or return 0; 134 141 … … 147 154 } 148 155 149 156 push @outline, $cur_pkg; 150 157 # say Dumper @outline; 151 158 return \@outline; 152 159 }
comment:3 Changed 2 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 2 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
1 1 package PPIx::EditorTools::Outline; 2 BEGIN { 3 $PPIx::EditorTools::Outline::VERSION = '0.13'; 4 } 2 5 3 6 # ABSTRACT: Collect use pragmata, modules, subroutiones 4 7 … … 6 9 use strict; 7 10 use warnings; 8 11 use Carp; 9 12 use Data::Dumper; 10 13 use base 'PPIx::EditorTools'; 11 14 use Class::XSAccessor accessors => {}; 12 15 13 16 use PPI; 14 17 15 =pod16 18 17 =head1 SYNOPSIS18 19 19 my $outline = PPIx::EditorTools::Outline->new->find(20 code => "package TestPackage;\nsub x { 1;\n"21 );22 print Dumper $outline;23 24 =head1 DESCRIPTION25 26 Return a list of pragmatas, modules, methods of a C<PPI::Document>.27 28 =head1 METHODS29 30 =over 431 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 containing40 the code (which will be converted into a C<PPI::Document>) to process.41 Return a reference to a hash.42 43 =back44 45 =cut46 47 48 20 sub find { 49 21 my ( $self, %args ) = @_; 50 22 $self->process_doc(%args); … … 74 46 my @outline = (); 75 47 my $cur_pkg = {}; 76 48 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 77 51 foreach my $thing (@things) { 78 52 if ( ref $thing eq 'PPI::Statement::Package' ) { 79 53 if ($not_first_one) { 80 54 if ( not $cur_pkg->{name} ) { 81 55 $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"; 82 59 } 83 60 push @outline, $cur_pkg; 84 61 $cur_pkg = {}; … … 86 63 $not_first_one = 1; 87 64 $cur_pkg->{name} = $thing->namespace; 88 65 $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' ) { 90 73 next if $thing->type eq 'no'; 91 74 if ( $thing->pragma ) { 92 75 push @{ $cur_pkg->{pragmata} }, { name => $thing->pragma, line => $thing->location->[0] }; 93 } elsif ( $thing->module ) { 76 } 77 elsif ( $thing->module ) { 94 78 push @{ $cur_pkg->{modules} }, { name => $thing->module, line => $thing->location->[0] }; 95 79 unless ($check_alternate_sub_decls) { 96 80 $check_alternate_sub_decls = 1 … … 99 83 'MooseX::Declare', 100 84 'MooseX::Method::Signatures' 101 85 ); 86 ## print "what have I found:". $thing->module; 87 # s/.*MooseX::Declare.*/1/; 88 # $mod_mxd = 1; 102 89 } 103 90 } 104 } elsif ( ref $thing eq 'PPI::Statement::Sub' ) { 91 } 92 93 elsif ( ref $thing eq 'PPI::Statement::Sub' ) { 105 94 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' ) { 107 98 108 99 # last resort, let's analyse further down... 109 100 my $node1 = $thing->first_element; … … 112 103 113 104 # Moose attribute declaration 114 105 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] }; 116 114 next; 117 115 } 118 116 … … 128 126 $ppi->find( 129 127 sub { 130 128 $_[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; 132 130 $_[1]->next_sibling->isa('PPI::Token::Whitespace') or return 0; 133 131 my $sib_content = $_[1]->next_sibling->next_sibling->content or return 0; 134 132 135 133 $sib_content =~ m/^\b(\w+)\b/; 136 134 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 } 137 146 138 147 push @{ $cur_pkg->{methods} }, { name => $1, line => $_[1]->line_number }; 139 148 … … 147 156 } 148 157 149 158 push @outline, $cur_pkg; 150 159 ## print Dumper @outline; 151 160 return \@outline; 152 161 } 153 162 154 163 1; 155 164 156 __END__157 165 166 167 =pod 168 169 =head1 NAME 170 171 PPIx::EditorTools::Outline - Collect use pragmata, modules, subroutiones 172 173 =head1 VERSION 174 175 version 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 186 Return a list of pragmatas, modules, methods of a C<PPI::Document>. 187 188 =head1 METHODS 189 190 =over 4 191 192 =item new() 193 194 Constructor. Generally shouldn't be called with any arguments. 195 196 =item find( ppi => PPI::Document $ppi ) 197 =item find( code => Str $code ) 198 199 Accepts either a C<PPI::Document> to process or a string containing 200 the code (which will be converted into a C<PPI::Document>) to process. 201 Return a reference to a hash. 202 203 =back 204 158 205 =head1 SEE ALSO 159 206 160 207 This class inherits from C<PPIx::EditorTools>. 161 208 Also see L<App::EditorTools>, L<Padre>, and L<PPI>. 162 209 210 =head1 AUTHORS 211 212 =over 4 213 214 =item * 215 216 Steffen Mueller C<smueller@cpan.org> 217 218 =item * 219 220 Repackaged by Mark Grimes C<mgrimes@cpan.org> 221 222 =item * 223 224 Ahmad M. Zawawi <ahmad.zawawi@gmail.com> 225 226 =back 227 228 =head1 COPYRIGHT AND LICENSE 229 230 This software is copyright (c) 2011 by The Padre development team as listed in Padre.pm. 231 232 This is free software; you can redistribute it and/or modify it under 233 the same terms as the Perl 5 programming language system itself. 234 163 235 =cut 164 236 237 238 __END__ 239 240 165 241 # Copyright 2008-2011 The Padre development team as listed in Padre.pm. 166 242 # LICENSE 167 243 # This program is free software; you can redistribute it and/or
comment:6 Changed 2 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 2 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.
comment:8 Changed 2 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 | % | coverage | branch | |
|---|---|---|---|---|
| 15 | 50 | T | F | if ($PPI::VERSION =~ /_/) |
| 142 | 100 | T | F | if ($$c{'file'}) |
| 143 | 50 | T | F | unless open my $fh, '<', $$c{'file'} |
| 150 | 0 | T | F | unless is_deeply($outline, $$c{'expected'}) |
| 269 | 50 | T | F | if ($$c{'file'}) |
| 270 | 50 | T | F | unless open my $fh, '<', $$c{'file'} |
| 275 | 0 | T | F | unless 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

Opps revision 14225