File Coverage

blib/lib/Perl/LanguageServer/IO.pm
Criterion Covered Total %
statement 15 68 22.0
branch 0 16 0.0
condition 0 15 0.0
subroutine 5 10 50.0
pod 0 1 0.0
total 20 110 18.1


line stmt bran cond sub pod time code
1             package Perl::LanguageServer::IO ;
2              
3 1     1   608 use Moose::Role ;
  1         3  
  1         11  
4              
5 1     1   5223 use Coro ;
  1         2  
  1         82  
6 1     1   8 use Coro::AIO ;
  1         2  
  1         312  
7 1     1   7 use Data::Dump qw{dump} ;
  1         2  
  1         41  
8              
9 1     1   5 no warnings 'uninitialized' ;
  1         4  
  1         893  
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           $self -> logger ("start @$cmd\n") ;
96              
97 0           require IPC::Open3 ;
98 0           require Symbol ;
99 0           $err = Symbol::gensym () ;
100 0 0         my $pid = IPC::Open3::open3($wtr, $rdr, $err, @$cmd) or die "Cannot run @$cmd" ;
101              
102 0           $self -> out_fh ($wtr) ;
103 0           $self -> in_fh ($rdr) ;
104              
105 0           $self -> logger ("@$cmd started\n") ;
106              
107             async
108             {
109 0     0     my $data ;
110 0           while ($self -> _read (\$data, 8192))
111             {
112 0           $self -> logger ("stdout ", $data, "\n") ;
113 0           $self -> $on_stdout ($data) ;
114             }
115 0           waitpid( $pid, 0 );
116 0           $self -> logger ("@$cmd ended\n") ;
117 0           Coro::cede_notself () ;
118 0           $self -> $on_exit ($?) ;
119 0           } ;
120              
121             async
122             {
123 0     0     my $data ;
124 0           while ($self -> _read (\$data, 8192, undef, $err))
125             {
126 0           $self -> logger ("stderr ", $data, "\n") ;
127 0           $self -> $on_stderr ($data) ;
128             }
129 0           } ;
130              
131 0           return $pid ;
132             }
133              
134              
135             1 ;
136