File Coverage

blib/lib/Locale/TextDomain/OO/Extract/Perl.pm
Criterion Covered Total %
statement 138 151 91.3
branch 43 56 76.7
condition 5 8 62.5
subroutine 18 18 100.0
pod 4 4 100.0
total 208 237 87.7


line stmt bran cond sub pod time code
1             package Locale::TextDomain::OO::Extract::Perl; ## no critic (TidyCode)
2            
3 3     3   154706 use strict;
  3         25  
  3         83  
4 3     3   14 use warnings;
  3         4  
  3         94  
5 3     3   15 use Carp qw(confess);
  3         7  
  3         139  
6 3     3   630 use Moo;
  3         15432  
  3         20  
7 3     3   2904 use MooX::Types::MooseLike::Base qw(ArrayRef Str);
  3         9161  
  3         186  
8 3     3   644 use namespace::autoclean;
  3         20362  
  3         16  
9            
10             our $VERSION = '2.011';
11            
12             extends qw(
13             Locale::TextDomain::OO::Extract::Base::RegexBasedExtractor
14             );
15             with qw(
16             Locale::TextDomain::OO::Extract::Role::File
17             );
18            
19             has filter => (
20             is => 'rw',
21             isa => ArrayRef[Str],
22             lazy => 1,
23             default => sub {[ 'all' ]},
24             );
25            
26             sub _filtered_start_rule {
27 14     14   28 my $self = shift;
28            
29 14         24 my %filter_of = map { $_ => 1 } @{ $self->filter };
  35         227  
  14         221  
30             my $list_if = sub {
31 224     224   412 my ( $key, @list ) = @_;
32             my $condition
33             = $filter_of{all} && ! $filter_of{"!$key"}
34 224   100     711 || $filter_of{$key};
35 224 100       569 return $condition ? @list : ();
36 14         75 };
37 14         48 my $with_bracket = join "\n| ", (
38             $list_if->('Gettext', 'N? __ n? p? x?'),
39             $list_if->('Gettext::DomainAndCategory', 'N? __ d? c? n? p? x?'),
40             $list_if->('Gettext::Loc', 'N? loc_ n? p? x?'),
41             $list_if->('Gettext::Loc::DomainAndCategory', 'N? loc_ d? c? n? p? x?'),
42             $list_if->('BabelFish::Loc', 'N? loc_b p?'),
43             $list_if->('BabelFish::Loc::DomainAndCategory', 'N? loc_b d? c? p?'),
44             $list_if->('Maketext::Loc', 'N? loc (?: _mp? )?'),
45             $list_if->('Maketext::Localise', 'N? localise (?: _mp? )?'),
46             $list_if->('Maketext::Localize', 'N? localize (?: _mp? )?'),
47             $list_if->('Maketext', 'N? maketext (?: _p )?'),
48             $list_if->('Gettext::DomainAndCategory', '__begin_ d? c?'),
49             $list_if->('Gettext::Loc::DomainAndCategory', 'loc_begin_ d? c?'),
50             $list_if->('BabelFish::Loc::DomainAndCategory', 'loc_begin_b d? c?'),
51             );
52 14   50     41 $with_bracket ||= '(?!)';
53 14         33 my $without = join q{}, map { "\n| $_" } (
  21         71  
54             $list_if->('Gettext::DomainAndCategory', '__end_ d? c?'),
55             $list_if->('Gettext::Loc::DomainAndCategory', 'loc_end_ d? c?'),
56             $list_if->('BabelFish::Loc::DomainAndCategory', 'loc_end_b d? c?'),
57             );
58            
59 14         486 return qr{
60             \b
61             (?:
62             (?: $with_bracket ) \s* [(]
63             $without
64             )
65             }xms;
66             }
67            
68             my $category_rule
69             = my $context_rule
70             = my $domain_rule
71             = my $domain_or_category_rule
72             = my $plural_rule
73             = my $singular_rule
74             = my $text_rule
75             = [
76             [
77             # 'text with 0 .. n escaped chars'
78             qr{
79             \s* ( ['] )
80             (
81             [^\\']* # normal text
82             (?: \\ . [^\\']* )* # maybe followed by escaped char and normal text
83             )
84             [']
85             }xms,
86             ],
87             'or',
88             [
89             # "text with 0 .. n escaped chars"
90             qr{
91             \s* ( ["] )
92             (
93             [^\\"]* # normal text
94             (?: \\ . [^\\"]* )* # maybe followed by escaped char and normal text
95             )
96             ["]
97             }xms,
98             ],
99             'or',
100             [
101             # q{text with 0 .. n {placeholders} and/or 0 .. n escaped chars}
102             ## no critic (EscapedMetacharacters)
103             qr{
104             \s* ( qq? \{ ) # q curly bracket quoted
105             (
106             (?:
107             [^\{\}\\] # normal text
108             | \\ . # escaped char
109             | \{ (?-1) \} # any pairs of curly brackets with the same stuff inside
110             )*
111             )
112             \} # end of quote
113             }xms,
114             ## use critic (EscapedMetacharacters)
115             ],
116             ];
117             my $comma_rule = qr{ \s* [,] }xms;
118             my $count_rule = qr{ \s* ( [^,)]+ ) }xms;
119             my $close_rule = qr{ \s* [,]? \s* ( [^)]* ) [)] }xms;
120            
121             my $rules = [
122             # loc_, __
123             [
124             'begin',
125             qr{ \b N? (?: loc_ | __ ) ( x? ) \s* [(] }xms,
126             'and',
127             $text_rule,
128             'and',
129             $close_rule,
130             'end',
131             ],
132             'or',
133             [
134             'begin',
135             qr{ \b N? (?: loc_ | __ ) ( n x? ) \s* [(] }xms,
136             'and',
137             $singular_rule,
138             'and',
139             $comma_rule,
140             'and',
141             $plural_rule,
142             'and',
143             $comma_rule,
144             'and',
145             $count_rule,
146             'and',
147             $close_rule,
148             'end',
149             ],
150             'or',
151             [
152             'begin',
153             qr{ \b N? (?: loc_ | __ ) ( p x? ) \s* [(] }xms,
154             'and',
155             $context_rule,
156             'and',
157             $comma_rule,
158             'and',
159             $text_rule,
160             'and',
161             $close_rule,
162             'end',
163             ],
164             'or',
165             [
166             'begin',
167             qr{ \b N? (?: loc_ | __ ) ( np x? ) \s* [(] }xms,
168             'and',
169             $context_rule,
170             'and',
171             $comma_rule,
172             'and',
173             $singular_rule,
174             'and',
175             $comma_rule,
176             'and',
177             $plural_rule,
178             'and',
179             $comma_rule,
180             'and',
181             $count_rule,
182             'and',
183             $close_rule,
184             'end',
185             ],
186            
187             # loc_d, __d
188             'or',
189             [
190             'begin',
191             qr{ \b N? (?: loc_ | __ ) ( d x? ) \s* [(] }xms,
192             'and',
193             $domain_rule,
194             'and',
195             $comma_rule,
196             'and',
197             $text_rule,
198             'and',
199             $close_rule,
200             'end',
201             ],
202             'or',
203             [
204             'begin',
205             qr{ \b N? (?: loc_ | __ ) ( dn x? ) \s* [(] }xms,
206             'and',
207             $domain_rule,
208             'and',
209             $comma_rule,
210             'and',
211             $singular_rule,
212             'and',
213             $comma_rule,
214             'and',
215             $plural_rule,
216             'and',
217             $comma_rule,
218             'and',
219             $count_rule,
220             'and',
221             $close_rule,
222             'end',
223             ],
224             'or',
225             [
226             'begin',
227             qr{ \b N? (?: loc_ | __ ) ( dp x? ) \s* [(] }xms,
228             'and',
229             $domain_rule,
230             'and',
231             $comma_rule,
232             'and',
233             $context_rule,
234             'and',
235             $comma_rule,
236             'and',
237             $text_rule,
238             'and',
239             $close_rule,
240             'end',
241             ],
242             'or',
243             [
244             'begin',
245             qr{ \b N? (?: loc_ | __ ) ( dnp x? ) \s* [(] }xms,
246             'and',
247             $domain_rule,
248             'and',
249             $comma_rule,
250             'and',
251             $context_rule,
252             'and',
253             $comma_rule,
254             'and',
255             $singular_rule,
256             'and',
257             $comma_rule,
258             'and',
259             $plural_rule,
260             'and',
261             $comma_rule,
262             'and',
263             $count_rule,
264             'and',
265             $close_rule,
266             'end',
267             ],
268            
269             # loc_c, __c
270             'or',
271             [
272             'begin',
273             qr{ \b N? (?: loc_ | __ ) ( c x? ) \s* [(] }xms,
274             'and',
275             $text_rule,
276             'and',
277             $comma_rule,
278             'and',
279             $category_rule,
280             'and',
281             $close_rule,
282             'end',
283             ],
284             'or',
285             [
286             'begin',
287             qr{ \b N? (?: loc_ | __ ) ( cn x? ) \s* [(] }xms,
288             'and',
289             $singular_rule,
290             'and',
291             $comma_rule,
292             'and',
293             $plural_rule,
294             'and',
295             $comma_rule,
296             'and',
297             $count_rule,
298             'and',
299             $comma_rule,
300             'and',
301             $category_rule,
302             'and',
303             $close_rule,
304             'end',
305             ],
306             'or',
307             [
308             'begin',
309             qr{ \b N? (?: loc_ | __ ) ( cp x? ) \s* [(] }xms,
310             'and',
311             $context_rule,
312             'and',
313             $comma_rule,
314             'and',
315             $text_rule,
316             'and',
317             $comma_rule,
318             'and',
319             $category_rule,
320             'and',
321             $close_rule,
322             'end',
323             ],
324             'or',
325             [
326             'begin',
327             qr{ \b N? (?: loc_ | __ ) ( cnp x? ) \s* [(] }xms,
328             'and',
329             $context_rule,
330             'and',
331             $comma_rule,
332             'and',
333             $singular_rule,
334             'and',
335             $comma_rule,
336             'and',
337             $plural_rule,
338             'and',
339             $comma_rule,
340             'and',
341             $count_rule,
342             'and',
343             $comma_rule,
344             'and',
345             $category_rule,
346             'and',
347             $close_rule,
348             'end',
349             ],
350            
351             # loc_dc, __dc
352             'or',
353             [
354             'begin',
355             qr{ \b N? (?: loc_ | __ ) ( dc x? ) \s* [(] }xms,
356             'and',
357             $domain_rule,
358             'and',
359             $comma_rule,
360             'and',
361             $text_rule,
362             'and',
363             $comma_rule,
364             'and',
365             $category_rule,
366             'and',
367             $close_rule,
368             'end',
369             ],
370             'or',
371             [
372             'begin',
373             qr{ \b N? (?: loc_ | __ ) ( dcn x? ) \s* [(] }xms,
374             'and',
375             $domain_rule,
376             'and',
377             $comma_rule,
378             'and',
379             $singular_rule,
380             'and',
381             $comma_rule,
382             'and',
383             $plural_rule,
384             'and',
385             $comma_rule,
386             'and',
387             $count_rule,
388             'and',
389             $comma_rule,
390             'and',
391             $category_rule,
392             'and',
393             $close_rule,
394             'end',
395             ],
396             'or',
397             [
398             'begin',
399             qr{ \b N? (?: loc_ | __ ) ( dcp x? ) \s* [(] }xms,
400             'and',
401             $domain_rule,
402             'and',
403             $comma_rule,
404             'and',
405             $context_rule,
406             'and',
407             $comma_rule,
408             'and',
409             $text_rule,
410             'and',
411             $comma_rule,
412             'and',
413             $category_rule,
414             'and',
415             $close_rule,
416             'end',
417             ],
418             'or',
419             [
420             'begin',
421             qr{ \b N? (?: loc_ | __ ) ( dcnp x? ) \s* [(] }xms,
422             'and',
423             $domain_rule,
424             'and',
425             $comma_rule,
426             'and',
427             $context_rule,
428             'and',
429             $comma_rule,
430             'and',
431             $singular_rule,
432             'and',
433             $comma_rule,
434             'and',
435             $plural_rule,
436             'and',
437             $comma_rule,
438             'and',
439             $count_rule,
440             'and',
441             $comma_rule,
442             'and',
443             $category_rule,
444             'and',
445             $close_rule,
446             'end',
447             ],
448            
449             # loc_b... (BabelFish)
450             'or',
451             [
452             'begin',
453             qr{ \b N? loc_b () \s* [(] }xms,
454             'and',
455             $text_rule,
456             'and',
457             $close_rule,
458             'end',
459             ],
460             'or',
461             [
462             'begin',
463             qr{ \b N? loc_b ( p ) \s* [(] }xms,
464             'and',
465             $context_rule,
466             'and',
467             $comma_rule,
468             'and',
469             $text_rule,
470             'and',
471             $close_rule,
472             'end',
473             ],
474             'or',
475             [
476             'begin',
477             qr{ \b N? loc_b ( d ) \s* [(] }xms,
478             'and',
479             $domain_rule,
480             'and',
481             $comma_rule,
482             'and',
483             $text_rule,
484             'and',
485             $close_rule,
486             'end',
487             ],
488             'or',
489             [
490             'begin',
491             qr{ \b N? loc_b ( dp ) \s* [(] }xms,
492             'and',
493             $domain_rule,
494             'and',
495             $comma_rule,
496             'and',
497             $context_rule,
498             'and',
499             $comma_rule,
500             'and',
501             $text_rule,
502             'and',
503             $close_rule,
504             'end',
505             ],
506             'or',
507             [
508             'begin',
509             qr{ \b N? loc_b ( c ) \s* [(] }xms,
510             'and',
511             $text_rule,
512             'and',
513             $comma_rule,
514             'and',
515             $category_rule,
516             'and',
517             $close_rule,
518             'end',
519             ],
520             'or',
521             [
522             'begin',
523             qr{ \b N? loc_b ( cp ) \s* [(] }xms,
524             'and',
525             $context_rule,
526             'and',
527             $comma_rule,
528             'and',
529             $text_rule,
530             'and',
531             $comma_rule,
532             'and',
533             $category_rule,
534             'and',
535             $close_rule,
536             'end',
537             ],
538             'or',
539             [
540             'begin',
541             qr{ \b N? loc_b ( dc ) \s* [(] }xms,
542             'and',
543             $domain_rule,
544             'and',
545             $comma_rule,
546             'and',
547             $text_rule,
548             'and',
549             $comma_rule,
550             'and',
551             $category_rule,
552             'and',
553             $close_rule,
554             'end',
555             ],
556             'or',
557             [
558             'begin',
559             qr{ \b N? loc_b ( dcp ) \s* [(] }xms,
560             $domain_rule,
561             'and',
562             $comma_rule,
563             'and',
564             $context_rule,
565             'and',
566             $comma_rule,
567             'and',
568             $text_rule,
569             'and',
570             $comma_rule,
571             'and',
572             $category_rule,
573             'and',
574             $close_rule,
575             'end',
576             ],
577            
578             # maketext loc, localise, localize
579             'or',
580             [
581             'begin',
582             qr{ \b N? loc (?: ali[sz]e )? (?: _m )? () \s* [(] }xms,
583             'and',
584             $text_rule,
585             'and',
586             $close_rule,
587             'end',
588             ],
589             'or',
590             [
591             'begin',
592             qr{ \b N? loc (?: ali[sz]e )? _m ( p ) \s* [(] }xms,
593             'and',
594             $context_rule,
595             'and',
596             $comma_rule,
597             'and',
598             $text_rule,
599             'and',
600             $close_rule,
601             'end',
602             ],
603            
604             # maketext
605             'or',
606             [
607             'begin',
608             qr{ \b N? maketext () \s* [(] }xms,
609             'and',
610             $text_rule,
611             'and',
612             $close_rule,
613             'end',
614             ],
615             'or',
616             [
617             'begin',
618             qr{ \b N? maketext_ ( p ) \s* [(] }xms,
619             'and',
620             $context_rule,
621             'and',
622             $comma_rule,
623             'and',
624             $text_rule,
625             'and',
626             $close_rule,
627             'end',
628             ],
629            
630             # begin
631             'or',
632             [
633             'begin',
634             qr{ \b (?: loc_ | __ ) ( begin ) _ ( [dc] ) \s* [(] }xms,
635             'and',
636             $domain_or_category_rule,
637             'end',
638             ],
639             'or',
640             [
641             'begin',
642             qr{ \b (?: loc_ | __ ) ( begin ) [_] ( dc ) \s* [(] }xms,
643             'and',
644             $domain_rule,
645             'and',
646             $comma_rule,
647             'and',
648             $category_rule,
649             'end',
650             ],
651             'or',
652             [
653             'begin',
654             qr{ \b loc_begin_b ( [dc] ) \s* [(] }xms,
655             'and',
656             $domain_or_category_rule,
657             'end',
658             ],
659             'or',
660             [
661             'begin',
662             qr{ \b loc_begin_b ( dc ) \s* [(] }xms,
663             'and',
664             $domain_rule,
665             'and',
666             $comma_rule,
667             'and',
668             $category_rule,
669             'end',
670             ],
671            
672             # end
673             'or',
674             [
675             'begin',
676             qr{ \b (?: loc_ | __ ) ( end ) [_] ( [dc] ) \b }xms,
677             'end',
678             ],
679             'or',
680             [
681             'begin',
682             qr{ \b (?: loc_ | __ ) ( end ) [_] ( dc ) \b }xms,
683             'end',
684             ],
685             'or',
686             [
687             'begin',
688             qr{ \b loc_end_b ( [dc] ) \b }xms,
689             'end',
690             ],
691             'or',
692             [
693             'begin',
694             qr{ \b loc_end_b ( dc ) \b }xms,
695             'end',
696             ],
697             ];
698            
699             # remove pod and all lines after __END__, handle different newlines
700             sub preprocess {
701 16     16 1 1579 my $self = shift;
702            
703 16         269 my $content_ref = $self->content_ref;
704            
705             # remove all lines after __END__
706             # replace pod without killing the line number
707 16         96 my ($is_pod, $is_end);
708 16         50 ${$content_ref}
709             = join "\n",
710             map {
711 16         33 $_ eq '__END__' ? do { $is_end = 1; q{} }
  16         32  
712             : $is_end ? ()
713             : m{ \A [=] ( \w+ ) }xms ? (
714             lc $1 eq 'cut'
715 2         6 ? do { $is_pod = 0; q{} }
  2         4  
716 1424 100       4573 : do { $is_pod = 1; q{} }
  2 100       6  
  2 100       6  
    100          
    100          
717             )
718             : $is_pod ? q{}
719             : $_;
720             }
721 16         35 split m{ \r? \n }xms, ${$content_ref};
  16         990  
722            
723             # replace heredoc's without killing the line number
724             # <<'...'
725             REPLACE: {
726 16 50       244 ${$content_ref} =~ s{
  16         30  
  16         72  
727             << \s* ' ( \w+ ) ' ( [^\n]* ) \n
728             ( .*? )
729             ^ \1 $
730             }
731             {
732 0         0 qq{\n'}
  0         0  
  0         0  
  0         0  
733             . do { my $text = $3; $text =~ s{'}{\\'}xmsg; $text }
734             . q{'}
735             . $2
736             }xmsge and redo REPLACE;
737             }
738             # <<...
739             # <<"..."
740 16 50       29 REPLACE: {
  16         23  
  16         56  
741             ${$content_ref} =~ s{
742             << \s* ( ["]? ) ( \w+ ) \1 ( [^\n]* ) \n
743             ( .*? )
744             ^ \2 $
745             }
746 0         0 {
  0         0  
  0         0  
  0         0  
747             qq{\n"}
748             . do { my $text = $4; $text =~ s{"}{\\"}xmsg; $text }
749             . q{"}
750             . $3
751             }xmsge and redo REPLACE;
752 16         48 }
753            
754             return $self;
755             }
756 281     281 1 550
757             sub interpolate_escape_sequence {
758             my ( undef, $string, $quot ) = @_;
759 281 100       541
760             # nothing to interpolate
761 278 50       470 defined $string
762             or return $string;
763             defined $quot
764 278   33     741 or confess 'Quote expected';
765 278 50       476
766             my $is_interpolate = $quot eq q{"} || $quot eq 'qq{';
767 278 100       460 if ( ! $is_interpolate ) {
768 272         434 # '...'
769 272         2002 if ( $quot eq q{'} ) {
770             $string =~ s{ \\ ( ['] ) }{$1}xmsg;
771             return $string;
772 6 50       16 }
773 6         24 # q{...}
774 6         94 if ( $quot eq 'q{' ) {
775             $string =~ s{ \\ ( [\{\}] ) }{$1}xmsg; ## no critic (EscapedMetacharacters)
776 0         0 return $string;
777             }
778             confess "Unknown quot $quot";
779             }
780            
781 0         0 # "..."
782             # qq{...}
783             my %char_of = (
784             b => "\b",
785             f => "\f",
786             n => "\n",
787             r => "\r",
788 0         0 t => "\t",
789             );
790             $string =~ s{
791             \\
792             (?:
793             ( [bfnrt] ) # Backspace
794             # Form feed
795             # New line
796             # Carriage return
797             # Horizontal tab
798             | ( [xN] ) # do not handle \x.., \x{...}, \N{...}
799             | (.) # Backslash itself
800             # Single quotation mark
801             # Double quotation mark
802             # anything else that needs no escape
803 0 0       0 )
    0          
804             }{
805             $1 ? $char_of{$1}
806             : $2 ? "\\$2"
807             : $3
808 0         0 }xmsge;
809            
810             return $string;
811             }
812 163     163 1 266
813             sub stack_item_mapping {
814 163         249 my $self = shift;
815            
816 163         214 my $match = $_->{match};
  163         292  
817 163 100       232 # The chars e.g. after loc_ were stored to make a decision now.
  163         321  
818             my $extra_parameter = shift @{$match};
819             @{$match}
820 157 100       317 or return;
821            
822             if ( $extra_parameter eq 'begin' ) {
823 2     2   4 {
  2         40  
824             d => sub {
825             push @{ $self->domain_stack }, $self->domain;
826 2         47 $self->domain(
  2         30  
827             scalar $self->interpolate_escape_sequence(
828             reverse splice @{$match}, 0, 2
829             ),
830             );
831 2     2   4 },
  2         47  
832             c => sub {
833             push @{ $self->category_stack }, $self->category;
834 2         66 $self->category(
  2         7  
835             scalar $self->interpolate_escape_sequence(
836             reverse splice @{$match}, 0, 2
837             ),
838             );
839 2     2   3 },
  2         34  
840             dc => sub {
841             push @{ $self->domain_stack }, $self->domain;
842 2         61 $self->domain(
  2         8  
843             scalar $self->interpolate_escape_sequence(
844             reverse splice @{$match}, 0, 2
845 2         67 ),
  2         28  
846             );
847             push @{ $self->category_stack }, $self->category;
848 2         40 $self->category(
  2         7  
849             scalar $self->interpolate_escape_sequence(
850             reverse splice @{$match}, 0, 2
851             ),
852 6         54 );
  6         41  
853 6         285 },
854             }->{ shift @{$match} }->();
855 151 100       291 return;
856             }
857             if ( $extra_parameter eq 'end' ) {
858 2 50   2   4 {
  2         35  
859             d => sub {
860 2         21 @{ $self->domain_stack }
  2         28  
861             or confess 'Domain stack is empty because end_d is called without begin_d or begin_dc before';
862             $self->domain( pop @{ $self->domain_stack } );
863 2 50   2   3 },
  2         35  
864             c => sub {
865 2         13 @{ $self->category_stack }
  2         28  
866             or confess 'Category stack is empty because end_c is called without begin_c or begin_dc before';
867             $self->category( pop @{ $self->category_stack } );
868 2 50   2   3 },
  2         34  
869             dc => sub {
870 2 50       13 @{ $self->domain_stack }
  2         29  
871             or confess 'Domain stack is empty because end_dc is called without begin_d or begin_dc before';
872 2         11 @{ $self->category_stack }
  2         29  
873 2         92 or confess 'Category stack is empty because end_dc is called without begin_c or begin_dc before';
  2         27  
874             $self->domain( pop @{ $self->domain_stack } );
875 6         42 $self->category( pop @{ $self->category_stack } );
  6         17  
876 6         311 },
877             }->{ shift @{$match} }->();
878             return;
879 145         184 }
880            
881             my $count;
882             $self->add_message({
883             reference => ( sprintf '%s:%s', $self->filename, $_->{line_number} ),
884 26         256 domain => $extra_parameter =~ m{ d }xms
885             ? scalar $self->interpolate_escape_sequence(
886             reverse splice @{$match}, 0, 2
887             )
888             : $self->domain,
889 48         986 msgctxt => $extra_parameter =~ m{ p }xms
890             ? scalar $self->interpolate_escape_sequence(
891             reverse splice @{$match}, 0, 2
892             )
893 145         2337 : undef,
894             msgid => scalar $self->interpolate_escape_sequence(
895             reverse splice @{$match}, 0, 2
896             ),
897             msgid_plural => $extra_parameter =~ m{ n }xms
898 28         42 ? do {
  28         78  
899             my $plural = $self->interpolate_escape_sequence(
900 28         50 reverse splice @{$match}, 0, 2
  28         48  
901 28         334 );
902             $count = shift @{$match};
903             $plural;
904             }
905             : undef,
906 26         60 category => $extra_parameter =~ m{ c }xms
907             ? scalar $self->interpolate_escape_sequence(
908             reverse splice @{$match}, 0, 2
909 145 100       2442 )
    100          
    100          
    100          
910 145         686 : $self->category,
  145         247  
911             automatic => do {
912 145         265 my $placeholders = shift @{$match};
913 290 100       491 my $string = join ', ', map { ## no critic (MutatingListFunctions)
914 170         365 defined $_
915 170         323 ? do {
916 170 100       489 s{ \s+ }{ }xmsg;
917             s{ \s+ \z }{}xms;
918             length $_ ? $_ : ();
919             }
920 145         228 : ();
921 145         835 } ( $count, $placeholders );
922             $string =~ s{ \A ( .{70} ) .+ \z }{$1 ...}xms;
923             $string;
924             },
925 145         496 });
926            
927             return;
928             }
929 14     14 1 11213
930             sub extract {
931 14         53 my $self = shift;
932 14         725
933 14         521 $self->start_rule( $self->_filtered_start_rule );
934 14         83 $self->rules($rules);
935 14         28 $self->preprocess;
  14         189  
936 163         401 $self->SUPER::extract;
937             for ( @{ $self->stack } ) {
938             $self->stack_item_mapping;
939 14         123 }
940            
941             return $self;
942             }
943            
944             __PACKAGE__->meta->make_immutable;
945            
946             1;
947            
948             __END__