PPIx-EditorTools-0.21/0000775000175000017500000000000013220016557014042 5ustar yanickyanickPPIx-EditorTools-0.21/xt/0000775000175000017500000000000013220016557014475 5ustar yanickyanickPPIx-EditorTools-0.21/xt/release/0000775000175000017500000000000013220016557016115 5ustar yanickyanickPPIx-EditorTools-0.21/xt/release/unused-vars.t0000644000175000017500000000036213220016557020555 0ustar yanickyanick#!perl use Test::More 0.96 tests => 1; eval { require Test::Vars }; SKIP: { skip 1 => 'Test::Vars required for testing for unused vars' if $@; Test::Vars->import; subtest 'unused vars' => sub { all_vars_ok(); }; }; PPIx-EditorTools-0.21/lib/0000775000175000017500000000000013220016557014610 5ustar yanickyanickPPIx-EditorTools-0.21/lib/PPIx/0000775000175000017500000000000013220016557015430 5ustar yanickyanickPPIx-EditorTools-0.21/lib/PPIx/EditorTools/0000775000175000017500000000000013220016557017677 5ustar yanickyanickPPIx-EditorTools-0.21/lib/PPIx/EditorTools/FindVariableDeclaration.pm0000644000175000017500000000577113220016557024741 0ustar yanickyanickpackage PPIx::EditorTools::FindVariableDeclaration; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Finds where a variable was declared using PPI $PPIx::EditorTools::FindVariableDeclaration::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use base 'PPIx::EditorTools'; use Class::XSAccessor accessors => { 'location' => 'location' }; sub find { my ( $self, %args ) = @_; $self->process_doc(%args); my $column = $args{column} or croak "column required"; my $line = $args{line} or croak "line required"; my $location = [ $line, $column ]; my $ppi = $self->ppi; $ppi->flush_locations; my $token = PPIx::EditorTools::find_token_at_location( $ppi, $location ); croak "no token" unless $token; my $declaration = PPIx::EditorTools::find_variable_declaration($token); croak "no declaration" unless $declaration; return PPIx::EditorTools::ReturnObject->new( ppi => $ppi, element => $declaration, ); } 1; =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::FindVariableDeclaration - Finds where a variable was declared using PPI =head1 VERSION version 0.21 =head1 SYNOPSIS # finds declaration of variable at cursor my $declaration = PPIx::EditorTools::FindVariableDeclaration->new->find( code => "package TestPackage;\nuse strict;\nBEGIN { \$^W = 1; }\nmy \$x=1;\n\$x++;" line => 5, column => 2, ); my $location = $declaration->element->location; =head1 DESCRIPTION Finds the location of a variable declaration. =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =item find( ppi => PPI::Document $ppi, line => $line, column => $column ) =item find( code => Str $code, line => $line, column => $column ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Searches for the variable declaration and returns a C with the declaration (C) available via the C accessor. Croaks with a "no token" exception if no token is found at the location. Croaks with a "no declaration" exception if unable to find the declaration. =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # Copyright 2008-2009 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself. PPIx-EditorTools-0.21/lib/PPIx/EditorTools/Outline.pm0000644000175000017500000001600213220016557021651 0ustar yanickyanickpackage PPIx::EditorTools::Outline; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Collect use pragmata, modules, subroutiones, methods, attributes $PPIx::EditorTools::Outline::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use Try::Tiny; use base 'PPIx::EditorTools'; use Class::XSAccessor accessors => {}; use PPI; sub find { my ( $self, %args ) = @_; $self->process_doc(%args); my $ppi = $self->ppi; return [] unless defined $ppi; $ppi->index_locations; # Search for interesting things require PPI::Find; # TODO things not very discriptive my @things = PPI::Find->new( sub { # This is a fairly ugly search return 1 if ref $_[0] eq 'PPI::Statement::Package'; return 1 if ref $_[0] eq 'PPI::Statement::Include'; return 1 if ref $_[0] eq 'PPI::Statement::Sub'; return 1 if ref $_[0] eq 'PPI::Statement'; } )->in($ppi); # Define a flag indicating that further Method::Signature/Moose check should run my $check_alternate_sub_decls = 0; # Build the outline structure from the search results my @outline = (); my $cur_pkg = {}; my $not_first_one = 0; foreach my $thing (@things) { if ( ref $thing eq 'PPI::Statement::Package' ) { if ($not_first_one) { if ( not $cur_pkg->{name} ) { $cur_pkg->{name} = 'main'; } push @outline, $cur_pkg; $cur_pkg = {}; } $not_first_one = 1; $cur_pkg->{name} = $thing->namespace; $cur_pkg->{line} = $thing->location->[0]; } elsif ( ref $thing eq 'PPI::Statement::Include' ) { next if $thing->type eq 'no'; if ( $thing->pragma ) { push @{ $cur_pkg->{pragmata} }, { name => $thing->pragma, line => $thing->location->[0] }; } elsif ( $thing->module ) { push @{ $cur_pkg->{modules} }, { name => $thing->module, line => $thing->location->[0] }; unless ($check_alternate_sub_decls) { $check_alternate_sub_decls = 1 if grep { $thing->module eq $_ } ( 'Method::Signatures', 'MooseX::Declare', 'MooseX::Method::Signatures', 'Moose::Role', 'Moose', ); } } } elsif ( ref $thing eq 'PPI::Statement::Sub' ) { push @{ $cur_pkg->{methods} }, { name => $thing->name, line => $thing->location->[0] }; } elsif ( ref $thing eq 'PPI::Statement' ) { # last resort, let's analyse further down... my $node1 = $thing->first_element; my $node2 = $thing->child(2); next unless defined $node2; # Tests for has followed by new line try { no warnings 'exiting'; # suppress warning Exiting eval via next if ( defined $node2->{content} ) { if ( $node2->{content} =~ /\n/ ) { next; } } }; # Moose attribute declaration if ( $node1->isa('PPI::Token::Word') && $node1->content eq 'has' ) { # p $_[1]->next_sibling->isa('PPI::Token::Whitespace'); $self->_Moo_Attributes( $node2, $cur_pkg, $thing ); next; } # MooseX::POE event declaration if ( $node1->isa('PPI::Token::Word') && $node1->content eq 'event' ) { push @{ $cur_pkg->{events} }, { name => $node2->content, line => $thing->location->[0] }; next; } } } if ($check_alternate_sub_decls) { $ppi->find( sub { $_[1]->isa('PPI::Token::Word') or return 0; $_[1]->content =~ /^(?:func|method|before|after|around|override|augment|class|role)\z/ or return 0; $_[1]->next_sibling->isa('PPI::Token::Whitespace') or return 0; my $sib_content = $_[1]->next_sibling->next_sibling->content or return 0; my $name = eval $sib_content; # if eval() failed for whatever reason, default to original trimmed original token $name ||= ( $sib_content =~ m/^\b(\w+)\b/ )[0]; return 0 unless defined $name; # test for MooseX::Declare class, role if ( $_[1]->content =~ m/(class|role)/ ) { $self->_Moo_PkgName( $cur_pkg, $sib_content, $_[1] ); return 1; # break out so we don't write Package name as method } push @{ $cur_pkg->{methods} }, { name => $name, line => $_[1]->line_number }; return 1; } ); } if ( not $cur_pkg->{name} ) { $cur_pkg->{name} = 'main'; } push @outline, $cur_pkg; return \@outline; } ######## # Composed Method, internal, Moose Attributes # cleans moose attributes up, and single lines them. # only runs if PPI finds has # prefix all vars with ma_ otherwise same name ######## sub _Moo_Attributes { my ( $self, $ma_node2, $ma_cur_pkg, $ma_thing ) = @_; my $line_num = $ma_thing->location->[0]; if ( $ma_node2->content =~ /[\n|;]/ ) { return; } my $attrs = eval $ma_node2->content; # if eval() failed for whatever reason, default to original token $attrs ||= $ma_node2->content; if ( ref $attrs eq 'ARRAY' ) { map { push @{ $ma_cur_pkg->{attributes} }, { name => $_, line => $line_num, } } grep {defined} @{$attrs}; } else { push @{ $ma_cur_pkg->{attributes} }, { name => $attrs, line => $line_num, }; } return; } ######## # Composed Method, internal, Moose Pakage Name # write first Class or Role as Package Name if none # prefix all vars with mpn_ otherwise same name ######## sub _Moo_PkgName { my ( $self, $mpn_cur_pkg, $mpn_sib_content, $mpn_ppi_tuple ) = @_; if ( $mpn_cur_pkg->{name} ) { return 1; } # break if we have a pkg name # add to outline $mpn_cur_pkg->{name} = $mpn_sib_content; # class or role name $mpn_cur_pkg->{line} = $mpn_ppi_tuple->line_number; # class or role location return 1; } 1; =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::Outline - Collect use pragmata, modules, subroutiones, methods, attributes =head1 VERSION version 0.21 =head1 SYNOPSIS my $outline = PPIx::EditorTools::Outline->new->find( code => "package TestPackage;\nsub x { 1;\n" ); print Dumper $outline; =head1 DESCRIPTION Return a list of pragmatas, modules, methods, attributes of a C. =head1 METHODS =over 4 =item * new() Constructor. Generally shouldn't be called with any arguments. =item * find() find( ppi => PPI::Document $ppi ) or find( code => Str $code ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Return a reference to a hash. =back =head2 Internal Methods =over 4 =item * _Moo_Attributes =item * _Moo_PkgName =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # Copyright 2008-2012 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself. PPIx-EditorTools-0.21/lib/PPIx/EditorTools/FindUnmatchedBrace.pm0000644000175000017500000000511413220016557023702 0ustar yanickyanickpackage PPIx::EditorTools::FindUnmatchedBrace; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: PPI-based unmatched-brace-finder $PPIx::EditorTools::FindUnmatchedBrace::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use base 'PPIx::EditorTools'; use Class::XSAccessor accessors => {}; use PPI; sub find { my ( $self, %args ) = @_; $self->process_doc(%args); my $ppi = $self->ppi; my $where = $ppi->find( \&PPIx::EditorTools::find_unmatched_brace ); if ($where) { @$where = sort { PPIx::EditorTools::element_depth($b) <=> PPIx::EditorTools::element_depth($a) or $a->location->[0] <=> $b->location->[0] or $a->location->[1] <=> $b->location->[1] } @$where; return PPIx::EditorTools::ReturnObject->new( ppi => $ppi, element => $where->[0] ); } return; } 1; =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::FindUnmatchedBrace - PPI-based unmatched-brace-finder =head1 VERSION version 0.21 =head1 SYNOPSIS my $brace = PPIx::EditorTools::FindUnmatchedBrace->new->find( code => "package TestPackage;\nsub x { 1;\n" ); my $location = $brace->element->location; =head1 DESCRIPTION Finds the location of unmatched braces in a C. =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =item find( ppi => PPI::Document $ppi ) =item find( code => Str $code ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Finds the location of unmatched braces. Returns a C with the unmatched brace (a C) available via the C accessor. If there is no unmatched brace, returns undef. =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # Copyright 2008-2009 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself. PPIx-EditorTools-0.21/lib/PPIx/EditorTools/IntroduceTemporaryVariable.pm0000644000175000017500000001404013220016557025537 0ustar yanickyanickpackage PPIx::EditorTools::IntroduceTemporaryVariable; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Introduces a temporary variable using PPI $PPIx::EditorTools::IntroduceTemporaryVariable::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use base 'PPIx::EditorTools'; use Class::XSAccessor accessors => { 'start_location' => 'start_location', 'end_location' => 'end_location', 'expression' => 'expression', 'location' => 'location', }; sub introduce { my ( $self, %args ) = @_; $self->process_doc(%args); my $start_loc = $args{start_location} or croak "start_location required"; my $end_loc = $args{end_location} or croak "end_location required"; my $varname = $args{varname}; $varname = 'tmp' if not defined $varname; $varname = '$' . $varname if $varname !~ /^[\$\@\%]/; my $ppi = $self->ppi; $ppi->flush_locations; my $token = PPIx::EditorTools::find_token_at_location( $ppi, $start_loc ); $ppi->flush_locations; die "no token" unless $token; my $statement = $token->statement(); die "no statement" unless $statement; # walk up the PPI tree until we reach a sort of structure that's not a statement. # FIXME: This may or may not be robust. A PPI::Statement claims to be what's # defined as "statements" in perlsyn, but it's not! perlsyn says all statements # end in a semicolon unless at the end of a block. # For PPI, Statements can be part of others and thus don't necessarily have # a semicolon. while (1) { my $parent = $statement->statement(); last if not defined $parent; if ( $parent eq $statement ) { # exactly the same object, ie. is a statement already $parent = $statement->parent(); # force the parent last if not $parent # stop if we're at a block or at the document level or $parent->isa('PPI::Structure::Block') or $parent->isa('PPI::Structure::Document'); $parent = $parent->statement(); # force it to be a statement } last if not $parent # stop if the parent isn't a statement or not $parent->isa('PPI::Statement'); $statement = $parent; } my $location_for_insert = $statement->location; $self->location($location_for_insert); # TODO: split on a look behind \n so we keep the \n my @code = map {"$_\n"} split( /\n/, $ppi->serialize ); my $expr; for my $line_num ( $start_loc->[0] .. $end_loc->[0] ) { my $line = $code[ $line_num - 1 ]; # 0 based index to 1 base line numbers substr( $line, $end_loc->[1] ) = '' if $line_num == $end_loc->[0]; substr( $line, 0, $start_loc->[1] - 1 ) = '' if $line_num == $start_loc->[0]; $expr .= $line; } $self->expression($expr); my $indent = ''; $indent = $1 if $code[ $location_for_insert->[0] - 1 ] =~ /^(\s+)/; my $place_holder = 'XXXXX_PPIx_EDITOR_PLACE_HOLDER_XXXXX'; substr( $code[ $location_for_insert->[0] - 1 ], $location_for_insert->[1] - 1, 0 ) = sprintf( "my %s = %s;\n%s", $varname, $place_holder, $indent ); # TODO: need to watch for word boundries etc... my $code = join( '', @code ); $code =~ s/\Q$expr\E/$varname/gm; $code =~ s/\Q$place_holder\E/$expr/gm; return PPIx::EditorTools::ReturnObject->new( code => $code, element => sub { PPIx::EditorTools::find_token_at_location( shift->ppi, $location_for_insert ); } ); } 1; =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::IntroduceTemporaryVariable - Introduces a temporary variable using PPI =head1 VERSION version 0.21 =head1 SYNOPSIS my $munged = PPIx::EditorTools::IntroduceTemporaryVariable->new->introduce( code => "use strict; BEGIN { $^W = 1; }\n\tmy $x = ( 1 + 10 / 12 ) * 2;\n\tmy $y = ( 3 + 10 / 12 ) * 2;\n", start_location => [ 2, 19 ], end_location => [ 2, 25 ], varname => '$foo', ); my $modified_code_as_string = $munged->code; my $location_of_new_var_declaration = $munged->element->location; =head1 DESCRIPTION Given a region of code within a statement, replaces all occurrences of that code with a temporary variable. Declares and initializes the temporary variable right above the statement that included the selected expression. =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =item find( ppi => PPI::Document, start_location => Int, end_location => Int, varname => Str ) =item find( code => Str, start_location => Int, end_location => Int, varname => Str ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Given the region of code specified by start_location and end_location, replaces that code with a temporary variable with the name given in varname (defaults to C). Declares and initializes the temporary variable right above the statement that included the selected expression. Returns a C with the modified code as a string available via the C accessor (or as a C via the C accessor), and the C where the new variable is declared available via the C accessor. Croaks with a "no token" exception if no token is found at the location. Croaks with a "no statement" exception if unable to find the statement. =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # Copyright 2008-2009 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself. PPIx-EditorTools-0.21/lib/PPIx/EditorTools/RenamePackageFromPath.pm0000644000175000017500000000643713220016557024371 0ustar yanickyanickpackage PPIx::EditorTools::RenamePackageFromPath; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Change the package name based on the files path $PPIx::EditorTools::RenamePackageFromPath::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use Class::XSAccessor accessors => { 'replacement' => 'replacement', 'filename' => 'filename', }; use base 'PPIx::EditorTools'; use PPIx::EditorTools::RenamePackage; use Carp; use File::Spec; use File::Basename; sub rename { my ( $self, %args ) = @_; $self->process_doc(%args); my $path = $args{filename} || croak "filename required"; my $dir = dirname $path; my $file = basename $path, qw/.pm .PM .Pm/; my @directories = grep { $_ && !/^\.$/ } File::Spec->splitdir( File::Spec->rel2abs($dir) ); my $replacement; if ( grep {/^lib$/} @directories ) { while ( shift(@directories) !~ /^lib$/ ) { } } else { @directories = grep { $_ && !/^\.$/ } File::Spec->splitdir($dir); } $replacement = join( '::', @directories, $file ); return PPIx::EditorTools::RenamePackage->new( ppi => $self->ppi )->rename( replacement => $replacement ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::RenamePackageFromPath - Change the package name based on the files path =head1 VERSION version 0.21 =head1 SYNOPSIS my $munged = PPIx::EditorTools::RenamePackageFromPath->new->rename( code => "package TestPackage;\nuse strict;\nBEGIN { $^W = 1; }\n1;\n", filename => './lib/Test/Code/Path.pm', ); my $new_code_as_string = $munged->code; my $package_ppi_element = $munged->element; =head1 DESCRIPTION This module uses PPI to change the package name of code. =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =item rename( ppi => PPI::Document $ppi, filename => Str ) =item rename( code => Str $code, filename => Str ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Replaces the package name with that supplied in the C parameter and returns a C with the new code available via the C or C accessors, as a C or C, respectively. An attempt will be made to derive the package name from the filename passed as a parameter. The filename's path will converted to an absolute path and it will be searched for a C directory which will be assumed the start of the package name. If no C directory can be found in the absolute path, the relative path will be used. Croaks with a "package name not found" exception if unable to find the package name. =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut PPIx-EditorTools-0.21/lib/PPIx/EditorTools/ReturnObject.pm0000644000175000017500000000704513220016557022647 0ustar yanickyanickpackage PPIx::EditorTools::ReturnObject; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Simple object to return values from PPIx::EditorTools $PPIx::EditorTools::ReturnObject::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; sub new { my $class = shift; return bless {@_}, ref($class) || $class; } sub element { my ($self) = @_; # If element is a code ref, run the code once then cache the # result if ( exists $self->{element} and ref( $self->{element} ) and ref( $self->{element} ) eq 'CODE' ) { $self->{element} = $self->{element}->(@_); } return $self->{element}; } sub ppi { my ( $self ) = @_; # $self->{ppi} = $doc if $doc; # TODO: and isa? return $self->{ppi} if $self->{ppi}; if ( $self->{code} ) { my $code = $self->{code}; $self->{ppi} = PPI::Document->new( \$code ); return $self->{ppi}; } return; } sub code { my ( $self ) = @_; # $self->{code} = $doc if $doc; return $self->{code} if $self->{code}; if ( $self->{ppi} ) { $self->{code} = $self->{ppi}->serialize; return $self->{code}; } return; } 1; =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::ReturnObject - Simple object to return values from PPIx::EditorTools =head1 VERSION version 0.21 =head1 SYNOPSIS my $brace = PPIx::EditorTools::FindUnmatchedBrace->new->find( code => "package TestPackage;\nsub x { 1;\n" ); my $location = $brace->element->location; my $ppi = $brace->element->ppi; =head1 DESCRIPTION Retuning a simple C from many of the C methods often results in the loss of the overall context for that element. C provides an object that can be passed around which retains the overall context. For example, in C if the unmatched brace were returned by its C the containing C is likely to go out of scope, thus the C method no longer returns a valid location (rather it returns undef). Using the C preserves the C and the containing context. =head1 METHODS =over 4 =item new() Constructor which should be used by C. Accepts the following named parameters: =over 4 =item ppi A C representing the (possibly modified) code. =item code A string representing the (possibly modified) code. =item element A C or a subclass thereof representing the interesting element. =back =item ppi Accessor to retrieve the C. May create the C from the $code string (lazily) if needed. =item code Accessor to retrieve the string representation of the code. May be retrieved from the C via the serialize method (lazily) if needed. =back =head1 SEE ALSO C, L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # Copyright 2008-2009 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself. PPIx-EditorTools-0.21/lib/PPIx/EditorTools/RenameVariable.pm0000644000175000017500000001735113220016557023117 0ustar yanickyanickpackage PPIx::EditorTools::RenameVariable; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Lexically replace a variable name in Perl code $PPIx::EditorTools::RenameVariable::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use base 'PPIx::EditorTools'; use Class::XSAccessor; sub rename { my ( $self, %args ) = @_; $self->process_doc(%args); my $column = $args{column} || croak "column required"; my $line = $args{line} || croak "line required"; my $location = [ $line, $column ]; my $replacement = $args{replacement}; if ( ( $args{to_camel_case} or $args{from_camel_case} ) and defined $replacement ) { croak("Can't accept both replacement name and to_camel_case/from_camel_case"); } elsif ( not $args{to_camel_case} and not $args{from_camel_case} and not defined $replacement ) { croak("Need either 'replacement' or to/from_camel_case options"); } my $doc = $self->ppi; my $token = PPIx::EditorTools::find_token_at_location( $doc, $location ); die "no token found" unless defined $token; my $declaration = PPIx::EditorTools::find_variable_declaration($token); die "no declaration" unless defined $declaration; $doc->index_locations; my $scope = $declaration; while ( not $scope->isa('PPI::Document') and not $scope->isa('PPI::Structure::Block') ) { $scope = $scope->parent; } my $varname = $token->symbol; if ( not defined $replacement ) { if ( $args{from_camel_case} ) { $replacement = _from_camel_case( $varname, $args{ucfirst} ); } else { # $args{to_camel_case} $replacement = _to_camel_case( $varname, $args{ucfirst} ); } if ( $varname eq $replacement ) { return PPIx::EditorTools::ReturnObject->new( ppi => $doc, element => $token ); } } #warn "VARNAME: $varname"; # TODO: This could be part of PPI somehow? # The following string of hacks is simply for finding symbols in quotelikes and regexes my $type = substr( $varname, 0, 1 ); my $brace = $type eq '@' ? '[' : ( $type eq '%' ? '{' : '' ); my @patterns; if ( $type eq '@' or $type eq '%' ) { my $accessv = $varname; $accessv =~ s/^\Q$type\E/\$/; @patterns = ( quotemeta( _curlify($varname) ), quotemeta($varname), quotemeta($accessv) . '(?=' . quotemeta($brace) . ')', ); if ( $type eq '%' ) { my $slicev = $varname; $slicev =~ s/^\%/\@/; push @patterns, quotemeta($slicev) . '(?=' . quotemeta($brace) . ')'; } elsif ( $type eq '@' ) { my $indexv = $varname; $indexv =~ s/^\@/\$\#/; push @patterns, quotemeta($indexv); } } else { @patterns = ( quotemeta( _curlify($varname) ), quotemeta($varname) . "(?![\[\{])" ); } my %unique; my $finder_regexp = '(?:' . join( '|', grep { !$unique{$_}++ } @patterns ) . ')'; $finder_regexp = qr/$finder_regexp/; # used to find symbols in quotelikes and regexes #warn $finder_regexp; $replacement =~ s/^\W+//; $scope->find( sub { my $node = $_[1]; if ( $node->isa("PPI::Token::Symbol") ) { return 0 unless $node->symbol eq $varname; # TODO do this without breaking encapsulation! $node->{content} = substr( $node->content(), 0, 1 ) . $replacement; } # This used to be a simple "if". Patrickas: "[elsif] resolves this # issue but it may introduce other bugs since I am not sure I # understand the code that follows it." # See Padre trac ticket #655 for the full comment. Remove this # comment if there are new bugs resulting from this change. elsif ( $type eq '@' and $node->isa("PPI::Token::ArrayIndex") ) { # $#foo return 0 unless substr( $node->content, 2 ) eq substr( $varname, 1 ); # TODO do this without breaking encapsulation! $node->{content} = '$#' . $replacement; } elsif ( $node->isa("PPI::Token") ) { # the case of potential quotelikes and regexes my $str = $node->content; if ($str =~ s{($finder_regexp)([\[\{]?)}< if ($1 =~ tr/{//) { substr($1, 0, ($1=~tr/#//)+1) . "{$replacement}$2" } else { substr($1, 0, ($1=~tr/#//)+1) . "$replacement$2" } >ge ) { # TODO do this without breaking encapsulation! $node->{content} = $str; } } return 0; }, ); return PPIx::EditorTools::ReturnObject->new( ppi => $doc, element => $token, ); } # converts a variable name to camel case and optionally converts the # first character to upper case sub _to_camel_case { my $var = shift; my $ucfirst = shift; my $prefix; if ( $var =~ s/^(\W*_)// ) { $prefix = $1; } $var =~ s/_([[:alpha:]])/\u$1/g; $var =~ s/^([^[:alpha:]]*)([[:alpha:]])/$1\u$2/ if $ucfirst; $var = $prefix . $var if defined $prefix; return $var; } sub _from_camel_case { my $var = shift; my $ucfirst = shift; my $prefix; if ( $var =~ s/^(\W*_?)// ) { $prefix = $1; } if ($ucfirst) { $var = lcfirst($var); $var =~ s/([[:upper:]])/_\u$1/g; $var =~ s/^([^[:alpha:]]*)([[:alpha:]])/$1\u$2/; } else { $var =~ s/^([^[:alpha:]]*)([[:alpha:]])/$1\l$2/; $var =~ s/([[:upper:]])/_\l$1/g; } $var = $prefix . $var if defined $prefix; return $var; } sub _curlify { my $var = shift; if ( $var =~ s/^([\$\@\%])(.+)$/${1}{$2}/ ) { return ($var); } return (); } 1; __END__ =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::RenameVariable - Lexically replace a variable name in Perl code =head1 VERSION version 0.21 =head1 SYNOPSIS my $munged = PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 15, column => 13, replacement => 'stuff', ); my $code_as_strig = $munged->code; my $code_as_ppi = $munged->ppi; my $location = $munged->element->location; =head1 DESCRIPTION This module will lexically replace a variable name. =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =item rename( ppi => PPI::Document $ppi, line => Int, column => Int, replacement => Str ) =item rename( code => Str $code, line => Int, column => Int, replacement => Str ) =item rename( code => Str $code, line => Int, column => Int, to_camel_case => Bool, [ucfirst => Bool] ) =item rename( code => Str $code, line => Int, column => Int, from_camel_case => Bool, [ucfirst => Bool] ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Renames the variable found at line, column with that supplied in the C parameter and returns a C with the new code available via the C or C accessors, as a C or C, respectively. The C found at line, column is available via the C accessor. Instead of specifying an explicit replacement variable name, you may choose to use the C or C options that automatically convert to/from camelCase. In that mode, the C option will force uppercasing of the first letter. You can not specify a replacement name and use the C options. Croaks with a "no token" exception if no token is found at the location. Croaks with a "no declaration" exception if unable to find the declaration. =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut PPIx-EditorTools-0.21/lib/PPIx/EditorTools/RenamePackage.pm0000644000175000017500000000540013220016557022715 0ustar yanickyanickpackage PPIx::EditorTools::RenamePackage; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Change the package name $PPIx::EditorTools::RenamePackage::VERSION = '0.21'; use strict; BEGIN { $^W = 1; } use base 'PPIx::EditorTools'; use Class::XSAccessor accessors => { 'replacement' => 'replacement' }; use PPI; use Carp; sub rename { my ( $self, %args ) = @_; $self->process_doc(%args); my $replacement = $args{replacement} || croak "replacement required"; my $doc = $self->ppi; # TODO: support MooseX::Declare my $package = $doc->find_first('PPI::Statement::Package') or die "no package found"; my $namespace = $package->schild(1) or croak "package name not found"; $namespace->isa('PPI::Token::Word') or croak "package name not found"; $namespace->{content} = $replacement; return PPIx::EditorTools::ReturnObject->new( ppi => $doc, element => $package ); } 1; __END__ =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::RenamePackage - Change the package name =head1 VERSION version 0.21 =head1 SYNOPSIS my $munged = PPIx::EditorTools::RenamePackage->new->rename( code => <<'END_CODE', package TestPackage; use strict; BEGIN { $^W = 1; } 1; END_CODE replacement => 'NewPackage' ); my $new_code_as_string = $munged->code; my $package_ppi_element = $munged->element; =head1 DESCRIPTION This module uses PPI to change the package name of code. =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =item rename( ppi => PPI::Document $ppi, replacement => Str ) =item rename( code => Str $code, replacement => Str ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Replaces the package name with that supplied in the C parameter and returns a C with the new code available via the C or C accessors, as a C or C, respectively. Croaks with a "package name not found" exception if unable to find the package name. =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut PPIx-EditorTools-0.21/lib/PPIx/EditorTools/Lexer.pm0000644000175000017500000001004313220016557021310 0ustar yanickyanickpackage PPIx::EditorTools::Lexer; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Simple Lexer used for syntax highlighting $PPIx::EditorTools::Lexer::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use base 'PPIx::EditorTools'; use Class::XSAccessor accessors => {}; use PPI; sub lexer { my ( $self, %args ) = @_; my $markup = delete $args{highlighter}; $self->process_doc(%args); my $ppi = $self->ppi; return [] unless defined $ppi; $ppi->index_locations; my @tokens = $ppi->tokens; foreach my $t (@tokens) { my ( $row, $rowchar ) = @{ $t->location }; my $css = class_to_css($t); my $len = $t->length; $markup->( $css, $row, $rowchar, $len ); } } sub class_to_css { my $Token = shift; if ( $Token->isa('PPI::Token::Word') ) { # There are some words we can be very confident are # being used as keywords unless ( $Token->snext_sibling and $Token->snext_sibling->content eq '=>' ) { if ( $Token->content =~ /^(?:sub|return)$/ ) { return 'keyword'; } elsif ( $Token->content =~ /^(?:undef|shift|defined|bless)$/ ) { return 'core'; } } if ( $Token->previous_sibling and $Token->previous_sibling->content eq '->' ) { if ( $Token->content =~ /^(?:new)$/ ) { return 'core'; } } if ( $Token->parent->isa('PPI::Statement::Include') ) { if ( $Token->content =~ /^(?:use|no)$/ ) { return 'keyword'; } if ( $Token->content eq $Token->parent->pragma ) { return 'pragma'; } } elsif ( $Token->parent->isa('PPI::Statement::Variable') ) { if ( $Token->content =~ /^(?:my|local|our)$/ ) { return 'keyword'; } } elsif ( $Token->parent->isa('PPI::Statement::Compound') ) { if ( $Token->content =~ /^(?:if|else|elsif|unless|for|foreach|while|my)$/ ) { return 'keyword'; } } elsif ( $Token->parent->isa('PPI::Statement::Package') ) { if ( $Token->content eq 'package' ) { return 'keyword'; } } elsif ( $Token->parent->isa('PPI::Statement::Scheduled') ) { return 'keyword'; } } # Normal coloring my $css = ref $Token; $css =~ s/^.+:://; $css; } 1; =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools::Lexer - Simple Lexer used for syntax highlighting =head1 VERSION version 0.21 =head1 SYNOPSIS PPIx::EditorTools::Lexer->new->lexer( code => "package TestPackage;\nsub x { 1;\n", highlighter => sub { my ( $css, $row, $rowchar, $len ) = @_; ... }, ); =head1 DESCRIPTION Go over the various interesting elements of a give piece of code or an already process PPI tree. For each token call the user supplied 'highlighter' function with the follow values: $css - The keyword that can be used for colouring. $row - The row number where the token starts $rowchar - The character within that row where the token starts $len - The length of the token =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =item find( ppi => PPI::Document $ppi, highlighter => sub {...} ) =item find( code => Str $code, highlighter => sub ...{} ) Accepts either a C to process or a string containing the code (which will be converted into a C) to process. Return a reference to an array. =back =head1 SEE ALSO This class inherits from C. Also see L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # Copyright 2008-2011 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself. PPIx-EditorTools-0.21/lib/PPIx/EditorTools.pm0000644000175000017500000002201413220016557020232 0ustar yanickyanickpackage PPIx::EditorTools; our $AUTHORITY = 'cpan:YANICK'; # ABSTRACT: Utility methods and base class for manipulating Perl via PPI $PPIx::EditorTools::VERSION = '0.21'; use 5.008; use strict; use warnings; use Carp; use Class::XSAccessor 1.02 constructor => 'new', accessors => { 'code' => 'code', 'ppi' => 'ppi', }; use PPI 1.203; use PPIx::EditorTools::ReturnObject; # Used by all the PPIx::EditorTools::* modules # Checks for either PPI::Document or take the code as a string and # creates the ppi document sub process_doc { my ( $self, %args ) = @_; $self->ppi( $args{ppi} ) if defined $args{ppi}; return 1 if $self->ppi && $self->ppi->isa('PPI::Document'); # TODO: inefficient to pass around full code/ppi $self->code( $args{code} ) if $args{code}; my $code = $self->code; $self->ppi( PPI::Document->new( \$code ) ); return 1 if $self->ppi && $self->ppi->isa('PPI::Document'); croak "arguments ppi or code required"; return; } ##################################################################### # Assorted Search Functions sub find_unmatched_brace { $_[1]->isa('PPI::Statement::UnmatchedBrace') and return 1; $_[1]->isa('PPI::Structure') or return ''; $_[1]->start and $_[1]->finish and return ''; return 1; } # scans a document for variable declarations and # sorts them into three categories: # lexical (my) # our (our, doh) # dynamic (local) # package (use vars) # Returns a hash reference containing the three category names # each pointing at a hash which contains '$variablename' => locations. # locations is an array reference containing one or more PPI-style # locations. Example: # { # lexical => { # '$foo' => [ [ 2, 3, 3], [ 6, 7, 7 ] ], # }, # ... # } # Thus, there are two places where a "my $foo" was declared. On line 2 col 3 # and line 6 col 7. sub get_all_variable_declarations { my $document = shift; my $declarations = $document->find( sub { return 0 unless $_[1]->isa('PPI::Statement::Variable') or $_[1]->isa('PPI::Statement::Include') or $_[1]->isa('PPI::Statement::Compound'); return 1; }, ); my %our; my %lexical; my %dynamic; my %package; foreach my $decl (@$declarations) { if ( $decl->isa('PPI::Statement::Variable') ) { my $type = $decl->type(); my @vars = $decl->variables; my $location = $decl->location; my $target_type; if ( $type eq 'my' ) { $target_type = \%lexical; } elsif ( $type eq 'our' ) { $target_type = \%our; } elsif ( $type eq 'local' ) { $target_type = \%dynamic; } foreach my $var (@vars) { $target_type->{$var} ||= []; push @{ $target_type->{$var} }, $location; } } # find use vars... elsif ( $decl->isa('PPI::Statement::Include') and $decl->module eq 'vars' and $decl->type eq 'use' ) { # do it the low-tech way my $string = $decl->content(); my $location = $decl->location; my @vars = $string =~ /([\%\@\$][\w_:]+)/g; foreach my $var (@vars) { $package{$var} ||= []; push @{ $package{$var} }, $location; } } # find for/foreach loop variables elsif ( $decl->isa('PPI::Statement::Compound') && ( $decl->type eq 'for' or $decl->type eq 'foreach' ) ) { my @elems = $decl->elements; next if scalar(@elems) < 5; my $location = $decl->location; my $type = $elems[2]->content(); if ( $elems[4]->isa('PPI::Token::Symbol') && ( $type eq 'my' || $type eq 'our' ) ) { my $target_type; # Only my and our are valid for loop variable if ( $type eq 'my' ) { $target_type = \%lexical; } elsif ( $type eq 'our' ) { $target_type = \%our; } my $var = $elems[4]->content(); $target_type->{$var} ||= []; push @{ $target_type->{$var} }, $location; } } } # end foreach declaration return ( { our => \%our, lexical => \%lexical, dynamic => \%dynamic, package => \%package } ); } ##################################################################### # Stuff that should be in PPI itself sub element_depth { my $cursor = shift; my $depth = 0; while ( $cursor = $cursor->parent ) { $depth += 1; } return $depth; } # TODO: PPIx::IndexOffsets or something similar might help. # TODO: See the 71... tests. If we don#t flush locations there, this breaks. sub find_token_at_location { my $document = shift; my $location = shift; if ( not defined $document or not $document->isa('PPI::Document') or not defined $location or not ref($location) eq 'ARRAY' ) { require Carp; Carp::croak("find_token_at_location() requires a PPI::Document and a PPI-style location as arguments"); } $document->index_locations(); foreach my $token ( $document->tokens ) { my $loc = $token->location; if ( $loc->[0] > $location->[0] or ( $loc->[0] == $location->[0] and $loc->[1] > $location->[1] ) ) { $document->flush_locations(); return $token->previous_token(); } } $document->flush_locations(); return (); } # given either a PPI::Token::Symbol (i.e. a variable) # or a PPI::Token which contains something that looks like # a variable (quoted vars, interpolated vars in regexes...) # find where that variable has been declared lexically. # Doesn't find stuff like "use vars...". sub find_variable_declaration { my $cursor = shift; return () if not $cursor or not $cursor->isa("PPI::Token"); my ( $varname, $token_str ); if ( $cursor->isa("PPI::Token::Symbol") ) { $varname = $cursor->symbol; $token_str = $cursor->content; } else { my $content = $cursor->content; if ( $content =~ /((?:\$#?|[@%*])[\w:\']+)/ ) { $varname = $1; $token_str = $1; } } return () if not defined $varname; $varname =~ s/^\$\#/@/; my $document = $cursor->top(); my $declaration; my $prev_cursor; # This finds variable declarations if you're above it if ( $cursor->parent->isa('PPI::Statement::Variable') ) { return $cursor->parent; } # This finds variable declarations if you're above it and it has the form my ($foo , $bar); if ( $cursor->parent->isa('PPI::Statement::Expression') && $cursor->parent->parent->parent->isa('PPI::Statement::Variable') ) { return $cursor->parent->parent->parent; } while (1) { $prev_cursor = $cursor; $cursor = $cursor->parent; if ( $cursor->isa("PPI::Structure::Block") or $cursor == $document ) { my @elems = $cursor->elements; foreach my $elem (@elems) { # Stop scanning this scope if we're at the branch we're coming # from. This is to ignore declarations later in the block. last if $elem == $prev_cursor; if ( $elem->isa("PPI::Statement::Variable") and grep { $_ eq $varname } $elem->variables ) { $declaration = $elem; last; } # find use vars ... elsif ( $elem->isa("PPI::Statement::Include") and $elem->module eq 'vars' and $elem->type eq 'use' ) { # do it the low-tech way my $string = $elem->content(); my @vars = $string =~ /([\%\@\$][\w_:]+)/g; if ( grep { $varname eq $_ } @vars ) { $declaration = $elem; last; } } } last if $declaration or $cursor == $document; } # this is for "foreach my $i ..." elsif ( $cursor->isa("PPI::Statement::Compound") and $cursor->type() =~ /^for/ ) { my @elems = $cursor->elements; foreach my $elem (@elems) { # Stop scanning this scope if we're at the branch we're coming # from. This is to ignore declarations later in the block. last if $elem == $prev_cursor; if ( $elem->isa("PPI::Token::Word") and $elem->content() =~ /^(?:my|our)$/ ) { my $nelem = $elem->snext_sibling(); if ( defined $nelem and $nelem->isa("PPI::Token::Symbol") and $nelem->symbol() eq $varname || $nelem->content() eq $token_str ) { $declaration = $nelem; last; } } } last if $declaration or $cursor == $document; } } # end while not top level return $declaration; } 1; =pod =encoding UTF-8 =head1 NAME PPIx::EditorTools - Utility methods and base class for manipulating Perl via PPI =head1 VERSION version 0.21 =head1 SYNOPSIS See PPIx::EditorTools::* =head1 DESCRIPTION Base class and utility methods for manipulating Perl via PPI. Pulled out from the C code. =head1 METHODS =over 4 =item new() Constructor. Generally shouldn't be called with any arguments. =back =head1 SEE ALSO C, L, L, L, and L. =head1 AUTHORS =over 4 =item * Steffen Mueller C =item * Mark Grimes C =item * Ahmad M. Zawawi =item * Gabor Szabo =item * Yanick Champoux =back =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut __END__ # Copyright 2008-2009 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself. PPIx-EditorTools-0.21/Makefile.PL0000644000175000017500000000367413220016557016024 0ustar yanickyanick# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.009. use strict; use warnings; use 5.008; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Utility methods and base class for manipulating Perl via PPI", "AUTHOR" => "Steffen Mueller C, Mark Grimes C, Ahmad M. Zawawi , Gabor Szabo , Yanick Champoux ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "PPIx-EditorTools", "LICENSE" => "perl", "MIN_PERL_VERSION" => "5.008", "NAME" => "PPIx::EditorTools", "PREREQ_PM" => { "Carp" => 0, "Class::XSAccessor" => "1.02", "File::Basename" => 0, "File::Spec" => 0, "PPI" => "1.203", "PPI::Find" => 0, "Try::Tiny" => 0, "base" => 0, "strict" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "ExtUtils::MakeMaker" => 0, "File::Spec" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "Test::Differences" => 0, "Test::Exception" => 0, "Test::More" => 0, "Test::Most" => 0 }, "VERSION" => "0.21", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "Carp" => 0, "Class::XSAccessor" => "1.02", "ExtUtils::MakeMaker" => 0, "File::Basename" => 0, "File::Spec" => 0, "File::Temp" => 0, "IO::Handle" => 0, "IPC::Open3" => 0, "PPI" => "1.203", "PPI::Find" => 0, "Test::Differences" => 0, "Test::Exception" => 0, "Test::More" => 0, "Test::Most" => 0, "Try::Tiny" => 0, "base" => 0, "strict" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); PPIx-EditorTools-0.21/MANIFEST0000644000175000017500000000214413220016557015172 0ustar yanickyanickCONTRIBUTORS Changes INSTALL LICENSE MANIFEST META.json META.yml Makefile.PL README README.mkdn SIGNATURE cpanfile doap.xml lib/PPIx/EditorTools.pm lib/PPIx/EditorTools/FindUnmatchedBrace.pm lib/PPIx/EditorTools/FindVariableDeclaration.pm lib/PPIx/EditorTools/IntroduceTemporaryVariable.pm lib/PPIx/EditorTools/Lexer.pm lib/PPIx/EditorTools/Outline.pm lib/PPIx/EditorTools/RenamePackage.pm lib/PPIx/EditorTools/RenamePackageFromPath.pm lib/PPIx/EditorTools/RenameVariable.pm lib/PPIx/EditorTools/ReturnObject.pm script/ppix_editortools t/00-compile.t t/00-ppix-editortools.t t/00-report-prereqs.dd t/00-report-prereqs.t t/01-findunmatchedbrace.t t/02-findvariabledeclaration.t t/03-introducetemporaryvariable.t t/04-renamepackage.t t/05-renamepackagefrompath.t t/06-camelcasing.t t/07-renamevariable.t t/08-getallvariabledeclarations.t t/09-outline.t t/10-lexer.t t/100-changes.t t/outline/Foo.pm t/outline/Mooclass.pm t/outline/MooclassVanilla.pm t/outline/Moofirst.pm t/outline/Moorole.pm t/outline/file1.pl t/outline/file2.pl t/outline/test_1435.pl t/rename_variable/1.in t/rename_variable/1.out xt/release/unused-vars.t PPIx-EditorTools-0.21/Changes0000644000175000017500000000567613220016557015351 0ustar yanickyanickRevision history for PPIx-EditorTools 0.21 2017-12-24 [ ENHANCEMENTS ] - remove spurious dependencies. (GH#8, Kent Fredic) [ STATISTICS ] - code churn: 6 files changed, 110 insertions(+), 94 deletions(-) 0.20 2017-10-22 - POD fixes. - maintainership passes to Yanick. - remove unused variables. [ STATISTICS ] - code churn: 18 files changed, 172 insertions(+), 204 deletions(-) 0.19 2014 .09.03 - Update the link to the GitHub repository. 0.18 2012 .10.20 - Including Module::Install 1.06 http://weblog.bulknews.net/post/33907905561/do-not-ship-modules-with-module-install-1-04 - Add test using Test::CPAN::Changes 0.17 2012 .08.19 - in Frankfurt am Main 0.16 2012 .08.15 - released based on 0.15_02 0.15_04 2012 .07.11 - suppress warning Exiting eval via next (BOWTIE) 0.15_03 2012 .07.07 - Add patches from #1435 inspired by dod++ (BOWTIE) - Add additional tests for #1435 (BOWTIE) 0.15_02 2012 .06.08 - Add patches from #401 by buff3r++ (BOWTIE) - Add Moose::Role support (BOWTIE) 0.15 2011 .05.06 - Parse Moose files as well (BOWTIE) 0.14 2011 .05.04 - Move from Dist::Zilla to Module::Install (-> LICENSE, META.json, README files removed, inc/ added) 0.13 2011 .03.24 - Copy the lexer code used for syntax highlighting in Padre::Document::Perl::PPILexer to PPIx::EditorTools::Lexer (SZABGAB) 0.12 2011 .03.23 - Copy the Outline generating code from Padre::Document::Perl::Outline to PPIx::EditorTools::Outline (SZABGAB) 0.11 2010 .11.18 - Fixed RT #63107: Finding declared variables fragile and misses loop variables OVID++ (AZAWAWI) - Moved to Dist::Zilla (AZAWAWI) 0.10 2010 .09.26 - Fixed Padre ticket #655: Can't rename to a variable with an underscore in it (PATRICKAS) - Fixed Padre ticket #653: Lexically rename doesn't work when clicking on declaration of variable (PATRICKAS) - Added feature to change variable style to/from camelCase (SMUELLER) 0.09 2009 .09.19 - Fixed Padre ticket:504 and ticket:586 which is basically about being able to rename a variable when the cursor is over its declaration (AZAWAWI) - Refactored code a bit and removed some dead code (AZAWAWI) - Fixed one passing TODO test in t/06-renamevariable.t (AZAWAWI) - Added a test to t/02-findvariabledeclaration.t to make sure this fix works in the future (AZAWAWI) 0.08 2009 .08.05 - updated location tests to work with the PPI v1.205 (RT#48449) (MGRIMES) - removed the INSTALL file: bad copyright and old install instuctions 0.07 2009 .07.21 - skip tests if PPI version includes an underscore _ (SZABGAB) 0.06 2009 .07.11 - fix MANIFEST.SKIP 0.05 2009 .07.07 - Switch Changes to be more machine parsable (ADAMK) - Added dependency versions - Removed needless 5.10 dependency that wasn't reflected in the code - Switched to Module::Install to auto-detect config from the code 0.04 2009 .06.25 - Added Changes file - Removed MANIFEST and META.yml from repository PPIx-EditorTools-0.21/LICENSE0000644000175000017500000004410013220016557015044 0ustar yanickyanickThis software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End PPIx-EditorTools-0.21/README.mkdn0000644000175000017500000000217313220016557015653 0ustar yanickyanick# NAME PPIx::EditorTools - Utility methods and base class for manipulating Perl via PPI # VERSION version 0.21 # SYNOPSIS ``` See PPIx::EditorTools::* ``` # DESCRIPTION Base class and utility methods for manipulating Perl via PPI. Pulled out from the `Padre::Task::PPI` code. # METHODS - new() Constructor. Generally shouldn't be called with any arguments. # SEE ALSO `PPIx::EditorTools::*`, [Padre](https://metacpan.org/pod/Padre), [App::EditorTools](https://metacpan.org/pod/App::EditorTools), [Padre](https://metacpan.org/pod/Padre), and [PPI](https://metacpan.org/pod/PPI). # AUTHORS - Steffen Mueller `smueller@cpan.org` - Mark Grimes `mgrimes@cpan.org` - Ahmad M. Zawawi - Gabor Szabo - Yanick Champoux [![endorse](http://api.coderwall.com/yanick/endorsecount.png)](http://coderwall.com/yanick) # COPYRIGHT AND LICENSE This software is copyright (c) 2017, 2014, 2012 by The Padre development team as listed in Padre.pm.. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. PPIx-EditorTools-0.21/SIGNATURE0000644000175000017500000000774113220016557015335 0ustar yanickyanickThis file contains message digests of all files listed in MANIFEST, signed via the Module::Signature module, version 0.79. To verify the content in this distribution, first make sure you have Module::Signature installed, then type: % cpansign -v It will check each file's integrity, as well as the signature's validity. If "==> Signature verified OK! <==" is not displayed, the distribution may already have been compromised, and you should not run its Makefile.PL or Build.PL. -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 SHA1 4699f561d8ea1911589f4cb5fbc0ea193238e3d4 CONTRIBUTORS SHA1 51fde09553ac9e886c05c964075b0fa525c08267 Changes SHA1 dc71f2f76914f43563f8c9b5c94dedffb786e22c INSTALL SHA1 c07cb3e4ee204b03d740b5685e1369722e8201ea LICENSE SHA1 ede61e8ad665984ba8dc73cd317671de1e402cd3 MANIFEST SHA1 c61568409a2c5ea6c456495eed392accc86f1ffa META.json SHA1 e596ee56a771a826919d343c268c4f48874da87d META.yml SHA1 942a6d201789512014955fdf643d856c22c583aa Makefile.PL SHA1 950f8db4957e1482191f1e28ec5c8a4bea9c9dc1 README SHA1 0d8265a050121b80f17ce18bd3c3d4ca108073a2 README.mkdn SHA1 6f4b6d6896959fa219d32bdf4bb5fb4e59cbc36b cpanfile SHA1 6444f2e532e5c5b9bf430da9bedf0d513dd83914 doap.xml SHA1 5de8f0695a50ab69ffe27eb0f2e598293a47a92f lib/PPIx/EditorTools.pm SHA1 0c427c7ae75f359cbfe46ab234aef21508c220ed lib/PPIx/EditorTools/FindUnmatchedBrace.pm SHA1 657c530d91d725e3da9ccd599b44e9b83bdc511d lib/PPIx/EditorTools/FindVariableDeclaration.pm SHA1 caa83d45b4f3d811a7ed5398bf85318b463d2e9b lib/PPIx/EditorTools/IntroduceTemporaryVariable.pm SHA1 837c0aac1f111f58e0d24b2e0bec0a12d0819667 lib/PPIx/EditorTools/Lexer.pm SHA1 71b1a51a172ae202e940a46e23d10dee37d8d6d0 lib/PPIx/EditorTools/Outline.pm SHA1 319ffea27efc0b09f3bab604d4146397652bac9f lib/PPIx/EditorTools/RenamePackage.pm SHA1 0904725e3044dfc472b95d608435789a840a62d9 lib/PPIx/EditorTools/RenamePackageFromPath.pm SHA1 dde6a4e6c1f7e91ee0ca22dfa312b864533a520f lib/PPIx/EditorTools/RenameVariable.pm SHA1 49bd4a45dd18a06a9409a3e9b9c8bc3bcd2e4707 lib/PPIx/EditorTools/ReturnObject.pm SHA1 e7e0e8952cb48e7cd27a950807a2f2dcfb227b38 script/ppix_editortools SHA1 20e771be9893e894e065e7674f9df2fcb03033f7 t/00-compile.t SHA1 4eb6e5b345bd77b0f12d71f4e5259696362189f7 t/00-ppix-editortools.t SHA1 d61ebf2fff63bc8b58bbbea0d5439e14d4c757d8 t/00-report-prereqs.dd SHA1 504a672015f8761f5bad3863d844954c9e803c3f t/00-report-prereqs.t SHA1 8ede358b2f277a091c497906169f5091ebeda334 t/01-findunmatchedbrace.t SHA1 f5e4bf0840ea8c792e08df27c43d34b684688ef9 t/02-findvariabledeclaration.t SHA1 aa6c8805c6bdbbcba097e934d80b0069d41c0459 t/03-introducetemporaryvariable.t SHA1 e1a8f732646954b48cb4b9fad2deeac9b30d3a13 t/04-renamepackage.t SHA1 00affe5390aaa87a25f59d27697a445cbe9b8154 t/05-renamepackagefrompath.t SHA1 1874ffb348e83253751012cc3b9fd79811e2d5e2 t/06-camelcasing.t SHA1 2a5bbc43c5df3c4c0d8f3966e41ccc2559b77646 t/07-renamevariable.t SHA1 57f5981a7c402004316db76be471ae91343d05fa t/08-getallvariabledeclarations.t SHA1 6e8fce32ac23e7322aabb131df02c85e4feb34ee t/09-outline.t SHA1 7899491a32986450670126afc2d5558488beda09 t/10-lexer.t SHA1 d3e6673c6ef0432c21ae5c45552059a7d6d56143 t/100-changes.t SHA1 5fcf28a1936774ac600d2460224bc437d108daf3 t/outline/Foo.pm SHA1 3ea5ddf93ad27b48571351735ba90883a39e1df3 t/outline/Mooclass.pm SHA1 05b8170bd92c2a45489b68078edc4883c1349122 t/outline/MooclassVanilla.pm SHA1 ba3986bf35f118a58466f564ddfa5c0ebb0b4649 t/outline/Moofirst.pm SHA1 1c9d951dcfdd1b9f40d9d0351e5104b22b8fb538 t/outline/Moorole.pm SHA1 f7b0b18756ebd7a360df4509830b0fb0a789f487 t/outline/file1.pl SHA1 ab06cc809ac916aa2692f59539b1a0215f563435 t/outline/file2.pl SHA1 26f6feb9d2f638ebd67ae0ba02324ae5a90c71f4 t/outline/test_1435.pl SHA1 eaa4fb32444b3841bda35b474c79eaa2cf006051 t/rename_variable/1.in SHA1 9cf8236dd9b2fd02c9e1ad97f14f554a32d51832 t/rename_variable/1.out SHA1 d1fe7d94b3edc7847eb187d4ee41f66e19cf8907 xt/release/unused-vars.t -----BEGIN PGP SIGNATURE----- iEYEARECAAYFAlpAHW8ACgkQ34Hwf+GwC4xcGQCgjcla4AsrHe6d25ZGk5IE968k oO8AoOOUI25L7B0hpCrYTSMnvtYNpKIv =Xtit -----END PGP SIGNATURE----- PPIx-EditorTools-0.21/INSTALL0000644000175000017500000000172513220016557015076 0ustar yanickyanickThis is the Perl distribution PPIx-EditorTools. Installing PPIx-EditorTools is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm PPIx::EditorTools If you are installing into a system-wide directory, you may need to pass the "-S" flag to cpanm, which uses sudo to install the module: % cpanm -S PPIx::EditorTools ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan PPIx::EditorTools ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, then build it: % perl Makefile.PL % make && make test Then install it: % make install If you are installing into a system-wide directory, you may need to run: % sudo make install ## Documentation PPIx-EditorTools documentation is available as POD. You can run perldoc from a shell to read the documentation: % perldoc PPIx::EditorTools PPIx-EditorTools-0.21/CONTRIBUTORS0000644000175000017500000000057713220016557015731 0ustar yanickyanick # PPIX-EDITORTOOLS CONTRIBUTORS # This is the (likely incomplete) list of people who have helped make this distribution what it is, either via code contributions, patches, bug reports, help with troubleshooting, etc. A huge 'thank you' to all of them. * Adam Kennedy * Florian Schlichting * Kent Fredric * Kevin Dawson * Ryan Niebur * Sebastian Willing PPIx-EditorTools-0.21/META.json0000644000175000017500000000762313220016557015471 0ustar yanickyanick{ "abstract" : "Utility methods and base class for manipulating Perl via PPI", "author" : [ "Steffen Mueller C", "Mark Grimes C", "Ahmad M. Zawawi ", "Gabor Szabo ", "Yanick Champoux " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.009, CPAN::Meta::Converter version 2.150001", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "PPIx-EditorTools", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Test::More" : "0.96", "Test::Vars" : "0" } }, "runtime" : { "requires" : { "Carp" : "0", "Class::XSAccessor" : "1.02", "File::Basename" : "0", "File::Spec" : "0", "PPI" : "1.203", "PPI::Find" : "0", "Try::Tiny" : "0", "base" : "0", "perl" : "5.008", "strict" : "0", "warnings" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "ExtUtils::MakeMaker" : "0", "File::Spec" : "0", "File::Temp" : "0", "IO::Handle" : "0", "IPC::Open3" : "0", "Test::Differences" : "0", "Test::Exception" : "0", "Test::More" : "0", "Test::Most" : "0" } } }, "provides" : { "PPIx::EditorTools" : { "file" : "lib/PPIx/EditorTools.pm", "version" : "0.21" }, "PPIx::EditorTools::FindUnmatchedBrace" : { "file" : "lib/PPIx/EditorTools/FindUnmatchedBrace.pm", "version" : "0.21" }, "PPIx::EditorTools::FindVariableDeclaration" : { "file" : "lib/PPIx/EditorTools/FindVariableDeclaration.pm", "version" : "0.21" }, "PPIx::EditorTools::IntroduceTemporaryVariable" : { "file" : "lib/PPIx/EditorTools/IntroduceTemporaryVariable.pm", "version" : "0.21" }, "PPIx::EditorTools::Lexer" : { "file" : "lib/PPIx/EditorTools/Lexer.pm", "version" : "0.21" }, "PPIx::EditorTools::Outline" : { "file" : "lib/PPIx/EditorTools/Outline.pm", "version" : "0.21" }, "PPIx::EditorTools::RenamePackage" : { "file" : "lib/PPIx/EditorTools/RenamePackage.pm", "version" : "0.21" }, "PPIx::EditorTools::RenamePackageFromPath" : { "file" : "lib/PPIx/EditorTools/RenamePackageFromPath.pm", "version" : "0.21" }, "PPIx::EditorTools::RenameVariable" : { "file" : "lib/PPIx/EditorTools/RenameVariable.pm", "version" : "0.21" }, "PPIx::EditorTools::ReturnObject" : { "file" : "lib/PPIx/EditorTools/ReturnObject.pm", "version" : "0.21" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/yanick/PPIx-EditorTools/issues" }, "homepage" : "https://github.com/yanick/PPIx-EditorTools", "repository" : { "type" : "git", "url" : "https://github.com/yanick/PPIx-EditorTools.git", "web" : "https://github.com/yanick/PPIx-EditorTools" } }, "version" : "0.21", "x_authority" : "cpan:YANICK", "x_contributors" : [ "Adam Kennedy ", "Florian Schlichting ", "Kent Fredric ", "Kevin Dawson ", "Ryan Niebur ", "Sebastian Willing " ], "x_serialization_backend" : "JSON::XS version 3.01" } PPIx-EditorTools-0.21/META.yml0000644000175000017500000000501013220016557015305 0ustar yanickyanick--- abstract: 'Utility methods and base class for manipulating Perl via PPI' author: - 'Steffen Mueller C' - 'Mark Grimes C' - 'Ahmad M. Zawawi ' - 'Gabor Szabo ' - 'Yanick Champoux ' build_requires: ExtUtils::MakeMaker: '0' File::Spec: '0' File::Temp: '0' IO::Handle: '0' IPC::Open3: '0' Test::Differences: '0' Test::Exception: '0' Test::More: '0' Test::Most: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.009, CPAN::Meta::Converter version 2.150001' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: PPIx-EditorTools provides: PPIx::EditorTools: file: lib/PPIx/EditorTools.pm version: '0.21' PPIx::EditorTools::FindUnmatchedBrace: file: lib/PPIx/EditorTools/FindUnmatchedBrace.pm version: '0.21' PPIx::EditorTools::FindVariableDeclaration: file: lib/PPIx/EditorTools/FindVariableDeclaration.pm version: '0.21' PPIx::EditorTools::IntroduceTemporaryVariable: file: lib/PPIx/EditorTools/IntroduceTemporaryVariable.pm version: '0.21' PPIx::EditorTools::Lexer: file: lib/PPIx/EditorTools/Lexer.pm version: '0.21' PPIx::EditorTools::Outline: file: lib/PPIx/EditorTools/Outline.pm version: '0.21' PPIx::EditorTools::RenamePackage: file: lib/PPIx/EditorTools/RenamePackage.pm version: '0.21' PPIx::EditorTools::RenamePackageFromPath: file: lib/PPIx/EditorTools/RenamePackageFromPath.pm version: '0.21' PPIx::EditorTools::RenameVariable: file: lib/PPIx/EditorTools/RenameVariable.pm version: '0.21' PPIx::EditorTools::ReturnObject: file: lib/PPIx/EditorTools/ReturnObject.pm version: '0.21' requires: Carp: '0' Class::XSAccessor: '1.02' File::Basename: '0' File::Spec: '0' PPI: '1.203' PPI::Find: '0' Try::Tiny: '0' base: '0' perl: '5.008' strict: '0' warnings: '0' resources: bugtracker: https://github.com/yanick/PPIx-EditorTools/issues homepage: https://github.com/yanick/PPIx-EditorTools repository: https://github.com/yanick/PPIx-EditorTools.git version: '0.21' x_authority: cpan:YANICK x_contributors: - 'Adam Kennedy ' - 'Florian Schlichting ' - 'Kent Fredric ' - 'Kevin Dawson ' - 'Ryan Niebur ' - 'Sebastian Willing ' x_serialization_backend: 'YAML::Tiny version 1.67' PPIx-EditorTools-0.21/cpanfile0000644000175000017500000000155513220016557015552 0ustar yanickyanickrequires "Carp" => "0"; requires "Class::XSAccessor" => "1.02"; requires "File::Basename" => "0"; requires "File::Spec" => "0"; requires "PPI" => "1.203"; requires "PPI::Find" => "0"; requires "Try::Tiny" => "0"; requires "base" => "0"; requires "perl" => "5.008"; requires "strict" => "0"; requires "warnings" => "0"; on 'test' => sub { requires "ExtUtils::MakeMaker" => "0"; requires "File::Spec" => "0"; requires "File::Temp" => "0"; requires "IO::Handle" => "0"; requires "IPC::Open3" => "0"; requires "Test::Differences" => "0"; requires "Test::Exception" => "0"; requires "Test::More" => "0"; requires "Test::Most" => "0"; }; on 'test' => sub { recommends "CPAN::Meta" => "2.120900"; }; on 'configure' => sub { requires "ExtUtils::MakeMaker" => "0"; }; on 'develop' => sub { requires "Test::More" => "0.96"; requires "Test::Vars" => "0"; }; PPIx-EditorTools-0.21/t/0000775000175000017500000000000013220016557014305 5ustar yanickyanickPPIx-EditorTools-0.21/t/00-ppix-editortools.t0000644000175000017500000000620313220016557020233 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Exception; my @classes = ( 'PPIx::EditorTools', 'PPIx::EditorTools::FindUnmatchedBrace', 'PPIx::EditorTools::FindVariableDeclaration', 'PPIx::EditorTools::IntroduceTemporaryVariable', 'PPIx::EditorTools::RenamePackage', 'PPIx::EditorTools::RenamePackageFromPath', 'PPIx::EditorTools::RenameVariable', 'PPIx::EditorTools::FindUnmatchedBrace', 'PPIx::EditorTools::Outline', 'PPIx::EditorTools::Lexer', 'PPIx::EditorTools::ReturnObject', ); my @subs = qw( new code ppi process_doc find_unmatched_brace get_all_variable_declarations element_depth find_token_at_location find_variable_declaration ); plan tests => 14 + @subs + 2 * @classes; foreach my $class (@classes) { require_ok($class); my $test_object = new_ok($class); } use_ok( 'PPIx::EditorTools', @subs ); foreach my $subs (@subs) { can_ok( 'PPIx::EditorTools', $subs ); } #TODO need more pkg tests ####### # Testing PPIx::EditorTools->process_doc() ####### # Check that something died - we do not care why dies_ok { PPIx::EditorTools->process_doc() } 'expecting PPIx::EditorTools->process_doc() to die'; # check code to ppi my @test_files = ( 't/outline/Foo.pm', 't/outline/file1.pl', 't/outline/file2.pl', 't/outline/Mooclass.pm', 't/outline/Moorole.pm', 't/outline/Moofirst.pm', ); my $obj = PPIx::EditorTools->new(); $obj->ppi(undef); $obj->code(undef); foreach my $file (@test_files) { my $code = do { open my $fh, '<', $file or die "Could not open '$file' $!"; local $/ = undef; <$fh>; }; ok( $obj->process_doc( code => $code ), "process_doc(code) from $file" ); } ## check ppi source my %ppi = ( 'attributes' => [ { 'line' => 7, 'name' => 'balance', }, { 'line' => 13, 'name' => 'overdraft', }, { 'line' => 23, 'name' => 'name', }, { 'line' => 25, 'name' => 'account', }, ], 'line' => 3, 'methods' => [ { 'line' => 27, 'name' => '_build_overdraft', }, ], 'modules' => [ { 'line' => 1, 'name' => 'MooseX::Declare', }, ], 'name' => 'Moofirst', 'pragmata' => [ { 'line' => 5, 'name' => 'version', }, ], ); $obj->ppi('PPI::Document'); $obj->code(undef); ok( $obj->process_doc(%ppi), 'process_doc(ppi)' ); ## check neither ppi or code fails $obj->ppi(undef); $obj->code(undef); my %case = ( one => 'ppi', two => 'code', three => 'PPI::Document', ); throws_ok { $obj->process_doc(%case) } '/arguments ppi or code required/', 'arguments ppi or code required'; #TODO add more tests dies_ok { PPIx::EditorTools->find_unmatched_brace() } 'expecting PPIx::EditorTools->find_unmatched_brace() to die'; #TODO add more tests dies_ok { PPIx::EditorTools->get_all_variable_declarations() } 'expecting PPIx::EditorTools->get_all_variable_declarations() to die'; #TODO add more tests dies_ok { PPIx::EditorTools->element_depth() } 'expecting PPIx::EditorTools->element_depth() to die'; #TODO add more tests dies_ok { PPIx::EditorTools->find_token_at_location() } 'expecting PPIx::EditorTools->find_token_at_location() to die'; #dies_ok { PPIx::EditorTools->find_variable_declaration() } 'expecting PPIx::EditorTools->find_variable_declaration() to die'; PPIx-EditorTools-0.21/t/01-findunmatchedbrace.t0000644000175000017500000000213013220016557020510 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } plan tests => 6; use PPIx::EditorTools::FindUnmatchedBrace; my $brace = PPIx::EditorTools::FindUnmatchedBrace->new->find( code => "package TestPackage;\nuse strict;\nuse warnings;\nsub x { 1;\n" ); isa_ok( $brace, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $brace->element, 'PPI::Structure::Block' ); location_is( $brace->element, [ 4, 7, 7 ], 'unclosed sub' ); $brace = PPIx::EditorTools::FindUnmatchedBrace->new->find( code => "package TestPackage;\nfor my \$x (1..2) { 1;\n" ); isa_ok( $brace, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $brace->element, 'PPI::Structure::Block' ); location_is( $brace->element, [ 2, 18, 18 ], 'unclosed for block' ); sub location_is { my ( $element, $location, $desc ) = @_; my $elem_loc = $element->location; $elem_loc = [ @$elem_loc[ 0 .. 2 ] ] if @$elem_loc > 3; is_deeply( $elem_loc, $location, $desc ); } PPIx-EditorTools-0.21/t/00-report-prereqs.t0000644000175000017500000001273113220016557017703 0ustar yanickyanick#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.021 use Test::More tests => 1; use ExtUtils::MakeMaker; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do 't/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; if ( $source && $HAS_CPAN_META ) { if ( my $meta = eval { CPAN::Meta->load_file($source) } ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } } else { $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if $mod eq 'perl'; next if grep { $_ eq $mod } @exclude; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; if ($prefix) { my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( @dep_errors ) { diag join("\n", "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n", "The following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass; # vim: ts=4 sts=4 sw=4 et: PPIx-EditorTools-0.21/t/00-report-prereqs.dd0000644000175000017500000000371713220016557020033 0ustar yanickyanickdo { my $x = { 'configure' => { 'requires' => { 'ExtUtils::MakeMaker' => '0' } }, 'develop' => { 'requires' => { 'Test::More' => '0.96', 'Test::Vars' => '0' } }, 'runtime' => { 'requires' => { 'Carp' => '0', 'Class::XSAccessor' => '1.02', 'File::Basename' => '0', 'File::Spec' => '0', 'PPI' => '1.203', 'PPI::Find' => '0', 'Try::Tiny' => '0', 'base' => '0', 'perl' => '5.008', 'strict' => '0', 'warnings' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'ExtUtils::MakeMaker' => '0', 'File::Spec' => '0', 'File::Temp' => '0', 'IO::Handle' => '0', 'IPC::Open3' => '0', 'Test::Differences' => '0', 'Test::Exception' => '0', 'Test::More' => '0', 'Test::Most' => '0' } } }; $x; }PPIx-EditorTools-0.21/t/08-getallvariabledeclarations.t0000644000175000017500000000204613220016557022266 0ustar yanickyanick#!/usr/bin/perl # Test for RT #63107: Finding declared variables fragile and misses loop variables # Courtesy of Ovid++ use strict; use warnings; use Test::Most 'no_plan'; use PPI; use PPIx::EditorTools; diag "PPI version is $PPI::VERSION"; my $code = <<'END_OF_CODE'; use warnings; foreach my $arg (@ARGV) { print $arg; } END_OF_CODE # Test finding variable declaration when on the variable my $declarations; lives_ok { $declarations = PPIx::EditorTools::get_all_variable_declarations( PPI::Document->new( \$code ) ); } 'We should be able to find variable declarations'; explain $declarations; ok exists $declarations->{lexical}{'$arg'}, '... and we should be able to find loop variables'; $code = <<'END_OF_CODE'; foreach my $arg (@ARGV) { print $arg; } END_OF_CODE lives_ok { $declarations = PPIx::EditorTools::get_all_variable_declarations( PPI::Document->new( \$code ) ); } 'We should be able to find variable declarations'; explain $declarations; ok exists $declarations->{lexical}{'$arg'}, '... and we should be able to find loop variables'; PPIx-EditorTools-0.21/t/10-lexer.t0000644000175000017500000001000413220016557016020 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } my @cases = ( { code => <<'END_CODE', use strict; use warnings; use Abc; my $global = 42; sub qwer { } END_CODE expected => [ [ 'keyword', 1, 1, 3 ], [ 'Whitespace', 1, 4, 1 ], [ 'pragma', 1, 5, 6 ], [ 'Structure', 1, 11, 1 ], [ 'Whitespace', 1, 12, 1 ], [ 'keyword', 1, 13, 3 ], [ 'Whitespace', 1, 16, 1 ], [ 'pragma', 1, 17, 8 ], [ 'Structure', 1, 25, 1 ], [ 'Whitespace', 1, 26, 1 ], [ 'keyword', 2, 1, 3 ], [ 'Whitespace', 2, 4, 1 ], [ 'Word', 2, 5, 3 ], [ 'Structure', 2, 8, 1 ], [ 'Whitespace', 2, 9, 1 ], [ 'Whitespace', 3, 1, 1 ], [ 'keyword', 4, 1, 2 ], [ 'Whitespace', 4, 3, 1 ], [ 'Symbol', 4, 4, 7 ], [ 'Whitespace', 4, 11, 1 ], [ 'Operator', 4, 12, 1 ], [ 'Whitespace', 4, 13, 1 ], [ 'Number', 4, 14, 2 ], [ 'Structure', 4, 16, 1 ], [ 'Whitespace', 4, 17, 1 ], [ 'Whitespace', 5, 1, 1 ], [ 'keyword', 6, 1, 3 ], [ 'Whitespace', 6, 4, 1 ], [ 'Word', 6, 5, 4 ], [ 'Whitespace', 6, 9, 1 ], [ 'Structure', 6, 10, 1 ], [ 'Whitespace', 6, 11, 1 ], [ 'Structure', 7, 1, 1 ], [ 'Whitespace', 7, 2, 1 ], [ 'Whitespace', 8, 1, 1 ], ], }, { code => <<'END_CODE', sub return func method before after around override augment END_CODE expected => [ [ 'keyword', 1, 1, 3 ], [ 'Whitespace', 1, 4, 1 ], [ 'keyword', 1, 5, 6 ], [ 'Whitespace', 1, 11, 1 ], [ 'Word', 1, 12, 4 ], [ 'Whitespace', 1, 16, 1 ], [ 'Word', 1, 17, 6 ], [ 'Whitespace', 1, 23, 1 ], [ 'Word', 1, 24, 6 ], [ 'Whitespace', 1, 30, 1 ], [ 'Word', 1, 31, 5 ], [ 'Whitespace', 1, 36, 1 ], [ 'Word', 1, 37, 6 ], [ 'Whitespace', 1, 43, 1 ], [ 'Word', 1, 44, 8 ], [ 'Whitespace', 1, 52, 1 ], [ 'Word', 1, 53, 7 ], [ 'Whitespace', 1, 60, 1 ], ], }, { code => <<'END_CODE', undef shift defined bless END_CODE expected => [ [ 'core', 1, 1, 5 ], [ 'Whitespace', 1, 6, 1 ], [ 'core', 1, 7, 5 ], [ 'Whitespace', 1, 12, 1 ], [ 'core', 1, 13, 7 ], [ 'Whitespace', 1, 20, 1 ], [ 'core', 1, 21, 5 ], [ 'Whitespace', 1, 26, 1 ], ], }, { code => <<'END_CODE', new END_CODE expected => [ [ 'Word', 1, 1, 3 ], [ 'Whitespace', 1, 4, 1 ], ], }, { code => <<'END_CODE', use no END_CODE expected => [ [ 'keyword', 1, 1, 3 ], [ 'Whitespace', 1, 4, 1 ], [ 'keyword', 1, 5, 2 ], [ 'Whitespace', 1, 7, 1 ], ], }, { code => <<'END_CODE', my local our END_CODE expected => [ [ 'keyword', 1, 1, 2 ], [ 'Whitespace', 1, 3, 1 ], [ 'keyword', 1, 4, 5 ], [ 'Whitespace', 1, 9, 1 ], [ 'keyword', 1, 10, 3 ], [ 'Whitespace', 1, 13, 1 ], ], }, { code => <<'END_CODE', if else elsif unless for foreach while my END_CODE expected => [ [ 'keyword', 1, 1, 2 ], [ 'Whitespace', 1, 3, 1 ], [ 'keyword', 1, 4, 4 ], [ 'Whitespace', 1, 8, 1 ], [ 'keyword', 1, 9, 5 ], [ 'Whitespace', 1, 14, 1 ], [ 'keyword', 1, 15, 6 ], [ 'Whitespace', 1, 21, 1 ], [ 'keyword', 1, 22, 3 ], [ 'Whitespace', 1, 25, 1 ], [ 'keyword', 1, 26, 7 ], [ 'Whitespace', 1, 33, 1 ], [ 'keyword', 1, 34, 5 ], [ 'Whitespace', 1, 39, 1 ], [ 'keyword', 1, 40, 2 ], [ 'Whitespace', 1, 42, 1 ], ], }, { code => <<'END_CODE', package END_CODE expected => [ [ 'keyword', 1, 1, 7 ], [ 'Whitespace', 1, 8, 1 ], ], }, ); plan tests => @cases * 1; use PPIx::EditorTools::Lexer; my @result; foreach my $c (@cases) { @result = (); PPIx::EditorTools::Lexer->new->lexer( code => $c->{code}, highlighter => \&highlighter ); #diag explain @result; is_deeply \@result, $c->{expected} or diag explain @result; } sub highlighter { push @result, [@_]; } PPIx-EditorTools-0.21/t/09-outline.t0000644000175000017500000001367713220016557016413 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; use PPIx::EditorTools::Outline; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } my @cases = ( { file => 't/outline/Foo.pm', expected => [ { 'modules' => [ { name => 'Method::Signatures', line => 3, }, ], 'methods' => [ { name => 'new', line => 5, }, { name => 'hello', line => 8, } ], 'line' => 1, 'name' => 'Foo', } ], }, { file => 't/outline/file1.pl', expected => [ { 'methods' => [ { 'line' => 6, 'name' => 'qwer' } ], 'modules' => [ { 'line' => 2, 'name' => 'Abc' } ], 'name' => 'main', 'pragmata' => [ { 'line' => 1, 'name' => 'strict' }, { 'line' => 1, 'name' => 'warnings' } ] } ], }, { code => <<'END_CODE', use strict; END_CODE expected => [ { 'pragmata' => [ { 'line' => 1, name => 'strict', }, ], 'name' => 'main', }, ], }, { file => 't/outline/file2.pl', expected => [ { 'methods' => [ { 'line' => 14, 'name' => 'abc' }, { 'line' => 19, 'name' => 'def' }, { 'line' => 26, 'name' => 'xyz' } ], 'name' => 'main', 'pragmata' => [ { 'line' => 4, 'name' => 'strict' }, { 'line' => 5, 'name' => 'autodie' }, { 'line' => 6, 'name' => 'warnings' }, { 'line' => 8, 'name' => 'lib' } ] } ] }, ); ############## # Moose outline testing follows ############## push @cases, ( { file => 't/outline/Mooclass.pm', expected => [ { 'modules' => [ { 'name' => 'MooseX::Declare', 'line' => 1, }, ], 'methods' => [ { 'name' => 'pub_sub', 'line' => 14, }, { 'name' => '_pri_sub', 'line' => 18, }, { 'name' => 'mm_before', 'line' => 22, }, { 'name' => 'mm_after', 'line' => 26, }, { 'name' => 'mm_around', 'line' => 30, }, { 'name' => 'mm_override', 'line' => 34, }, { 'name' => 'mm_augment', 'line' => 38, }, ], 'line' => 3, 'name' => 'Mooclass', 'attributes' => [ { 'name' => 'moo_att', 'line' => 5 }, { 'name' => 'label', 'line' => 7 }, { 'name' => 'progress', 'line' => 7 }, { 'name' => 'butWarn', 'line' => 7 }, { 'name' => 'butTime', 'line' => 7 }, { 'name' => 'start_stop', 'line' => 7 }, { 'name' => 'account', 'line' => 10 }, { 'name' => 'non_quoted_attr', 'line' => 12 }, ], } ], }, # can we do the same thing with vanilla Moose class definitions? { file => 't/outline/MooclassVanilla.pm', expected => [ { 'modules' => [ { 'name' => 'Moose', 'line' => 3, }, ], 'methods' => [ { 'name' => 'pub_sub', 'line' => 13, }, { 'name' => '_pri_sub', 'line' => 17, }, { 'name' => 'mm_before', 'line' => 21, }, { 'name' => 'mm_after', 'line' => 25, }, { 'name' => 'mm_around', 'line' => 29, }, { 'name' => 'mm_override', 'line' => 33, }, { 'name' => 'mm_augment', 'line' => 37, }, ], 'line' => 1, 'name' => 'Moose::Declarations::MethodModifiers::Vanilla', 'attributes' => [ { 'name' => 'moo_att', 'line' => 5, }, { 'name' => 'label', 'line' => 7, }, { 'name' => 'progress', 'line' => 7, }, { 'name' => 'butWarn', 'line' => 7, }, { 'name' => 'butTime', 'line' => 7, }, { 'name' => 'start_stop', 'line' => 7, }, { 'name' => 'account', 'line' => 9, }, { 'name' => 'non_quoted_attr', 'line' => 11, }, ], } ], }, { file => 't/outline/Moorole.pm', expected => [ { 'modules' => [ { 'name' => 'MooseX::Declare', 'line' => 1, }, ], 'line' => 3, 'name' => 'Moorole', 'attributes' => [ { 'line' => 7, 'name' => 'balance' }, { 'line' => 13, 'name' => 'overdraft' } ], 'pragmata' => [ { 'line' => 5, 'name' => 'version' } ] } ] }, { file => 't/outline/Moofirst.pm', expected => [ { 'attributes' => [ { 'line' => 7, 'name' => 'balance' }, { 'line' => 13, 'name' => 'overdraft' }, { 'line' => 23, 'name' => 'name' }, { 'line' => 25, 'name' => 'account' } ], 'line' => 3, 'methods' => [ { 'line' => 27, 'name' => '_build_overdraft' } ], 'modules' => [ { 'line' => 1, 'name' => 'MooseX::Declare' } ], 'name' => 'Moofirst', 'pragmata' => [ { 'line' => 5, 'name' => 'version' } ] } ] }, ); ############## # has outline testing #1435 ############## push @cases, ( { file => 't/outline/test_1435.pl', expected => [ { 'attributes' => [ { 'name' => 'first', 'line' => 3, }, { 'name' => 'second', 'line' => 5, }, ], 'modules' => [ { 'line' => 1, 'name' => 'Class::Accessor' } ], 'name' => 'main', } ], }, ); plan tests => @cases * 1; foreach my $c (@cases) { my $code = $c->{code}; if ( $c->{file} ) { open my $fh, '<', $c->{file} or die( "couldn't read file: ", $c->{file}, ": $!" ); local $/ = undef; $code = <$fh>; } my $outline = PPIx::EditorTools::Outline->new->find( code => $code ); #diag explain $outline; is_deeply ( $outline, $c->{expected}, $c->{file} ) or diag explain $outline; } PPIx-EditorTools-0.21/t/02-findvariabledeclaration.t0000644000175000017500000000255413220016557021551 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } plan tests => 6; use PPIx::EditorTools::FindVariableDeclaration; my $code = <<'END_OF_CODE'; package TestPackage; use strict; use warnings; my $x=1; $x++; END_OF_CODE my $declaration; # Test finding variable declaration when on the variable $declaration = PPIx::EditorTools::FindVariableDeclaration->new->find( code => $code, line => 5, column => 2, ); isa_ok( $declaration, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $declaration->element, 'PPI::Statement::Variable' ); location_is( $declaration->element, [ 4, 1, 1 ], 'simple scalar' ); # Test finding variable declaration when on declaration itself $declaration = PPIx::EditorTools::FindVariableDeclaration->new->find( code => $code, line => 4, column => 4, ); isa_ok( $declaration, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $declaration->element, 'PPI::Statement::Variable' ); location_is( $declaration->element, [ 4, 1, 1 ], 'simple scalar' ); # Helper function sub location_is { my ( $element, $location, $desc ) = @_; my $elem_loc = $element->location; $elem_loc = [ @$elem_loc[ 0 .. 2 ] ] if @$elem_loc > 3; is_deeply( $elem_loc, $location, $desc ); } PPIx-EditorTools-0.21/t/rename_variable/0000775000175000017500000000000013220016557017421 5ustar yanickyanickPPIx-EditorTools-0.21/t/rename_variable/1.in0000644000175000017500000000054413220016557020112 0ustar yanickyanickuse MooseX::Declare; class Test { has a_var => ( is => 'rw', isa => 'Str' ); has b_var => ( is => 'rw', isa => 'Str' ); method some_method { my $x_var = 1; print "Do stuff with ${x_var}\n"; $x_var += 1; my %hash; for my $i (1..5) { $hash{$i} = $x_var; } } } PPIx-EditorTools-0.21/t/rename_variable/1.out0000644000175000017500000000054413220016557020313 0ustar yanickyanickuse MooseX::Declare; class Test { has a_var => ( is => 'rw', isa => 'Str' ); has b_var => ( is => 'rw', isa => 'Str' ); method some_method { my $shiny = 1; print "Do stuff with ${shiny}\n"; $shiny += 1; my %hash; for my $i (1..5) { $hash{$i} = $shiny; } } } PPIx-EditorTools-0.21/t/03-introducetemporaryvariable.t0000644000175000017500000000613713220016557022364 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } plan tests => 10; use PPIx::EditorTools::IntroduceTemporaryVariable; my $code = <<'END_CODE'; use strict; use warnings; my $x = ( 1 + 10 / 12 ) * 2; my $y = ( 3 + 10 / 12 ) * 2; END_CODE my $new_code = PPIx::EditorTools::IntroduceTemporaryVariable->new->introduce( code => $code, start_location => [ 2, 19 ], # or just character position end_location => [ 2, 25 ], # or ppi-style location varname => '$foo', ); isa_ok( $new_code, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $new_code->element, 'PPI::Token' ); location_is( $new_code->element, [ 2, 5, 5 ], 'temp var location' ); eq_or_diff( $new_code->code, <<'RESULT', '10 / 12' ); use strict; use warnings; my $foo = 10 / 12; my $x = ( 1 + $foo ) * 2; my $y = ( 3 + $foo ) * 2; RESULT $new_code = PPIx::EditorTools::IntroduceTemporaryVariable->new->introduce( code => $code, start_location => [ 2, 13 ], # or just character position end_location => [ 2, 27 ], # or ppi-style location varname => '$foo', ); eq_or_diff( $new_code->code, <<'RESULT', '( 1 + 10 / 12 )' ); use strict; use warnings; my $foo = ( 1 + 10 / 12 ); my $x = $foo * 2; my $y = ( 3 + 10 / 12 ) * 2; RESULT $code = <<'END_CODE2'; use strict; use warnings; my $x = ( 1 + 10 / 12 ) * 2; my $y = ( 3 + 10 / 12 ) * 2; END_CODE2 $new_code = PPIx::EditorTools::IntroduceTemporaryVariable->new->introduce( code => $code, start_location => [ 2, 9 ], # or just character position end_location => [ 3, 10 ], # or ppi-style location # varname => '$foo', ); eq_or_diff( $new_code->code, <<'RESULT', '( 1 + 10 \n / 12 )' ); use strict; use warnings; my $tmp = ( 1 + 10 / 12 ); my $x = $tmp * 2; my $y = ( 3 + 10 / 12 ) * 2; RESULT my $code3 = <<'END_CODE3'; use strict; use warnings; sub one { my $x = ( 1 + 10 / 12 ) * 2; my $y = ( 3 + 10 / 12 ) * 2; } sub two { my $y = ( 3 + 10 / 12 ) * 2; } END_CODE3 my $new_code3 = PPIx::EditorTools::IntroduceTemporaryVariable->new->introduce( code => $code3, start_location => [ 3, 19 ], # or just character position end_location => [ 3, 25 ], # or ppi-style location varname => '$foo', ); isa_ok( $new_code3, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $new_code3->element, 'PPI::Token' ); location_is( $new_code3->element, [ 3, 5, 5 ], 'temp var location' ); TODO: { local $TODO = 'Bug: RT#60042 - replace does not respect lexical scope'; eq_or_diff( $new_code3->code, <<'RESULT3', 'lexically scoped' ); use strict; use warnings; sub one { my $foo = 10 / 12; my $x = ( 1 + $foo ) * 2; my $y = ( 3 + $foo ) * 2; } sub two { my $y = ( 3 + 10 / 12 ) * 2; } RESULT3 } sub location_is { my ( $element, $location, $desc ) = @_; my $elem_loc = $element->location; $elem_loc = [ @$elem_loc[ 0 .. 2 ] ] if @$elem_loc > 3; is_deeply( $elem_loc, $location, $desc ); } PPIx-EditorTools-0.21/t/00-compile.t0000644000175000017500000000273413220016557016343 0ustar yanickyanickuse 5.006; use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::Test::Compile 2.052 use Test::More; plan tests => 10 + ($ENV{AUTHOR_TESTING} ? 1 : 0); my @module_files = ( 'PPIx/EditorTools.pm', 'PPIx/EditorTools/FindUnmatchedBrace.pm', 'PPIx/EditorTools/FindVariableDeclaration.pm', 'PPIx/EditorTools/IntroduceTemporaryVariable.pm', 'PPIx/EditorTools/Lexer.pm', 'PPIx/EditorTools/Outline.pm', 'PPIx/EditorTools/RenamePackage.pm', 'PPIx/EditorTools/RenamePackageFromPath.pm', 'PPIx/EditorTools/RenameVariable.pm', 'PPIx/EditorTools/ReturnObject.pm' ); # no fake home requested my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib'; use File::Spec; use IPC::Open3; use IO::Handle; open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; my @warnings; for my $lib (@module_files) { # see L my $stderr = IO::Handle->new; my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]"); binmode $stderr, ':crlf' if $^O eq 'MSWin32'; my @_warnings = <$stderr>; waitpid($pid, 0); is($?, 0, "$lib loaded ok"); if (@_warnings) { warn @_warnings; push @warnings, @_warnings; } } is(scalar(@warnings), 0, 'no warnings found') or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; PPIx-EditorTools-0.21/t/100-changes.t0000644000175000017500000000020313220016557016371 0ustar yanickyanickuse Test::More; eval 'use Test::CPAN::Changes'; plan skip_all => 'Test::CPAN::Changes required for this test' if $@; changes_ok(); PPIx-EditorTools-0.21/t/04-renamepackage.t0000644000175000017500000000365113220016557017501 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } plan tests => 5; use PPIx::EditorTools::RenamePackage; my $munged = PPIx::EditorTools::RenamePackage->new->rename( code => "package TestPackage;\nuse strict;\nBEGIN { $^W = 1; }\n1;\n", replacement => 'NewPackage' ); isa_ok( $munged, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $munged->element, 'PPI::Statement::Package' ); eq_or_diff( $munged->code, "package NewPackage;\nuse strict;\nBEGIN { $^W = 1; }\n1;\n", 'simple package' ); eq_or_diff( $munged->ppi->serialize, "package NewPackage;\nuse strict;\nBEGIN { $^W = 1; }\n1;\n", 'simple package' ); my $code = <<'END_CODE'; use MooseX::Declare; class Test { has a_var => ( is => 'rw', isa => 'Str' ); has b_var => ( is => 'rw', isa => 'Str' ); method some_method { my $x_var = 1; print "Do stuff with ${x_var}\n"; $x_var += 1; my %hash; for my $i (1..5) { $hash{$i} = $x_var; } } } END_CODE my $shiny_replacement = <<'SHINY_REPLACEMENT'; use MooseX::Declare; class NewPackage { has a_var => ( is => 'rw', isa => 'Str' ); has b_var => ( is => 'rw', isa => 'Str' ); method some_method { my $x_var = 1; print "Do stuff with ${x_var}\n"; $x_var += 1; my %hash; for my $i (1..5) { $hash{$i} = $x_var; } } } SHINY_REPLACEMENT TODO: { local $TODO = 'RenamePackage does not support MooseX::Declare yet'; # The unimplemented stuff throws warnings local $^W = 0; my $result = eval { my $munged = PPIx::EditorTools::RenamePackage->new->rename( code => $code, replacement => 'NewPackage', ); $munged->code; }; eq_or_diff( $result, $shiny_replacement, 'replace scalar' ); } PPIx-EditorTools-0.21/t/05-renamepackagefrompath.t0000644000175000017500000000421313220016557021236 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } plan tests => 4; use PPIx::EditorTools::RenamePackageFromPath; my $code = "package TestPackage;\nuse strict;\nBEGIN { $^W = 1; }\n1;\n"; sub new_code { return sprintf "package %s;\nuse strict;\nBEGIN { $^W = 1; }\n1;\n", shift; } my $munged = PPIx::EditorTools::RenamePackageFromPath->new->rename( code => $code, filename => './lib/Test/Code/Path.pm', ); eq_or_diff( $munged->code, new_code("Test::Code::Path"), 'simple package' ); eq_or_diff( PPIx::EditorTools::RenamePackageFromPath->new->rename( code => $code, filename => './Test/Code/Path.pm', )->code, new_code("Test::Code::Path"), 'no lib package' ); eq_or_diff( PPIx::EditorTools::RenamePackageFromPath->new->rename( code => $code, filename => 'lib/Test/./Code/Path.pm', )->code, new_code("Test::Code::Path"), 'with /./ part' ); TODO: { local $TODO = 'Does not support /../ path constructs yet'; eq_or_diff( PPIx::EditorTools::RenamePackageFromPath->new->rename( code => $code, filename => 'lib/Test/Ignore/../Code/Path.pm', )->code, new_code("Test::Code::Path"), 'strip .. from package' ); } __END__ my $stuff_replacement = <<'STUFF_REPLACEMENT'; use MooseX::Declare; class Test { has a_var => ( is => 'rw', isa => 'Str' ); has b_var => ( is => 'rw', isa => 'Str' ); method some_method { my $x_var = 1; print "Do stuff with ${x_var}\n"; $x_var += 1; my %stuff; for my $i (1..5) { $stuff{$i} = $x_var; } } } STUFF_REPLACEMENT eq_or_diff( PPIx::EditorTools::RenameVariable->new( code => $code ) ->replace_var( line => 15, column => 13, replacement => 'stuff', ), $stuff_replacement, 'replace hash' ); my $replacer = PPIx::EditorTools::RenameVariable->new( code => $code ); my $doc = $replacer->replace_var( line => 15, column => 13, replacement => 'stuff', ); my $token = $replacer->token; isa_ok( $token, 'PPI::Token::Symbol' ); PPIx-EditorTools-0.21/t/outline/0000775000175000017500000000000013220016557015764 5ustar yanickyanickPPIx-EditorTools-0.21/t/outline/Foo.pm0000644000175000017500000000014413220016557017042 0ustar yanickyanickpackage Foo; use Method::Signatures; method new (%data) { } func hello($name, $daytime) { } 1; PPIx-EditorTools-0.21/t/outline/file2.pl0000644000175000017500000000041013220016557017313 0ustar yanickyanick#!/usr/bin/perl use 5.008; use strict; use autodie; use warnings FATAL => 'all'; use lib ('/opt/perl5/lib'); my $global = 42; print "start"; sub abc { print 1; my $private = 42; sub def { } print 2; } print "ok"; sub xyz { } print "end"; PPIx-EditorTools-0.21/t/outline/Moofirst.pm0000644000175000017500000000071613220016557020126 0ustar yanickyanickuse MooseX::Declare; role Moofirst { requires '_build_overdraft'; use version; our $VERSION = version->new('1.0.1'); has 'balance' => ( isa => 'Num', is => 'rw', default => 0 ); has 'overdraft' => ( isa => 'Bool', is => 'rw', lazy_build => 1, init_arg => undef, ); } class Mooclass { has 'name' => ( isa => 'Str', is => 'rw', ); has qw(account) => ( is => 'rw', ); method _build_overdraft { return; } } PPIx-EditorTools-0.21/t/outline/Moorole.pm0000644000175000017500000000047413220016557017741 0ustar yanickyanickuse MooseX::Declare; role Moorole { requires '_build_overdraft'; use version; our $VERSION = version->new('1.0.1'); has 'balance' => ( isa => 'Num', is => 'rw', default => 0 ); has 'overdraft' => ( isa => 'Bool', is => 'rw', lazy_build => 1, init_arg => undef, ); } PPIx-EditorTools-0.21/t/outline/Mooclass.pm0000644000175000017500000000075313220016557020105 0ustar yanickyanickuse MooseX::Declare; class Mooclass { has 'moo_att' => ( is => 'rw', ); has [qw/ label progress butWarn butTime start_stop /] => ( isa => 'Ref', is => 'rw' ); has qw(account) => ( is => 'rw', ); has non_quoted_attr => ( is=> 'rw' ); method pub_sub { return; } method _pri_sub { return; } before mm_before { return; } after mm_after { return; } around mm_around { return; } override mm_override { return; } augment mm_augment { return; } } PPIx-EditorTools-0.21/t/outline/test_1435.pl0000644000175000017500000000015013220016557017746 0ustar yanickyanickuse Class::Accessor 'antlers'; has first => ( is => 'rw' ); has ;#comment has second => ( is => 'ro' );PPIx-EditorTools-0.21/t/outline/MooclassVanilla.pm0000644000175000017500000000103613220016557021407 0ustar yanickyanickpackage Moose::Declarations::MethodModifiers::Vanilla; use Moose; has 'moo_att' => ( is => 'rw', ); has [qw/ label progress butWarn butTime start_stop /] => ( isa => 'Ref', is => 'rw' ); has qw(account) => ( is => 'rw', ); has non_quoted_attr => ( is => 'rw' ); sub pub_sub { return; } sub _pri_sub { return; } before 'mm_before' => sub { return; }; after 'mm_after' => sub { return; }; around 'mm_around' => sub { return; }; override 'mm_override' => sub { return; }; augment 'mm_augment' => sub { return; }; 1; __END__ PPIx-EditorTools-0.21/t/outline/file1.pl0000644000175000017500000000010413220016557017312 0ustar yanickyanickuse strict; use warnings; use Abc; my $global = 42; sub qwer { } PPIx-EditorTools-0.21/t/07-renamevariable.t0000644000175000017500000001045613220016557017677 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; use File::Temp qw(tempdir); my $tempdir = tempdir( CLEANUP => 1 ); BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } plan tests => 17; use PPIx::EditorTools::RenameVariable; my $code = read_file('t/rename_variable/1.in'); my $shiny_replacement = read_file('t/rename_variable/1.out'); eq_or_diff( eval { PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 8, column => 12, replacement => 'shiny', )->code; } || "", $shiny_replacement, 'replace scalar' ); test_cli($code, "--RenameVariable --line 8 --column 12 --replacement shiny", $shiny_replacement, 'replace scalar on command line'); eq_or_diff( PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 11, column => 9, replacement => 'shiny', )->code, $shiny_replacement, 'replace scalar' ); test_cli($code, "--RenameVariable --line 11 --column 9 --replacement shiny", $shiny_replacement, 'replace scalar on command line'); my $stuff_replacement = <<'STUFF_REPLACEMENT'; use MooseX::Declare; class Test { has a_var => ( is => 'rw', isa => 'Str' ); has b_var => ( is => 'rw', isa => 'Str' ); method some_method { my $x_var = 1; print "Do stuff with ${x_var}\n"; $x_var += 1; my %stuff; for my $i (1..5) { $stuff{$i} = $x_var; } } } STUFF_REPLACEMENT eq_or_diff( PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 15, column => 13, replacement => 'stuff', )->code, $stuff_replacement, 'replace hash' ); test_cli($code, "--RenameVariable --line 15 --column 13 --replacement stuff", $stuff_replacement, 'replace hash on command line'); my $munged = PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 15, column => 13, replacement => 'stuff', ); isa_ok( $munged, 'PPIx::EditorTools::ReturnObject' ); isa_ok( $munged->element, 'PPI::Token::Symbol' ); # tests for camel casing $code = <<'END_CODE'; sub foo { my $x_var = 1; print "Do stuff with ${x_var}\n"; $x_var += 1; my $_someVariable = 2; $_someVariable++; } END_CODE my $xvar_replacement = $code; $xvar_replacement =~ s/x_var/xVar/g; # yes, this is simple eq_or_diff( PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 2, column => 8, to_camel_case => 1, )->code, $xvar_replacement, 'camelCase xVar' ); test_cli($code, "--RenameVariable --line 2 --column 8 --to-camel-case 1", $xvar_replacement, 'camelCase xVar on command line'); $xvar_replacement =~ s/x_?var/XVar/gi; # yes, this is simple eq_or_diff( PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 2, column => 8, to_camel_case => 1, 'ucfirst' => 1, )->code, $xvar_replacement, 'camelCase xVar (ucfirst)' ); my $yvar_replacement = $code; $yvar_replacement =~ s/_someVariable/_some_variable/g; eq_or_diff( PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 7, column => 8, from_camel_case => 1, )->code, $yvar_replacement, 'from camelCase _some_variable' ); $yvar_replacement =~ s/_some_variable/_Some_Variable/g; eq_or_diff( PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => 7, column => 8, from_camel_case => 1, 'ucfirst' => 1 )->code, $yvar_replacement, 'from camelCase _some_variable (ucfirst)' ); # exerimental test code for experimental command line tool sub test_cli { my ($original, $params, $expected, $title) = @_; my $file = "$tempdir/source.pl"; open my $out, '>', $file or die; print $out $original; close $out; my $cmd = "$^X -Ilib script/ppix_editortools --inplace $params $file"; #diag $cmd; is system($cmd), 0, 'system'; open my $in, '<', $file or die; my $result = do {local $/ = undef; <$in>; }; close $in; eq_or_diff($result, $expected, $title); } sub read_file { my $file = shift; open my $fh, '<', $file or die; local $/ = undef; my $code = scalar <$fh>; $code =~ s/\xD//g; # remove carrige return return $code; } PPIx-EditorTools-0.21/t/06-camelcasing.t0000644000175000017500000000437213220016557017167 0ustar yanickyanick#!/usr/bin/perl use strict; BEGIN { $^W = 1; } use Test::More; use Test::Differences; use PPI; BEGIN { if ( $PPI::VERSION =~ /_/ ) { plan skip_all => "Need released version of PPI. You have $PPI::VERSION"; exit 0; } } use PPIx::EditorTools::RenameVariable; my @to_camel_tests = ( # test expected ucfirst [qw(abc abc 0)], [qw(abc Abc 1)], [qw(Abc Abc 0)], [qw(Abc Abc 1)], [qw(abc_def abcDef 0)], [qw(abc_def AbcDef 1)], [qw(a_b_c_D_E aBCDE 0)], [qw(a_b_c_D_E ABCDE 1)], [qw(A_b_c_D_E ABCDE 1)], [qw(A_b_c_D_E ABCDE 0)], [qw(_this_is_a_var _thisIsAVar 0)], [qw(_this_is_a_var _ThisIsAVar 1)], ); my @from_camel_tests = ( # test expected ucfirst [qw(abc abc 0)], [qw(abc Abc 1)], [qw(Abc abc 0)], [qw(Abc Abc 1)], [qw(abcDef abc_def 0)], [qw(abcDef Abc_Def 1)], [qw(AbcDef abc_def 0)], [qw(AbcDef Abc_Def 1)], [qw(aBCDE a_b_c_d_e 0)], [qw(aBCDE A_B_C_D_E 1)], [qw(ABCDE a_b_c_d_e 0)], [qw(ABCDE A_B_C_D_E 1)], [qw(_abc _abc 0)], [qw(_abc _Abc 1)], [qw(_thisIsAVar _this_is_a_var 0)], [qw(_thisIsAVar _This_Is_A_Var 1)], [qw(_ThisIsAVar _this_is_a_var 0)], [qw(_ThisIsAVar _This_Is_A_Var 1)], ); plan tests => @to_camel_tests * 3 + @from_camel_tests * 3; foreach my $test (@to_camel_tests) { my ( $src, $exp, $ucfirst ) = @$test; is( PPIx::EditorTools::RenameVariable::_to_camel_case( $src, $ucfirst ), $exp, "to-camel-case '$src' with ucfirst=$ucfirst" ); $_ = '$' . $_ for ( $src, $exp ); is( PPIx::EditorTools::RenameVariable::_to_camel_case( $src, $ucfirst ), $exp, "to-camel-case '$src' with ucfirst=$ucfirst" ); s/^\$/\$#/ for ( $src, $exp ); is( PPIx::EditorTools::RenameVariable::_to_camel_case( $src, $ucfirst ), $exp, "to-camel-case '$src' with ucfirst=$ucfirst" ); } foreach my $test (@from_camel_tests) { my ( $src, $exp, $ucfirst ) = @$test; is( PPIx::EditorTools::RenameVariable::_from_camel_case( $src, $ucfirst ), $exp, "from-camel-case '$src' with ucfirst=$ucfirst" ); $_ = '$' . $_ for ( $src, $exp ); is( PPIx::EditorTools::RenameVariable::_from_camel_case( $src, $ucfirst ), $exp, "from-camel-case '$src' with ucfirst=$ucfirst" ); s/^\$/\$#/ for ( $src, $exp ); is( PPIx::EditorTools::RenameVariable::_from_camel_case( $src, $ucfirst ), $exp, "from-camel-case '$src' with ucfirst=$ucfirst" ); } PPIx-EditorTools-0.21/script/0000775000175000017500000000000013220016557015346 5ustar yanickyanickPPIx-EditorTools-0.21/script/ppix_editortools0000644000175000017500000000267413220016557020707 0ustar yanickyanick#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw(GetOptions); use Pod::Usage qw(pod2usage); # This is a command line script to use the capabilities of this package # with a temporary API and a temporary name! pod2usage() if not @ARGV; my %opt; GetOptions(\%opt, 'inplace', 'RenameVariable', 'line=i', 'column=i', 'replacement=s', 'to-camel-case=s', 'help', ) or pod2usage(); pod2usage() if $opt{help}; if ($opt{RenameVariable}) { require PPIx::EditorTools::RenameVariable; my $file = shift @ARGV; my $code = read_file($file); my %param; if (exists $opt{replacement}) { $param{replacement} = $opt{replacement}; } elsif (exists $opt{'to-camel-case'}) { $param{'to_camel_case'} = $opt{'to-camel-case'}; } else { die 'Need eiher replacement or to-camel-case'; } my $result = PPIx::EditorTools::RenameVariable->new->rename( code => $code, line => $opt{line}, column => $opt{column}, %param, )->code; ; write_file($file, $result); } else { pod2usage(); } exit; sub read_file { my ($file) = @_; open my $in, '<', $file or die "Could not open file '$file' for reading: $!"; local $/ = undef; return <$in>; } sub write_file { my ($file, $data) = @_; open my $out, '>', $file or die; print $out $data; } =head1 NAME ppix_editortools - command line interface for the PPIx::EditorTools =head1 SYNOPSIS --RenameVariable --line 8 column 12 --replacement NEW_NAME --inplace =cut PPIx-EditorTools-0.21/doap.xml0000644000175000017500000001613213220016557015510 0ustar yanickyanick PPIx-EditorTools Utility methods and base class for manipulating Perl via PPI Ahmad M. Zawawi Gabor Szabo Yanick Champoux Adam Kennedy Florian Schlichting Kent Fredric Kevin Dawson Ryan Niebur Sebastian Willing 0.04 2009 0.05 2009 0.06 2009 0.07 2009 0.08 2009 0.09 2009 0.10 2010 0.11 2010 0.12 2011 0.13 2011 0.14 2011 0.15 2011 0.15_02 2012 0.15_03 2012 0.15_04 2012 0.16 2012 0.17 2012 0.18 2012 0.19 2014 0.20 2017-10-22 Perl PPIx-EditorTools-0.21/README0000644000175000017500000000111113220016557014712 0ustar yanickyanickNAME PPIx::EditorTools - Utility methods and base class for manipulating Perl via PPI SYNOPSIS See PPIx::EditorTools::* DESCRIPTION Base class and utility methods for manipulating Perl via PPI. Pulled out from the "Padre::Task::PPI" code. METHODS new() Constructor. Generally shouldn't be called with any arguments. AUTHORS Gabor Szabo CONTRIBUTORS ADAMK AZAWAWI BOWTIE buff3r MGRIMES PATRICKAS SMUELLER SEE ALSO "PPIx::EditorTools::*", Padre, App::EditorTools, Padre, and PPI.