File Coverage

blib/lib/PPIx/Shorthand.pm
Criterion Covered Total %
statement 66 66 100.0
branch 14 14 100.0
condition n/a
subroutine 14 14 100.0
pod 5 5 100.0
total 99 99 100.0


line stmt bran cond sub pod time code
1             package PPIx::Shorthand;
2              
3 6     6   183173 use utf8;
  6         14  
  6         45  
4 6     6   282 use 5.008001;
  6         26  
  6         262  
5              
6 6     6   40 use strict;
  6         16  
  6         281  
7 6     6   85 use warnings;
  6         11  
  6         190  
8              
9 6     6   50 use Readonly;
  6         12  
  6         472  
10 6     6   64 use Carp;
  6         29  
  6         595  
11              
12 6     6   44 use version; our $VERSION = qv('v1.2.0');
  6         11  
  6         107  
13              
14 6     6   645 use Exporter qw< import >;
  6         23  
  6         12115  
15              
16             our @EXPORT_OK =
17             qw<
18             get_ppi_class
19             >;
20             our %EXPORT_TAGS = (
21             all => [@EXPORT_OK],
22             );
23              
24              
25             Readonly my $EMPTY_STRING => q<>;
26              
27             Readonly my @PPI_TOKEN_CLASSES => qw<
28             PPI::Element
29             PPI::Node
30             PPI::Document
31             PPI::Document::Fragment
32             PPI::Statement
33             PPI::Statement::Package
34             PPI::Statement::Include
35             PPI::Statement::Sub
36             PPI::Statement::Scheduled
37             PPI::Statement::Compound
38             PPI::Statement::Break
39             PPI::Statement::Given
40             PPI::Statement::When
41             PPI::Statement::Data
42             PPI::Statement::End
43             PPI::Statement::Expression
44             PPI::Statement::Variable
45             PPI::Statement::Null
46             PPI::Statement::UnmatchedBrace
47             PPI::Statement::Unknown
48             PPI::Structure
49             PPI::Structure::Block
50             PPI::Structure::Subscript
51             PPI::Structure::Constructor
52             PPI::Structure::Condition
53             PPI::Structure::List
54             PPI::Structure::For
55             PPI::Structure::Given
56             PPI::Structure::When
57             PPI::Structure::Unknown
58             PPI::Token
59             PPI::Token::Whitespace
60             PPI::Token::Comment
61             PPI::Token::Pod
62             PPI::Token::Number
63             PPI::Token::Number::Binary
64             PPI::Token::Number::Octal
65             PPI::Token::Number::Hex
66             PPI::Token::Number::Float
67             PPI::Token::Number::Exp
68             PPI::Token::Number::Version
69             PPI::Token::Word
70             PPI::Token::DashedWord
71             PPI::Token::Symbol
72             PPI::Token::Magic
73             PPI::Token::ArrayIndex
74             PPI::Token::Operator
75             PPI::Token::Quote
76             PPI::Token::Quote::Single
77             PPI::Token::Quote::Double
78             PPI::Token::Quote::Literal
79             PPI::Token::Quote::Interpolate
80             PPI::Token::QuoteLike
81             PPI::Token::QuoteLike::Backtick
82             PPI::Token::QuoteLike::Command
83             PPI::Token::QuoteLike::Regexp
84             PPI::Token::QuoteLike::Words
85             PPI::Token::QuoteLike::Readline
86             PPI::Token::Regexp
87             PPI::Token::Regexp::Match
88             PPI::Token::Regexp::Substitute
89             PPI::Token::Regexp::Transliterate
90             PPI::Token::HereDoc
91             PPI::Token::Cast
92             PPI::Token::Structure
93             PPI::Token::Label
94             PPI::Token::Separator
95             PPI::Token::Data
96             PPI::Token::End
97             PPI::Token::Prototype
98             PPI::Token::Attribute
99             PPI::Token::Unknown
100             >;
101              
102             Readonly my %PPI_TOKEN_CLASSES => map { $_ => 1 } @PPI_TOKEN_CLASSES;
103              
104             Readonly my $PPI_PREFIX_LENGTH => length 'PPI::';
105              
106             Readonly my @NON_UNIQUE_BASENAME_CLASSES => qw<
107             Data
108             End
109             Given
110             Regexp
111             Structure
112             Unknown
113             When
114             >;
115              
116             Readonly my $GLOBAL_INSTANCE => PPIx::Shorthand->new();
117              
118              
119             sub get_ppi_class {
120 2876     2876 1 1705227 my ($name) = @_;
121              
122 2876         8551 return $GLOBAL_INSTANCE->get_class($name);
123             } # end get_ppi_class()
124              
125              
126             sub new {
127 8     8 1 798 my ($class) = @_;
128              
129 8         33 my $self = bless {}, $class;
130              
131 8         42 foreach my $ppi_class (@PPI_TOKEN_CLASSES) {
132 576         3876 $self->{lc $ppi_class} = $ppi_class;
133 576         5419 $self->_add_plural($ppi_class, $ppi_class);
134              
135 576         1434 my $no_prefix = lc substr $ppi_class, $PPI_PREFIX_LENGTH;
136 576         4124 $self->{$no_prefix} = $ppi_class;
137 576         1092 $self->_add_plural($no_prefix, $ppi_class);
138              
139 576         1942 my @components = split m/::/xms, $no_prefix;
140 576         1012 foreach my $separator ( qw< _ - . : >, $EMPTY_STRING ) {
141 2880         6719 my $shorthand = join $separator, @components;
142 2880         14455 $self->{$shorthand} = $ppi_class;
143 2880         13545 $self->_add_plural($shorthand, $ppi_class);
144             } # end foreach
145              
146 576         1342 $self->{ $components[-1] } = $ppi_class;
147 576         1204 $self->_add_plural($components[-1], $ppi_class);
148             } # end foreach
149              
150 8         58 foreach my $basename_class (@NON_UNIQUE_BASENAME_CLASSES) {
151 56         864 my $fullname = "PPI::Token::$basename_class";
152              
153 56         320 $self->{ lc $basename_class } = $fullname;
154 56         104 $self->_add_plural($basename_class, $fullname);
155             } # end foreach
156              
157 8         319 return $self;
158             } # end new()
159              
160             sub _add_plural {
161 4664     4664   7277 my ($self, $basename_class, $ppi_class) = @_;
162 4664         27166 my $plural = lc $basename_class;
163              
164 4664 100       12790 return if $plural =~ m/ \b word \z /xms; # What a wonderous exception.
165              
166 4616         22282 $plural =~ s< ( [^sy] ) \z ><${1}s>xms;
167 4616         8158 $plural =~ s< y \z >xms;
168              
169 4616         18800 $self->{$plural} = $ppi_class;
170              
171 4616         13877 return;
172             }
173              
174              
175             sub get_class {
176 2883     2883 1 19399 my ($self, $name) = @_;
177              
178 2883 100       16200 croak 'Must specify name.' if not $name;
179              
180 2879         20323 return $self->{ lc $name };
181             } # end get_class()
182              
183              
184             sub add_class_translation {
185 7     7 1 4014 my ($self, $name, $ppi_class) = @_;
186              
187 7 100       50 croak 'Must specify name.' if not $name;
188 5 100       36 croak 'Must specify PPI class.' if not $ppi_class;
189 3 100       22 croak qq<"$ppi_class" is not a known subclass of PPI::Element.>
190             if not $PPI_TOKEN_CLASSES{$ppi_class};
191              
192              
193 2         27 $self->{lc $name} = $ppi_class;
194              
195 2         6 return;
196             } # end add_class_translation()
197              
198              
199             sub remove_class_translation {
200 5     5 1 2076 my ($self, $name) = @_;
201              
202 5 100       37 croak 'Must specify name.' if not $name;
203 3 100       24 croak qq<"$name" is not a known translation.>
204             if not delete $self->{lc $name};
205              
206 2         5 return;
207             } # end remove_class_translation()
208              
209              
210             1;
211              
212             __END__