File Coverage

blib/lib/Module/CPANfile/Writer.pm
Criterion Covered Total %
statement 63 64 98.4
branch 18 26 69.2
condition 8 8 100.0
subroutine 13 13 100.0
pod 4 4 100.0
total 106 115 92.1


line stmt bran cond sub pod time code
1             package Module::CPANfile::Writer;
2 5     5   308944 use strict;
  5         46  
  5         158  
3 5     5   27 use warnings;
  5         11  
  5         139  
4 5     5   33 use Carp qw/croak/;
  5         7  
  5         230  
5              
6 5     5   2209 use Babble::Match;
  5         487193  
  5         207  
7 5     5   4060 use PPR;
  5         189116  
  5         3576  
8              
9             our $VERSION = "0.01";
10              
11             sub new {
12 5     5 1 6749 my ($class, $f) = @_;
13 5 50       26 croak('Usage: Module::CPANfile::Writer->new($f)') unless defined $f;
14              
15 5         14 my $src;
16 5 100       26 if (ref $f) {
17 4 50       22 croak('Not a SCALAR reference') unless ref $f eq 'SCALAR';
18              
19 4         11 $src = $$f;
20             } else {
21 1         3 $src = do {
22 1 50       32 open my $fh, '<', $f or die $!;
23 1         6 local $/; <$fh>;
  1         33  
24             };
25             }
26              
27 5         35 return bless {
28             src => $src,
29             prereqs => [],
30             }, $class;
31             }
32              
33             sub src {
34 5     5 1 26 my $self = shift;
35              
36 5         74 my $top = Babble::Match->new(top_rule => 'Document', text => $self->{src});
37             $top->each_match_within('Call' => [
38             [ relationship => '(?:requires|recommends|suggests|conflicts)' ],
39             '(?&PerlOWS) \(? (?&PerlOWS)',
40             [ module => '(?: (?&PerlString) | (?&PerlBareword) )' ],
41             [ arg1_before => '(?&PerlOWS) (?: (?>(?&PerlComma)) (?&PerlOWS) )*' ],
42             [ arg1 => '(?&PerlAssignment)?' ],
43             '(?&PerlOWS) (?: (?>(?&PerlComma)) (?&PerlOWS) )*',
44             [ args => '(?&PerlCommaList)?' ],
45             '\)? (?&PerlOWS)',
46             ] => sub {
47 28     28   328814 my ($m) = @_;
48 28         567 my $relationship = $m->submatches->{relationship}->text;
49 28         1119461 my $module = _perl_string_or_bareword($m->submatches->{module}->text);
50              
51 28 50       609 my $prereq = _find_prereq($self->{add_prereqs}, $module, $relationship) or return;
52              
53 28         102 my $version = $prereq->{version};
54 28 100 100     787 if ($m->submatches->{arg1}->text eq '' || # no arguments except module name
55             _args_num($m->submatches->{args}->text) % 2 == 1 # not specify module version but there are options
56             ) {
57             # requires 'A';
58             # requires 'B', dist => '...';
59 13 50       262 if ($version) {
60 13         265 $m->submatches->{module}->transform_text(sub { s/$/, '$version'/ });
  13         500  
61             }
62             } else {
63             # requires 'C', '0.01';
64 15 100       141 if ($version) {
65 12         748 $m->submatches->{arg1}->replace_text(qq{'$version'});
66             } else {
67 3         146 $m->submatches->{arg1}->replace_text('');
68 3         1045 $m->submatches->{arg1_before}->replace_text('');
69             }
70             }
71 5         7239 });
72              
73 5         430743 return $top->text;
74             }
75              
76             sub save {
77 1     1 1 13 my ($self, $file) = @_;
78 1 50       4 croak('Usage: $self->save($file)') unless defined $file;
79              
80 1 50       63 open my $fh, '>', $file or die $!;
81 1         3 print {$fh} $self->src;
  1         5  
82             }
83              
84             sub add_prereq {
85 27     27 1 117 my ($self, $module, $version, %opts) = @_;
86 27 50       51 croak('Usage: $self->prereq($module, [$version, relationship => $relationship])') unless defined $module;
87              
88 27   100     72 my $relationship = $opts{relationship} || 'requires';
89              
90 27         36 push @{$self->{add_prereqs}}, {
  27         103  
91             module => $module,
92             version => $version,
93             relationship => $relationship,
94             };
95             }
96              
97             sub _find_prereq {
98 28     28   135 my ($prereqs, $module, $relationship) = @_;
99              
100 28         118 for my $prereq (@$prereqs) {
101 304 100 100     1022 if ($prereq->{module} eq $module && $prereq->{relationship} eq $relationship) {
102 28         166 return $prereq;
103             }
104             }
105              
106 0         0 return undef;
107             }
108              
109             sub _perl_string_or_bareword {
110 28     28   417 my ($s) = @_;
111              
112 28 100       988823 if ($s =~ /\A (?&PerlString) \Z $PPR::GRAMMAR/x) {
113 27         2754 return eval $s;
114             }
115              
116             # bareword
117 1         128 return $s;
118             }
119              
120             sub _args_num {
121 16     16   667 my ($s) = @_;
122              
123             # count number of arguments from PerlCommaList
124 16         656594 return scalar grep defined, $s =~ m{
125             \G (?: (?>(?&PerlComma)) (?&PerlOWS) )* ((?&PerlAssignment))
126             $PPR::GRAMMAR
127             }gcx;
128             }
129              
130             1;
131             __END__