File Coverage

blib/lib/String/InterpolatedVariables.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod 1 1 100.0
total 20 20 100.0


line stmt bran cond sub pod time code
1             package String::InterpolatedVariables;
2              
3 2     2   25096 use strict;
  2         3  
  2         68  
4 2     2   11 use warnings;
  2         2  
  2         71  
5              
6 2     2   1378 use Readonly;
  2         7290  
  2         503  
7              
8              
9             =head1 NAME
10              
11             String::InterpolatedVariables - Extract variable names from interpolated strings.
12              
13              
14             =head1 VERSION
15              
16             Version 1.1.0
17              
18             =cut
19              
20             our $VERSION = '1.1.0';
21              
22              
23             =head1 SYNOPSIS
24              
25             use String::InterpolatedVariables;
26              
27             my $variables = String::InterpolatedVariables::extract(
28             'A $test->{string} from a PPI::Token::Quote::Double $object.'
29             );
30              
31             # $variables now contains:
32             # [
33             # '$test->{string}',
34             # '$object',
35             # ]
36              
37              
38             =head1 DESCRIPTION
39              
40             String::InterpolatedVariables offers a way to extract the name of the variables
41             that are present in interpolated strings.
42              
43             This is particularly useful if you are using L<PPI> to parse Perl documents,
44             and you want to know what variables would be interpolated inside the
45             L<PPI::Token::Quote::Double> and L<PPI::Token::Quote::Interpolate> objects you
46             find there. A practical example of this use can be found in
47             L<Perl::Critic::Policy::ValuesAndExpressions::PreventSQLInjection>.
48              
49             =cut
50              
51             Readonly::Scalar my $VARIABLES_REGEX => qr/
52             # Ignore escaped sigils, since those wouldn't get interpreted as variables to interpolate.
53             (?<!\\)
54             # Allow literal, non-escapy backslashes.
55             (?:\\\\)*
56             (
57             # The variable needs to start with a sigil.
58             [\$\@]
59             # Account for the dereferencing, such as "$$" or "@$".
60             \$?
61             # Variable name.
62             (?:
63             # Note: include '::' to support package variables here.
64             \{(?:\w+|::)\} # Explicit {variable} name.
65             |
66             (?:\w|::)+ # Variable name.
67             )
68             # Catch nested data structures.
69             (?:
70             # Allow for a dereferencing ->.
71             (?:->)?
72             # Can be followed by either a hash or an array.
73             (?:
74             \{(?:\w+|'[^']+'|"[^"]+")\} # Hash element.
75             |
76             \[['"]?\d+['"]?\] # Array element.
77             )
78             )*
79             )
80             /x;
81              
82              
83             =head1 FUNCTIONS
84              
85             =head2 extract()
86              
87             Extract variables from interpolated strings.
88              
89             my $variables = String::InterpolatedVariables::extract(
90             'A $test->{string} from a PPI::Token::Quote::Double $object.'
91             );
92              
93             # $variables now contains:
94             # [
95             # '$test->{string}',
96             # '$object',
97             # ]
98              
99             Note that you need to pass the text of the string, even if the string itself is
100             destined to be interpolated. In other words, passing C<"Test $test"> would not
101             find any variables, as C<$test> would get interpolated by Perl before the
102             string is passed to the C<extract()> function. This function is thus more
103             useful if you are using using a tool such as L<PPI> to read Perl code, since
104             PPI will give you access to the text of the string itself for strings that
105             would otherwise be interpolated during execution.
106              
107             =cut
108              
109             sub extract
110             {
111 9     9 1 3184 my ( $string ) = @_;
112              
113 9         11 my $variables = [];
114 9         102 while ( my ( $variable ) = $string =~ $VARIABLES_REGEX )
115             {
116 11         16 push( @$variables, $variable );
117 11         147 $string =~ s/\Q$variable\E//g;
118             }
119              
120 9         15 return $variables;
121             }
122              
123              
124             =head1 BUGS
125              
126             Please report any bugs or feature requests through the web interface at
127             L<https://github.com/guillaumeaubert/String-InterpolatedVariables/issues>.
128             I will be notified, and then you'll automatically be notified of progress on
129             your bug as I make changes.
130              
131              
132             =head1 SUPPORT
133              
134             You can find documentation for this module with the perldoc command.
135              
136             perldoc String::InterpolatedVariables
137              
138              
139             You can also look for information at:
140              
141             =over 4
142              
143             =item * GitHub (report bugs there)
144              
145             L<https://github.com/guillaumeaubert/String-InterpolatedVariables/issues>
146              
147             =item * AnnoCPAN: Annotated CPAN documentation
148              
149             L<http://annocpan.org/dist/String-InterpolatedVariables>
150              
151             =item * CPAN Ratings
152              
153             L<http://cpanratings.perl.org/d/String-InterpolatedVariables>
154              
155             =item * MetaCPAN
156              
157             L<https://metacpan.org/release/String-InterpolatedVariables>
158              
159             =back
160              
161              
162             =head1 AUTHOR
163              
164             L<Guillaume Aubert|https://metacpan.org/author/AUBERTG>,
165             C<< <aubertg at cpan.org> >>.
166              
167              
168             =head1 COPYRIGHT & LICENSE
169              
170             Copyright 2014-2017 Guillaume Aubert.
171              
172             This code is free software; you can redistribute it and/or modify it under the
173             same terms as Perl 5 itself.
174              
175             This program is distributed in the hope that it will be useful, but WITHOUT ANY
176             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
177             PARTICULAR PURPOSE. See the LICENSE file for more details.
178              
179             =cut
180              
181             1;