File Coverage

lib/Comment/Spell.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1 4     4   59965 use 5.008; # open scalar
  4         13  
  4         150  
2 4     4   18 use strict;
  4         5  
  4         126  
3 4     4   24 use warnings;
  4         4  
  4         233  
4              
5             package Comment::Spell;
6              
7             our $VERSION = '0.001001';
8              
9             # ABSTRACT: Spell Checking for your comments
10              
11             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
12              
13 4     4   16 use Carp qw( croak );
  4         4  
  4         302  
14 4     4   2188 use Moo qw( has );
  4         50227  
  4         27  
15 4     4   7256 use Pod::Wordlist 1.07;
  4         1646282  
  4         275  
16 4     4   4226 use PPI;
  0            
  0            
17             use Path::Tiny qw( path );
18             use IO::Handle;
19             use Text::Wrap qw( wrap );
20              
21             # this comment is for self testing
22             ## this comment is hidden for self testing
23              
24             has stopwords => (
25             is => 'rw',
26             lazy => 1,
27             builder => '_build_stopwords',
28             handles => {
29             '_learn_stopwords' => 'learn_stopwords',
30             },
31             );
32              
33             has output_filehandle => (
34             is => 'ro' =>,
35             writer => 'set_output_filehandle',
36             builder => '_build_output_filehandle',
37             handles => {
38             '_print_output' => 'print',
39             '_printf_output' => 'printf',
40             '_flush_output' => 'flush',
41             },
42             );
43              
44             sub _build_stopwords {
45             return Pod::Wordlist->new();
46             }
47              
48             sub _build_output_filehandle {
49             return \*STDOUT;
50             }
51              
52             sub set_output_file {
53             my ( $self, $filename ) = @_;
54             $self->set_output_filehandle( path($filename)->openw_raw );
55             return;
56             }
57              
58             sub set_output_string { ## no critic (Subroutines::RequireArgUnpacking)
59             open my $fh, '>', \$_[1] or croak 'Cant construct a scalar filehandle'; ## no critic ( InputOutput::RequireBriefOpen )
60             $_[0]->set_output_filehandle($fh);
61             return;
62             }
63              
64             sub _ppi_fh {
65             my ( undef, $fh ) = @_;
66             my $content = do {
67             local $/ = undef;
68             scalar <$fh>;
69             };
70             return PPI::Document->new( \$content, readonly => 1 );
71             }
72              
73             sub _ppi_file {
74             my ( undef, $file ) = @_;
75             return PPI::Document->new( $file, readonly => 1 );
76             }
77              
78             sub _ppi_string { ## no critic (Subroutines::RequireArgUnpacking)
79             return PPI::Document->new( \$_[1], readonly => 1 );
80             }
81              
82             sub _skip_comment {
83             my ( undef, $comment ) = @_;
84             if ( $comment->content =~ /\A[#]{2}/msx ) {
85             return 1;
86             }
87             return;
88             }
89              
90             sub _comment_text {
91             my ( undef, $comment ) = @_;
92             my $content = $comment->content;
93             $content =~ s/\A[#]//msx;
94             $content =~ s/\r?\n\z//msx;
95             return $content;
96             }
97              
98             sub _handle_comment_text {
99             my ( $self, $comment_text ) = @_;
100             return $self->_print_words( $self->stopwords->strip_stopwords($comment_text) );
101             }
102              
103             sub _handle_comment {
104             my ( $self, $comment ) = @_;
105             return $self->_handle_comment_text( $self->_comment_text($comment) );
106             }
107              
108             sub _print_words {
109             my ( $self, $text ) = @_;
110             if ( length $text ) {
111             local $Text::Wrap::huge = 'overflow'; ## no critic (Variables::ProhibitPackageVars)
112             $self->_print_output( wrap( q[], q[], $text ) . "\n\n" );
113             }
114             return;
115             }
116              
117             sub parse_from_document {
118             my ( $self, $document ) = @_;
119             my (@comments) = @{ $document->find('PPI::Token::Comment') || [] };
120             for my $comment (@comments) {
121             next if $self->_skip_comment($comment);
122             $self->_handle_comment($comment);
123             }
124             $self->_flush_output;
125             return;
126             }
127              
128             sub parse_from_filehandle {
129             my ( $self, $infh ) = @_;
130             return $self->parse_from_document( $self->_ppi_fh($infh) );
131             }
132              
133             sub parse_from_file {
134             my ( $self, $infile ) = @_;
135             return $self->parse_from_document( $self->_ppi_file($infile) );
136             }
137              
138             sub parse_from_string { ## no critic (Subroutines::RequireArgUnpacking)
139             return $_[0]->parse_from_document( $_[0]->_ppi_string( $_[1] ) );
140             }
141              
142             no Moo;
143              
144             1;
145              
146             __END__