File Coverage

blib/lib/Perl/LanguageServer/IO.pm
Criterion Covered Total %
statement 15 75 20.0
branch 0 24 0.0
condition 0 15 0.0
subroutine 5 10 50.0
pod 0 1 0.0
total 20 125 16.0


line stmt bran cond sub pod time code
1             package Perl::LanguageServer::IO ;
2              
3 1     1   575 use Moose::Role ;
  1         3  
  1         7  
4              
5 1     1   5138 use Coro ;
  1         2  
  1         83  
6 1     1   9 use Coro::AIO ;
  1         3  
  1         314  
7 1     1   8 use Data::Dump qw{dump} ;
  1         3  
  1         42  
8              
9 1     1   6 no warnings 'uninitialized' ;
  1         6  
  1         1046  
10              
11             has 'out_fh' =>
12             (
13             is => 'rw',
14             #isa => 'Int',
15             ) ;
16              
17             has 'in_fh' =>
18             (
19             is => 'rw',
20             #isa => 'Int',
21             ) ;
22              
23             # ---------------------------------------------------------------------------
24              
25             our $windows= ($^O =~ /Win/)?1:0 ;
26              
27             # ---------------------------------------------------------------------------
28              
29             sub _read
30             {
31 0     0     my ($self, $data, $length, $dataoffset, $fh, $readline) = @_ ;
32              
33 0   0       $fh ||= $self -> in_fh ;
34              
35 0 0         if (ref ($fh) =~ /^Coro::Handle/)
36             {
37 0 0         if ($readline)
38             {
39 0           $$data = $fh -> readline ;
40 0           return length ($$data) ;
41             }
42 0           return $fh -> sysread ($$data, $length, $dataoffset) ;
43             }
44 0 0 0       if (!$windows || !ref $fh)
45             {
46 0           return aio_read ($fh, undef, $length, $$data, $dataoffset) ;
47             }
48              
49 0           my $timeout = 0.01 ;
50              
51 0           my $s = IO::Select -> new ();
52 0           $s -> add($fh) ;
53 0           my @ready ;
54 0           while (!(@ready = $s -> can_read (0)))
55             {
56 0           Coro::AnyEvent::sleep ($timeout) ;
57             }
58 0 0         $length = length ($$data) if (!defined ($length)) ;
59 0           return sysread ($fh, $$data, $length, $dataoffset) ;
60             }
61              
62             # ---------------------------------------------------------------------------
63              
64             sub _write
65             {
66 0     0     my ($self, $data, $length, $dataoffset) = @_ ;
67              
68 0           my $fh = $self -> out_fh ;
69 0 0         if (ref ($fh) =~ /^Coro::Handle/)
70             {
71 0           return $fh -> syswrite ($data, $length, $dataoffset) ;
72             }
73              
74 0 0 0       if (!$windows || !ref $fh)
75             {
76 0           return aio_write ($fh, undef, $length, $data, $dataoffset) ;
77             }
78              
79 0 0         $length = length ($data) if (!defined ($length)) ;
80 0           return syswrite ($fh, $data, $length, $dataoffset) ;
81             }
82              
83             # ---------------------------------------------------------------------------
84              
85             sub run_async
86             {
87 0     0 0   my ($self, $cmd, $on_stdout, $on_stderr, $on_exit) = @_ ;
88              
89 0   0       $on_stdout ||= 'on_stdout' ;
90 0   0       $on_stderr ||= 'on_stderr' ;
91 0   0       $on_exit ||= 'on_exit' ;
92              
93 0           my($wtr, $rdr, $err);
94              
95 0 0         if ( ref($cmd) )
96             {
97 0           $self -> logger ("start @$cmd\n") ;
98             } else
99             {
100 0           $self -> logger ("start $cmd\n") ;
101             }
102              
103 0           require IPC::Open3 ;
104 0           require Symbol ;
105 0           $err = Symbol::gensym () ;
106 0           my $pid;
107 0 0         if ( ref($cmd) )
108             {
109 0 0         $pid = IPC::Open3::open3($wtr, $rdr, $err, @$cmd) or die "Cannot run @$cmd" ;
110             } else
111             {
112 0 0         $pid = IPC::Open3::open3($wtr, $rdr, $err, $cmd) or die "Cannot run $cmd" ;
113             }
114              
115 0           $self -> out_fh ($wtr) ;
116 0           $self -> in_fh ($rdr) ;
117              
118 0 0         if ( ref($cmd) )
119             {
120 0           $self -> logger ("@$cmd started\n") ;
121             } else
122             {
123 0           $self -> logger ("$cmd started\n") ;
124             }
125              
126             async
127             {
128 0     0     my $data ;
129 0           while ($self -> _read (\$data, 8192))
130             {
131 0           $self -> logger ("stdout ", $data, "\n") ;
132 0           $self -> $on_stdout ($data) ;
133             }
134 0           waitpid( $pid, 0 );
135 0           $self -> logger ("@$cmd ended\n") ;
136 0           Coro::cede_notself () ;
137 0           $self -> $on_exit ($?) ;
138 0           } ;
139              
140             async
141             {
142 0     0     my $data ;
143 0           while ($self -> _read (\$data, 8192, undef, $err))
144             {
145 0           $self -> logger ("stderr ", $data, "\n") ;
146 0           $self -> $on_stderr ($data) ;
147             }
148 0           } ;
149              
150 0           return $pid ;
151             }
152              
153              
154             1 ;
155